nac3core: refactor codegen

This commit is contained in:
pca006132 2021-11-20 19:50:25 +08:00
parent 439cef636f
commit ba08deada6
13 changed files with 406 additions and 148 deletions

View File

@ -2,6 +2,7 @@ use nac3core::{
codegen::{expr::gen_call, stmt::gen_with, CodeGenContext, CodeGenerator}, codegen::{expr::gen_call, stmt::gen_with, CodeGenContext, CodeGenerator},
toplevel::DefinitionId, toplevel::DefinitionId,
typecheck::typedef::{FunSignature, Type}, typecheck::typedef::{FunSignature, Type},
symbol_resolver::ValueEnum,
}; };
use nac3parser::ast::{Expr, ExprKind, Located, Stmt, StmtKind, StrRef}; use nac3parser::ast::{Expr, ExprKind, Located, Stmt, StmtKind, StrRef};
@ -38,13 +39,13 @@ impl<'b> CodeGenerator for ArtiqCodeGenerator<'b> {
fn gen_call<'ctx, 'a>( fn gen_call<'ctx, 'a>(
&mut self, &mut 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),
params: Vec<(Option<StrRef>, BasicValueEnum<'ctx>)>, params: Vec<(Option<StrRef>, ValueEnum<'ctx>)>,
) -> Option<BasicValueEnum<'ctx>> { ) -> Option<BasicValueEnum<'ctx>> {
let result = gen_call(self, ctx, obj, fun, params); let result = gen_call(self, ctx, obj, fun, params);
if let Some(end) = self.end.clone() { if let Some(end) = self.end.clone() {
let old_end = self.gen_expr(ctx, &end).unwrap(); let old_end = self.gen_expr(ctx, &end).unwrap().to_basic_value_enum(ctx);
let now = self.timeline.emit_now_mu(ctx); let now = self.timeline.emit_now_mu(ctx);
let smax = ctx.module.get_function("llvm.smax.i64").unwrap_or_else(|| { let smax = ctx.module.get_function("llvm.smax.i64").unwrap_or_else(|| {
let i64 = ctx.ctx.i64_type(); let i64 = ctx.ctx.i64_type();
@ -64,7 +65,7 @@ impl<'b> CodeGenerator for ArtiqCodeGenerator<'b> {
ctx.builder.build_store(end_store, max); ctx.builder.build_store(end_store, max);
} }
if let Some(start) = self.start.clone() { if let Some(start) = self.start.clone() {
let start_val = self.gen_expr(ctx, &start).unwrap(); let start_val = self.gen_expr(ctx, &start).unwrap().to_basic_value_enum(ctx);
self.timeline.emit_at_mu(ctx, start_val); self.timeline.emit_at_mu(ctx, start_val);
} }
result result
@ -96,7 +97,7 @@ impl<'b> CodeGenerator for ArtiqCodeGenerator<'b> {
let old_start = self.start.take(); let old_start = self.start.take();
let old_end = self.end.take(); let old_end = self.end.take();
let now = if let Some(old_start) = &old_start { let now = if let Some(old_start) = &old_start {
self.gen_expr(ctx, old_start).unwrap() self.gen_expr(ctx, old_start).unwrap().to_basic_value_enum(ctx)
} else { } else {
self.timeline.emit_now_mu(ctx) self.timeline.emit_now_mu(ctx)
}; };
@ -145,7 +146,7 @@ impl<'b> CodeGenerator for ArtiqCodeGenerator<'b> {
} }
// set duration // set duration
let end_expr = self.end.take().unwrap(); let end_expr = self.end.take().unwrap();
let end_val = self.gen_expr(ctx, &end_expr).unwrap(); let end_val = self.gen_expr(ctx, &end_expr).unwrap().to_basic_value_enum(ctx);
// inside an sequential block // inside an sequential block
if old_start.is_none() { if old_start.is_none() {
@ -153,7 +154,7 @@ impl<'b> CodeGenerator for ArtiqCodeGenerator<'b> {
} }
// inside a parallel block, should update the outer max now_mu // inside a parallel block, should update the outer max now_mu
if let Some(old_end) = &old_end { if let Some(old_end) = &old_end {
let outer_end_val = self.gen_expr(ctx, old_end).unwrap(); let outer_end_val = self.gen_expr(ctx, old_end).unwrap().to_basic_value_enum(ctx);
let smax = ctx.module.get_function("llvm.smax.i64").unwrap_or_else(|| { let smax = ctx.module.get_function("llvm.smax.i64").unwrap_or_else(|| {
let i64 = ctx.ctx.i64_type(); let i64 = ctx.ctx.i64_type();
ctx.module.add_function( ctx.module.add_function(

View File

@ -443,6 +443,7 @@ impl Nac3 {
store, store,
unifier_index: instance.unifier_id, unifier_index: instance.unifier_id,
calls: instance.calls, calls: instance.calls,
id: 0,
}; };
let isa = self.isa; let isa = self.isa;
let working_directory = self.working_directory.path().to_owned(); let working_directory = self.working_directory.path().to_owned();

View File

@ -2,7 +2,7 @@ use inkwell::{types::BasicType, values::BasicValueEnum, AddressSpace};
use nac3core::{ use nac3core::{
codegen::CodeGenContext, codegen::CodeGenContext,
location::Location, location::Location,
symbol_resolver::SymbolResolver, symbol_resolver::{SymbolResolver, ValueEnum},
toplevel::{DefinitionId, TopLevelDef}, toplevel::{DefinitionId, TopLevelDef},
typecheck::{ typecheck::{
type_inferencer::PrimitiveStore, type_inferencer::PrimitiveStore,
@ -456,8 +456,8 @@ impl SymbolResolver for Resolver {
&self, &self,
id: StrRef, id: StrRef,
ctx: &mut CodeGenContext<'ctx, 'a>, ctx: &mut CodeGenContext<'ctx, 'a>,
) -> Option<BasicValueEnum<'ctx>> { ) -> Option<ValueEnum<'ctx>> {
Python::with_gil(|py| -> PyResult<Option<BasicValueEnum<'ctx>>> { Python::with_gil(|py| -> PyResult<Option<ValueEnum<'ctx>>> {
let obj: &PyAny = self.module.extract(py)?; let obj: &PyAny = self.module.extract(py)?;
let members: &PyList = PyModule::import(py, "inspect")? let members: &PyList = PyModule::import(py, "inspect")?
.getattr("getmembers")? .getattr("getmembers")?
@ -478,7 +478,7 @@ impl SymbolResolver for Resolver {
break; break;
} }
} }
Ok(sym_value) Ok(sym_value.map(|v| v.into()))
}) })
.unwrap() .unwrap()
} }

View File

@ -5,7 +5,7 @@ use crate::{
concrete_type::{ConcreteFuncArg, ConcreteTypeEnum, ConcreteTypeStore}, concrete_type::{ConcreteFuncArg, ConcreteTypeEnum, ConcreteTypeStore},
get_llvm_type, CodeGenContext, CodeGenTask, get_llvm_type, CodeGenContext, CodeGenTask,
}, },
symbol_resolver::SymbolValue, symbol_resolver::{SymbolValue, ValueEnum},
toplevel::{DefinitionId, TopLevelDef}, toplevel::{DefinitionId, TopLevelDef},
typecheck::typedef::{FunSignature, FuncArg, Type, TypeEnum}, typecheck::typedef::{FunSignature, FuncArg, Type, TypeEnum},
}; };
@ -15,9 +15,7 @@ use inkwell::{
AddressSpace, AddressSpace,
}; };
use itertools::{chain, izip, zip, Itertools}; use itertools::{chain, izip, zip, Itertools};
use nac3parser::ast::{ use nac3parser::ast::{self, Boolop, Comprehension, Constant, Expr, ExprKind, Operator, StrRef};
self, Boolop, Comprehension, Constant, Expr, ExprKind, Operator, StrRef,
};
use super::CodeGenerator; use super::CodeGenerator;
@ -222,7 +220,7 @@ pub fn gen_constructor<'ctx, 'a, G: CodeGenerator + ?Sized>(
ctx: &mut CodeGenContext<'ctx, 'a>, ctx: &mut CodeGenContext<'ctx, 'a>,
signature: &FunSignature, signature: &FunSignature,
def: &TopLevelDef, def: &TopLevelDef,
params: Vec<(Option<StrRef>, BasicValueEnum<'ctx>)>, params: Vec<(Option<StrRef>, ValueEnum<'ctx>)>,
) -> BasicValueEnum<'ctx> { ) -> BasicValueEnum<'ctx> {
match def { match def {
TopLevelDef::Class { methods, .. } => { TopLevelDef::Class { methods, .. } => {
@ -235,12 +233,17 @@ pub fn gen_constructor<'ctx, 'a, G: CodeGenerator + ?Sized>(
} }
let ty = ctx.get_llvm_type(signature.ret).into_pointer_type(); let ty = ctx.get_llvm_type(signature.ret).into_pointer_type();
let zelf_ty: BasicTypeEnum = ty.get_element_type().try_into().unwrap(); let zelf_ty: BasicTypeEnum = ty.get_element_type().try_into().unwrap();
let zelf = ctx.builder.build_alloca(zelf_ty, "alloca").into(); let zelf: BasicValueEnum<'ctx> = ctx.builder.build_alloca(zelf_ty, "alloca").into();
// call `__init__` if there is one // call `__init__` if there is one
if let Some(fun_id) = fun_id { if let Some(fun_id) = fun_id {
let mut sign = signature.clone(); let mut sign = signature.clone();
sign.ret = ctx.primitives.none; sign.ret = ctx.primitives.none;
generator.gen_call(ctx, Some((signature.ret, zelf)), (&sign, fun_id), params); generator.gen_call(
ctx,
Some((signature.ret, zelf.into())),
(&sign, fun_id),
params,
);
} }
zelf zelf
} }
@ -250,8 +253,9 @@ pub fn gen_constructor<'ctx, 'a, G: CodeGenerator + ?Sized>(
pub fn gen_func_instance<'ctx, 'a>( pub fn gen_func_instance<'ctx, 'a>(
ctx: &mut CodeGenContext<'ctx, 'a>, ctx: &mut CodeGenContext<'ctx, 'a>,
obj: Option<(Type, BasicValueEnum<'ctx>)>, obj: Option<(Type, ValueEnum<'ctx>)>,
fun: (&FunSignature, &mut TopLevelDef, String), fun: (&FunSignature, &mut TopLevelDef, String),
id: usize,
) -> String { ) -> String {
if let ( if let (
sign, sign,
@ -263,8 +267,8 @@ pub fn gen_func_instance<'ctx, 'a>(
{ {
instance_to_symbol.get(&key).cloned().unwrap_or_else(|| { instance_to_symbol.get(&key).cloned().unwrap_or_else(|| {
let symbol = format!("{}.{}", name, instance_to_symbol.len()); let symbol = format!("{}.{}", name, instance_to_symbol.len());
instance_to_symbol.insert(key, symbol.clone()); instance_to_symbol.insert(key.clone(), symbol.clone());
let key = ctx.get_subst_key(obj.map(|a| a.0), sign, Some(var_id)); let key = ctx.get_subst_key(obj.as_ref().map(|a| a.0), sign, Some(var_id));
let instance = instance_to_stmt.get(&key).unwrap(); let instance = instance_to_stmt.get(&key).unwrap();
let mut store = ConcreteTypeStore::new(); let mut store = ConcreteTypeStore::new();
@ -307,6 +311,7 @@ pub fn gen_func_instance<'ctx, 'a>(
signature, signature,
store, store,
unifier_index: instance.unifier_id, unifier_index: instance.unifier_id,
id,
}); });
symbol symbol
}) })
@ -318,20 +323,86 @@ pub fn gen_func_instance<'ctx, 'a>(
pub fn gen_call<'ctx, 'a, G: CodeGenerator + ?Sized>( pub fn gen_call<'ctx, 'a, G: CodeGenerator + ?Sized>(
generator: &mut G, generator: &mut G,
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),
params: Vec<(Option<StrRef>, BasicValueEnum<'ctx>)>, params: Vec<(Option<StrRef>, ValueEnum<'ctx>)>,
) -> Option<BasicValueEnum<'ctx>> { ) -> Option<BasicValueEnum<'ctx>> {
let definition = ctx.top_level.definitions.read().get(fun.1 .0).cloned().unwrap(); let definition = ctx.top_level.definitions.read().get(fun.1 .0).cloned().unwrap();
let key = ctx.get_subst_key(obj.map(|a| a.0), fun.0, None);
let id;
let key;
let param_vals;
let symbol = { let symbol = {
// make sure this lock guard is dropped at the end of this scope... // make sure this lock guard is dropped at the end of this scope...
let def = definition.read(); let def = definition.read();
match &*def { match &*def {
TopLevelDef::Function { instance_to_symbol, codegen_callback, .. } => { TopLevelDef::Function {
instance_to_symbol,
instance_to_stmt,
codegen_callback,
..
} => {
if let Some(callback) = codegen_callback { if let Some(callback) = codegen_callback {
// TODO: Change signature
let obj = obj.map(|(t, v)| (t, v.to_basic_value_enum(ctx)));
let params = params
.into_iter()
.map(|(name, val)| (name, val.to_basic_value_enum(ctx)))
.collect();
return callback.run(ctx, obj, fun, params); 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 mut keys = fun.0.args.clone();
let mut mapping = HashMap::new();
for (key, value) in params.into_iter() {
mapping.insert(key.unwrap_or_else(|| keys.remove(0).name), value);
}
// default value handling
for k in keys.into_iter() {
mapping.insert(k.name, ctx.gen_symbol_val(&k.default_value.unwrap()).into());
}
// reorder the parameters
let mut real_params =
fun.0.args.iter().map(|arg| mapping.remove(&arg.name).unwrap()).collect_vec();
if let Some(obj) = &obj {
real_params.insert(0, obj.1.clone());
}
let static_params = real_params
.iter()
.enumerate()
.filter_map(|(i, v)| {
if let ValueEnum::Static(s) = v {
Some((i, s.clone()))
} else {
None
}
})
.collect_vec();
id = {
let ids = static_params
.iter()
.map(|(i, v)| (*i, v.get_unique_identifier()))
.collect_vec();
let mut store = ctx.static_value_store.lock();
match store.lookup.get(&ids) {
Some(index) => *index,
None => {
let length = store.store.len();
store.lookup.insert(ids, length);
store.store.push(static_params.into_iter().collect());
length
}
}
};
// special case: extern functions
key = if instance_to_stmt.is_empty() {
"".to_string()
} else {
format!("{}:{}", id, old_key)
};
param_vals =
real_params.into_iter().map(|p| p.to_basic_value_enum(ctx)).collect_vec();
instance_to_symbol.get(&key).cloned() instance_to_symbol.get(&key).cloned()
} }
TopLevelDef::Class { .. } => { TopLevelDef::Class { .. } => {
@ -340,7 +411,7 @@ pub fn gen_call<'ctx, 'a, G: CodeGenerator + ?Sized>(
} }
} }
.unwrap_or_else(|| { .unwrap_or_else(|| {
generator.gen_func_instance(ctx, obj, (fun.0, &mut *definition.write(), key)) generator.gen_func_instance(ctx, obj.clone(), (fun.0, &mut *definition.write(), key), id)
}); });
let fun_val = ctx.module.get_function(&symbol).unwrap_or_else(|| { let fun_val = ctx.module.get_function(&symbol).unwrap_or_else(|| {
let mut args = fun.0.args.clone(); let mut args = fun.0.args.clone();
@ -355,21 +426,7 @@ pub fn gen_call<'ctx, 'a, G: CodeGenerator + ?Sized>(
}; };
ctx.module.add_function(&symbol, fun_ty, None) ctx.module.add_function(&symbol, fun_ty, None)
}); });
let mut keys = fun.0.args.clone(); ctx.builder.build_call(fun_val, &param_vals, "call").try_as_basic_value().left()
let mut mapping = HashMap::new();
for (key, value) in params.into_iter() {
mapping.insert(key.unwrap_or_else(|| keys.remove(0).name), value);
}
// default value handling
for k in keys.into_iter() {
mapping.insert(k.name, ctx.gen_symbol_val(&k.default_value.unwrap()));
}
// reorder the parameters
let mut params = fun.0.args.iter().map(|arg| mapping.remove(&arg.name).unwrap()).collect_vec();
if let Some(obj) = obj {
params.insert(0, obj.1);
}
ctx.builder.build_call(fun_val, &params, "call").try_as_basic_value().left()
} }
pub fn destructure_range<'ctx, 'a>( pub fn destructure_range<'ctx, 'a>(
@ -426,7 +483,7 @@ pub fn gen_comprehension<'ctx, 'a, G: CodeGenerator + ?Sized>(
let cont_bb = ctx.ctx.append_basic_block(current, "cont"); let cont_bb = ctx.ctx.append_basic_block(current, "cont");
let Comprehension { target, iter, ifs, .. } = &generators[0]; let Comprehension { target, iter, ifs, .. } = &generators[0];
let iter_val = generator.gen_expr(ctx, iter).unwrap(); let iter_val = generator.gen_expr(ctx, iter).unwrap().to_basic_value_enum(ctx);
let int32 = ctx.ctx.i32_type(); let int32 = ctx.ctx.i32_type();
let zero = int32.const_zero(); let zero = int32.const_zero();
@ -525,10 +582,11 @@ pub fn gen_comprehension<'ctx, 'a, G: CodeGenerator + ?Sized>(
) )
.into_pointer_value(); .into_pointer_value();
let val = ctx.build_gep_and_load(arr_ptr, &[tmp]); let val = ctx.build_gep_and_load(arr_ptr, &[tmp]);
generator.gen_assign(ctx, target, val); generator.gen_assign(ctx, target, val.into());
} }
for cond in ifs.iter() { for cond in ifs.iter() {
let result = generator.gen_expr(ctx, cond).unwrap().into_int_value(); let result =
generator.gen_expr(ctx, cond).unwrap().to_basic_value_enum(ctx).into_int_value();
let succ = ctx.ctx.append_basic_block(current, "then"); let succ = ctx.ctx.append_basic_block(current, "then");
ctx.builder.build_conditional_branch(result, succ, test_bb); ctx.builder.build_conditional_branch(result, succ, test_bb);
ctx.builder.position_at_end(succ); ctx.builder.position_at_end(succ);
@ -536,7 +594,8 @@ pub fn gen_comprehension<'ctx, 'a, G: CodeGenerator + ?Sized>(
let elem = generator.gen_expr(ctx, elt).unwrap(); let elem = generator.gen_expr(ctx, elt).unwrap();
let i = ctx.builder.build_load(index, "i").into_int_value(); let i = ctx.builder.build_load(index, "i").into_int_value();
let elem_ptr = unsafe { ctx.builder.build_gep(list_content, &[i], "elem_ptr") }; let elem_ptr = unsafe { ctx.builder.build_gep(list_content, &[i], "elem_ptr") };
ctx.builder.build_store(elem_ptr, elem); let val = elem.to_basic_value_enum(ctx);
ctx.builder.build_store(elem_ptr, val);
ctx.builder ctx.builder
.build_store(index, ctx.builder.build_int_add(i, int32.const_int(1, false), "inc")); .build_store(index, ctx.builder.build_int_add(i, int32.const_int(1, false), "inc"));
ctx.builder.build_unconditional_branch(test_bb); ctx.builder.build_unconditional_branch(test_bb);
@ -553,27 +612,29 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator + ?Sized>(
generator: &mut G, generator: &mut G,
ctx: &mut CodeGenContext<'ctx, 'a>, ctx: &mut CodeGenContext<'ctx, 'a>,
expr: &Expr<Option<Type>>, expr: &Expr<Option<Type>>,
) -> Option<BasicValueEnum<'ctx>> { ) -> Option<ValueEnum<'ctx>> {
let int32 = ctx.ctx.i32_type(); let int32 = ctx.ctx.i32_type();
let zero = int32.const_int(0, false); let zero = int32.const_int(0, false);
Some(match &expr.node { Some(match &expr.node {
ExprKind::Constant { value, .. } => { ExprKind::Constant { value, .. } => {
let ty = expr.custom.unwrap(); let ty = expr.custom.unwrap();
ctx.gen_const(value, ty) ctx.gen_const(value, ty).into()
} }
ExprKind::Name { id, .. } => { ExprKind::Name { id, .. } => match ctx.var_assignment.get(id) {
let ptr = ctx.var_assignment.get(id); Some((ptr, None, _)) => ctx.builder.build_load(*ptr, "load").into(),
if let Some(ptr) = ptr { Some((_, Some(static_value), _)) => ValueEnum::Static(static_value.clone()),
ctx.builder.build_load(*ptr, "load") None => {
} else {
let resolver = ctx.resolver.clone(); let resolver = ctx.resolver.clone();
resolver.get_symbol_value(*id, ctx).unwrap() resolver.get_symbol_value(*id, ctx).unwrap()
} }
} },
ExprKind::List { elts, .. } => { ExprKind::List { elts, .. } => {
// this shall be optimized later for constant primitive lists... // this shall be optimized later for constant primitive lists...
// we should use memcpy for that instead of generating thousands of stores // we should use memcpy for that instead of generating thousands of stores
let elements = elts.iter().map(|x| generator.gen_expr(ctx, x).unwrap()).collect_vec(); let elements = elts
.iter()
.map(|x| generator.gen_expr(ctx, x).unwrap().to_basic_value_enum(ctx))
.collect_vec();
let ty = if elements.is_empty() { int32.into() } else { elements[0].get_type() }; let ty = if elements.is_empty() { int32.into() } else { elements[0].get_type() };
let length = int32.const_int(elements.len() as u64, false); let length = int32.const_int(elements.len() as u64, false);
let arr_str_ptr = allocate_list(ctx, ty, length); let arr_str_ptr = allocate_list(ctx, ty, length);
@ -593,8 +654,10 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator + ?Sized>(
arr_str_ptr.into() arr_str_ptr.into()
} }
ExprKind::Tuple { elts, .. } => { ExprKind::Tuple { elts, .. } => {
let element_val = let element_val = elts
elts.iter().map(|x| generator.gen_expr(ctx, x).unwrap()).collect_vec(); .iter()
.map(|x| generator.gen_expr(ctx, x).unwrap().to_basic_value_enum(ctx))
.collect_vec();
let element_ty = element_val.iter().map(BasicValueEnum::get_type).collect_vec(); let element_ty = element_val.iter().map(BasicValueEnum::get_type).collect_vec();
let tuple_ty = ctx.ctx.struct_type(&element_ty, false); let tuple_ty = ctx.ctx.struct_type(&element_ty, false);
let tuple_ptr = ctx.builder.build_alloca(tuple_ty, "tuple"); let tuple_ptr = ctx.builder.build_alloca(tuple_ty, "tuple");
@ -612,13 +675,24 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator + ?Sized>(
} }
ExprKind::Attribute { value, attr, .. } => { ExprKind::Attribute { value, attr, .. } => {
// note that we would handle class methods directly in calls // note that we would handle class methods directly in calls
let index = ctx.get_attr_index(value.custom.unwrap(), *attr); match generator.gen_expr(ctx, value).unwrap() {
let ptr = generator.gen_expr(ctx, value).unwrap().into_pointer_value(); ValueEnum::Static(v) => v.get_field(*attr, ctx).unwrap(),
ctx.build_gep_and_load(ptr, &[zero, int32.const_int(index as u64, false)]) ValueEnum::Dynamic(v) => {
let index = ctx.get_attr_index(value.custom.unwrap(), *attr);
ValueEnum::Dynamic(ctx.build_gep_and_load(
v.into_pointer_value(),
&[zero, int32.const_int(index as u64, false)],
))
}
}
} }
ExprKind::BoolOp { op, values } => { ExprKind::BoolOp { op, values } => {
// requires conditional branches for short-circuiting... // requires conditional branches for short-circuiting...
let left = generator.gen_expr(ctx, &values[0]).unwrap().into_int_value(); let left = generator
.gen_expr(ctx, &values[0])
.unwrap()
.to_basic_value_enum(ctx)
.into_int_value();
let current = ctx.builder.get_insert_block().unwrap().get_parent().unwrap(); let current = ctx.builder.get_insert_block().unwrap().get_parent().unwrap();
let a_bb = ctx.ctx.append_basic_block(current, "a"); let a_bb = ctx.ctx.append_basic_block(current, "a");
let b_bb = ctx.ctx.append_basic_block(current, "b"); let b_bb = ctx.ctx.append_basic_block(current, "b");
@ -630,13 +704,21 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator + ?Sized>(
let a = ctx.ctx.bool_type().const_int(1, false); let a = ctx.ctx.bool_type().const_int(1, false);
ctx.builder.build_unconditional_branch(cont_bb); ctx.builder.build_unconditional_branch(cont_bb);
ctx.builder.position_at_end(b_bb); ctx.builder.position_at_end(b_bb);
let b = generator.gen_expr(ctx, &values[1]).unwrap().into_int_value(); let b = generator
.gen_expr(ctx, &values[1])
.unwrap()
.to_basic_value_enum(ctx)
.into_int_value();
ctx.builder.build_unconditional_branch(cont_bb); ctx.builder.build_unconditional_branch(cont_bb);
(a, b) (a, b)
} }
Boolop::And => { Boolop::And => {
ctx.builder.position_at_end(a_bb); ctx.builder.position_at_end(a_bb);
let a = generator.gen_expr(ctx, &values[1]).unwrap().into_int_value(); let a = generator
.gen_expr(ctx, &values[1])
.unwrap()
.to_basic_value_enum(ctx)
.into_int_value();
ctx.builder.build_unconditional_branch(cont_bb); ctx.builder.build_unconditional_branch(cont_bb);
ctx.builder.position_at_end(b_bb); ctx.builder.position_at_end(b_bb);
let b = ctx.ctx.bool_type().const_int(0, false); let b = ctx.ctx.bool_type().const_int(0, false);
@ -647,13 +729,13 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator + ?Sized>(
ctx.builder.position_at_end(cont_bb); ctx.builder.position_at_end(cont_bb);
let phi = ctx.builder.build_phi(ctx.ctx.bool_type(), "phi"); let phi = ctx.builder.build_phi(ctx.ctx.bool_type(), "phi");
phi.add_incoming(&[(&a, a_bb), (&b, b_bb)]); phi.add_incoming(&[(&a, a_bb), (&b, b_bb)]);
phi.as_basic_value() phi.as_basic_value().into()
} }
ExprKind::BinOp { op, left, right } => { ExprKind::BinOp { op, left, right } => {
let ty1 = ctx.unifier.get_representative(left.custom.unwrap()); let ty1 = ctx.unifier.get_representative(left.custom.unwrap());
let ty2 = ctx.unifier.get_representative(right.custom.unwrap()); let ty2 = ctx.unifier.get_representative(right.custom.unwrap());
let left = generator.gen_expr(ctx, left).unwrap(); let left = generator.gen_expr(ctx, left).unwrap().to_basic_value_enum(ctx);
let right = generator.gen_expr(ctx, right).unwrap(); let right = generator.gen_expr(ctx, right).unwrap().to_basic_value_enum(ctx);
// we can directly compare the types, because we've got their representatives // we can directly compare the types, because we've got their representatives
// which would be unchanged until further unification, which we would never do // which would be unchanged until further unification, which we would never do
@ -665,10 +747,11 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator + ?Sized>(
} else { } else {
unimplemented!() unimplemented!()
} }
.into()
} }
ExprKind::UnaryOp { op, operand } => { ExprKind::UnaryOp { op, operand } => {
let ty = ctx.unifier.get_representative(operand.custom.unwrap()); let ty = ctx.unifier.get_representative(operand.custom.unwrap());
let val = generator.gen_expr(ctx, operand).unwrap(); let val = generator.gen_expr(ctx, operand).unwrap().to_basic_value_enum(ctx);
if ty == ctx.primitives.bool { if ty == ctx.primitives.bool {
let val = val.into_int_value(); let val = val.into_int_value();
match op { match op {
@ -725,8 +808,8 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator + ?Sized>(
BasicValueEnum::IntValue(lhs), BasicValueEnum::IntValue(lhs),
BasicValueEnum::IntValue(rhs), BasicValueEnum::IntValue(rhs),
) = ( ) = (
generator.gen_expr(ctx, lhs).unwrap(), generator.gen_expr(ctx, lhs).unwrap().to_basic_value_enum(ctx),
generator.gen_expr(ctx, rhs).unwrap(), generator.gen_expr(ctx, rhs).unwrap().to_basic_value_enum(ctx),
) { ) {
(lhs, rhs) (lhs, rhs)
} else { } else {
@ -747,8 +830,8 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator + ?Sized>(
BasicValueEnum::FloatValue(lhs), BasicValueEnum::FloatValue(lhs),
BasicValueEnum::FloatValue(rhs), BasicValueEnum::FloatValue(rhs),
) = ( ) = (
generator.gen_expr(ctx, lhs).unwrap(), generator.gen_expr(ctx, lhs).unwrap().to_basic_value_enum(ctx),
generator.gen_expr(ctx, rhs).unwrap(), generator.gen_expr(ctx, rhs).unwrap().to_basic_value_enum(ctx),
) { ) {
(lhs, rhs) (lhs, rhs)
} else { } else {
@ -773,22 +856,23 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator + ?Sized>(
.into() // as there should be at least 1 element, it should never be none .into() // as there should be at least 1 element, it should never be none
} }
ExprKind::IfExp { test, body, orelse } => { ExprKind::IfExp { test, body, orelse } => {
let test = generator.gen_expr(ctx, test).unwrap().into_int_value(); let test =
generator.gen_expr(ctx, test).unwrap().to_basic_value_enum(ctx).into_int_value();
let current = ctx.builder.get_insert_block().unwrap().get_parent().unwrap(); let current = ctx.builder.get_insert_block().unwrap().get_parent().unwrap();
let then_bb = ctx.ctx.append_basic_block(current, "then"); let then_bb = ctx.ctx.append_basic_block(current, "then");
let else_bb = ctx.ctx.append_basic_block(current, "else"); let else_bb = ctx.ctx.append_basic_block(current, "else");
let cont_bb = ctx.ctx.append_basic_block(current, "cont"); let cont_bb = ctx.ctx.append_basic_block(current, "cont");
ctx.builder.build_conditional_branch(test, then_bb, else_bb); ctx.builder.build_conditional_branch(test, then_bb, else_bb);
ctx.builder.position_at_end(then_bb); ctx.builder.position_at_end(then_bb);
let a = generator.gen_expr(ctx, body).unwrap(); let a = generator.gen_expr(ctx, body).unwrap().to_basic_value_enum(ctx);
ctx.builder.build_unconditional_branch(cont_bb); ctx.builder.build_unconditional_branch(cont_bb);
ctx.builder.position_at_end(else_bb); ctx.builder.position_at_end(else_bb);
let b = generator.gen_expr(ctx, orelse).unwrap(); let b = generator.gen_expr(ctx, orelse).unwrap().to_basic_value_enum(ctx);
ctx.builder.build_unconditional_branch(cont_bb); ctx.builder.build_unconditional_branch(cont_bb);
ctx.builder.position_at_end(cont_bb); ctx.builder.position_at_end(cont_bb);
let phi = ctx.builder.build_phi(a.get_type(), "ifexpr"); let phi = ctx.builder.build_phi(a.get_type(), "ifexpr");
phi.add_incoming(&[(&a, then_bb), (&b, else_bb)]); phi.add_incoming(&[(&a, then_bb), (&b, else_bb)]);
phi.as_basic_value() phi.as_basic_value().into()
} }
ExprKind::Call { func, args, keywords } => { ExprKind::Call { func, args, keywords } => {
let mut params = let mut params =
@ -816,7 +900,9 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator + ?Sized>(
ExprKind::Name { id, .. } => { ExprKind::Name { id, .. } => {
// TODO: handle primitive casts and function pointers // TODO: handle primitive casts and function pointers
let fun = ctx.resolver.get_identifier_def(*id).expect("Unknown identifier"); let fun = ctx.resolver.get_identifier_def(*id).expect("Unknown identifier");
return generator.gen_call(ctx, None, (&signature, fun), params); return generator
.gen_call(ctx, None, (&signature, fun), params)
.map(|v| v.into());
} }
ExprKind::Attribute { value, attr, .. } => { ExprKind::Attribute { value, attr, .. } => {
let val = generator.gen_expr(ctx, value).unwrap(); let val = generator.gen_expr(ctx, value).unwrap();
@ -842,12 +928,14 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator + ?Sized>(
unreachable!() unreachable!()
} }
}; };
return generator.gen_call( return generator
ctx, .gen_call(
Some((value.custom.unwrap(), val)), ctx,
(&signature, fun_id), Some((value.custom.unwrap(), val)),
params, (&signature, fun_id),
); params,
)
.map(|v| v.into());
} }
_ => unimplemented!(), _ => unimplemented!(),
} }
@ -858,19 +946,36 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator + ?Sized>(
unimplemented!() unimplemented!()
} else { } else {
// TODO: bound check // TODO: bound check
let v = generator.gen_expr(ctx, value).unwrap().into_pointer_value(); let v = generator
let index = generator.gen_expr(ctx, slice).unwrap().into_int_value(); .gen_expr(ctx, value)
.unwrap()
.to_basic_value_enum(ctx)
.into_pointer_value();
let index = generator
.gen_expr(ctx, slice)
.unwrap()
.to_basic_value_enum(ctx)
.into_int_value();
let arr_ptr = let arr_ptr =
ctx.build_gep_and_load(v, &[int32.const_zero(), int32.const_int(1, false)]); ctx.build_gep_and_load(v, &[int32.const_zero(), int32.const_int(1, false)]);
ctx.build_gep_and_load(arr_ptr.into_pointer_value(), &[index]) ctx.build_gep_and_load(arr_ptr.into_pointer_value(), &[index])
} }
} else { } else {
let v = generator.gen_expr(ctx, value).unwrap().into_pointer_value(); let v = generator
let index = generator.gen_expr(ctx, slice).unwrap().into_int_value(); .gen_expr(ctx, value)
.unwrap()
.to_basic_value_enum(ctx)
.into_pointer_value();
let index = generator
.gen_expr(ctx, slice)
.unwrap()
.to_basic_value_enum(ctx)
.into_int_value();
ctx.build_gep_and_load(v, &[int32.const_zero(), index]) ctx.build_gep_and_load(v, &[int32.const_zero(), index])
} }
} }
ExprKind::ListComp { .. } => gen_comprehension(generator, ctx, expr), .into(),
ExprKind::ListComp { .. } => gen_comprehension(generator, ctx, expr).into(),
_ => unimplemented!(), _ => unimplemented!(),
}) })
} }

View File

@ -1,5 +1,6 @@
use crate::{ use crate::{
codegen::{expr::*, stmt::*, CodeGenContext}, codegen::{expr::*, stmt::*, CodeGenContext},
symbol_resolver::ValueEnum,
toplevel::{DefinitionId, TopLevelDef}, toplevel::{DefinitionId, TopLevelDef},
typecheck::typedef::{FunSignature, Type}, typecheck::typedef::{FunSignature, Type},
}; };
@ -18,9 +19,9 @@ pub trait CodeGenerator {
fn gen_call<'ctx, 'a>( fn gen_call<'ctx, 'a>(
&mut self, &mut 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),
params: Vec<(Option<StrRef>, BasicValueEnum<'ctx>)>, params: Vec<(Option<StrRef>, ValueEnum<'ctx>)>,
) -> Option<BasicValueEnum<'ctx>> { ) -> Option<BasicValueEnum<'ctx>> {
gen_call(self, ctx, obj, fun, params) gen_call(self, ctx, obj, fun, params)
} }
@ -34,7 +35,7 @@ pub trait CodeGenerator {
ctx: &mut CodeGenContext<'ctx, 'a>, ctx: &mut CodeGenContext<'ctx, 'a>,
signature: &FunSignature, signature: &FunSignature,
def: &TopLevelDef, def: &TopLevelDef,
params: Vec<(Option<StrRef>, BasicValueEnum<'ctx>)>, params: Vec<(Option<StrRef>, ValueEnum<'ctx>)>,
) -> BasicValueEnum<'ctx> { ) -> BasicValueEnum<'ctx> {
gen_constructor(self, ctx, signature, def, params) gen_constructor(self, ctx, signature, def, params)
} }
@ -49,10 +50,11 @@ pub trait CodeGenerator {
fn gen_func_instance<'ctx, 'a>( fn gen_func_instance<'ctx, 'a>(
&mut self, &mut self,
ctx: &mut CodeGenContext<'ctx, 'a>, ctx: &mut CodeGenContext<'ctx, 'a>,
obj: Option<(Type, BasicValueEnum<'ctx>)>, obj: Option<(Type, ValueEnum<'ctx>)>,
fun: (&FunSignature, &mut TopLevelDef, String), fun: (&FunSignature, &mut TopLevelDef, String),
id: usize,
) -> String { ) -> String {
gen_func_instance(ctx, obj, fun) gen_func_instance(ctx, obj, fun, id)
} }
/// Generate the code for an expression. /// Generate the code for an expression.
@ -60,7 +62,7 @@ pub trait CodeGenerator {
&mut self, &mut self,
ctx: &mut CodeGenContext<'ctx, 'a>, ctx: &mut CodeGenContext<'ctx, 'a>,
expr: &Expr<Option<Type>>, expr: &Expr<Option<Type>>,
) -> Option<BasicValueEnum<'ctx>> { ) -> Option<ValueEnum<'ctx>> {
gen_expr(self, ctx, expr) gen_expr(self, ctx, expr)
} }
@ -88,7 +90,7 @@ pub trait CodeGenerator {
&mut self, &mut self,
ctx: &mut CodeGenContext<'ctx, 'a>, ctx: &mut CodeGenContext<'ctx, 'a>,
target: &Expr<Option<Type>>, target: &Expr<Option<Type>>,
value: BasicValueEnum<'ctx>, value: ValueEnum<'ctx>,
) { ) {
gen_assign(self, ctx, target, value) gen_assign(self, ctx, target, value)
} }

View File

@ -1,5 +1,5 @@
use crate::{ use crate::{
symbol_resolver::SymbolResolver, symbol_resolver::{StaticValue, SymbolResolver},
toplevel::{TopLevelContext, TopLevelDef}, toplevel::{TopLevelContext, TopLevelDef},
typecheck::{ typecheck::{
type_inferencer::{CodeLocation, PrimitiveStore}, type_inferencer::{CodeLocation, PrimitiveStore},
@ -18,8 +18,8 @@ use inkwell::{
AddressSpace, OptimizationLevel, AddressSpace, OptimizationLevel,
}; };
use itertools::Itertools; use itertools::Itertools;
use parking_lot::{Condvar, Mutex};
use nac3parser::ast::{Stmt, StrRef}; use nac3parser::ast::{Stmt, StrRef};
use parking_lot::{Condvar, Mutex};
use std::collections::HashMap; use std::collections::HashMap;
use std::sync::{ use std::sync::{
atomic::{AtomicBool, Ordering}, atomic::{AtomicBool, Ordering},
@ -29,8 +29,8 @@ use std::thread;
pub mod concrete_type; pub mod concrete_type;
pub mod expr; pub mod expr;
pub mod stmt;
mod generator; mod generator;
pub mod stmt;
#[cfg(test)] #[cfg(test)]
mod test; mod test;
@ -38,6 +38,14 @@ mod test;
use concrete_type::{ConcreteType, ConcreteTypeEnum, ConcreteTypeStore}; use concrete_type::{ConcreteType, ConcreteTypeEnum, ConcreteTypeStore};
pub use generator::{CodeGenerator, DefaultCodeGenerator}; pub use generator::{CodeGenerator, DefaultCodeGenerator};
#[derive(Default)]
pub struct StaticValueStore {
pub lookup: HashMap<Vec<(usize, u64)>, usize>,
pub store: Vec<HashMap<usize, Arc<dyn StaticValue + Send + Sync>>>,
}
pub type VarValue<'ctx> = (PointerValue<'ctx>, Option<Arc<dyn StaticValue + Send + Sync>>, i64);
pub struct CodeGenContext<'ctx, 'a> { pub struct CodeGenContext<'ctx, 'a> {
pub ctx: &'ctx Context, pub ctx: &'ctx Context,
pub builder: Builder<'ctx>, pub builder: Builder<'ctx>,
@ -45,7 +53,8 @@ pub struct CodeGenContext<'ctx, 'a> {
pub top_level: &'a TopLevelContext, pub top_level: &'a TopLevelContext,
pub unifier: Unifier, pub unifier: Unifier,
pub resolver: Arc<dyn SymbolResolver + Send + Sync>, pub resolver: Arc<dyn SymbolResolver + Send + Sync>,
pub var_assignment: HashMap<StrRef, PointerValue<'ctx>>, pub static_value_store: Arc<Mutex<StaticValueStore>>,
pub var_assignment: HashMap<StrRef, VarValue<'ctx>>,
pub type_cache: HashMap<Type, BasicTypeEnum<'ctx>>, pub type_cache: HashMap<Type, BasicTypeEnum<'ctx>>,
pub primitives: PrimitiveStore, pub primitives: PrimitiveStore,
pub calls: Arc<HashMap<CodeLocation, CallId>>, pub calls: Arc<HashMap<CodeLocation, CallId>>,
@ -80,6 +89,8 @@ pub struct WorkerRegistry {
task_count: Mutex<usize>, task_count: Mutex<usize>,
thread_count: usize, thread_count: usize,
wait_condvar: Condvar, wait_condvar: Condvar,
top_level_ctx: Arc<TopLevelContext>,
static_value_store: Arc<Mutex<StaticValueStore>>,
} }
impl WorkerRegistry { impl WorkerRegistry {
@ -92,23 +103,29 @@ impl WorkerRegistry {
let task_count = Mutex::new(0); let task_count = Mutex::new(0);
let wait_condvar = Condvar::new(); let wait_condvar = Condvar::new();
// init: 0 to be empty
let mut static_value_store: StaticValueStore = Default::default();
static_value_store.lookup.insert(Default::default(), 0);
static_value_store.store.push(Default::default());
let registry = Arc::new(WorkerRegistry { let registry = Arc::new(WorkerRegistry {
sender: Arc::new(sender), sender: Arc::new(sender),
receiver: Arc::new(receiver), receiver: Arc::new(receiver),
thread_count: generators.len(), thread_count: generators.len(),
panicked: AtomicBool::new(false), panicked: AtomicBool::new(false),
static_value_store: Arc::new(Mutex::new(static_value_store)),
task_count, task_count,
wait_condvar, wait_condvar,
top_level_ctx,
}); });
let mut handles = Vec::new(); let mut handles = Vec::new();
for mut generator in generators.into_iter() { for mut generator in generators.into_iter() {
let top_level_ctx = top_level_ctx.clone();
let registry = registry.clone(); let registry = registry.clone();
let registry2 = registry.clone(); let registry2 = registry.clone();
let f = f.clone(); let f = f.clone();
let handle = thread::spawn(move || { let handle = thread::spawn(move || {
registry.worker_thread(generator.as_mut(), top_level_ctx, f); registry.worker_thread(generator.as_mut(), f);
}); });
let handle = thread::spawn(move || { let handle = thread::spawn(move || {
if let Err(e) = handle.join() { if let Err(e) = handle.join() {
@ -161,12 +178,7 @@ impl WorkerRegistry {
self.sender.send(Some(task)).unwrap(); self.sender.send(Some(task)).unwrap();
} }
fn worker_thread<G: CodeGenerator>( fn worker_thread<G: CodeGenerator>(&self, generator: &mut G, f: Arc<WithCall>) {
&self,
generator: &mut G,
top_level_ctx: Arc<TopLevelContext>,
f: Arc<WithCall>,
) {
let context = Context::create(); let context = Context::create();
let mut builder = context.create_builder(); let mut builder = context.create_builder();
let mut module = context.create_module(generator.get_name()); let mut module = context.create_module(generator.get_name());
@ -177,8 +189,7 @@ impl WorkerRegistry {
pass_builder.populate_function_pass_manager(&passes); pass_builder.populate_function_pass_manager(&passes);
while let Some(task) = self.receiver.recv().unwrap() { while let Some(task) = self.receiver.recv().unwrap() {
let result = let result = gen_func(&context, generator, self, builder, module, task);
gen_func(&context, generator, self, builder, module, task, top_level_ctx.clone());
builder = result.0; builder = result.0;
module = result.1; module = result.1;
passes.run_on(&result.2); passes.run_on(&result.2);
@ -208,6 +219,7 @@ pub struct CodeGenTask {
pub calls: Arc<HashMap<CodeLocation, CallId>>, pub calls: Arc<HashMap<CodeLocation, CallId>>,
pub unifier_index: usize, pub unifier_index: usize,
pub resolver: Arc<dyn SymbolResolver + Send + Sync>, pub resolver: Arc<dyn SymbolResolver + Send + Sync>,
pub id: usize,
} }
fn get_llvm_type<'ctx>( fn get_llvm_type<'ctx>(
@ -268,8 +280,9 @@ pub fn gen_func<'ctx, G: CodeGenerator + ?Sized>(
builder: Builder<'ctx>, builder: Builder<'ctx>,
module: Module<'ctx>, module: Module<'ctx>,
task: CodeGenTask, task: CodeGenTask,
top_level_ctx: Arc<TopLevelContext>,
) -> (Builder<'ctx>, Module<'ctx>, FunctionValue<'ctx>) { ) -> (Builder<'ctx>, Module<'ctx>, FunctionValue<'ctx>) {
let top_level_ctx = registry.top_level_ctx.clone();
let static_value_store = registry.static_value_store.clone();
let (mut unifier, primitives) = { let (mut unifier, primitives) = {
let (unifier, primitives) = &top_level_ctx.unifiers.read()[task.unifier_index]; let (unifier, primitives) = &top_level_ctx.unifiers.read()[task.unifier_index];
(Unifier::from_shared_unifier(unifier), *primitives) (Unifier::from_shared_unifier(unifier), *primitives)
@ -299,7 +312,10 @@ pub fn gen_func<'ctx, G: CodeGenerator + ?Sized>(
(unifier.get_representative(primitives.int64), context.i64_type().into()), (unifier.get_representative(primitives.int64), context.i64_type().into()),
(unifier.get_representative(primitives.float), context.f64_type().into()), (unifier.get_representative(primitives.float), context.f64_type().into()),
(unifier.get_representative(primitives.bool), context.bool_type().into()), (unifier.get_representative(primitives.bool), context.bool_type().into()),
(unifier.get_representative(primitives.str), context.i8_type().ptr_type(AddressSpace::Generic).into()), (
unifier.get_representative(primitives.str),
context.i8_type().ptr_type(AddressSpace::Generic).into(),
),
] ]
.iter() .iter()
.cloned() .cloned()
@ -359,8 +375,17 @@ pub fn gen_func<'ctx, G: CodeGenerator + ?Sized>(
&arg.name.to_string(), &arg.name.to_string(),
); );
builder.build_store(alloca, param); builder.build_store(alloca, param);
var_assignment.insert(arg.name, alloca); var_assignment.insert(arg.name, (alloca, None, 0));
} }
let static_values = {
let store = registry.static_value_store.lock();
store.store[task.id].clone()
};
for (k, v) in static_values.into_iter() {
let (_, static_val, _) = var_assignment.get_mut(&args[k].name).unwrap();
*static_val = Some(v);
}
builder.build_unconditional_branch(body_bb); builder.build_unconditional_branch(body_bb);
builder.position_at_end(body_bb); builder.position_at_end(body_bb);
@ -378,6 +403,7 @@ pub fn gen_func<'ctx, G: CodeGenerator + ?Sized>(
builder, builder,
module, module,
unifier, unifier,
static_value_store,
}; };
let mut returned = false; let mut returned = false;

View File

@ -1,4 +1,4 @@
use super::{expr::destructure_range, CodeGenContext, CodeGenerator}; use super::{expr::destructure_range, CodeGenContext, CodeGenerator, super::symbol_resolver::ValueEnum};
use crate::typecheck::typedef::Type; use crate::typecheck::typedef::Type;
use inkwell::values::{BasicValue, BasicValueEnum, PointerValue}; use inkwell::values::{BasicValue, BasicValueEnum, PointerValue};
use nac3parser::ast::{Expr, ExprKind, Stmt, StmtKind}; use nac3parser::ast::{Expr, ExprKind, Stmt, StmtKind};
@ -22,14 +22,14 @@ pub fn gen_store_target<'ctx, 'a, G: CodeGenerator + ?Sized>(
// very similar to gen_expr, but we don't do an extra load at the end // very similar to gen_expr, but we don't do an extra load at the end
// and we flatten nested tuples // and we flatten nested tuples
match &pattern.node { match &pattern.node {
ExprKind::Name { id, .. } => ctx.var_assignment.get(id).cloned().unwrap_or_else(|| { ExprKind::Name { id, .. } => ctx.var_assignment.get(id).map(|v| v.0).unwrap_or_else(|| {
let ptr = generator.gen_var_alloc(ctx, pattern.custom.unwrap()); let ptr = generator.gen_var_alloc(ctx, pattern.custom.unwrap());
ctx.var_assignment.insert(*id, ptr); ctx.var_assignment.insert(*id, (ptr, None, 0));
ptr ptr
}), }),
ExprKind::Attribute { value, attr, .. } => { ExprKind::Attribute { value, attr, .. } => {
let index = ctx.get_attr_index(value.custom.unwrap(), *attr); let index = ctx.get_attr_index(value.custom.unwrap(), *attr);
let val = generator.gen_expr(ctx, value).unwrap(); let val = generator.gen_expr(ctx, value).unwrap().to_basic_value_enum(ctx);
let ptr = if let BasicValueEnum::PointerValue(v) = val { let ptr = if let BasicValueEnum::PointerValue(v) = val {
v v
} else { } else {
@ -48,8 +48,13 @@ pub fn gen_store_target<'ctx, 'a, G: CodeGenerator + ?Sized>(
} }
ExprKind::Subscript { value, slice, .. } => { ExprKind::Subscript { value, slice, .. } => {
let i32_type = ctx.ctx.i32_type(); let i32_type = ctx.ctx.i32_type();
let v = generator.gen_expr(ctx, value).unwrap().into_pointer_value(); let v = generator
let index = generator.gen_expr(ctx, slice).unwrap().into_int_value(); .gen_expr(ctx, value)
.unwrap()
.to_basic_value_enum(ctx)
.into_pointer_value();
let index =
generator.gen_expr(ctx, slice).unwrap().to_basic_value_enum(ctx).into_int_value();
unsafe { unsafe {
let arr_ptr = ctx let arr_ptr = ctx
.build_gep_and_load(v, &[i32_type.const_zero(), i32_type.const_int(1, false)]) .build_gep_and_load(v, &[i32_type.const_zero(), i32_type.const_int(1, false)])
@ -65,24 +70,32 @@ pub fn gen_assign<'ctx, 'a, G: CodeGenerator + ?Sized>(
generator: &mut G, generator: &mut G,
ctx: &mut CodeGenContext<'ctx, 'a>, ctx: &mut CodeGenContext<'ctx, 'a>,
target: &Expr<Option<Type>>, target: &Expr<Option<Type>>,
value: BasicValueEnum<'ctx>, value: ValueEnum<'ctx>,
) { ) {
let i32_type = ctx.ctx.i32_type();
if let ExprKind::Tuple { elts, .. } = &target.node { if let ExprKind::Tuple { elts, .. } = &target.node {
if let BasicValueEnum::PointerValue(ptr) = value { if let BasicValueEnum::PointerValue(ptr) = value.to_basic_value_enum(ctx) {
let i32_type = ctx.ctx.i32_type();
for (i, elt) in elts.iter().enumerate() { for (i, elt) in elts.iter().enumerate() {
let v = ctx.build_gep_and_load( let v = ctx.build_gep_and_load(
ptr, ptr,
&[i32_type.const_zero(), i32_type.const_int(i as u64, false)], &[i32_type.const_zero(), i32_type.const_int(i as u64, false)],
); );
generator.gen_assign(ctx, elt, v); generator.gen_assign(ctx, elt, v.into());
} }
} else { } else {
unreachable!() unreachable!()
} }
} else { } else {
let ptr = generator.gen_store_target(ctx, target); let ptr = generator.gen_store_target(ctx, target);
ctx.builder.build_store(ptr, value); if let ExprKind::Name { id, .. } = &target.node {
let (_, static_value, counter) = ctx.var_assignment.get_mut(id).unwrap();
*counter += 1;
if let ValueEnum::Static(s) = &value {
*static_value = Some(s.clone());
}
}
let val = value.to_basic_value_enum(ctx);
ctx.builder.build_store(ptr, val);
} }
} }
@ -92,6 +105,10 @@ pub fn gen_for<'ctx, 'a, G: CodeGenerator + ?Sized>(
stmt: &Stmt<Option<Type>>, stmt: &Stmt<Option<Type>>,
) { ) {
if let StmtKind::For { iter, target, body, orelse, .. } = &stmt.node { if let StmtKind::For { iter, target, body, orelse, .. } = &stmt.node {
// var_assignment static values may be changed in another branch
// if so, remove the static value as it may not be correct in this branch
let var_assignment = ctx.var_assignment.clone();
let int32 = ctx.ctx.i32_type(); let int32 = ctx.ctx.i32_type();
let zero = int32.const_zero(); let zero = int32.const_zero();
let current = ctx.builder.get_insert_block().unwrap().get_parent().unwrap(); let current = ctx.builder.get_insert_block().unwrap().get_parent().unwrap();
@ -104,7 +121,7 @@ pub fn gen_for<'ctx, 'a, G: CodeGenerator + ?Sized>(
// store loop bb information and restore it later // store loop bb information and restore it later
let loop_bb = ctx.loop_bb.replace((test_bb, cont_bb)); let loop_bb = ctx.loop_bb.replace((test_bb, cont_bb));
let iter_val = generator.gen_expr(ctx, iter).unwrap(); let iter_val = generator.gen_expr(ctx, iter).unwrap().to_basic_value_enum(ctx);
if ctx.unifier.unioned(iter.custom.unwrap(), ctx.primitives.range) { if ctx.unifier.unioned(iter.custom.unwrap(), ctx.primitives.range) {
// setup // setup
let iter_val = iter_val.into_pointer_value(); let iter_val = iter_val.into_pointer_value();
@ -160,12 +177,18 @@ pub fn gen_for<'ctx, 'a, G: CodeGenerator + ?Sized>(
) )
.into_pointer_value(); .into_pointer_value();
let val = ctx.build_gep_and_load(arr_ptr, &[tmp]); let val = ctx.build_gep_and_load(arr_ptr, &[tmp]);
generator.gen_assign(ctx, target, val); generator.gen_assign(ctx, target, val.into());
} }
for stmt in body.iter() { for stmt in body.iter() {
generator.gen_stmt(ctx, stmt); generator.gen_stmt(ctx, stmt);
} }
for (k, (_, _, counter)) in var_assignment.iter() {
let (_, static_val, counter2) = ctx.var_assignment.get_mut(k).unwrap();
if counter != counter2 {
*static_val = None;
}
}
ctx.builder.build_unconditional_branch(test_bb); ctx.builder.build_unconditional_branch(test_bb);
if !orelse.is_empty() { if !orelse.is_empty() {
ctx.builder.position_at_end(orelse_bb); ctx.builder.position_at_end(orelse_bb);
@ -174,6 +197,12 @@ pub fn gen_for<'ctx, 'a, G: CodeGenerator + ?Sized>(
} }
ctx.builder.build_unconditional_branch(cont_bb); ctx.builder.build_unconditional_branch(cont_bb);
} }
for (k, (_, _, counter)) in var_assignment.iter() {
let (_, static_val, counter2) = ctx.var_assignment.get_mut(k).unwrap();
if counter != counter2 {
*static_val = None;
}
}
ctx.builder.position_at_end(cont_bb); ctx.builder.position_at_end(cont_bb);
ctx.loop_bb = loop_bb; ctx.loop_bb = loop_bb;
} else { } else {
@ -187,6 +216,10 @@ pub fn gen_while<'ctx, 'a, G: CodeGenerator + ?Sized>(
stmt: &Stmt<Option<Type>>, stmt: &Stmt<Option<Type>>,
) { ) {
if let StmtKind::While { test, body, orelse, .. } = &stmt.node { if let StmtKind::While { test, body, orelse, .. } = &stmt.node {
// var_assignment static values may be changed in another branch
// if so, remove the static value as it may not be correct in this branch
let var_assignment = ctx.var_assignment.clone();
let current = ctx.builder.get_insert_block().unwrap().get_parent().unwrap(); let current = ctx.builder.get_insert_block().unwrap().get_parent().unwrap();
let test_bb = ctx.ctx.append_basic_block(current, "test"); let test_bb = ctx.ctx.append_basic_block(current, "test");
let body_bb = ctx.ctx.append_basic_block(current, "body"); let body_bb = ctx.ctx.append_basic_block(current, "body");
@ -198,7 +231,7 @@ pub fn gen_while<'ctx, 'a, G: CodeGenerator + ?Sized>(
let loop_bb = ctx.loop_bb.replace((test_bb, cont_bb)); let loop_bb = ctx.loop_bb.replace((test_bb, cont_bb));
ctx.builder.build_unconditional_branch(test_bb); ctx.builder.build_unconditional_branch(test_bb);
ctx.builder.position_at_end(test_bb); ctx.builder.position_at_end(test_bb);
let test = generator.gen_expr(ctx, test).unwrap(); let test = generator.gen_expr(ctx, test).unwrap().to_basic_value_enum(ctx);
if let BasicValueEnum::IntValue(test) = test { if let BasicValueEnum::IntValue(test) = test {
ctx.builder.build_conditional_branch(test, body_bb, orelse_bb); ctx.builder.build_conditional_branch(test, body_bb, orelse_bb);
} else { } else {
@ -208,6 +241,12 @@ pub fn gen_while<'ctx, 'a, G: CodeGenerator + ?Sized>(
for stmt in body.iter() { for stmt in body.iter() {
generator.gen_stmt(ctx, stmt); generator.gen_stmt(ctx, stmt);
} }
for (k, (_, _, counter)) in var_assignment.iter() {
let (_, static_val, counter2) = ctx.var_assignment.get_mut(k).unwrap();
if counter != counter2 {
*static_val = None;
}
}
ctx.builder.build_unconditional_branch(test_bb); ctx.builder.build_unconditional_branch(test_bb);
if !orelse.is_empty() { if !orelse.is_empty() {
ctx.builder.position_at_end(orelse_bb); ctx.builder.position_at_end(orelse_bb);
@ -216,6 +255,12 @@ pub fn gen_while<'ctx, 'a, G: CodeGenerator + ?Sized>(
} }
ctx.builder.build_unconditional_branch(cont_bb); ctx.builder.build_unconditional_branch(cont_bb);
} }
for (k, (_, _, counter)) in var_assignment.iter() {
let (_, static_val, counter2) = ctx.var_assignment.get_mut(k).unwrap();
if counter != counter2 {
*static_val = None;
}
}
ctx.builder.position_at_end(cont_bb); ctx.builder.position_at_end(cont_bb);
ctx.loop_bb = loop_bb; ctx.loop_bb = loop_bb;
} else { } else {
@ -229,6 +274,10 @@ pub fn gen_if<'ctx, 'a, G: CodeGenerator + ?Sized>(
stmt: &Stmt<Option<Type>>, stmt: &Stmt<Option<Type>>,
) -> bool { ) -> bool {
if let StmtKind::If { test, body, orelse, .. } = &stmt.node { if let StmtKind::If { test, body, orelse, .. } = &stmt.node {
// var_assignment static values may be changed in another branch
// if so, remove the static value as it may not be correct in this branch
let var_assignment = ctx.var_assignment.clone();
let current = ctx.builder.get_insert_block().unwrap().get_parent().unwrap(); let current = ctx.builder.get_insert_block().unwrap().get_parent().unwrap();
let test_bb = ctx.ctx.append_basic_block(current, "test"); let test_bb = ctx.ctx.append_basic_block(current, "test");
let body_bb = ctx.ctx.append_basic_block(current, "body"); let body_bb = ctx.ctx.append_basic_block(current, "body");
@ -242,7 +291,7 @@ pub fn gen_if<'ctx, 'a, G: CodeGenerator + ?Sized>(
}; };
ctx.builder.build_unconditional_branch(test_bb); ctx.builder.build_unconditional_branch(test_bb);
ctx.builder.position_at_end(test_bb); ctx.builder.position_at_end(test_bb);
let test = generator.gen_expr(ctx, test).unwrap(); let test = generator.gen_expr(ctx, test).unwrap().to_basic_value_enum(ctx);
if let BasicValueEnum::IntValue(test) = test { if let BasicValueEnum::IntValue(test) = test {
ctx.builder.build_conditional_branch(test, body_bb, orelse_bb); ctx.builder.build_conditional_branch(test, body_bb, orelse_bb);
} else { } else {
@ -256,6 +305,13 @@ pub fn gen_if<'ctx, 'a, G: CodeGenerator + ?Sized>(
break; break;
} }
} }
for (k, (_, _, counter)) in var_assignment.iter() {
let (_, static_val, counter2) = ctx.var_assignment.get_mut(k).unwrap();
if counter != counter2 {
*static_val = None;
}
}
if !exited { if !exited {
if cont_bb.is_none() { if cont_bb.is_none() {
cont_bb = Some(ctx.ctx.append_basic_block(current, "cont")); cont_bb = Some(ctx.ctx.append_basic_block(current, "cont"));
@ -285,6 +341,12 @@ pub fn gen_if<'ctx, 'a, G: CodeGenerator + ?Sized>(
if let Some(cont_bb) = cont_bb { if let Some(cont_bb) = cont_bb {
ctx.builder.position_at_end(cont_bb); ctx.builder.position_at_end(cont_bb);
} }
for (k, (_, _, counter)) in var_assignment.iter() {
let (_, static_val, counter2) = ctx.var_assignment.get_mut(k).unwrap();
if counter != counter2 {
*static_val = None;
}
}
then_exited && else_exited then_exited && else_exited
} else { } else {
unreachable!() unreachable!()
@ -306,12 +368,14 @@ pub fn gen_stmt<'ctx, 'a, G: CodeGenerator + ?Sized>(
stmt: &Stmt<Option<Type>>, stmt: &Stmt<Option<Type>>,
) -> bool { ) -> bool {
match &stmt.node { match &stmt.node {
StmtKind::Pass { .. } => {} StmtKind::Pass { .. } => {}
StmtKind::Expr { value, .. } => { StmtKind::Expr { value, .. } => {
generator.gen_expr(ctx, value); generator.gen_expr(ctx, value);
} }
StmtKind::Return { value, .. } => { StmtKind::Return { value, .. } => {
let value = value.as_ref().map(|v| generator.gen_expr(ctx, v).unwrap()); let value = value
.as_ref()
.map(|v| generator.gen_expr(ctx, v).unwrap().to_basic_value_enum(ctx));
let value = value.as_ref().map(|v| v as &dyn BasicValue); let value = value.as_ref().map(|v| v as &dyn BasicValue);
ctx.builder.build_return(value); ctx.builder.build_return(value);
return true; return true;
@ -325,14 +389,14 @@ pub fn gen_stmt<'ctx, 'a, G: CodeGenerator + ?Sized>(
StmtKind::Assign { targets, value, .. } => { StmtKind::Assign { targets, value, .. } => {
let value = generator.gen_expr(ctx, value).unwrap(); let value = generator.gen_expr(ctx, value).unwrap();
for target in targets.iter() { for target in targets.iter() {
generator.gen_assign(ctx, target, value); generator.gen_assign(ctx, target, value.clone());
} }
} }
StmtKind::Continue { .. } => { StmtKind::Continue { .. } => {
ctx.builder.build_unconditional_branch(ctx.loop_bb.unwrap().0); ctx.builder.build_unconditional_branch(ctx.loop_bb.unwrap().0);
return true; return true;
} }
StmtKind::Break { .. }=> { StmtKind::Break { .. } => {
ctx.builder.build_unconditional_branch(ctx.loop_bb.unwrap().1); ctx.builder.build_unconditional_branch(ctx.loop_bb.unwrap().1);
return true; return true;
} }
@ -344,8 +408,8 @@ pub fn gen_stmt<'ctx, 'a, G: CodeGenerator + ?Sized>(
let value = { let value = {
let ty1 = ctx.unifier.get_representative(target.custom.unwrap()); let ty1 = ctx.unifier.get_representative(target.custom.unwrap());
let ty2 = ctx.unifier.get_representative(value.custom.unwrap()); let ty2 = ctx.unifier.get_representative(value.custom.unwrap());
let left = generator.gen_expr(ctx, target).unwrap(); let left = generator.gen_expr(ctx, target).unwrap().to_basic_value_enum(ctx);
let right = generator.gen_expr(ctx, value).unwrap(); let right = generator.gen_expr(ctx, value).unwrap().to_basic_value_enum(ctx);
// we can directly compare the types, because we've got their representatives // we can directly compare the types, because we've got their representatives
// which would be unchanged until further unification, which we would never do // which would be unchanged until further unification, which we would never do
@ -358,7 +422,7 @@ pub fn gen_stmt<'ctx, 'a, G: CodeGenerator + ?Sized>(
unimplemented!() unimplemented!()
} }
}; };
generator.gen_assign(ctx, target, value); generator.gen_assign(ctx, target, value.into());
} }
_ => unimplemented!(), _ => unimplemented!(),
}; };

View File

@ -4,7 +4,7 @@ use crate::{
WithCall, WorkerRegistry, WithCall, WorkerRegistry,
}, },
location::Location, location::Location,
symbol_resolver::SymbolResolver, symbol_resolver::{SymbolResolver, ValueEnum},
toplevel::{ toplevel::{
composer::TopLevelComposer, DefinitionId, FunInstance, TopLevelContext, TopLevelDef, composer::TopLevelComposer, DefinitionId, FunInstance, TopLevelContext, TopLevelDef,
}, },
@ -14,12 +14,11 @@ use crate::{
}, },
}; };
use indoc::indoc; use indoc::indoc;
use inkwell::values::BasicValueEnum;
use parking_lot::RwLock;
use nac3parser::{ use nac3parser::{
ast::{fold::Fold, StrRef}, ast::{fold::Fold, StrRef},
parser::parse_program, parser::parse_program,
}; };
use parking_lot::RwLock;
use std::cell::RefCell; use std::cell::RefCell;
use std::collections::{HashMap, HashSet}; use std::collections::{HashMap, HashSet};
use std::sync::Arc; use std::sync::Arc;
@ -51,7 +50,7 @@ impl SymbolResolver for Resolver {
&self, &self,
_: StrRef, _: StrRef,
_: &mut CodeGenContext<'ctx, 'a>, _: &mut CodeGenContext<'ctx, 'a>,
) -> Option<BasicValueEnum<'ctx>> { ) -> Option<ValueEnum<'ctx>> {
unimplemented!() unimplemented!()
} }
@ -143,6 +142,7 @@ fn test_primitives() {
resolver, resolver,
store, store,
signature, signature,
id: 0,
}; };
let f = Arc::new(WithCall::new(Box::new(|module| { let f = Arc::new(WithCall::new(Box::new(|module| {
// the following IR is equivalent to // the following IR is equivalent to
@ -310,6 +310,7 @@ fn test_simple_call() {
resolver, resolver,
signature, signature,
store, store,
id: 0,
}; };
let f = Arc::new(WithCall::new(Box::new(|module| { let f = Arc::new(WithCall::new(Box::new(|module| {
let expected = indoc! {" let expected = indoc! {"

View File

@ -11,7 +11,7 @@ use crate::{
toplevel::{DefinitionId, TopLevelDef}, toplevel::{DefinitionId, TopLevelDef},
}; };
use crate::{location::Location, typecheck::typedef::TypeEnum}; use crate::{location::Location, typecheck::typedef::TypeEnum};
use inkwell::values::BasicValueEnum; use inkwell::values::{BasicValueEnum, FloatValue, IntValue, PointerValue};
use itertools::{chain, izip}; use itertools::{chain, izip};
use nac3parser::ast::{Expr, StrRef}; use nac3parser::ast::{Expr, StrRef};
use parking_lot::RwLock; use parking_lot::RwLock;
@ -23,8 +23,63 @@ pub enum SymbolValue {
Double(f64), Double(f64),
Bool(bool), Bool(bool),
Tuple(Vec<SymbolValue>), Tuple(Vec<SymbolValue>),
// we should think about how to implement bytes later... }
// Bytes(&'a [u8]),
pub trait StaticValue {
fn get_unique_identifier(&self) -> u64;
fn to_basic_value_enum<'ctx, 'a>(
&self,
ctx: &mut CodeGenContext<'ctx, 'a>,
) -> BasicValueEnum<'ctx>;
fn get_field<'ctx, 'a>(
&self,
name: StrRef,
ctx: &mut CodeGenContext<'ctx, 'a>,
) -> Option<ValueEnum<'ctx>>;
}
#[derive(Clone)]
pub enum ValueEnum<'ctx> {
Static(Arc<dyn StaticValue + Send + Sync>),
Dynamic(BasicValueEnum<'ctx>),
}
impl<'ctx> From<BasicValueEnum<'ctx>> for ValueEnum<'ctx> {
fn from(v: BasicValueEnum<'ctx>) -> Self {
ValueEnum::Dynamic(v)
}
}
impl<'ctx> From<PointerValue<'ctx>> for ValueEnum<'ctx> {
fn from(v: PointerValue<'ctx>) -> Self {
ValueEnum::Dynamic(v.into())
}
}
impl<'ctx> From<IntValue<'ctx>> for ValueEnum<'ctx> {
fn from(v: IntValue<'ctx>) -> Self {
ValueEnum::Dynamic(v.into())
}
}
impl<'ctx> From<FloatValue<'ctx>> for ValueEnum<'ctx> {
fn from(v: FloatValue<'ctx>) -> Self {
ValueEnum::Dynamic(v.into())
}
}
impl<'ctx> ValueEnum<'ctx> {
pub fn to_basic_value_enum<'a>(
self,
ctx: &mut CodeGenContext<'ctx, 'a>,
) -> BasicValueEnum<'ctx> {
match self {
ValueEnum::Static(v) => v.to_basic_value_enum(ctx),
ValueEnum::Dynamic(v) => v,
}
}
} }
pub trait SymbolResolver { pub trait SymbolResolver {
@ -36,13 +91,16 @@ pub trait SymbolResolver {
primitives: &PrimitiveStore, primitives: &PrimitiveStore,
str: StrRef, str: StrRef,
) -> Option<Type>; ) -> Option<Type>;
// get the top-level definition of identifiers // get the top-level definition of identifiers
fn get_identifier_def(&self, str: StrRef) -> Option<DefinitionId>; fn get_identifier_def(&self, str: StrRef) -> Option<DefinitionId>;
fn get_symbol_value<'ctx, 'a>( fn get_symbol_value<'ctx, 'a>(
&self, &self,
str: StrRef, str: StrRef,
ctx: &mut CodeGenContext<'ctx, 'a>, ctx: &mut CodeGenContext<'ctx, 'a>,
) -> Option<BasicValueEnum<'ctx>>; ) -> Option<ValueEnum<'ctx>>;
fn get_symbol_location(&self, str: StrRef) -> Option<Location>; fn get_symbol_location(&self, str: StrRef) -> Option<Location>;
// handle function call etc. // handle function call etc.
} }

View File

@ -1,7 +1,7 @@
use crate::{ use crate::{
codegen::CodeGenContext, codegen::CodeGenContext,
location::Location, location::Location,
symbol_resolver::SymbolResolver, symbol_resolver::{SymbolResolver, ValueEnum},
toplevel::DefinitionId, toplevel::DefinitionId,
typecheck::{ typecheck::{
type_inferencer::PrimitiveStore, type_inferencer::PrimitiveStore,
@ -50,7 +50,7 @@ impl SymbolResolver for Resolver {
&self, &self,
_: StrRef, _: StrRef,
_: &mut CodeGenContext<'ctx, 'a>, _: &mut CodeGenContext<'ctx, 'a>,
) -> Option<BasicValueEnum<'ctx>> { ) -> Option<ValueEnum<'ctx>> {
unimplemented!() unimplemented!()
} }

View File

@ -3,10 +3,10 @@ use super::*;
use crate::{ use crate::{
codegen::CodeGenContext, codegen::CodeGenContext,
location::Location, location::Location,
symbol_resolver::ValueEnum,
toplevel::{DefinitionId, TopLevelDef}, toplevel::{DefinitionId, TopLevelDef},
}; };
use indoc::indoc; use indoc::indoc;
use inkwell::values::BasicValueEnum;
use itertools::zip; use itertools::zip;
use nac3parser::parser::parse_program; use nac3parser::parser::parse_program;
use parking_lot::RwLock; use parking_lot::RwLock;
@ -33,7 +33,7 @@ impl SymbolResolver for Resolver {
&self, &self,
_: StrRef, _: StrRef,
_: &mut CodeGenContext<'ctx, 'a>, _: &mut CodeGenContext<'ctx, 'a>,
) -> Option<BasicValueEnum<'ctx>> { ) -> Option<ValueEnum<'ctx>> {
unimplemented!() unimplemented!()
} }

View File

@ -1,16 +1,15 @@
use inkwell::values::BasicValueEnum;
use nac3core::{ use nac3core::{
codegen::CodeGenContext, codegen::CodeGenContext,
location::Location, location::Location,
symbol_resolver::SymbolResolver, symbol_resolver::{SymbolResolver, ValueEnum},
toplevel::{DefinitionId, TopLevelDef}, toplevel::{DefinitionId, TopLevelDef},
typecheck::{ typecheck::{
type_inferencer::PrimitiveStore, type_inferencer::PrimitiveStore,
typedef::{Type, Unifier}, typedef::{Type, Unifier},
}, },
}; };
use parking_lot::{Mutex, RwLock};
use nac3parser::ast::StrRef; use nac3parser::ast::StrRef;
use parking_lot::{Mutex, RwLock};
use std::{collections::HashMap, sync::Arc}; use std::{collections::HashMap, sync::Arc};
pub struct ResolverInternal { pub struct ResolverInternal {
@ -50,7 +49,7 @@ impl SymbolResolver for Resolver {
&self, &self,
_: StrRef, _: StrRef,
_: &mut CodeGenContext<'ctx, 'a>, _: &mut CodeGenContext<'ctx, 'a>,
) -> Option<BasicValueEnum<'ctx>> { ) -> Option<ValueEnum<'ctx>> {
unimplemented!() unimplemented!()
} }

View File

@ -123,6 +123,7 @@ fn main() {
store, store,
unifier_index: instance.unifier_id, unifier_index: instance.unifier_id,
calls: instance.calls, calls: instance.calls,
id: 0,
}; };
let f = Arc::new(WithCall::new(Box::new(move |module| { let f = Arc::new(WithCall::new(Box::new(move |module| {
let builder = PassManagerBuilder::create(); let builder = PassManagerBuilder::create();