Get intrinsics to inline at codegen
This commit is contained in:
parent
436ab319b8
commit
8810d34d54
@ -5,5 +5,5 @@ fn main() -> u32 {
|
||||
let value = 6;
|
||||
let other = 15;
|
||||
|
||||
return value + other;
|
||||
return value * other + 7 * -value;
|
||||
}
|
||||
|
@ -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,
|
||||
}
|
||||
|
@ -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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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<dyn IntrinsicFunction>),
|
||||
}
|
||||
|
||||
impl<'ctx> StackBinopDefinition<'ctx> {
|
||||
@ -197,20 +203,30 @@ impl<'ctx> StackBinopDefinition<'ctx> {
|
||||
lhs: &StackValue,
|
||||
rhs: &StackValue,
|
||||
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 {
|
||||
(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));
|
||||
|
@ -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<FunctionDefinition> {
|
||||
let mut intrinsics = Vec::new();
|
||||
let intrinsics = Vec::new();
|
||||
|
||||
intrinsics
|
||||
}
|
||||
@ -57,25 +52,32 @@ pub fn form_intrinsic_binops() -> Vec<BinopDefinition> {
|
||||
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<StackValue, ErrorKind>;
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct IntrinsicIAdd(TypeKind);
|
||||
|
||||
impl IntrinsicFunction for IntrinsicIAdd {
|
||||
fn codegen<'ctx, 'a>(
|
||||
&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()))
|
||||
}
|
||||
}
|
||||
|
@ -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<dyn IntrinsicFunction>),
|
||||
}
|
||||
|
||||
impl FunctionDefinition {
|
||||
|
Loading…
Reference in New Issue
Block a user