forked from M-Labs/nac3
core: split codegen irrt into modules
This commit is contained in:
parent
71e05c17b9
commit
7742fbf9e0
|
@ -1,136 +0,0 @@
|
||||||
use inkwell::types::IntType;
|
|
||||||
|
|
||||||
use crate::codegen::optics::*;
|
|
||||||
use crate::codegen::CodeGenContext;
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct StrLens<'ctx> {
|
|
||||||
pub size_type: IntType<'ctx>,
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: nac3core has hardcoded a lot of "str"
|
|
||||||
pub struct StrFields<'ctx> {
|
|
||||||
pub content: GepGetter<AddressLens<IntLens<'ctx>>>,
|
|
||||||
pub length: GepGetter<IntLens<'ctx>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'ctx> StructureOptic<'ctx> for StrLens<'ctx> {
|
|
||||||
type Fields = StrFields<'ctx>;
|
|
||||||
|
|
||||||
fn struct_name(&self) -> &'static str {
|
|
||||||
"str"
|
|
||||||
}
|
|
||||||
|
|
||||||
fn build_fields(&self, builder: &mut FieldBuilder<'ctx>) -> Self::Fields {
|
|
||||||
StrFields {
|
|
||||||
content: builder.add_field("content", AddressLens(IntLens(builder.ctx.i8_type()))),
|
|
||||||
length: builder.add_field("length", IntLens(self.size_type)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct NpArrayFields<'ctx> {
|
|
||||||
pub data: GepGetter<AddressLens<IntLens<'ctx>>>,
|
|
||||||
pub itemsize: GepGetter<IntLens<'ctx>>,
|
|
||||||
pub ndims: GepGetter<IntLens<'ctx>>,
|
|
||||||
pub shape: GepGetter<AddressLens<IntLens<'ctx>>>,
|
|
||||||
pub strides: GepGetter<AddressLens<IntLens<'ctx>>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
|
||||||
pub struct NpArrayLens<'ctx> {
|
|
||||||
pub size_type: IntType<'ctx>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'ctx> StructureOptic<'ctx> for NpArrayLens<'ctx> {
|
|
||||||
type Fields = NpArrayFields<'ctx>;
|
|
||||||
|
|
||||||
fn struct_name(&self) -> &'static str {
|
|
||||||
"NDArray"
|
|
||||||
}
|
|
||||||
|
|
||||||
fn build_fields(&self, builder: &mut FieldBuilder<'ctx>) -> Self::Fields {
|
|
||||||
NpArrayFields {
|
|
||||||
data: builder.add_field("data", AddressLens(IntLens(builder.ctx.i8_type()))),
|
|
||||||
itemsize: builder.add_field("itemsize", IntLens(builder.ctx.i8_type())),
|
|
||||||
ndims: builder.add_field("ndims", IntLens(builder.ctx.i8_type())),
|
|
||||||
shape: builder.add_field("shape", AddressLens(IntLens(self.size_type))),
|
|
||||||
strides: builder.add_field("strides", AddressLens(IntLens(self.size_type))),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Other convenient utilities for NpArray
|
|
||||||
impl<'ctx> Address<'ctx, NpArrayLens<'ctx>> {
|
|
||||||
pub fn shape_array(&self, ctx: &CodeGenContext<'ctx, '_>) -> ArraySlice<'ctx, IntLens<'ctx>> {
|
|
||||||
let ndims = self.focus(ctx, |fields| &fields.ndims).load(ctx, "ndims");
|
|
||||||
let shape_base_ptr = self.focus(ctx, |fields| &fields.shape).load(ctx, "shape");
|
|
||||||
ArraySlice { num_elements: ndims, base: shape_base_ptr }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn strides_array(&self, ctx: &CodeGenContext<'ctx, '_>) -> ArraySlice<'ctx, IntLens<'ctx>> {
|
|
||||||
let ndims = self.focus(ctx, |fields| &fields.ndims).load(ctx, "ndims");
|
|
||||||
let strides_base_ptr = self.focus(ctx, |fields| &fields.strides).load(ctx, "strides");
|
|
||||||
ArraySlice { num_elements: ndims, base: strides_base_ptr }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct ErrorIdsFields<'ctx> {
|
|
||||||
pub index_error: GepGetter<IntLens<'ctx>>,
|
|
||||||
pub value_error: GepGetter<IntLens<'ctx>>,
|
|
||||||
pub assertion_error: GepGetter<IntLens<'ctx>>,
|
|
||||||
pub runtime_error: GepGetter<IntLens<'ctx>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct ErrorIdsLens;
|
|
||||||
|
|
||||||
impl<'ctx> StructureOptic<'ctx> for ErrorIdsLens {
|
|
||||||
type Fields = ErrorIdsFields<'ctx>;
|
|
||||||
|
|
||||||
fn struct_name(&self) -> &'static str {
|
|
||||||
"ErrorIds"
|
|
||||||
}
|
|
||||||
|
|
||||||
fn build_fields(&self, builder: &mut FieldBuilder<'ctx>) -> Self::Fields {
|
|
||||||
let i32_lens = IntLens(builder.ctx.i32_type());
|
|
||||||
ErrorIdsFields {
|
|
||||||
index_error: builder.add_field("index_error", i32_lens),
|
|
||||||
value_error: builder.add_field("value_error", i32_lens),
|
|
||||||
assertion_error: builder.add_field("assertion_error", i32_lens),
|
|
||||||
runtime_error: builder.add_field("runtime_error", i32_lens),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct ErrorContextFields<'ctx> {
|
|
||||||
pub error_ids: GepGetter<AddressLens<ErrorIdsLens>>,
|
|
||||||
pub error_id: GepGetter<IntLens<'ctx>>,
|
|
||||||
pub message_template: GepGetter<AddressLens<IntLens<'ctx>>>,
|
|
||||||
pub param1: GepGetter<IntLens<'ctx>>,
|
|
||||||
pub param2: GepGetter<IntLens<'ctx>>,
|
|
||||||
pub param3: GepGetter<IntLens<'ctx>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
|
||||||
pub struct ErrorContextLens;
|
|
||||||
|
|
||||||
impl<'ctx> StructureOptic<'ctx> for ErrorContextLens {
|
|
||||||
type Fields = ErrorContextFields<'ctx>;
|
|
||||||
|
|
||||||
fn struct_name(&self) -> &'static str {
|
|
||||||
"ErrorContext"
|
|
||||||
}
|
|
||||||
|
|
||||||
fn build_fields(&self, builder: &mut FieldBuilder<'ctx>) -> Self::Fields {
|
|
||||||
ErrorContextFields {
|
|
||||||
error_ids: builder.add_field("error_ids", AddressLens(ErrorIdsLens)),
|
|
||||||
error_id: builder.add_field("error_id", IntLens(builder.ctx.i32_type())),
|
|
||||||
message_template: builder
|
|
||||||
.add_field("message_template", AddressLens(IntLens(builder.ctx.i8_type()))),
|
|
||||||
param1: builder.add_field("param1", IntLens(builder.ctx.i64_type())),
|
|
||||||
param2: builder.add_field("param2", IntLens(builder.ctx.i64_type())),
|
|
||||||
param3: builder.add_field("param3", IntLens(builder.ctx.i64_type())),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,87 +1,96 @@
|
||||||
use inkwell::{
|
use inkwell::types::IntType;
|
||||||
types::{BasicMetadataTypeEnum, BasicType, IntType},
|
use inkwell::values::IntValue;
|
||||||
values::{AnyValue, BasicMetadataValueEnum, IntValue},
|
|
||||||
};
|
|
||||||
|
|
||||||
use crate::codegen::{
|
use crate::codegen::optics::*;
|
||||||
optics::{
|
use crate::codegen::CodeGenContext;
|
||||||
address::{Address, AddressLens},
|
use crate::codegen::CodeGenerator;
|
||||||
core::{Optic, OpticValue, Prism},
|
|
||||||
int::IntLens,
|
|
||||||
},
|
|
||||||
CodeGenContext, CodeGenerator,
|
|
||||||
};
|
|
||||||
use crate::util::SizeVariant;
|
|
||||||
|
|
||||||
use super::classes::{ErrorContextLens, ErrorIdsLens, StrLens};
|
use super::util::get_sized_dependent_function_name;
|
||||||
|
use super::util::FunctionBuilder;
|
||||||
|
|
||||||
fn get_size_variant(ty: IntType) -> SizeVariant {
|
#[derive(Debug, Clone)]
|
||||||
match ty.get_bit_width() {
|
pub struct StrLens<'ctx> {
|
||||||
32 => SizeVariant::Bits32,
|
pub size_type: IntType<'ctx>,
|
||||||
64 => SizeVariant::Bits64,
|
|
||||||
_ => unreachable!("Unsupported int type bit width {}", ty.get_bit_width()),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[must_use]
|
// TODO: nac3core has hardcoded a lot of "str"
|
||||||
pub fn get_sized_dependent_function_name(ty: IntType, fn_name: &str) -> String {
|
pub struct StrFields<'ctx> {
|
||||||
let mut fn_name = fn_name.to_owned();
|
pub content: GepGetter<AddressLens<IntLens<'ctx>>>,
|
||||||
match get_size_variant(ty) {
|
pub length: GepGetter<IntLens<'ctx>>,
|
||||||
SizeVariant::Bits32 => {
|
}
|
||||||
// Do nothing, `fn_name` already has the correct name
|
|
||||||
}
|
impl<'ctx> StructureOptic<'ctx> for StrLens<'ctx> {
|
||||||
SizeVariant::Bits64 => {
|
type Fields = StrFields<'ctx>;
|
||||||
// Append "64", this is the naming convention
|
|
||||||
fn_name.push_str("64");
|
fn struct_name(&self) -> &'static str {
|
||||||
|
"str"
|
||||||
|
}
|
||||||
|
|
||||||
|
fn build_fields(&self, builder: &mut FieldBuilder<'ctx>) -> Self::Fields {
|
||||||
|
StrFields {
|
||||||
|
content: builder.add_field("content", AddressLens(IntLens(builder.ctx.i8_type()))),
|
||||||
|
length: builder.add_field("length", IntLens(self.size_type)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn_name
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Variadic argument?
|
pub struct ErrorIdsFields<'ctx> {
|
||||||
pub struct FunctionBuilder<'ctx, 'a> {
|
pub index_error: GepGetter<IntLens<'ctx>>,
|
||||||
ctx: &'a CodeGenContext<'ctx, 'a>,
|
pub value_error: GepGetter<IntLens<'ctx>>,
|
||||||
fn_name: &'a str,
|
pub assertion_error: GepGetter<IntLens<'ctx>>,
|
||||||
arguments: Vec<(BasicMetadataTypeEnum<'ctx>, BasicMetadataValueEnum<'ctx>)>,
|
pub runtime_error: GepGetter<IntLens<'ctx>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'ctx, 'a> FunctionBuilder<'ctx, 'a> {
|
#[derive(Debug, Clone)]
|
||||||
pub fn begin(ctx: &'a CodeGenContext<'ctx, 'a>, fn_name: &'a str) -> Self {
|
pub struct ErrorIdsLens;
|
||||||
FunctionBuilder { ctx, fn_name, arguments: Vec::new() }
|
|
||||||
|
impl<'ctx> StructureOptic<'ctx> for ErrorIdsLens {
|
||||||
|
type Fields = ErrorIdsFields<'ctx>;
|
||||||
|
|
||||||
|
fn struct_name(&self) -> &'static str {
|
||||||
|
"ErrorIds"
|
||||||
}
|
}
|
||||||
|
|
||||||
// The name is for self-documentation
|
fn build_fields(&self, builder: &mut FieldBuilder<'ctx>) -> Self::Fields {
|
||||||
#[must_use]
|
let i32_lens = IntLens(builder.ctx.i32_type());
|
||||||
pub fn arg<S: Optic<'ctx>>(mut self, _name: &'static str, optic: &S, arg: &S::Value) -> Self {
|
ErrorIdsFields {
|
||||||
self.arguments
|
index_error: builder.add_field("index_error", i32_lens),
|
||||||
.push((optic.get_llvm_type(self.ctx.ctx).into(), arg.get_llvm_value().into()));
|
value_error: builder.add_field("value_error", i32_lens),
|
||||||
self
|
assertion_error: builder.add_field("assertion_error", i32_lens),
|
||||||
|
runtime_error: builder.add_field("runtime_error", i32_lens),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct ErrorContextFields<'ctx> {
|
||||||
|
pub error_ids: GepGetter<AddressLens<ErrorIdsLens>>,
|
||||||
|
pub error_id: GepGetter<IntLens<'ctx>>,
|
||||||
|
pub message_template: GepGetter<AddressLens<IntLens<'ctx>>>,
|
||||||
|
pub param1: GepGetter<IntLens<'ctx>>,
|
||||||
|
pub param2: GepGetter<IntLens<'ctx>>,
|
||||||
|
pub param3: GepGetter<IntLens<'ctx>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
pub struct ErrorContextLens;
|
||||||
|
|
||||||
|
impl<'ctx> StructureOptic<'ctx> for ErrorContextLens {
|
||||||
|
type Fields = ErrorContextFields<'ctx>;
|
||||||
|
|
||||||
|
fn struct_name(&self) -> &'static str {
|
||||||
|
"ErrorContext"
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn returning<S: Prism<'ctx>>(self, name: &'static str, return_prism: &S) -> S::Value {
|
fn build_fields(&self, builder: &mut FieldBuilder<'ctx>) -> Self::Fields {
|
||||||
let (param_tys, param_vals): (Vec<_>, Vec<_>) = self.arguments.into_iter().unzip();
|
ErrorContextFields {
|
||||||
|
error_ids: builder.add_field("error_ids", AddressLens(ErrorIdsLens)),
|
||||||
let function = self.ctx.module.get_function(self.fn_name).unwrap_or_else(|| {
|
error_id: builder.add_field("error_id", IntLens(builder.ctx.i32_type())),
|
||||||
let return_type = return_prism.get_llvm_type(self.ctx.ctx);
|
message_template: builder
|
||||||
let fn_type = return_type.fn_type(¶m_tys, false);
|
.add_field("message_template", AddressLens(IntLens(builder.ctx.i8_type()))),
|
||||||
self.ctx.module.add_function(self.fn_name, fn_type, None)
|
param1: builder.add_field("param1", IntLens(builder.ctx.i64_type())),
|
||||||
});
|
param2: builder.add_field("param2", IntLens(builder.ctx.i64_type())),
|
||||||
|
param3: builder.add_field("param3", IntLens(builder.ctx.i64_type())),
|
||||||
let ret = self.ctx.builder.build_call(function, ¶m_vals, name).unwrap();
|
}
|
||||||
return_prism.review(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(¶m_tys, false);
|
|
||||||
self.ctx.module.add_function(self.fn_name, fn_type, None)
|
|
||||||
});
|
|
||||||
|
|
||||||
self.ctx.builder.build_call(function, ¶m_vals, "").unwrap();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,5 @@
|
||||||
use crate::typecheck::typedef::Type;
|
use crate::typecheck::typedef::Type;
|
||||||
|
|
||||||
pub mod numpy;
|
|
||||||
mod test;
|
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
classes::{
|
classes::{
|
||||||
ArrayLikeIndexer, ArrayLikeValue, ArraySliceValue, ListValue, NDArrayValue,
|
ArrayLikeIndexer, ArrayLikeValue, ArraySliceValue, ListValue, NDArrayValue,
|
||||||
|
@ -24,8 +21,10 @@ use inkwell::{
|
||||||
use itertools::Either;
|
use itertools::Either;
|
||||||
use nac3parser::ast::Expr;
|
use nac3parser::ast::Expr;
|
||||||
|
|
||||||
pub mod classes;
|
pub mod error_context;
|
||||||
pub mod new;
|
pub mod numpy;
|
||||||
|
pub mod test;
|
||||||
|
pub mod util;
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn load_irrt(ctx: &Context) -> Module {
|
pub fn load_irrt(ctx: &Context) -> Module {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
use inkwell::{
|
use inkwell::{
|
||||||
types::{BasicType, BasicTypeEnum},
|
types::{BasicType, BasicTypeEnum, IntType},
|
||||||
values::{BasicValueEnum, IntValue},
|
values::{BasicValueEnum, IntValue},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -16,13 +16,56 @@ use crate::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
classes::{ErrorContextLens, NpArrayLens},
|
error_context::{check_error_context, prepare_error_context, ErrorContextLens},
|
||||||
new::{
|
util::{get_sized_dependent_function_name, FunctionBuilder},
|
||||||
check_error_context, get_sized_dependent_function_name, prepare_error_context,
|
|
||||||
FunctionBuilder,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub struct NpArrayFields<'ctx> {
|
||||||
|
pub data: GepGetter<AddressLens<IntLens<'ctx>>>,
|
||||||
|
pub itemsize: GepGetter<IntLens<'ctx>>,
|
||||||
|
pub ndims: GepGetter<IntLens<'ctx>>,
|
||||||
|
pub shape: GepGetter<AddressLens<IntLens<'ctx>>>,
|
||||||
|
pub strides: GepGetter<AddressLens<IntLens<'ctx>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
pub struct NpArrayLens<'ctx> {
|
||||||
|
pub size_type: IntType<'ctx>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'ctx> StructureOptic<'ctx> for NpArrayLens<'ctx> {
|
||||||
|
type Fields = NpArrayFields<'ctx>;
|
||||||
|
|
||||||
|
fn struct_name(&self) -> &'static str {
|
||||||
|
"NDArray"
|
||||||
|
}
|
||||||
|
|
||||||
|
fn build_fields(&self, builder: &mut FieldBuilder<'ctx>) -> Self::Fields {
|
||||||
|
NpArrayFields {
|
||||||
|
data: builder.add_field("data", AddressLens(IntLens(builder.ctx.i8_type()))),
|
||||||
|
itemsize: builder.add_field("itemsize", IntLens(builder.ctx.i8_type())),
|
||||||
|
ndims: builder.add_field("ndims", IntLens(builder.ctx.i8_type())),
|
||||||
|
shape: builder.add_field("shape", AddressLens(IntLens(self.size_type))),
|
||||||
|
strides: builder.add_field("strides", AddressLens(IntLens(self.size_type))),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Other convenient utilities for NpArray
|
||||||
|
impl<'ctx> Address<'ctx, NpArrayLens<'ctx>> {
|
||||||
|
pub fn shape_array(&self, ctx: &CodeGenContext<'ctx, '_>) -> ArraySlice<'ctx, IntLens<'ctx>> {
|
||||||
|
let ndims = self.focus(ctx, |fields| &fields.ndims).load(ctx, "ndims");
|
||||||
|
let shape_base_ptr = self.focus(ctx, |fields| &fields.shape).load(ctx, "shape");
|
||||||
|
ArraySlice { num_elements: ndims, base: shape_base_ptr }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn strides_array(&self, ctx: &CodeGenContext<'ctx, '_>) -> ArraySlice<'ctx, IntLens<'ctx>> {
|
||||||
|
let ndims = self.focus(ctx, |fields| &fields.ndims).load(ctx, "ndims");
|
||||||
|
let strides_base_ptr = self.focus(ctx, |fields| &fields.strides).load(ctx, "strides");
|
||||||
|
ArraySlice { num_elements: ndims, base: strides_base_ptr }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type ProducerWriteToArray<'ctx, G, ElementOptic> = Box<
|
type ProducerWriteToArray<'ctx, G, ElementOptic> = Box<
|
||||||
dyn Fn(
|
dyn Fn(
|
||||||
&mut G,
|
&mut G,
|
||||||
|
|
|
@ -0,0 +1,77 @@
|
||||||
|
use inkwell::{
|
||||||
|
types::{BasicMetadataTypeEnum, BasicType, IntType},
|
||||||
|
values::{AnyValue, BasicMetadataValueEnum},
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::codegen::optics::*;
|
||||||
|
use crate::{codegen::CodeGenContext, util::SizeVariant};
|
||||||
|
|
||||||
|
fn get_size_variant(ty: IntType) -> SizeVariant {
|
||||||
|
match ty.get_bit_width() {
|
||||||
|
32 => SizeVariant::Bits32,
|
||||||
|
64 => SizeVariant::Bits64,
|
||||||
|
_ => unreachable!("Unsupported int type bit width {}", ty.get_bit_width()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn get_sized_dependent_function_name(ty: IntType, fn_name: &str) -> String {
|
||||||
|
let mut fn_name = fn_name.to_owned();
|
||||||
|
match get_size_variant(ty) {
|
||||||
|
SizeVariant::Bits32 => {
|
||||||
|
// Do nothing, `fn_name` already has the correct name
|
||||||
|
}
|
||||||
|
SizeVariant::Bits64 => {
|
||||||
|
// Append "64", this is the naming convention
|
||||||
|
fn_name.push_str("64");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn_name
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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() }
|
||||||
|
}
|
||||||
|
|
||||||
|
// The name is for self-documentation
|
||||||
|
#[must_use]
|
||||||
|
pub fn arg<S: Optic<'ctx>>(mut self, _name: &'static str, optic: &S, arg: &S::Value) -> Self {
|
||||||
|
self.arguments
|
||||||
|
.push((optic.get_llvm_type(self.ctx.ctx).into(), arg.get_llvm_value().into()));
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn returning<S: Prism<'ctx>>(self, name: &'static str, return_prism: &S) -> S::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_prism.get_llvm_type(self.ctx.ctx);
|
||||||
|
let fn_type = return_type.fn_type(¶m_tys, false);
|
||||||
|
self.ctx.module.add_function(self.fn_name, fn_type, None)
|
||||||
|
});
|
||||||
|
|
||||||
|
let ret = self.ctx.builder.build_call(function, ¶m_vals, name).unwrap();
|
||||||
|
return_prism.review(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(¶m_tys, false);
|
||||||
|
self.ctx.module.add_function(self.fn_name, fn_type, None)
|
||||||
|
});
|
||||||
|
|
||||||
|
self.ctx.builder.build_call(function, ¶m_vals, "").unwrap();
|
||||||
|
}
|
||||||
|
}
|
|
@ -23,7 +23,7 @@ use inkwell::{
|
||||||
values::{BasicValueEnum, FunctionValue, IntValue, PhiValue, PointerValue},
|
values::{BasicValueEnum, FunctionValue, IntValue, PhiValue, PointerValue},
|
||||||
AddressSpace, IntPredicate, OptimizationLevel,
|
AddressSpace, IntPredicate, OptimizationLevel,
|
||||||
};
|
};
|
||||||
use irrt::classes::StrLens;
|
use irrt::error_context::StrLens;
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use nac3parser::ast::{Location, Stmt, StrRef};
|
use nac3parser::ast::{Location, Stmt, StrRef};
|
||||||
use optics::Optic as _;
|
use optics::Optic as _;
|
||||||
|
|
Loading…
Reference in New Issue