Get intrinsics to inline at codegen

This commit is contained in:
Sofia 2025-07-24 17:13:02 +03:00
parent 436ab319b8
commit 8810d34d54
6 changed files with 166 additions and 124 deletions

View File

@ -5,5 +5,5 @@ fn main() -> u32 {
let value = 6; let value = 6;
let other = 15; let other = 15;
return value + other; return value * other + 7 * -value;
} }

View File

@ -8,7 +8,7 @@ use std::{
}; };
use llvm_sys::{ use llvm_sys::{
LLVMIntPredicate, LLVMLinkage, LLVMRealPredicate, LLVMValueKind, LLVMAttributeIndex, LLVMIntPredicate, LLVMLinkage, LLVMRealPredicate, LLVMValueKind,
analysis::LLVMVerifyModule, analysis::LLVMVerifyModule,
core::*, core::*,
debuginfo::*, debuginfo::*,
@ -86,7 +86,7 @@ impl CompiledModule {
triple, triple,
c"generic".as_ptr(), c"generic".as_ptr(),
c"".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::LLVMRelocMode::LLVMRelocDefault,
llvm_sys::target_machine::LLVMCodeModel::LLVMCodeModelDefault, llvm_sys::target_machine::LLVMCodeModel::LLVMCodeModelDefault,
); );
@ -601,6 +601,15 @@ impl FunctionHolder {
let function_ref = let function_ref =
LLVMAddFunction(module_ref, into_cstring(&self.data.name).as_ptr(), fn_type); 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 { let metadata = if let Some(debug) = debug {
if let Some(value) = &self.data.debug { if let Some(value) = &self.data.debug {
let subprogram = debug.debug.get_subprogram_data_unchecked(&value); let subprogram = debug.debug.get_subprogram_data_unchecked(&value);
@ -1215,3 +1224,7 @@ impl Type {
} }
} }
} }
pub enum LLVMEnumAttribute {
AlwaysInline = 3,
}

View File

@ -148,6 +148,7 @@ pub struct FunctionFlags {
pub is_main: bool, pub is_main: bool,
pub is_pub: bool, pub is_pub: bool,
pub is_imported: bool, pub is_imported: bool,
pub inline: bool,
} }
impl Default for FunctionFlags { impl Default for FunctionFlags {
@ -157,6 +158,7 @@ impl Default for FunctionFlags {
is_main: false, is_main: false,
is_pub: false, is_pub: false,
is_imported: false, is_imported: false,
inline: false,
} }
} }
} }

View File

@ -16,6 +16,7 @@ use reid_lib::{
use crate::{ use crate::{
allocator::{Allocator, AllocatorScope}, allocator::{Allocator, AllocatorScope},
intrinsics::IntrinsicFunction,
lexer::{FullToken, Position}, lexer::{FullToken, Position},
mir::{ mir::{
self, self,
@ -137,7 +138,7 @@ pub struct Debug<'ctx> {
} }
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]
pub struct StackValue(StackValueKind, TypeKind); pub struct StackValue(pub(super) StackValueKind, pub(super) TypeKind);
impl StackValue { impl StackValue {
fn instr(&self) -> InstructionValue { fn instr(&self) -> InstructionValue {
@ -188,7 +189,12 @@ impl StackValueKind {
pub struct StackBinopDefinition<'ctx> { pub struct StackBinopDefinition<'ctx> {
parameters: ((String, TypeKind), (String, TypeKind)), parameters: ((String, TypeKind), (String, TypeKind)),
return_ty: TypeKind, return_ty: TypeKind,
ir: Function<'ctx>, kind: StackBinopFunctionKind<'ctx>,
}
pub enum StackBinopFunctionKind<'ctx> {
UserGenerated(Function<'ctx>),
Intrinsic(&'ctx Box<dyn IntrinsicFunction>),
} }
impl<'ctx> StackBinopDefinition<'ctx> { impl<'ctx> StackBinopDefinition<'ctx> {
@ -197,20 +203,30 @@ impl<'ctx> StackBinopDefinition<'ctx> {
lhs: &StackValue, lhs: &StackValue,
rhs: &StackValue, rhs: &StackValue,
scope: &mut Scope<'ctx, 'a>, scope: &mut Scope<'ctx, 'a>,
) -> StackValue { ) -> Result<StackValue, ErrorKind> {
let (lhs, rhs) = if lhs.1 == self.parameters.0 .1 && rhs.1 == self.parameters.1 .1 { let (lhs, rhs) = if lhs.1 == self.parameters.0 .1 && rhs.1 == self.parameters.1 .1 {
(lhs, rhs) (lhs, rhs)
} else { } else {
(rhs, lhs) (rhs, lhs)
}; };
let instr = scope match &self.kind {
.block StackBinopFunctionKind::UserGenerated(ir) => {
.build(Instr::FunctionCall( let instr = scope
self.ir.value(), .block
vec![lhs.instr(), rhs.instr()], .build(Instr::FunctionCall(
)) ir.value(),
.unwrap(); vec![lhs.instr(), rhs.instr()],
StackValue(StackValueKind::Immutable(instr), self.return_ty.clone()) ))
.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 is_main = self.is_main && function.name == "main";
let func = match &function.kind { let func = match &function.kind {
mir::FunctionDefinitionKind::Local(_, _) => module.function( mir::FunctionDefinitionKind::Local(_, _) => Some(module.function(
&function.name, &function.name,
function.return_type.get_type(&type_values), function.return_type.get_type(&type_values),
param_types, param_types,
@ -336,8 +352,8 @@ impl mir::Module {
is_imported: function.is_imported, is_imported: function.is_imported,
..FunctionFlags::default() ..FunctionFlags::default()
}, },
), )),
mir::FunctionDefinitionKind::Extern(imported) => module.function( mir::FunctionDefinitionKind::Extern(imported) => Some(module.function(
&function.name, &function.name,
function.return_type.get_type(&type_values), function.return_type.get_type(&type_values),
param_types, param_types,
@ -346,87 +362,17 @@ impl mir::Module {
is_imported: *imported, is_imported: *imported,
..FunctionFlags::default() ..FunctionFlags::default()
}, },
), )),
mir::FunctionDefinitionKind::Intrinsic(_) => module.function( mir::FunctionDefinitionKind::Intrinsic(_) => None,
&function.name,
function.return_type.get_type(&type_values),
param_types,
FunctionFlags {
..FunctionFlags::default()
},
),
}; };
functions.insert(function.name.clone(), func); if let Some(func) = func {
functions.insert(function.name.clone(), func);
}
} }
let mut binops = HashMap::new(); let mut binops = HashMap::new();
for binop in &self.binop_defs { 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( binops.insert(
ScopeBinopKey { ScopeBinopKey {
params: (binop.lhs.1.clone(), binop.rhs.1.clone()), params: (binop.lhs.1.clone(), binop.rhs.1.clone()),
@ -435,7 +381,83 @@ impl mir::Module {
StackBinopDefinition { StackBinopDefinition {
parameters: (binop.lhs.clone(), binop.rhs.clone()), parameters: (binop.lhs.clone(), binop.rhs.clone()),
return_ty: binop.return_type.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::Extern(_) => {}
mir::FunctionDefinitionKind::Intrinsic(kind) => kind.codegen(scope)?, mir::FunctionDefinitionKind::Intrinsic(_) => {}
}; };
Ok(()) Ok(())
} }
@ -877,7 +899,10 @@ impl mir::Expression {
}); });
if let Some(operation) = operation { 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 { } else {
dbg!((lhs_val.1.clone(), rhs_val.1.clone())); dbg!((lhs_val.1.clone(), rhs_val.1.clone()));
dbg!(&operation.map(|b| &b.return_ty)); dbg!(&operation.map(|b| &b.return_ty));

View File

@ -1,20 +1,15 @@
use reid_lib::Instr; use reid_lib::{builder::InstructionValue, Instr};
use crate::{ use crate::{
codegen::{ErrorKind, Scope}, codegen::{ErrorKind, Scope, StackValue, StackValueKind},
mir::{BinaryOperator, BinopDefinition, FunctionDefinition, FunctionDefinitionKind, TypeKind}, mir::{BinaryOperator, BinopDefinition, FunctionDefinition, FunctionDefinitionKind, TypeKind},
}; };
#[derive(Debug, Clone, Copy)]
pub enum InstrinsicKind {
IAdd,
}
fn intrinsic( fn intrinsic(
name: &str, name: &str,
ret_ty: TypeKind, ret_ty: TypeKind,
params: Vec<(&str, TypeKind)>, params: Vec<(&str, TypeKind)>,
kind: InstrinsicKind, fun: impl IntrinsicFunction + 'static,
) -> FunctionDefinition { ) -> FunctionDefinition {
FunctionDefinition { FunctionDefinition {
name: name.into(), name: name.into(),
@ -22,7 +17,7 @@ fn intrinsic(
is_imported: false, is_imported: false,
return_type: ret_ty, return_type: ret_ty,
parameters: params.into_iter().map(|(n, ty)| (n.into(), ty)).collect(), 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, lhs: TypeKind,
rhs: TypeKind, rhs: TypeKind,
ret_ty: TypeKind, ret_ty: TypeKind,
kind: InstrinsicKind, fun: impl IntrinsicFunction + 'static,
) -> BinopDefinition { ) -> BinopDefinition {
BinopDefinition { BinopDefinition {
lhs: ("lhs".to_string(), lhs), lhs: ("lhs".to_string(), lhs),
op, op,
rhs: ("rhs".to_owned(), rhs), rhs: ("rhs".to_owned(), rhs),
return_type: ret_ty, return_type: ret_ty,
fn_kind: FunctionDefinitionKind::Intrinsic(kind), fn_kind: FunctionDefinitionKind::Intrinsic(Box::new(fun)),
meta: Default::default(), meta: Default::default(),
} }
} }
pub fn form_intrinsics() -> Vec<FunctionDefinition> { pub fn form_intrinsics() -> Vec<FunctionDefinition> {
let mut intrinsics = Vec::new(); let intrinsics = Vec::new();
intrinsics intrinsics
} }
@ -57,25 +52,32 @@ pub fn form_intrinsic_binops() -> Vec<BinopDefinition> {
TypeKind::U32, TypeKind::U32,
TypeKind::U32, TypeKind::U32,
TypeKind::U32, TypeKind::U32,
InstrinsicKind::IAdd, IntrinsicIAdd(TypeKind::U32),
)); ));
intrinsics intrinsics
} }
impl InstrinsicKind { pub trait IntrinsicFunction: std::fmt::Debug {
pub fn codegen<'ctx, 'a>(&self, scope: &mut Scope<'ctx, 'a>) -> Result<(), ErrorKind> { fn codegen<'ctx, 'a>(
match self { &self,
InstrinsicKind::IAdd => { scope: &mut Scope<'ctx, 'a>,
let lhs = scope.block.build(Instr::Param(0)).unwrap(); params: &[InstructionValue],
let rhs = scope.block.build(Instr::Param(1)).unwrap(); ) -> Result<StackValue, ErrorKind>;
let add = scope.block.build(Instr::Add(lhs, rhs)).unwrap(); }
scope
.block #[derive(Debug, Clone)]
.terminate(reid_lib::TerminatorKind::Ret(add)) pub struct IntrinsicIAdd(TypeKind);
.unwrap()
} impl IntrinsicFunction for IntrinsicIAdd {
} fn codegen<'ctx, 'a>(
Ok(()) &self,
scope: &mut Scope<'ctx, 'a>,
params: &[InstructionValue],
) -> Result<StackValue, ErrorKind> {
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()))
} }
} }

View File

@ -5,7 +5,7 @@
use std::{collections::HashMap, path::PathBuf}; use std::{collections::HashMap, path::PathBuf};
use crate::{ use crate::{
intrinsics::InstrinsicKind, intrinsics::IntrinsicFunction,
lexer::{FullToken, Position}, lexer::{FullToken, Position},
token_stream::TokenRange, token_stream::TokenRange,
}; };
@ -303,7 +303,7 @@ pub enum FunctionDefinitionKind {
/// True = imported from other module, False = Is user defined extern /// True = imported from other module, False = Is user defined extern
Extern(bool), Extern(bool),
/// Intrinsic definition, defined within the compiler /// Intrinsic definition, defined within the compiler
Intrinsic(InstrinsicKind), Intrinsic(Box<dyn IntrinsicFunction>),
} }
impl FunctionDefinition { impl FunctionDefinition {