From 8810d34d54009e25784ec4349ff9dacbf1a30766 Mon Sep 17 00:00:00 2001 From: sofia Date: Thu, 24 Jul 2025 17:13:02 +0300 Subject: [PATCH] Get intrinsics to inline at codegen --- examples/arithmetic.reid | 2 +- reid-llvm-lib/src/compile.rs | 17 ++- reid-llvm-lib/src/lib.rs | 2 + reid/src/codegen.rs | 209 ++++++++++++++++++++--------------- reid/src/intrinsics.rs | 56 +++++----- reid/src/mir/mod.rs | 4 +- 6 files changed, 166 insertions(+), 124 deletions(-) diff --git a/examples/arithmetic.reid b/examples/arithmetic.reid index 6a6bd80..95223af 100644 --- a/examples/arithmetic.reid +++ b/examples/arithmetic.reid @@ -5,5 +5,5 @@ fn main() -> u32 { let value = 6; let other = 15; - return value + other; + return value * other + 7 * -value; } diff --git a/reid-llvm-lib/src/compile.rs b/reid-llvm-lib/src/compile.rs index 3629914..a0f8aca 100644 --- a/reid-llvm-lib/src/compile.rs +++ b/reid-llvm-lib/src/compile.rs @@ -8,7 +8,7 @@ use std::{ }; use llvm_sys::{ - LLVMIntPredicate, LLVMLinkage, LLVMRealPredicate, LLVMValueKind, + LLVMAttributeIndex, LLVMIntPredicate, LLVMLinkage, LLVMRealPredicate, LLVMValueKind, analysis::LLVMVerifyModule, core::*, debuginfo::*, @@ -86,7 +86,7 @@ impl CompiledModule { triple, c"generic".as_ptr(), c"".as_ptr(), - llvm_sys::target_machine::LLVMCodeGenOptLevel::LLVMCodeGenLevelNone, + llvm_sys::target_machine::LLVMCodeGenOptLevel::LLVMCodeGenLevelLess, llvm_sys::target_machine::LLVMRelocMode::LLVMRelocDefault, llvm_sys::target_machine::LLVMCodeModel::LLVMCodeModelDefault, ); @@ -601,6 +601,15 @@ impl FunctionHolder { let function_ref = LLVMAddFunction(module_ref, into_cstring(&self.data.name).as_ptr(), fn_type); + if self.data.flags.inline { + let attribute = LLVMCreateEnumAttribute( + context.context_ref, + LLVMEnumAttribute::AlwaysInline as u32, + 0, + ); + LLVMAddAttributeAtIndex(function_ref, 0, attribute); + } + let metadata = if let Some(debug) = debug { if let Some(value) = &self.data.debug { let subprogram = debug.debug.get_subprogram_data_unchecked(&value); @@ -1215,3 +1224,7 @@ impl Type { } } } + +pub enum LLVMEnumAttribute { + AlwaysInline = 3, +} diff --git a/reid-llvm-lib/src/lib.rs b/reid-llvm-lib/src/lib.rs index 5263e54..b9c9039 100644 --- a/reid-llvm-lib/src/lib.rs +++ b/reid-llvm-lib/src/lib.rs @@ -148,6 +148,7 @@ pub struct FunctionFlags { pub is_main: bool, pub is_pub: bool, pub is_imported: bool, + pub inline: bool, } impl Default for FunctionFlags { @@ -157,6 +158,7 @@ impl Default for FunctionFlags { is_main: false, is_pub: false, is_imported: false, + inline: false, } } } diff --git a/reid/src/codegen.rs b/reid/src/codegen.rs index 9cf5b2a..b1e3965 100644 --- a/reid/src/codegen.rs +++ b/reid/src/codegen.rs @@ -16,6 +16,7 @@ use reid_lib::{ use crate::{ allocator::{Allocator, AllocatorScope}, + intrinsics::IntrinsicFunction, lexer::{FullToken, Position}, mir::{ self, @@ -137,7 +138,7 @@ pub struct Debug<'ctx> { } #[derive(Debug, Clone, PartialEq, Eq)] -pub struct StackValue(StackValueKind, TypeKind); +pub struct StackValue(pub(super) StackValueKind, pub(super) TypeKind); impl StackValue { fn instr(&self) -> InstructionValue { @@ -188,7 +189,12 @@ impl StackValueKind { pub struct StackBinopDefinition<'ctx> { parameters: ((String, TypeKind), (String, TypeKind)), return_ty: TypeKind, - ir: Function<'ctx>, + kind: StackBinopFunctionKind<'ctx>, +} + +pub enum StackBinopFunctionKind<'ctx> { + UserGenerated(Function<'ctx>), + Intrinsic(&'ctx Box), } impl<'ctx> StackBinopDefinition<'ctx> { @@ -197,20 +203,30 @@ impl<'ctx> StackBinopDefinition<'ctx> { lhs: &StackValue, rhs: &StackValue, scope: &mut Scope<'ctx, 'a>, - ) -> StackValue { + ) -> Result { let (lhs, rhs) = if lhs.1 == self.parameters.0 .1 && rhs.1 == self.parameters.1 .1 { (lhs, rhs) } else { (rhs, lhs) }; - let instr = scope - .block - .build(Instr::FunctionCall( - self.ir.value(), - vec![lhs.instr(), rhs.instr()], - )) - .unwrap(); - StackValue(StackValueKind::Immutable(instr), self.return_ty.clone()) + match &self.kind { + StackBinopFunctionKind::UserGenerated(ir) => { + let instr = scope + .block + .build(Instr::FunctionCall( + ir.value(), + vec![lhs.instr(), rhs.instr()], + )) + .unwrap(); + Ok(StackValue( + StackValueKind::Immutable(instr), + self.return_ty.clone(), + )) + } + StackBinopFunctionKind::Intrinsic(fun) => { + fun.codegen(scope, &[lhs.instr(), rhs.instr()]) + } + } } } @@ -326,7 +342,7 @@ impl mir::Module { let is_main = self.is_main && function.name == "main"; let func = match &function.kind { - mir::FunctionDefinitionKind::Local(_, _) => module.function( + mir::FunctionDefinitionKind::Local(_, _) => Some(module.function( &function.name, function.return_type.get_type(&type_values), param_types, @@ -336,8 +352,8 @@ impl mir::Module { is_imported: function.is_imported, ..FunctionFlags::default() }, - ), - mir::FunctionDefinitionKind::Extern(imported) => module.function( + )), + mir::FunctionDefinitionKind::Extern(imported) => Some(module.function( &function.name, function.return_type.get_type(&type_values), param_types, @@ -346,87 +362,17 @@ impl mir::Module { is_imported: *imported, ..FunctionFlags::default() }, - ), - mir::FunctionDefinitionKind::Intrinsic(_) => module.function( - &function.name, - function.return_type.get_type(&type_values), - param_types, - FunctionFlags { - ..FunctionFlags::default() - }, - ), + )), + mir::FunctionDefinitionKind::Intrinsic(_) => None, }; - functions.insert(function.name.clone(), func); + if let Some(func) = func { + functions.insert(function.name.clone(), func); + } } 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 - ); - 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::default(), - ); - let mut entry = ir_function.block("entry"); - - let allocator = Allocator::from( - &binop.fn_kind, - &vec![binop.lhs.clone(), binop.rhs.clone()], - &mut AllocatorScope { - block: &mut entry, - module_id: self.module_id, - type_values: &type_values, - }, - ); - - let mut scope = Scope { - context, - modules: &modules, - tokens, - module: &module, - module_id: self.module_id, - function: &ir_function, - block: entry, - functions: &functions, - types: &types, - type_values: &type_values, - stack_values: HashMap::new(), - debug: Some(Debug { - info: &debug, - scope: compile_unit, - types: &debug_types, - }), - binops: &binops, - allocator: Rc::new(RefCell::new(allocator)), - }; - - binop - .fn_kind - .codegen( - binop_fn_name.clone(), - false, - &mut scope, - &vec![binop.lhs.clone(), binop.rhs.clone()], - &binop.return_type, - &ir_function, - match &binop.fn_kind { - FunctionDefinitionKind::Local(_, meta) => { - meta.into_debug(tokens, compile_unit) - } - FunctionDefinitionKind::Extern(_) => None, - FunctionDefinitionKind::Intrinsic(_) => None, - }, - ) - .unwrap(); - binops.insert( ScopeBinopKey { params: (binop.lhs.1.clone(), binop.rhs.1.clone()), @@ -435,7 +381,83 @@ impl mir::Module { StackBinopDefinition { parameters: (binop.lhs.clone(), binop.rhs.clone()), return_ty: binop.return_type.clone(), - ir: ir_function, + 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, + ..Default::default() + }, + ); + let mut entry = ir_function.block("entry"); + + let allocator = Allocator::from( + &binop.fn_kind, + &vec![binop.lhs.clone(), binop.rhs.clone()], + &mut AllocatorScope { + block: &mut entry, + module_id: self.module_id, + type_values: &type_values, + }, + ); + + let mut scope = Scope { + context, + modules: &modules, + tokens, + module: &module, + module_id: self.module_id, + function: &ir_function, + block: entry, + functions: &functions, + types: &types, + type_values: &type_values, + stack_values: HashMap::new(), + debug: Some(Debug { + info: &debug, + scope: compile_unit, + types: &debug_types, + }), + binops: &binops, + allocator: Rc::new(RefCell::new(allocator)), + }; + + binop + .fn_kind + .codegen( + binop_fn_name.clone(), + false, + &mut scope, + &vec![binop.lhs.clone(), binop.rhs.clone()], + &binop.return_type, + &ir_function, + match &binop.fn_kind { + FunctionDefinitionKind::Local(_, meta) => { + meta.into_debug(tokens, compile_unit) + } + FunctionDefinitionKind::Extern(_) => None, + FunctionDefinitionKind::Intrinsic(_) => None, + }, + ) + .unwrap(); + + StackBinopFunctionKind::UserGenerated(ir_function) + } + FunctionDefinitionKind::Extern(_) => todo!(), + FunctionDefinitionKind::Intrinsic(intrinsic_function) => { + StackBinopFunctionKind::Intrinsic(intrinsic_function) + } + }, }, ); } @@ -619,7 +641,7 @@ impl FunctionDefinitionKind { } } mir::FunctionDefinitionKind::Extern(_) => {} - mir::FunctionDefinitionKind::Intrinsic(kind) => kind.codegen(scope)?, + mir::FunctionDefinitionKind::Intrinsic(_) => {} }; Ok(()) } @@ -877,7 +899,10 @@ impl mir::Expression { }); if let Some(operation) = operation { - Some(operation.codegen(&lhs_val, &rhs_val, scope)) + let a = operation.codegen(&lhs_val, &rhs_val, scope)?; + dbg!(&scope.context); + dbg!(&a); + Some(a) } else { dbg!((lhs_val.1.clone(), rhs_val.1.clone())); dbg!(&operation.map(|b| &b.return_ty)); diff --git a/reid/src/intrinsics.rs b/reid/src/intrinsics.rs index a743aee..087651a 100644 --- a/reid/src/intrinsics.rs +++ b/reid/src/intrinsics.rs @@ -1,20 +1,15 @@ -use reid_lib::Instr; +use reid_lib::{builder::InstructionValue, Instr}; use crate::{ - codegen::{ErrorKind, Scope}, + codegen::{ErrorKind, Scope, StackValue, StackValueKind}, mir::{BinaryOperator, BinopDefinition, FunctionDefinition, FunctionDefinitionKind, TypeKind}, }; -#[derive(Debug, Clone, Copy)] -pub enum InstrinsicKind { - IAdd, -} - fn intrinsic( name: &str, ret_ty: TypeKind, params: Vec<(&str, TypeKind)>, - kind: InstrinsicKind, + fun: impl IntrinsicFunction + 'static, ) -> FunctionDefinition { FunctionDefinition { name: name.into(), @@ -22,7 +17,7 @@ fn intrinsic( is_imported: false, return_type: ret_ty, parameters: params.into_iter().map(|(n, ty)| (n.into(), ty)).collect(), - kind: FunctionDefinitionKind::Intrinsic(kind), + kind: FunctionDefinitionKind::Intrinsic(Box::new(fun)), } } @@ -31,20 +26,20 @@ fn intrinsic_binop( lhs: TypeKind, rhs: TypeKind, ret_ty: TypeKind, - kind: InstrinsicKind, + fun: impl IntrinsicFunction + 'static, ) -> BinopDefinition { BinopDefinition { lhs: ("lhs".to_string(), lhs), op, rhs: ("rhs".to_owned(), rhs), return_type: ret_ty, - fn_kind: FunctionDefinitionKind::Intrinsic(kind), + fn_kind: FunctionDefinitionKind::Intrinsic(Box::new(fun)), meta: Default::default(), } } pub fn form_intrinsics() -> Vec { - let mut intrinsics = Vec::new(); + let intrinsics = Vec::new(); intrinsics } @@ -57,25 +52,32 @@ pub fn form_intrinsic_binops() -> Vec { TypeKind::U32, TypeKind::U32, TypeKind::U32, - InstrinsicKind::IAdd, + IntrinsicIAdd(TypeKind::U32), )); intrinsics } -impl InstrinsicKind { - pub fn codegen<'ctx, 'a>(&self, scope: &mut Scope<'ctx, 'a>) -> Result<(), ErrorKind> { - match self { - InstrinsicKind::IAdd => { - let lhs = scope.block.build(Instr::Param(0)).unwrap(); - let rhs = scope.block.build(Instr::Param(1)).unwrap(); - let add = scope.block.build(Instr::Add(lhs, rhs)).unwrap(); - scope - .block - .terminate(reid_lib::TerminatorKind::Ret(add)) - .unwrap() - } - } - Ok(()) +pub trait IntrinsicFunction: std::fmt::Debug { + fn codegen<'ctx, 'a>( + &self, + scope: &mut Scope<'ctx, 'a>, + params: &[InstructionValue], + ) -> Result; +} + +#[derive(Debug, Clone)] +pub struct IntrinsicIAdd(TypeKind); + +impl IntrinsicFunction for IntrinsicIAdd { + fn codegen<'ctx, 'a>( + &self, + scope: &mut Scope<'ctx, 'a>, + params: &[InstructionValue], + ) -> Result { + let lhs = params.get(0).unwrap(); + let rhs = params.get(1).unwrap(); + let add = scope.block.build(Instr::Add(*lhs, *rhs)).unwrap(); + Ok(StackValue(StackValueKind::Literal(add), self.0.clone())) } } diff --git a/reid/src/mir/mod.rs b/reid/src/mir/mod.rs index 09652a7..b43eef9 100644 --- a/reid/src/mir/mod.rs +++ b/reid/src/mir/mod.rs @@ -5,7 +5,7 @@ use std::{collections::HashMap, path::PathBuf}; use crate::{ - intrinsics::InstrinsicKind, + intrinsics::IntrinsicFunction, lexer::{FullToken, Position}, token_stream::TokenRange, }; @@ -303,7 +303,7 @@ pub enum FunctionDefinitionKind { /// True = imported from other module, False = Is user defined extern Extern(bool), /// Intrinsic definition, defined within the compiler - Intrinsic(InstrinsicKind), + Intrinsic(Box), } impl FunctionDefinition {