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 { if let Some(callback) = codegen_callback {
// TODO: Change signature return callback.run(ctx, obj, fun, params, generator);
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);
} }
let old_key = ctx.get_subst_key(obj.as_ref().map(|a| a.0), fun.0, None); let old_key = ctx.get_subst_key(obj.as_ref().map(|a| a.0), fun.0, None);
let mut keys = fun.0.args.clone(); let mut keys = fun.0.args.clone();
@ -431,7 +425,7 @@ pub fn gen_call<'ctx, 'a, G: CodeGenerator>(
}; };
param_vals = real_params param_vals = real_params
.into_iter() .into_iter()
.map(|p| p.to_basic_value_enum(ctx, generator).into()) .map(|p| p.to_basic_value_enum(ctx, generator))
.collect_vec(); .collect_vec();
instance_to_symbol.get(&key).cloned() 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(), instance_to_stmt: Default::default(),
resolver: None, resolver: None,
codegen_callback: Some(Arc::new(GenCall::new(Box::new( codegen_callback: Some(Arc::new(GenCall::new(Box::new(
|ctx, _, fun, args| { |ctx, _, fun, args, generator| {
let int32 = ctx.primitives.int32; let int32 = ctx.primitives.int32;
let int64 = ctx.primitives.int64; let int64 = ctx.primitives.int64;
let float = ctx.primitives.float; let float = ctx.primitives.float;
let boolean = ctx.primitives.bool; let boolean = ctx.primitives.bool;
let arg_ty = fun.0.args[0].ty; 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) { if ctx.unifier.unioned(arg_ty, boolean) {
Some( Some(
ctx.builder ctx.builder
@ -120,13 +120,13 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
instance_to_stmt: Default::default(), instance_to_stmt: Default::default(),
resolver: None, resolver: None,
codegen_callback: Some(Arc::new(GenCall::new(Box::new( codegen_callback: Some(Arc::new(GenCall::new(Box::new(
|ctx, _, fun, args| { |ctx, _, fun, args, generator| {
let int32 = ctx.primitives.int32; let int32 = ctx.primitives.int32;
let int64 = ctx.primitives.int64; let int64 = ctx.primitives.int64;
let float = ctx.primitives.float; let float = ctx.primitives.float;
let boolean = ctx.primitives.bool; let boolean = ctx.primitives.bool;
let arg_ty = fun.0.args[0].ty; 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) if ctx.unifier.unioned(arg_ty, boolean)
|| ctx.unifier.unioned(arg_ty, int32) || ctx.unifier.unioned(arg_ty, int32)
{ {
@ -170,18 +170,18 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
instance_to_stmt: Default::default(), instance_to_stmt: Default::default(),
resolver: None, resolver: None,
codegen_callback: Some(Arc::new(GenCall::new(Box::new( codegen_callback: Some(Arc::new(GenCall::new(Box::new(
|ctx, _, fun, args| { |ctx, _, fun, args, generator| {
let int32 = ctx.primitives.int32; let int32 = ctx.primitives.int32;
let int64 = ctx.primitives.int64; let int64 = ctx.primitives.int64;
let boolean = ctx.primitives.bool; let boolean = ctx.primitives.bool;
let float = ctx.primitives.float; let float = ctx.primitives.float;
let arg_ty = fun.0.args[0].ty; 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) if ctx.unifier.unioned(arg_ty, boolean)
|| ctx.unifier.unioned(arg_ty, int32) || ctx.unifier.unioned(arg_ty, int32)
|| ctx.unifier.unioned(arg_ty, int64) || ctx.unifier.unioned(arg_ty, int64)
{ {
let arg = args[0].1.into_int_value(); let arg = arg.into_int_value();
let val = ctx let val = ctx
.builder .builder
.build_signed_int_to_float(arg, ctx.ctx.f64_type(), "sitofp") .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_symbol: Default::default(),
instance_to_stmt: Default::default(), instance_to_stmt: Default::default(),
resolver: None, 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 arg = args[0].1; let arg = args[0].1.clone().to_basic_value_enum(ctx, generator);
let round_intrinsic = let round_intrinsic =
ctx.module.get_function("llvm.round.f64").unwrap_or_else(|| { ctx.module.get_function("llvm.round.f64").unwrap_or_else(|| {
let float = ctx.ctx.f64_type(); 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_symbol: Default::default(),
instance_to_stmt: Default::default(), instance_to_stmt: Default::default(),
resolver: None, 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 arg = args[0].1; let arg = args[0].1.clone().to_basic_value_enum(ctx, generator);
let round_intrinsic = let round_intrinsic =
ctx.module.get_function("llvm.round.f64").unwrap_or_else(|| { ctx.module.get_function("llvm.round.f64").unwrap_or_else(|| {
let float = ctx.ctx.f64_type(); 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_symbol: Default::default(),
instance_to_stmt: Default::default(), instance_to_stmt: Default::default(),
resolver: None, 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 start = None;
let mut stop = None; let mut stop = None;
let mut step = None; let mut step = None;
@ -302,17 +302,17 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
let zero = int32.const_zero(); let zero = int32.const_zero();
for (i, arg) in args.iter().enumerate() { for (i, arg) in args.iter().enumerate() {
if arg.0 == Some("start".into()) { 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()) { } 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()) { } 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 { } else if i == 0 {
start = Some(arg.1); start = Some(arg.1.clone().to_basic_value_enum(ctx, generator));
} else if i == 1 { } else if i == 1 {
stop = Some(arg.1); stop = Some(arg.1.clone().to_basic_value_enum(ctx, generator));
} else if i == 2 { } else if i == 2 {
step = Some(arg.1); step = Some(arg.1.clone().to_basic_value_enum(ctx, generator));
} }
} }
// TODO: error when step == 0 // 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_symbol: Default::default(),
instance_to_stmt: Default::default(), instance_to_stmt: Default::default(),
resolver: None, resolver: None,
codegen_callback: Some(Arc::new(GenCall::new(Box::new(|_, _, _, args| { codegen_callback: Some(Arc::new(GenCall::new(Box::new(|ctx, _, _, args, generator| {
Some(args[0].1) Some(args[0].1.clone().to_basic_value_enum(ctx, generator))
})))), })))),
})), })),
Arc::new(RwLock::new(TopLevelDef::Function { Arc::new(RwLock::new(TopLevelDef::Function {
@ -373,13 +373,13 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
instance_to_stmt: Default::default(), instance_to_stmt: Default::default(),
resolver: None, resolver: None,
codegen_callback: Some(Arc::new(GenCall::new(Box::new( codegen_callback: Some(Arc::new(GenCall::new(Box::new(
|ctx, _, fun, args| { |ctx, _, fun, args, generator| {
let int32 = ctx.primitives.int32; let int32 = ctx.primitives.int32;
let int64 = ctx.primitives.int64; let int64 = ctx.primitives.int64;
let float = ctx.primitives.float; let float = ctx.primitives.float;
let boolean = ctx.primitives.bool; let boolean = ctx.primitives.bool;
let arg_ty = fun.0.args[0].ty; 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) { if ctx.unifier.unioned(arg_ty, boolean) {
Some(arg) Some(arg)
} else if ctx.unifier.unioned(arg_ty, int32) { } 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_symbol: Default::default(),
instance_to_stmt: Default::default(), instance_to_stmt: Default::default(),
resolver: None, 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 arg = args[0].1; let arg = args[0].1.clone().to_basic_value_enum(ctx, generator);
let floor_intrinsic = let floor_intrinsic =
ctx.module.get_function("llvm.floor.f64").unwrap_or_else(|| { ctx.module.get_function("llvm.floor.f64").unwrap_or_else(|| {
let float = ctx.ctx.f64_type(); 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_symbol: Default::default(),
instance_to_stmt: Default::default(), instance_to_stmt: Default::default(),
resolver: None, 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 arg = args[0].1; let arg = args[0].1.clone().to_basic_value_enum(ctx, generator);
let floor_intrinsic = let floor_intrinsic =
ctx.module.get_function("llvm.floor.f64").unwrap_or_else(|| { ctx.module.get_function("llvm.floor.f64").unwrap_or_else(|| {
let float = ctx.ctx.f64_type(); 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_symbol: Default::default(),
instance_to_stmt: Default::default(), instance_to_stmt: Default::default(),
resolver: None, 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 arg = args[0].1; let arg = args[0].1.clone().to_basic_value_enum(ctx, generator);
let ceil_intrinsic = let ceil_intrinsic =
ctx.module.get_function("llvm.ceil.f64").unwrap_or_else(|| { ctx.module.get_function("llvm.ceil.f64").unwrap_or_else(|| {
let float = ctx.ctx.f64_type(); 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_symbol: Default::default(),
instance_to_stmt: Default::default(), instance_to_stmt: Default::default(),
resolver: None, 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 arg = args[0].1; let arg = args[0].1.clone().to_basic_value_enum(ctx, generator);
let ceil_intrinsic = let ceil_intrinsic =
ctx.module.get_function("llvm.ceil.f64").unwrap_or_else(|| { ctx.module.get_function("llvm.ceil.f64").unwrap_or_else(|| {
let float = ctx.ctx.f64_type(); let float = ctx.ctx.f64_type();
@ -581,10 +581,10 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
instance_to_stmt: Default::default(), instance_to_stmt: Default::default(),
resolver: None, resolver: None,
codegen_callback: Some(Arc::new(GenCall::new(Box::new( codegen_callback: Some(Arc::new(GenCall::new(Box::new(
|ctx, _, fun, args| { |ctx, _, fun, args, generator| {
let range_ty = ctx.primitives.range; let range_ty = ctx.primitives.range;
let arg_ty = fun.0.args[0].ty; 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) { if ctx.unifier.unioned(arg_ty, range_ty) {
let arg = arg.into_pointer_value(); let arg = arg.into_pointer_value();
let (start, end, step) = destructure_range(ctx, arg); 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::type_inferencer::PrimitiveStore;
use super::typecheck::typedef::{FunSignature, FuncArg, SharedUnifier, Type, TypeEnum, Unifier}; use super::typecheck::typedef::{FunSignature, FuncArg, SharedUnifier, Type, TypeEnum, Unifier};
use crate::{ use crate::{
symbol_resolver::SymbolResolver, codegen::CodeGenerator,
symbol_resolver::{SymbolResolver, ValueEnum},
typecheck::{type_inferencer::CodeLocation, typedef::CallId}, 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 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)] #[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash, Debug)]
pub struct DefinitionId(pub usize); pub struct DefinitionId(pub usize);
pub mod builtins;
pub mod composer; pub mod composer;
pub mod helper; pub mod helper;
pub mod builtins;
pub mod type_annotation; pub mod type_annotation;
use composer::*; use composer::*;
use type_annotation::*; use type_annotation::*;
@ -34,9 +35,10 @@ mod test;
type GenCallCallback = Box< type GenCallCallback = Box<
dyn for<'ctx, 'a> Fn( dyn for<'ctx, 'a> Fn(
&mut CodeGenContext<'ctx, 'a>, &mut CodeGenContext<'ctx, 'a>,
Option<(Type, BasicValueEnum)>, Option<(Type, ValueEnum<'ctx>)>,
(&FunSignature, DefinitionId), (&FunSignature, DefinitionId),
Vec<(Option<StrRef>, BasicValueEnum<'ctx>)>, Vec<(Option<StrRef>, ValueEnum<'ctx>)>,
&mut dyn CodeGenerator,
) -> Option<BasicValueEnum<'ctx>> ) -> Option<BasicValueEnum<'ctx>>
+ Send + Send
+ Sync, + Sync,
@ -54,11 +56,12 @@ impl GenCall {
pub fn run<'ctx, 'a>( pub fn run<'ctx, 'a>(
&self, &self,
ctx: &mut CodeGenContext<'ctx, 'a>, ctx: &mut CodeGenContext<'ctx, 'a>,
obj: Option<(Type, BasicValueEnum<'ctx>)>, obj: Option<(Type, ValueEnum<'ctx>)>,
fun: (&FunSignature, DefinitionId), fun: (&FunSignature, DefinitionId),
args: Vec<(Option<StrRef>, BasicValueEnum<'ctx>)>, args: Vec<(Option<StrRef>, ValueEnum<'ctx>)>,
generator: &mut dyn CodeGenerator,
) -> Option<BasicValueEnum<'ctx>> { ) -> 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 // symbol resolver of the module defined the class
resolver: Option<Arc<dyn SymbolResolver + Send + Sync>>, resolver: Option<Arc<dyn SymbolResolver + Send + Sync>>,
// custom codegen callback // custom codegen callback
codegen_callback: Option<Arc<GenCall>> codegen_callback: Option<Arc<GenCall>>,
}, },
} }