nac3core: function codegen callback changes

Added code generator argument to the callback, so it would be easier to
write complicated codegen with that callback. To prepare for RPC
codegen.
This commit is contained in:
pca006132 2022-02-12 21:00:12 +08:00
parent ffe89eec86
commit 050c862c1a
3 changed files with 48 additions and 51 deletions

View File

@ -371,13 +371,7 @@ pub fn gen_call<'ctx, 'a, G: CodeGenerator>(
..
} => {
if let Some(callback) = codegen_callback {
// TODO: Change signature
let obj = obj.map(|(t, v)| (t, v.to_basic_value_enum(ctx, generator)));
let params = params
.into_iter()
.map(|(name, val)| (name, val.to_basic_value_enum(ctx, generator)))
.collect();
return callback.run(ctx, obj, fun, params);
return callback.run(ctx, obj, fun, params, generator);
}
let old_key = ctx.get_subst_key(obj.as_ref().map(|a| a.0), fun.0, None);
let mut keys = fun.0.args.clone();
@ -431,7 +425,7 @@ pub fn gen_call<'ctx, 'a, G: CodeGenerator>(
};
param_vals = real_params
.into_iter()
.map(|p| p.to_basic_value_enum(ctx, generator).into())
.map(|p| p.to_basic_value_enum(ctx, generator))
.collect_vec();
instance_to_symbol.get(&key).cloned()
}

View File

@ -62,13 +62,13 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
instance_to_stmt: Default::default(),
resolver: None,
codegen_callback: Some(Arc::new(GenCall::new(Box::new(
|ctx, _, fun, args| {
|ctx, _, fun, args, generator| {
let int32 = ctx.primitives.int32;
let int64 = ctx.primitives.int64;
let float = ctx.primitives.float;
let boolean = ctx.primitives.bool;
let arg_ty = fun.0.args[0].ty;
let arg = args[0].1;
let arg = args[0].1.clone().to_basic_value_enum(ctx, generator);
if ctx.unifier.unioned(arg_ty, boolean) {
Some(
ctx.builder
@ -120,13 +120,13 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
instance_to_stmt: Default::default(),
resolver: None,
codegen_callback: Some(Arc::new(GenCall::new(Box::new(
|ctx, _, fun, args| {
|ctx, _, fun, args, generator| {
let int32 = ctx.primitives.int32;
let int64 = ctx.primitives.int64;
let float = ctx.primitives.float;
let boolean = ctx.primitives.bool;
let arg_ty = fun.0.args[0].ty;
let arg = args[0].1;
let arg = args[0].1.clone().to_basic_value_enum(ctx, generator);
if ctx.unifier.unioned(arg_ty, boolean)
|| ctx.unifier.unioned(arg_ty, int32)
{
@ -170,18 +170,18 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
instance_to_stmt: Default::default(),
resolver: None,
codegen_callback: Some(Arc::new(GenCall::new(Box::new(
|ctx, _, fun, args| {
|ctx, _, fun, args, generator| {
let int32 = ctx.primitives.int32;
let int64 = ctx.primitives.int64;
let boolean = ctx.primitives.bool;
let float = ctx.primitives.float;
let arg_ty = fun.0.args[0].ty;
let arg = args[0].1;
let arg = args[0].1.clone().to_basic_value_enum(ctx, generator);
if ctx.unifier.unioned(arg_ty, boolean)
|| ctx.unifier.unioned(arg_ty, int32)
|| ctx.unifier.unioned(arg_ty, int64)
{
let arg = args[0].1.into_int_value();
let arg = arg.into_int_value();
let val = ctx
.builder
.build_signed_int_to_float(arg, ctx.ctx.f64_type(), "sitofp")
@ -207,8 +207,8 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
instance_to_symbol: Default::default(),
instance_to_stmt: Default::default(),
resolver: None,
codegen_callback: Some(Arc::new(GenCall::new(Box::new(|ctx, _, _, args| {
let arg = args[0].1;
codegen_callback: Some(Arc::new(GenCall::new(Box::new(|ctx, _, _, args, generator| {
let arg = args[0].1.clone().to_basic_value_enum(ctx, generator);
let round_intrinsic =
ctx.module.get_function("llvm.round.f64").unwrap_or_else(|| {
let float = ctx.ctx.f64_type();
@ -244,8 +244,8 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
instance_to_symbol: Default::default(),
instance_to_stmt: Default::default(),
resolver: None,
codegen_callback: Some(Arc::new(GenCall::new(Box::new(|ctx, _, _, args| {
let arg = args[0].1;
codegen_callback: Some(Arc::new(GenCall::new(Box::new(|ctx, _, _, args, generator| {
let arg = args[0].1.clone().to_basic_value_enum(ctx, generator);
let round_intrinsic =
ctx.module.get_function("llvm.round.f64").unwrap_or_else(|| {
let float = ctx.ctx.f64_type();
@ -294,7 +294,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
instance_to_symbol: Default::default(),
instance_to_stmt: Default::default(),
resolver: None,
codegen_callback: Some(Arc::new(GenCall::new(Box::new(|ctx, _, _, args| {
codegen_callback: Some(Arc::new(GenCall::new(Box::new(|ctx, _, _, args, generator| {
let mut start = None;
let mut stop = None;
let mut step = None;
@ -302,17 +302,17 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
let zero = int32.const_zero();
for (i, arg) in args.iter().enumerate() {
if arg.0 == Some("start".into()) {
start = Some(arg.1);
start = Some(arg.1.clone().to_basic_value_enum(ctx, generator));
} else if arg.0 == Some("stop".into()) {
stop = Some(arg.1);
stop = Some(arg.1.clone().to_basic_value_enum(ctx, generator));
} else if arg.0 == Some("step".into()) {
step = Some(arg.1);
step = Some(arg.1.clone().to_basic_value_enum(ctx, generator));
} else if i == 0 {
start = Some(arg.1);
start = Some(arg.1.clone().to_basic_value_enum(ctx, generator));
} else if i == 1 {
stop = Some(arg.1);
stop = Some(arg.1.clone().to_basic_value_enum(ctx, generator));
} else if i == 2 {
step = Some(arg.1);
step = Some(arg.1.clone().to_basic_value_enum(ctx, generator));
}
}
// TODO: error when step == 0
@ -356,8 +356,8 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
instance_to_symbol: Default::default(),
instance_to_stmt: Default::default(),
resolver: None,
codegen_callback: Some(Arc::new(GenCall::new(Box::new(|_, _, _, args| {
Some(args[0].1)
codegen_callback: Some(Arc::new(GenCall::new(Box::new(|ctx, _, _, args, generator| {
Some(args[0].1.clone().to_basic_value_enum(ctx, generator))
})))),
})),
Arc::new(RwLock::new(TopLevelDef::Function {
@ -373,13 +373,13 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
instance_to_stmt: Default::default(),
resolver: None,
codegen_callback: Some(Arc::new(GenCall::new(Box::new(
|ctx, _, fun, args| {
|ctx, _, fun, args, generator| {
let int32 = ctx.primitives.int32;
let int64 = ctx.primitives.int64;
let float = ctx.primitives.float;
let boolean = ctx.primitives.bool;
let arg_ty = fun.0.args[0].ty;
let arg = args[0].1;
let arg = args[0].1.clone().to_basic_value_enum(ctx, generator);
if ctx.unifier.unioned(arg_ty, boolean) {
Some(arg)
} else if ctx.unifier.unioned(arg_ty, int32) {
@ -424,8 +424,8 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
instance_to_symbol: Default::default(),
instance_to_stmt: Default::default(),
resolver: None,
codegen_callback: Some(Arc::new(GenCall::new(Box::new(|ctx, _, _, args| {
let arg = args[0].1;
codegen_callback: Some(Arc::new(GenCall::new(Box::new(|ctx, _, _, args, generator| {
let arg = args[0].1.clone().to_basic_value_enum(ctx, generator);
let floor_intrinsic =
ctx.module.get_function("llvm.floor.f64").unwrap_or_else(|| {
let float = ctx.ctx.f64_type();
@ -461,8 +461,8 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
instance_to_symbol: Default::default(),
instance_to_stmt: Default::default(),
resolver: None,
codegen_callback: Some(Arc::new(GenCall::new(Box::new(|ctx, _, _, args| {
let arg = args[0].1;
codegen_callback: Some(Arc::new(GenCall::new(Box::new(|ctx, _, _, args, generator| {
let arg = args[0].1.clone().to_basic_value_enum(ctx, generator);
let floor_intrinsic =
ctx.module.get_function("llvm.floor.f64").unwrap_or_else(|| {
let float = ctx.ctx.f64_type();
@ -498,8 +498,8 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
instance_to_symbol: Default::default(),
instance_to_stmt: Default::default(),
resolver: None,
codegen_callback: Some(Arc::new(GenCall::new(Box::new(|ctx, _, _, args| {
let arg = args[0].1;
codegen_callback: Some(Arc::new(GenCall::new(Box::new(|ctx, _, _, args, generator| {
let arg = args[0].1.clone().to_basic_value_enum(ctx, generator);
let ceil_intrinsic =
ctx.module.get_function("llvm.ceil.f64").unwrap_or_else(|| {
let float = ctx.ctx.f64_type();
@ -535,8 +535,8 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
instance_to_symbol: Default::default(),
instance_to_stmt: Default::default(),
resolver: None,
codegen_callback: Some(Arc::new(GenCall::new(Box::new(|ctx, _, _, args| {
let arg = args[0].1;
codegen_callback: Some(Arc::new(GenCall::new(Box::new(|ctx, _, _, args, generator| {
let arg = args[0].1.clone().to_basic_value_enum(ctx, generator);
let ceil_intrinsic =
ctx.module.get_function("llvm.ceil.f64").unwrap_or_else(|| {
let float = ctx.ctx.f64_type();
@ -581,10 +581,10 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
instance_to_stmt: Default::default(),
resolver: None,
codegen_callback: Some(Arc::new(GenCall::new(Box::new(
|ctx, _, fun, args| {
|ctx, _, fun, args, generator| {
let range_ty = ctx.primitives.range;
let arg_ty = fun.0.args[0].ty;
let arg = args[0].1;
let arg = args[0].1.clone().to_basic_value_enum(ctx, generator);
if ctx.unifier.unioned(arg_ty, range_ty) {
let arg = arg.into_pointer_value();
let (start, end, step) = destructure_range(ctx, arg);

View File

@ -11,20 +11,21 @@ use super::codegen::CodeGenContext;
use super::typecheck::type_inferencer::PrimitiveStore;
use super::typecheck::typedef::{FunSignature, FuncArg, SharedUnifier, Type, TypeEnum, Unifier};
use crate::{
symbol_resolver::SymbolResolver,
codegen::CodeGenerator,
symbol_resolver::{SymbolResolver, ValueEnum},
typecheck::{type_inferencer::CodeLocation, typedef::CallId},
};
use itertools::{izip, Itertools};
use parking_lot::RwLock;
use nac3parser::ast::{self, Stmt, StrRef};
use inkwell::values::BasicValueEnum;
use itertools::{izip, Itertools};
use nac3parser::ast::{self, Stmt, StrRef};
use parking_lot::RwLock;
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash, Debug)]
pub struct DefinitionId(pub usize);
pub mod builtins;
pub mod composer;
pub mod helper;
pub mod builtins;
pub mod type_annotation;
use composer::*;
use type_annotation::*;
@ -34,9 +35,10 @@ mod test;
type GenCallCallback = Box<
dyn for<'ctx, 'a> Fn(
&mut CodeGenContext<'ctx, 'a>,
Option<(Type, BasicValueEnum)>,
Option<(Type, ValueEnum<'ctx>)>,
(&FunSignature, DefinitionId),
Vec<(Option<StrRef>, BasicValueEnum<'ctx>)>,
Vec<(Option<StrRef>, ValueEnum<'ctx>)>,
&mut dyn CodeGenerator,
) -> Option<BasicValueEnum<'ctx>>
+ Send
+ Sync,
@ -54,11 +56,12 @@ impl GenCall {
pub fn run<'ctx, 'a>(
&self,
ctx: &mut CodeGenContext<'ctx, 'a>,
obj: Option<(Type, BasicValueEnum<'ctx>)>,
obj: Option<(Type, ValueEnum<'ctx>)>,
fun: (&FunSignature, DefinitionId),
args: Vec<(Option<StrRef>, BasicValueEnum<'ctx>)>,
args: Vec<(Option<StrRef>, ValueEnum<'ctx>)>,
generator: &mut dyn CodeGenerator,
) -> Option<BasicValueEnum<'ctx>> {
(self.fp)(ctx, obj, fun, args)
(self.fp)(ctx, obj, fun, args, generator)
}
}
@ -120,7 +123,7 @@ pub enum TopLevelDef {
// symbol resolver of the module defined the class
resolver: Option<Arc<dyn SymbolResolver + Send + Sync>>,
// custom codegen callback
codegen_callback: Option<Arc<GenCall>>
codegen_callback: Option<Arc<GenCall>>,
},
}