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.
escape-analysis
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>>,
}, },
} }