forked from M-Labs/nac3
1
0
Fork 0

core/model: add FunctionBuilder

This commit is contained in:
lyken 2024-07-17 13:33:16 +08:00
parent 06b64ea888
commit 2525369760
2 changed files with 57 additions and 0 deletions

View File

@ -0,0 +1,55 @@
use inkwell::{
types::{BasicMetadataTypeEnum, BasicType},
values::{AnyValue, BasicMetadataValueEnum},
};
use crate::codegen::{model::*, CodeGenContext};
// TODO: Variadic argument?
pub struct FunctionBuilder<'ctx, 'a> {
ctx: &'a CodeGenContext<'ctx, 'a>,
fn_name: &'a str,
arguments: Vec<(BasicMetadataTypeEnum<'ctx>, BasicMetadataValueEnum<'ctx>)>,
}
impl<'ctx, 'a> FunctionBuilder<'ctx, 'a> {
pub fn begin(ctx: &'a CodeGenContext<'ctx, 'a>, fn_name: &'a str) -> Self {
FunctionBuilder { ctx, fn_name, arguments: Vec::new() }
}
// NOTE: `_name` is for self-documentation
#[must_use]
pub fn arg<M: Model<'ctx>>(mut self, _name: &'static str, model: M, value: M::Value) -> Self {
model.check(self.ctx.ctx, value); // Panics if the passed `value` has the incorrect type.
self.arguments
.push((model.get_llvm_type(self.ctx.ctx).into(), value.get_llvm_value().into()));
self
}
pub fn returning<M: Model<'ctx>>(self, name: &'static str, return_model: M) -> M::Value {
let (param_tys, param_vals): (Vec<_>, Vec<_>) = self.arguments.into_iter().unzip();
let function = self.ctx.module.get_function(self.fn_name).unwrap_or_else(|| {
let return_type = return_model.get_llvm_type(self.ctx.ctx);
let fn_type = return_type.fn_type(&param_tys, false);
self.ctx.module.add_function(self.fn_name, fn_type, None)
});
let ret = self.ctx.builder.build_call(function, &param_vals, name).unwrap();
return_model.review(self.ctx.ctx, ret.as_any_value_enum())
}
// TODO: Code duplication, but otherwise returning<S: Optic<'ctx>> cannot resolve S if return_optic = None
pub fn returning_void(self) {
let (param_tys, param_vals): (Vec<_>, Vec<_>) = self.arguments.into_iter().unzip();
let function = self.ctx.module.get_function(self.fn_name).unwrap_or_else(|| {
let return_type = self.ctx.ctx.void_type();
let fn_type = return_type.fn_type(&param_tys, false);
self.ctx.module.add_function(self.fn_name, fn_type, None)
});
self.ctx.builder.build_call(function, &param_vals, "").unwrap();
}
}

View File

@ -1,5 +1,6 @@
pub mod core;
pub mod fixed_int;
pub mod function_builder;
pub mod int;
mod int_util;
pub mod opaque;
@ -9,6 +10,7 @@ pub mod structure;
pub use core::*;
pub use fixed_int::*;
pub use function_builder::*;
pub use int::*;
pub use opaque::*;
pub use pointer::*;