Compare commits
No commits in common. "012af93cfa0436cbf838b2909bc655164e796aaa" and "8c26f186b54a82e684fb45a72ca8216a493ebd35" have entirely different histories.
012af93cfa
...
8c26f186b5
|
@ -521,7 +521,6 @@ dependencies = [
|
||||||
"inkwell",
|
"inkwell",
|
||||||
"insta",
|
"insta",
|
||||||
"itertools",
|
"itertools",
|
||||||
"lazy_static",
|
|
||||||
"nac3parser",
|
"nac3parser",
|
||||||
"parking_lot 0.11.2",
|
"parking_lot 0.11.2",
|
||||||
"rayon",
|
"rayon",
|
||||||
|
|
|
@ -10,7 +10,6 @@ crossbeam = "0.8.1"
|
||||||
parking_lot = "0.11.1"
|
parking_lot = "0.11.1"
|
||||||
rayon = "1.5.1"
|
rayon = "1.5.1"
|
||||||
nac3parser = { path = "../nac3parser" }
|
nac3parser = { path = "../nac3parser" }
|
||||||
lazy_static = "1.4.0"
|
|
||||||
|
|
||||||
[dependencies.inkwell]
|
[dependencies.inkwell]
|
||||||
git = "https://github.com/TheDan64/inkwell.git"
|
git = "https://github.com/TheDan64/inkwell.git"
|
||||||
|
|
|
@ -165,7 +165,6 @@ impl<'ctx, 'a> CodeGenContext<'ctx, 'a> {
|
||||||
) -> BasicTypeEnum<'ctx> {
|
) -> BasicTypeEnum<'ctx> {
|
||||||
get_llvm_type(
|
get_llvm_type(
|
||||||
self.ctx,
|
self.ctx,
|
||||||
&self.module,
|
|
||||||
generator,
|
generator,
|
||||||
&mut self.unifier,
|
&mut self.unifier,
|
||||||
self.top_level,
|
self.top_level,
|
||||||
|
|
|
@ -31,7 +31,6 @@ use std::sync::{
|
||||||
Arc,
|
Arc,
|
||||||
};
|
};
|
||||||
use std::thread;
|
use std::thread;
|
||||||
use lazy_static::lazy_static;
|
|
||||||
|
|
||||||
pub mod concrete_type;
|
pub mod concrete_type;
|
||||||
pub mod expr;
|
pub mod expr;
|
||||||
|
@ -53,12 +52,6 @@ pub struct StaticValueStore {
|
||||||
|
|
||||||
pub type VarValue<'ctx> = (PointerValue<'ctx>, Option<Arc<dyn StaticValue + Send + Sync>>, i64);
|
pub type VarValue<'ctx> = (PointerValue<'ctx>, Option<Arc<dyn StaticValue + Send + Sync>>, i64);
|
||||||
|
|
||||||
lazy_static!(
|
|
||||||
// HACK: The Mutex is a work-around for issue
|
|
||||||
// https://git.m-labs.hk/M-Labs/nac3/issues/275
|
|
||||||
static ref PASSES_INIT_LOCK: Mutex<AtomicBool> = Mutex::new(AtomicBool::new(true));
|
|
||||||
);
|
|
||||||
|
|
||||||
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>,
|
||||||
|
@ -212,7 +205,7 @@ impl WorkerRegistry {
|
||||||
fn worker_thread<G: CodeGenerator>(&self, generator: &mut G, f: Arc<WithCall>) {
|
fn worker_thread<G: CodeGenerator>(&self, generator: &mut G, 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 module = context.create_module(generator.get_name());
|
||||||
|
|
||||||
module.add_basic_value_flag(
|
module.add_basic_value_flag(
|
||||||
"Debug Info Version",
|
"Debug Info Version",
|
||||||
|
@ -225,30 +218,23 @@ impl WorkerRegistry {
|
||||||
context.i32_type().const_int(4, false),
|
context.i32_type().const_int(4, false),
|
||||||
);
|
);
|
||||||
|
|
||||||
let passes = PassManager::create(&module);
|
|
||||||
|
|
||||||
// HACK: This critical section is a work-around for issue
|
|
||||||
// https://git.m-labs.hk/M-Labs/nac3/issues/275
|
|
||||||
{
|
|
||||||
let _data = PASSES_INIT_LOCK.lock();
|
|
||||||
let pass_builder = PassManagerBuilder::create();
|
let pass_builder = PassManagerBuilder::create();
|
||||||
pass_builder.set_optimization_level(OptimizationLevel::Default);
|
pass_builder.set_optimization_level(OptimizationLevel::Default);
|
||||||
|
let passes = PassManager::create(&module);
|
||||||
pass_builder.populate_function_pass_manager(&passes);
|
pass_builder.populate_function_pass_manager(&passes);
|
||||||
}
|
|
||||||
|
|
||||||
let mut errors = HashSet::new();
|
let mut errors = HashSet::new();
|
||||||
while let Some(task) = self.receiver.recv().unwrap() {
|
while let Some(task) = self.receiver.recv().unwrap() {
|
||||||
match gen_func(&context, generator, self, builder, module, task) {
|
let tmp_module = context.create_module("tmp");
|
||||||
|
match gen_func(&context, generator, self, builder, tmp_module, task) {
|
||||||
Ok(result) => {
|
Ok(result) => {
|
||||||
builder = result.0;
|
builder = result.0;
|
||||||
passes.run_on(&result.2);
|
passes.run_on(&result.2);
|
||||||
module = result.1;
|
module.link_in_module(result.1).unwrap();
|
||||||
}
|
}
|
||||||
Err((old_builder, e)) => {
|
Err((old_builder, e)) => {
|
||||||
builder = old_builder;
|
builder = old_builder;
|
||||||
errors.insert(e);
|
errors.insert(e);
|
||||||
// create a new empty module just to continue codegen and collect errors
|
|
||||||
module = context.create_module(&format!("{}_recover", generator.get_name()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*self.task_count.lock() -= 1;
|
*self.task_count.lock() -= 1;
|
||||||
|
@ -285,7 +271,6 @@ pub struct CodeGenTask {
|
||||||
|
|
||||||
fn get_llvm_type<'ctx>(
|
fn get_llvm_type<'ctx>(
|
||||||
ctx: &'ctx Context,
|
ctx: &'ctx Context,
|
||||||
module: &Module<'ctx>,
|
|
||||||
generator: &mut dyn CodeGenerator,
|
generator: &mut dyn CodeGenerator,
|
||||||
unifier: &mut Unifier,
|
unifier: &mut Unifier,
|
||||||
top_level: &TopLevelContext,
|
top_level: &TopLevelContext,
|
||||||
|
@ -310,7 +295,6 @@ fn get_llvm_type<'ctx>(
|
||||||
) if *obj_id == *opt_id => {
|
) if *obj_id == *opt_id => {
|
||||||
return get_llvm_type(
|
return get_llvm_type(
|
||||||
ctx,
|
ctx,
|
||||||
module,
|
|
||||||
generator,
|
generator,
|
||||||
unifier,
|
unifier,
|
||||||
top_level,
|
top_level,
|
||||||
|
@ -327,24 +311,16 @@ fn get_llvm_type<'ctx>(
|
||||||
// a struct with fields in the order of declaration
|
// a struct with fields in the order of declaration
|
||||||
let top_level_defs = top_level.definitions.read();
|
let top_level_defs = top_level.definitions.read();
|
||||||
let definition = top_level_defs.get(obj_id.0).unwrap();
|
let definition = top_level_defs.get(obj_id.0).unwrap();
|
||||||
let ty = if let TopLevelDef::Class { fields: fields_list, .. } =
|
let ty = if let TopLevelDef::Class { name, fields: fields_list, .. } =
|
||||||
&*definition.read()
|
&*definition.read()
|
||||||
{
|
{
|
||||||
let name = unifier.stringify(ty);
|
let struct_type = ctx.opaque_struct_type(&name.to_string());
|
||||||
match module.get_struct_type(&name) {
|
type_cache.insert(unifier.get_representative(ty), struct_type.ptr_type(AddressSpace::Generic).into());
|
||||||
Some(t) => t.ptr_type(AddressSpace::Generic).into(),
|
|
||||||
None => {
|
|
||||||
let struct_type = ctx.opaque_struct_type(&name);
|
|
||||||
type_cache.insert(
|
|
||||||
unifier.get_representative(ty),
|
|
||||||
struct_type.ptr_type(AddressSpace::Generic).into()
|
|
||||||
);
|
|
||||||
let fields = fields_list
|
let fields = fields_list
|
||||||
.iter()
|
.iter()
|
||||||
.map(|f| {
|
.map(|f| {
|
||||||
get_llvm_type(
|
get_llvm_type(
|
||||||
ctx,
|
ctx,
|
||||||
module,
|
|
||||||
generator,
|
generator,
|
||||||
unifier,
|
unifier,
|
||||||
top_level,
|
top_level,
|
||||||
|
@ -356,8 +332,6 @@ fn get_llvm_type<'ctx>(
|
||||||
.collect_vec();
|
.collect_vec();
|
||||||
struct_type.set_body(&fields, false);
|
struct_type.set_body(&fields, false);
|
||||||
struct_type.ptr_type(AddressSpace::Generic).into()
|
struct_type.ptr_type(AddressSpace::Generic).into()
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
};
|
};
|
||||||
|
@ -367,19 +341,14 @@ fn get_llvm_type<'ctx>(
|
||||||
// a struct with fields in the order present in the tuple
|
// a struct with fields in the order present in the tuple
|
||||||
let fields = ty
|
let fields = ty
|
||||||
.iter()
|
.iter()
|
||||||
.map(|ty| {
|
.map(|ty| get_llvm_type(ctx, generator, unifier, top_level, type_cache, primitives, *ty))
|
||||||
get_llvm_type(
|
|
||||||
ctx, module, generator, unifier, top_level, type_cache, primitives, *ty,
|
|
||||||
)
|
|
||||||
})
|
|
||||||
.collect_vec();
|
.collect_vec();
|
||||||
ctx.struct_type(&fields, false).into()
|
ctx.struct_type(&fields, false).into()
|
||||||
}
|
}
|
||||||
TList { ty } => {
|
TList { ty } => {
|
||||||
// a struct with an integer and a pointer to an array
|
// a struct with an integer and a pointer to an array
|
||||||
let element_type = get_llvm_type(
|
let element_type =
|
||||||
ctx, module, generator, unifier, top_level, type_cache, primitives, *ty,
|
get_llvm_type(ctx, generator, unifier, top_level, type_cache, primitives, *ty);
|
||||||
);
|
|
||||||
let fields = [
|
let fields = [
|
||||||
element_type.ptr_type(AddressSpace::Generic).into(),
|
element_type.ptr_type(AddressSpace::Generic).into(),
|
||||||
generator.get_size_type(ctx).into(),
|
generator.get_size_type(ctx).into(),
|
||||||
|
@ -465,9 +434,6 @@ pub fn gen_func_impl<'ctx, G: CodeGenerator, F: FnOnce(&mut G, &mut CodeGenConte
|
||||||
(primitives.float, context.f64_type().into()),
|
(primitives.float, context.f64_type().into()),
|
||||||
(primitives.bool, context.bool_type().into()),
|
(primitives.bool, context.bool_type().into()),
|
||||||
(primitives.str, {
|
(primitives.str, {
|
||||||
let name = "str";
|
|
||||||
match module.get_struct_type(name) {
|
|
||||||
None => {
|
|
||||||
let str_type = context.opaque_struct_type("str");
|
let str_type = context.opaque_struct_type("str");
|
||||||
let fields = [
|
let fields = [
|
||||||
context.i8_type().ptr_type(AddressSpace::Generic).into(),
|
context.i8_type().ptr_type(AddressSpace::Generic).into(),
|
||||||
|
@ -475,30 +441,21 @@ pub fn gen_func_impl<'ctx, G: CodeGenerator, F: FnOnce(&mut G, &mut CodeGenConte
|
||||||
];
|
];
|
||||||
str_type.set_body(&fields, false);
|
str_type.set_body(&fields, false);
|
||||||
str_type.into()
|
str_type.into()
|
||||||
}
|
|
||||||
Some(t) => t.as_basic_type_enum()
|
|
||||||
}
|
|
||||||
}),
|
}),
|
||||||
(primitives.range, context.i32_type().array_type(3).ptr_type(AddressSpace::Generic).into()),
|
(primitives.range, context.i32_type().array_type(3).ptr_type(AddressSpace::Generic).into()),
|
||||||
(primitives.exception, {
|
|
||||||
let name = "Exception";
|
|
||||||
match module.get_struct_type(name) {
|
|
||||||
Some(t) => t.ptr_type(AddressSpace::Generic).as_basic_type_enum(),
|
|
||||||
None => {
|
|
||||||
let exception = context.opaque_struct_type("Exception");
|
|
||||||
let int32 = context.i32_type().into();
|
|
||||||
let int64 = context.i64_type().into();
|
|
||||||
let str_ty = module.get_struct_type("str").unwrap().as_basic_type_enum();
|
|
||||||
let fields = [int32, str_ty, int32, int32, str_ty, str_ty, int64, int64, int64];
|
|
||||||
exception.set_body(&fields, false);
|
|
||||||
exception.ptr_type(AddressSpace::Generic).as_basic_type_enum()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
]
|
]
|
||||||
.iter()
|
.iter()
|
||||||
.cloned()
|
.cloned()
|
||||||
.collect();
|
.collect();
|
||||||
|
type_cache.insert(primitives.exception, {
|
||||||
|
let exception = context.opaque_struct_type("Exception");
|
||||||
|
let int32 = context.i32_type().into();
|
||||||
|
let int64 = context.i64_type().into();
|
||||||
|
let str_ty = *type_cache.get(&primitives.str).unwrap();
|
||||||
|
let fields = [int32, str_ty, int32, int32, str_ty, str_ty, int64, int64, int64];
|
||||||
|
exception.set_body(&fields, false);
|
||||||
|
exception.ptr_type(AddressSpace::Generic).into()
|
||||||
|
});
|
||||||
// NOTE: special handling of option cannot use this type cache since it contains type var,
|
// NOTE: special handling of option cannot use this type cache since it contains type var,
|
||||||
// handled inside get_llvm_type instead
|
// handled inside get_llvm_type instead
|
||||||
|
|
||||||
|
@ -521,7 +478,7 @@ pub fn gen_func_impl<'ctx, G: CodeGenerator, F: FnOnce(&mut G, &mut CodeGenConte
|
||||||
let ret_type = if unifier.unioned(ret, primitives.none) {
|
let ret_type = if unifier.unioned(ret, primitives.none) {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
Some(get_llvm_type(context, &module, generator, &mut unifier, top_level_ctx.as_ref(), &mut type_cache, &primitives, ret))
|
Some(get_llvm_type(context, generator, &mut unifier, top_level_ctx.as_ref(), &mut type_cache, &primitives, ret))
|
||||||
};
|
};
|
||||||
|
|
||||||
let has_sret = ret_type.map_or(false, |ty| need_sret(context, ty));
|
let has_sret = ret_type.map_or(false, |ty| need_sret(context, ty));
|
||||||
|
@ -530,7 +487,6 @@ pub fn gen_func_impl<'ctx, G: CodeGenerator, F: FnOnce(&mut G, &mut CodeGenConte
|
||||||
.map(|arg| {
|
.map(|arg| {
|
||||||
get_llvm_type(
|
get_llvm_type(
|
||||||
context,
|
context,
|
||||||
&module,
|
|
||||||
generator,
|
generator,
|
||||||
&mut unifier,
|
&mut unifier,
|
||||||
top_level_ctx.as_ref(),
|
top_level_ctx.as_ref(),
|
||||||
|
@ -579,7 +535,6 @@ pub fn gen_func_impl<'ctx, G: CodeGenerator, F: FnOnce(&mut G, &mut CodeGenConte
|
||||||
let alloca = builder.build_alloca(
|
let alloca = builder.build_alloca(
|
||||||
get_llvm_type(
|
get_llvm_type(
|
||||||
context,
|
context,
|
||||||
&module,
|
|
||||||
generator,
|
generator,
|
||||||
&mut unifier,
|
&mut unifier,
|
||||||
top_level_ctx.as_ref(),
|
top_level_ctx.as_ref(),
|
||||||
|
|
|
@ -105,7 +105,7 @@ impl SymbolResolver for Resolver {
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.c: int32 = 4
|
self.c: int32 = 4
|
||||||
self.a: bool = True
|
self.a: bool = True
|
||||||
"},
|
"}
|
||||||
];
|
];
|
||||||
"register"
|
"register"
|
||||||
)]
|
)]
|
||||||
|
@ -120,22 +120,6 @@ fn test_simple_register(source: Vec<&str>) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test_case(
|
|
||||||
indoc! {"
|
|
||||||
class A:
|
|
||||||
def foo(self):
|
|
||||||
pass
|
|
||||||
"};
|
|
||||||
"register"
|
|
||||||
)]
|
|
||||||
fn test_simple_register_without_constructor(source: &str) {
|
|
||||||
let mut composer: TopLevelComposer = Default::default();
|
|
||||||
let ast = parse_program(source, Default::default()).unwrap();
|
|
||||||
let ast = ast[0].clone();
|
|
||||||
composer.register_top_level(ast, None, "".into(), false).unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#[test_case(
|
#[test_case(
|
||||||
vec![
|
vec![
|
||||||
indoc! {"
|
indoc! {"
|
||||||
|
|
Loading…
Reference in New Issue