diff --git a/examples/imported_type.reid b/examples/imported_type.reid index d020484..9d06a13 100644 --- a/examples/imported_type.reid +++ b/examples/imported_type.reid @@ -14,6 +14,6 @@ fn otus(param: &mut String) { fn main() -> u8 { let mut otus = from_str("hello"); otus(&mut otus); - print(otus); + print(otus + " beep"); return 0; } \ No newline at end of file diff --git a/reid-llvm-lib/src/lib.rs b/reid-llvm-lib/src/lib.rs index b9c9039..6b34787 100644 --- a/reid-llvm-lib/src/lib.rs +++ b/reid-llvm-lib/src/lib.rs @@ -5,9 +5,7 @@ use std::{fmt::Debug, marker::PhantomData}; use builder::{BlockValue, Builder, FunctionValue, InstructionValue, ModuleValue, TypeValue}; -use debug_information::{ - DebugFileData, DebugInformation, DebugLocationValue, DebugMetadataValue, DebugProgramValue, -}; +use debug_information::{DebugFileData, DebugInformation, DebugLocationValue, DebugMetadataValue, DebugProgramValue}; use fmt::PrintableModule; pub mod builder; @@ -66,13 +64,7 @@ pub struct Module<'ctx> { } impl<'ctx> Module<'ctx> { - pub fn function( - &self, - name: &str, - ret: Type, - params: Vec, - flags: FunctionFlags, - ) -> Function<'ctx> { + pub fn function(&self, name: &str, ret: Type, params: Vec, flags: FunctionFlags) -> Function<'ctx> { unsafe { Function { phantom: PhantomData, @@ -111,10 +103,7 @@ impl<'ctx> Module<'ctx> { } } - pub fn create_debug_info( - &mut self, - file: DebugFileData, - ) -> (DebugInformation, DebugProgramValue) { + pub fn create_debug_info(&mut self, file: DebugFileData) -> (DebugInformation, DebugProgramValue) { let (debug_info, program_value) = DebugInformation::from_file(file); self.debug_info = Some(debug_info.clone()); (debug_info, program_value) @@ -144,10 +133,17 @@ pub struct FunctionData { #[derive(Debug, Clone, Copy, Hash)] pub struct FunctionFlags { + /// True in the destination module of the import, false in the source module. pub is_extern: bool, + /// Whether this function is the main function of the module, that should be + /// executed (and linked externally also). pub is_main: bool, + /// Whether this function should be available externally always. pub is_pub: bool, + /// If this function is an imported function (either in the source or + /// destination module) pub is_imported: bool, + /// Whether this function should add "alwaysinline"-attribute. pub inline: bool, } @@ -260,11 +256,7 @@ impl Instr { } impl<'builder> Block<'builder> { - pub fn build_named>( - &mut self, - name: T, - instruction: Instr, - ) -> CompileResult { + pub fn build_named>(&mut self, name: T, instruction: Instr) -> CompileResult { unsafe { self.builder.add_instruction( &self.value, @@ -295,15 +287,13 @@ impl<'builder> Block<'builder> { pub fn set_instr_location(&self, instruction: InstructionValue, location: DebugLocationValue) { unsafe { - self.builder - .add_instruction_location(&instruction, location); + self.builder.add_instruction_location(&instruction, location); } } pub fn set_instr_metadata(&self, instruction: InstructionValue, location: DebugMetadataValue) { unsafe { - self.builder - .add_instruction_metadata(&instruction, location); + self.builder.add_instruction_metadata(&instruction, location); } } @@ -610,16 +600,10 @@ impl Type { | Type::U32 | Type::U64 | Type::U128 => TypeCategory::Integer, - Type::F16 - | Type::F32B - | Type::F32 - | Type::F64 - | Type::F80 - | Type::F128 - | Type::F128PPC => TypeCategory::Real, - Type::Bool | Type::Void | Type::CustomType(_) | Type::Array(_, _) | Type::Ptr(_) => { - TypeCategory::Other + Type::F16 | Type::F32B | Type::F32 | Type::F64 | Type::F80 | Type::F128 | Type::F128PPC => { + TypeCategory::Real } + Type::Bool | Type::Void | Type::CustomType(_) | Type::Array(_, _) | Type::Ptr(_) => TypeCategory::Other, } } @@ -630,23 +614,15 @@ impl Type { (I16, I32 | I64 | I128) => Some(Instr::SExt(value, other.clone())), (I32, I64 | I128) => Some(Instr::SExt(value, other.clone())), (I64, I128) => Some(Instr::SExt(value, other.clone())), - (I128 | U128, I64 | U64 | I32 | U32 | I16 | U16 | I8 | U8) => { - Some(Instr::Trunc(value, other.clone())) - } - (I64 | U64, I32 | U32 | I16 | U16 | I8 | U8) => { - Some(Instr::Trunc(value, other.clone())) - } + (I128 | U128, I64 | U64 | I32 | U32 | I16 | U16 | I8 | U8) => Some(Instr::Trunc(value, other.clone())), + (I64 | U64, I32 | U32 | I16 | U16 | I8 | U8) => Some(Instr::Trunc(value, other.clone())), (I32 | U32, I16 | U16 | I8 | U8) => Some(Instr::Trunc(value, other.clone())), (I16 | U16, I8 | U8) => Some(Instr::Trunc(value, other.clone())), (U8 | I8, U8 | I8 | U16 | I16 | U32 | I32 | U64 | I64 | U128 | I128) => { Some(Instr::ZExt(value, other.clone())) } - (U16 | I16, U16 | I16 | U32 | I32 | U64 | I64 | U128 | I128) => { - Some(Instr::ZExt(value, other.clone())) - } - (U32 | I32, U32 | I32 | U64 | I64 | U128 | I128) => { - Some(Instr::ZExt(value, other.clone())) - } + (U16 | I16, U16 | I16 | U32 | I32 | U64 | I64 | U128 | I128) => Some(Instr::ZExt(value, other.clone())), + (U32 | I32, U32 | I32 | U64 | I64 | U128 | I128) => Some(Instr::ZExt(value, other.clone())), (U64 | I64, U64 | I64 | U128 | I128) => Some(Instr::ZExt(value, other.clone())), (U128 | I128, U128 | I128) => Some(Instr::ZExt(value, other.clone())), (U8 | U16 | U32 | U64 | U128, F16 | F32 | F32B | F64 | F80 | F128 | F128PPC) => { @@ -667,15 +643,11 @@ impl Type { (Ptr(_), I128 | U128 | I64 | U64 | I32 | U32 | I16 | U16 | I8 | U8) => { Some(Instr::PtrToInt(value, other.clone())) } - (F16, F32 | F32B | F64 | F80 | F128 | F128PPC) => { - Some(Instr::FPExt(value, other.clone())) - } + (F16, F32 | F32B | F64 | F80 | F128 | F128PPC) => Some(Instr::FPExt(value, other.clone())), (F32 | F32B, F64 | F80 | F128 | F128PPC) => Some(Instr::FPExt(value, other.clone())), (F64, F80 | F128 | F128PPC) => Some(Instr::FPExt(value, other.clone())), (F80, F128 | F128PPC) => Some(Instr::FPExt(value, other.clone())), - (F128PPC | F128, F80 | F64 | F32B | F32 | F16) => { - Some(Instr::FPTrunc(value, other.clone())) - } + (F128PPC | F128, F80 | F64 | F32B | F32 | F16) => Some(Instr::FPTrunc(value, other.clone())), (F80, F64 | F32B | F32 | F16) => Some(Instr::FPTrunc(value, other.clone())), (F64, F32B | F32 | F16) => Some(Instr::FPTrunc(value, other.clone())), (F32B | F32, F16) => Some(Instr::FPTrunc(value, other.clone())), diff --git a/reid/lib/std.reid b/reid/lib/std.reid index d5089af..e133222 100644 --- a/reid/lib/std.reid +++ b/reid/lib/std.reid @@ -4,6 +4,21 @@ extern fn malloc(size: u64) -> *u8; extern fn free(ptr: *u8); extern fn div(numerator: i32, denominator: i32) -> div_t; +struct String { + inner: *char, + length: u64, + max_length: u64, + must_be_freed: bool, +} + +impl binop (lhs: String) + (rhs: *char) -> String { + let mut new = lhs; + let added = from_str(rhs); + concat_strings(&mut new, added); + free_string(&added); + return lhs; +} + struct div_t { quotient: i32, remainder: i32, @@ -21,13 +36,6 @@ pub fn allocate(size: u64) -> *u8 { malloc(size) } -struct String { - inner: *char, - length: u64, - max_length: u64, - must_be_freed: bool, -} - pub fn new_string() -> String { String { inner: allocate(0), diff --git a/reid/src/ast/process.rs b/reid/src/ast/process.rs index 6d161fc..9afbd76 100644 --- a/reid/src/ast/process.rs +++ b/reid/src/ast/process.rs @@ -117,6 +117,7 @@ impl ast::Module { block.2.as_meta(module_id), ), meta: signature_range.as_meta(module_id), + exported: false, }); } } diff --git a/reid/src/codegen/intrinsics.rs b/reid/src/codegen/intrinsics.rs index 3ad2184..bdb8180 100644 --- a/reid/src/codegen/intrinsics.rs +++ b/reid/src/codegen/intrinsics.rs @@ -49,6 +49,7 @@ where return_type: ty.clone(), fn_kind: FunctionDefinitionKind::Intrinsic(Box::new(IntrinsicSimpleInstr(fun))), meta: Default::default(), + exported: false, } } @@ -63,6 +64,7 @@ where return_type: TypeKind::Bool, fn_kind: FunctionDefinitionKind::Intrinsic(Box::new(IntrinsicBooleanInstr(fun))), meta: Default::default(), + exported: false, } } diff --git a/reid/src/codegen/mod.rs b/reid/src/codegen/mod.rs index 3c12391..d63d79c 100644 --- a/reid/src/codegen/mod.rs +++ b/reid/src/codegen/mod.rs @@ -15,7 +15,7 @@ use scope::*; use crate::{ mir::{ - self, implement::TypeCategory, pass::ScopeBinopKey, CustomTypeKey, FunctionDefinitionKind, NamedVariableRef, + self, implement::TypeCategory, pass::BinopKey, CustomTypeKey, FunctionDefinitionKind, NamedVariableRef, SourceModuleId, StructField, StructType, TypeDefinition, TypeDefinitionKind, TypeKind, WhileStatement, }, util::try_all, @@ -214,8 +214,12 @@ impl mir::Module { let mut binops = HashMap::new(); for binop in &self.binop_defs { + let binop_fn_name = format!( + "binop.{}.{:?}.{}.{}", + binop.lhs.1, binop.op, binop.rhs.1, binop.return_type + ); binops.insert( - ScopeBinopKey { + BinopKey { params: (binop.lhs.1.clone(), binop.rhs.1.clone()), operator: binop.op, }, @@ -224,16 +228,14 @@ impl mir::Module { return_ty: binop.return_type.clone(), kind: match &binop.fn_kind { FunctionDefinitionKind::Local(block, metadata) => { - let binop_fn_name = format!( - "binop.{}.{:?}.{}.{}", - binop.lhs.1, binop.op, binop.rhs.1, binop.return_type - ); let ir_function = module.function( &binop_fn_name, binop.return_type.get_type(&type_values), vec![binop.lhs.1.get_type(&type_values), binop.rhs.1.get_type(&type_values)], FunctionFlags { inline: true, + is_pub: binop.exported, + is_imported: binop.exported, ..Default::default() }, ); @@ -289,7 +291,18 @@ impl mir::Module { StackBinopFunctionKind::UserGenerated(ir_function) } - FunctionDefinitionKind::Extern(_) => todo!(), + FunctionDefinitionKind::Extern(imported) => { + StackBinopFunctionKind::UserGenerated(module.function( + &binop_fn_name, + binop.return_type.get_type(&type_values), + vec![binop.lhs.1.get_type(&type_values), binop.rhs.1.get_type(&type_values)], + FunctionFlags { + is_extern: true, + is_imported: *imported, + ..FunctionFlags::default() + }, + )) + } FunctionDefinitionKind::Intrinsic(intrinsic_function) => { StackBinopFunctionKind::Intrinsic(intrinsic_function) } @@ -704,7 +717,7 @@ impl mir::Expression { let lhs = lhs_val.instr(); let rhs = rhs_val.instr(); - let operation = scope.binops.get(&ScopeBinopKey { + let operation = scope.binops.get(&BinopKey { params: (lhs_val.1.clone(), rhs_val.1.clone()), operator: *binop, }); diff --git a/reid/src/codegen/scope.rs b/reid/src/codegen/scope.rs index 1232ae2..fbbf8f1 100644 --- a/reid/src/codegen/scope.rs +++ b/reid/src/codegen/scope.rs @@ -8,7 +8,7 @@ use reid_lib::{ use crate::{ lexer::FullToken, - mir::{pass::ScopeBinopKey, CustomTypeKey, SourceModuleId, TypeDefinition, TypeKind}, + mir::{pass::BinopKey, CustomTypeKey, SourceModuleId, TypeDefinition, TypeKind}, }; use super::{allocator::Allocator, ErrorKind, IntrinsicFunction, ModuleCodegen}; @@ -24,7 +24,7 @@ pub struct Scope<'ctx, 'scope> { pub(super) types: &'scope HashMap, pub(super) type_values: &'scope HashMap, pub(super) functions: &'scope HashMap>, - pub(super) binops: &'scope HashMap>, + pub(super) binops: &'scope HashMap>, pub(super) stack_values: HashMap, pub(super) debug: Option>, pub(super) allocator: Rc>, @@ -150,15 +150,9 @@ impl<'ctx> StackBinopDefinition<'ctx> { StackBinopFunctionKind::UserGenerated(ir) => { let instr = scope .block - .build(Instr::FunctionCall( - ir.value(), - vec![lhs.instr(), rhs.instr()], - )) + .build(Instr::FunctionCall(ir.value(), vec![lhs.instr(), rhs.instr()])) .unwrap(); - Ok(StackValue( - StackValueKind::Immutable(instr), - self.return_ty.clone(), - )) + Ok(StackValue(StackValueKind::Immutable(instr), self.return_ty.clone())) } StackBinopFunctionKind::Intrinsic(fun) => fun.codegen(scope, &[&lhs, &rhs]), } diff --git a/reid/src/lib.rs b/reid/src/lib.rs index 97c811a..6dcb79c 100644 --- a/reid/src/lib.rs +++ b/reid/src/lib.rs @@ -130,7 +130,7 @@ pub fn perform_all_passes<'map>( for intrinsic in form_intrinsic_binops() { binops .set( - mir::pass::ScopeBinopKey { + mir::pass::BinopKey { params: (intrinsic.lhs.1.clone(), intrinsic.rhs.1.clone()), operator: intrinsic.op, }, diff --git a/reid/src/mir/fmt.rs b/reid/src/mir/fmt.rs index 52b05bc..8e9b5f7 100644 --- a/reid/src/mir/fmt.rs +++ b/reid/src/mir/fmt.rs @@ -66,8 +66,14 @@ impl Display for BinopDefinition { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!( f, - "impl binop ({}: {:#}) {} ({}: {:#}) -> {:#} ", - self.lhs.0, self.lhs.1, self.op, self.rhs.0, self.rhs.1, self.return_type + "{}impl binop ({}: {:#}) {} ({}: {:#}) -> {:#} ", + if self.exported { "exported " } else { "" }, + self.lhs.0, + self.lhs.1, + self.op, + self.rhs.0, + self.rhs.1, + self.return_type )?; Display::fmt(&self.fn_kind, f) } diff --git a/reid/src/mir/linker.rs b/reid/src/mir/linker.rs index d3facc1..962b7fb 100644 --- a/reid/src/mir/linker.rs +++ b/reid/src/mir/linker.rs @@ -11,7 +11,10 @@ use crate::{ codegen::scope, compile_module, error_raporting::{ErrorModules, ReidError}, - mir::{CustomTypeKey, FunctionDefinitionKind, SourceModuleId, TypeDefinition, TypeKind}, + mir::{ + pass::BinopKey, BinopDefinition, CustomTypeKey, FunctionDefinitionKind, SourceModuleId, TypeDefinition, + TypeKind, + }, parse_module, }; @@ -110,6 +113,7 @@ impl<'map> Pass for LinkerPass<'map> { let mut modules_to_process: Vec>> = modules.values().cloned().collect(); let mut already_imported_types = HashSet::::new(); + let mut already_imported_binops = HashSet::::new(); while let Some(module) = modules_to_process.pop() { let mut extern_types = HashMap::new(); @@ -232,10 +236,39 @@ impl<'map> Pass for LinkerPass<'map> { kind: super::FunctionDefinitionKind::Extern(true), }); } else if let Some(ty) = imported.typedefs.iter_mut().find(|f| f.name == *import_name) { - dbg!("hello??"); let external_key = CustomTypeKey(ty.name.clone(), ty.source_module); + let imported_ty = TypeKind::CustomType(external_key.clone()); imported_types.push((external_key, true)); - dbg!(&imported_types); + + for binop in &mut imported.binop_defs { + if binop.lhs.1 != imported_ty && binop.rhs.1 != imported_ty { + continue; + } + let binop_key = BinopKey { + params: (binop.lhs.1.clone(), binop.rhs.1.clone()), + operator: binop.op, + }; + if already_imported_binops.contains(&binop_key) { + continue; + } + binop.exported = true; + already_imported_binops.insert(binop_key); + match &binop.fn_kind { + FunctionDefinitionKind::Local(block, metadata) => { + importer_module.binop_defs.push(BinopDefinition { + lhs: binop.lhs.clone(), + op: binop.op, + rhs: binop.rhs.clone(), + return_type: binop.return_type.clone(), + fn_kind: FunctionDefinitionKind::Extern(true), + meta: binop.meta.clone(), + exported: false, + }); + } + FunctionDefinitionKind::Extern(_) => {} + FunctionDefinitionKind::Intrinsic(_) => {} + } + } } else { state.ok::<_, Infallible>( Err(ErrorKind::ImportDoesNotExist(module_name.clone(), import_name.clone())), diff --git a/reid/src/mir/mod.rs b/reid/src/mir/mod.rs index 5b72174..52f6eb2 100644 --- a/reid/src/mir/mod.rs +++ b/reid/src/mir/mod.rs @@ -370,6 +370,8 @@ pub struct BinopDefinition { pub return_type: TypeKind, pub fn_kind: FunctionDefinitionKind, pub meta: Metadata, + // Wether this binop definition has been imported into another module. + pub exported: bool, } impl BinopDefinition { diff --git a/reid/src/mir/pass.rs b/reid/src/mir/pass.rs index e2c7321..2ed78d8 100644 --- a/reid/src/mir/pass.rs +++ b/reid/src/mir/pass.rs @@ -117,7 +117,7 @@ impl Storage { } } -pub type BinopMap = Storage; +pub type BinopMap = Storage; #[derive(Clone, Default, Debug)] pub struct Scope { @@ -182,7 +182,7 @@ pub struct ScopeVariable { } #[derive(Clone, Debug, Eq)] -pub struct ScopeBinopKey { +pub struct BinopKey { pub params: (TypeKind, TypeKind), pub operator: BinaryOperator, } @@ -194,7 +194,7 @@ pub enum CommutativeKind { Any, } -impl PartialEq for ScopeBinopKey { +impl PartialEq for BinopKey { fn eq(&self, other: &Self) -> bool { if self.operator != other.operator { return false; @@ -216,7 +216,7 @@ impl PartialEq for ScopeBinopKey { } } -impl std::hash::Hash for ScopeBinopKey { +impl std::hash::Hash for BinopKey { fn hash(&self, state: &mut H) { if self.operator.is_commutative() { let mut sorted = vec![&self.params.0, &self.params.1]; @@ -336,7 +336,7 @@ impl Context { scope .binops .set( - ScopeBinopKey { + BinopKey { params: (intrinsic.lhs.1.clone(), intrinsic.rhs.1.clone()), operator: intrinsic.op, }, @@ -374,7 +374,7 @@ impl Module { scope .binops .set( - ScopeBinopKey { + BinopKey { params: (binop.lhs.1.clone(), binop.rhs.1.clone()), operator: binop.op, }, diff --git a/reid/src/mir/typecheck/typecheck.rs b/reid/src/mir/typecheck/typecheck.rs index e77bf55..5b1304a 100644 --- a/reid/src/mir/typecheck/typecheck.rs +++ b/reid/src/mir/typecheck/typecheck.rs @@ -422,7 +422,7 @@ impl Expression { ); }; - let binops = state.scope.binops.filter(&pass::ScopeBinopKey { + let binops = state.scope.binops.filter(&pass::BinopKey { params: (lhs_type.clone(), rhs_type.clone()), operator: *op, }); diff --git a/reid/src/mir/typecheck/typeinference.rs b/reid/src/mir/typecheck/typeinference.rs index ca72bba..d103586 100644 --- a/reid/src/mir/typecheck/typeinference.rs +++ b/reid/src/mir/typecheck/typeinference.rs @@ -20,7 +20,7 @@ use crate::{ use super::{ super::{ - pass::{Pass, PassResult, PassState, ScopeBinopKey}, + pass::{BinopKey, Pass, PassResult, PassState}, TypeKind::*, VagueType::*, }, @@ -62,7 +62,7 @@ impl<'t> Pass for TypeInference<'t> { let mut seen_binops = HashSet::new(); for binop in &module.binop_defs { - let binop_key = ScopeBinopKey { + let binop_key = BinopKey { params: (binop.lhs.1.clone(), binop.rhs.1.clone()), operator: binop.op, }; diff --git a/reid/src/mir/typecheck/typerefs.rs b/reid/src/mir/typecheck/typerefs.rs index 08d934f..e7f3a51 100644 --- a/reid/src/mir/typecheck/typerefs.rs +++ b/reid/src/mir/typecheck/typerefs.rs @@ -10,7 +10,7 @@ use crate::{ }; use super::{ - super::pass::{ScopeBinopDef, ScopeBinopKey, Storage}, + super::pass::{BinopKey, ScopeBinopDef, Storage}, ErrorKind, };