Compare commits

...

3 Commits

Author SHA1 Message Date
David Mak a2fce49b26 core: Allocate exceptions at the beginning of function
Only one instance of exception is necessary, as exceptions will always
be initialized before being thrown.
2023-10-06 12:13:20 +08:00
David Mak 60a503a791 core: Allocate more stack variables at the beginning of function
All allocas for temporary objects are now placed in the beginning of the
function. Allocas for on-temporary objects are not modified because
these variables may appear in a loop and thus must be uniquely
allocated by different allocas.
2023-10-06 11:42:47 +08:00
David Mak 0c49b30a90 core: Restore debug info before function call is invoked
Previously, the IR which sets up the call to the target function will
have its debug location pointing at the last argument of the function
call instead of the function call itself.
2023-10-06 11:35:23 +08:00
3 changed files with 28 additions and 7 deletions

View File

@ -120,7 +120,7 @@ impl<'ctx, 'a> CodeGenContext<'ctx, 'a> {
let vals = ls.iter().map(|v| self.gen_symbol_val(generator, v, ty)).collect_vec(); let vals = ls.iter().map(|v| self.gen_symbol_val(generator, v, ty)).collect_vec();
let fields = vals.iter().map(|v| v.get_type()).collect_vec(); let fields = vals.iter().map(|v| v.get_type()).collect_vec();
let ty = self.ctx.struct_type(&fields, false); let ty = self.ctx.struct_type(&fields, false);
let ptr = self.builder.build_alloca(ty, "tuple"); let ptr = gen_var(self, ty.into(), Some("tuple")).unwrap();
let zero = self.ctx.i32_type().const_zero(); let zero = self.ctx.i32_type().const_zero();
unsafe { unsafe {
for (i, val) in vals.into_iter().enumerate() { for (i, val) in vals.into_iter().enumerate() {
@ -144,7 +144,7 @@ impl<'ctx, 'a> CodeGenContext<'ctx, 'a> {
_ => unreachable!("must be option type"), _ => unreachable!("must be option type"),
}; };
let val = self.gen_symbol_val(generator, v, ty); let val = self.gen_symbol_val(generator, v, ty);
let ptr = self.builder.build_alloca(val.get_type(), "default_opt_some"); let ptr = generator.gen_var_alloc(self, val.get_type(), Some("default_opt_some")).unwrap();
self.builder.build_store(ptr, val); self.builder.build_store(ptr, val);
ptr.into() ptr.into()
} }
@ -365,6 +365,15 @@ impl<'ctx, 'a> CodeGenContext<'ctx, 'a> {
let mut loc_params: Vec<BasicValueEnum<'ctx>> = Vec::new(); let mut loc_params: Vec<BasicValueEnum<'ctx>> = Vec::new();
let mut return_slot = None; let mut return_slot = None;
let loc = self.debug_info.0.create_debug_location(
self.ctx,
self.current_loc.row as u32,
self.current_loc.column as u32,
self.debug_info.2,
None,
);
self.builder.set_current_debug_location(loc);
if fun.count_params() > 0 { if fun.count_params() > 0 {
let sret_id = Attribute::get_named_enum_kind_id("sret"); let sret_id = Attribute::get_named_enum_kind_id("sret");
let byref_id = Attribute::get_named_enum_kind_id("byref"); let byref_id = Attribute::get_named_enum_kind_id("byref");
@ -450,9 +459,14 @@ impl<'ctx, 'a> CodeGenContext<'ctx, 'a> {
params: [Option<IntValue<'ctx>>; 3], params: [Option<IntValue<'ctx>>; 3],
loc: Location, loc: Location,
) { ) {
let ty = self.get_llvm_type(generator, self.primitives.exception).into_pointer_type(); let zelf = if let Some(exception_val) = self.exception_val {
let zelf_ty: BasicTypeEnum = ty.get_element_type().into_struct_type().into(); exception_val
let zelf = generator.gen_var_alloc(self, zelf_ty, Some("exn")).unwrap(); } else {
let ty = self.get_llvm_type(generator, self.primitives.exception).into_pointer_type();
let zelf_ty: BasicTypeEnum = ty.get_element_type().into_struct_type().into();
let zelf = generator.gen_var_alloc(self, zelf_ty, Some("exn")).unwrap();
self.exception_val.insert(zelf).to_owned()
};
let int32 = self.ctx.i32_type(); let int32 = self.ctx.i32_type();
let zero = int32.const_zero(); let zero = int32.const_zero();
unsafe { unsafe {
@ -655,6 +669,7 @@ pub fn gen_call<'ctx, 'a, G: CodeGenerator>(
let key; let key;
let param_vals; let param_vals;
let is_extern; let is_extern;
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();
@ -1648,6 +1663,10 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>(
_ => unreachable!("option must be static or ptr") _ => unreachable!("option must be static or ptr")
} }
} }
// Reset current_loc back to the location of the call
ctx.current_loc = expr.location;
return Ok(generator return Ok(generator
.gen_call( .gen_call(
ctx, ctx,

View File

@ -146,6 +146,7 @@ pub struct CodeGenContext<'ctx, 'a> {
pub const_strings: HashMap<String, BasicValueEnum<'ctx>>, pub const_strings: HashMap<String, BasicValueEnum<'ctx>>,
// stores the alloca for variables // stores the alloca for variables
pub init_bb: BasicBlock<'ctx>, pub init_bb: BasicBlock<'ctx>,
pub exception_val: Option<PointerValue<'ctx>>,
/// The header and exit basic blocks of a loop in this context. See /// The header and exit basic blocks of a loop in this context. See
/// https://llvm.org/docs/LoopTerminology.html for explanation of these terminology. /// https://llvm.org/docs/LoopTerminology.html for explanation of these terminology.
pub loop_target: Option<(BasicBlock<'ctx>, BasicBlock<'ctx>)>, pub loop_target: Option<(BasicBlock<'ctx>, BasicBlock<'ctx>)>,
@ -802,6 +803,7 @@ pub fn gen_func_impl<'ctx, G: CodeGenerator, F: FnOnce(&mut G, &mut CodeGenConte
type_cache, type_cache,
primitives, primitives,
init_bb, init_bb,
exception_val: Default::default(),
builder, builder,
module, module,
unifier, unifier,

View File

@ -710,7 +710,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
}); });
let start = start.unwrap_or_else(|| int32.const_zero().into()); let start = start.unwrap_or_else(|| int32.const_zero().into());
let ty = int32.array_type(3); let ty = int32.array_type(3);
let ptr = ctx.builder.build_alloca(ty, "range"); let ptr = generator.gen_var_alloc(ctx, ty.into(), Some("range")).unwrap();
unsafe { unsafe {
let a = ctx.builder.build_in_bounds_gep(ptr, &[zero, zero], "start"); let a = ctx.builder.build_in_bounds_gep(ptr, &[zero, zero], "start");
let b = ctx.builder.build_in_bounds_gep( let b = ctx.builder.build_in_bounds_gep(
@ -1236,7 +1236,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
|ctx, _, fun, args, generator| { |ctx, _, fun, args, generator| {
let arg_ty = fun.0.args[0].ty; let arg_ty = fun.0.args[0].ty;
let arg_val = args[0].1.clone().to_basic_value_enum(ctx, generator, arg_ty)?; let arg_val = args[0].1.clone().to_basic_value_enum(ctx, generator, arg_ty)?;
let alloca = ctx.builder.build_alloca(arg_val.get_type(), "alloca_some"); let alloca = generator.gen_var_alloc(ctx, arg_val.get_type(), Some("alloca_some")).unwrap();
ctx.builder.build_store(alloca, arg_val); ctx.builder.build_store(alloca, arg_val);
Ok(Some(alloca.into())) Ok(Some(alloca.into()))
}, },