nac3core: add location information to codegen context

This commit is contained in:
ychenfo 2022-04-04 23:21:00 +08:00
parent e05b0bf5dc
commit 0fb9998a96
4 changed files with 51 additions and 34 deletions

View File

@ -395,9 +395,9 @@ impl<'ctx, 'a> CodeGenContext<'ctx, 'a> {
self.gen_const(generator, &nac3parser::ast::Constant::Str(s.into()), self.primitives.str) self.gen_const(generator, &nac3parser::ast::Constant::Str(s.into()), self.primitives.str)
} }
pub fn raise_exn<G: CodeGenerator>( pub fn raise_exn(
&mut self, &mut self,
generator: &mut G, generator: &mut dyn CodeGenerator,
name: &str, name: &str,
msg: BasicValueEnum<'ctx>, msg: BasicValueEnum<'ctx>,
params: [Option<IntValue<'ctx>>; 3], params: [Option<IntValue<'ctx>>; 3],
@ -434,9 +434,9 @@ impl<'ctx, 'a> CodeGenContext<'ctx, 'a> {
gen_raise(generator, self, Some(&zelf.into()), loc); gen_raise(generator, self, Some(&zelf.into()), loc);
} }
pub fn make_assert<G: CodeGenerator>( pub fn make_assert(
&mut self, &mut self,
generator: &mut G, generator: &mut dyn CodeGenerator,
cond: IntValue<'ctx>, cond: IntValue<'ctx>,
err_name: &str, err_name: &str,
err_msg: &str, err_msg: &str,
@ -447,9 +447,9 @@ impl<'ctx, 'a> CodeGenContext<'ctx, 'a> {
self.make_assert_impl(generator, cond, err_name, err_msg, params, loc) self.make_assert_impl(generator, cond, err_name, err_msg, params, loc)
} }
pub fn make_assert_impl<G: CodeGenerator>( pub fn make_assert_impl(
&mut self, &mut self,
generator: &mut G, generator: &mut dyn CodeGenerator,
cond: IntValue<'ctx>, cond: IntValue<'ctx>,
err_name: &str, err_name: &str,
err_msg: BasicValueEnum<'ctx>, err_msg: BasicValueEnum<'ctx>,
@ -969,6 +969,7 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>(
ctx: &mut CodeGenContext<'ctx, 'a>, ctx: &mut CodeGenContext<'ctx, 'a>,
expr: &Expr<Option<Type>>, expr: &Expr<Option<Type>>,
) -> Result<Option<ValueEnum<'ctx>>, String> { ) -> Result<Option<ValueEnum<'ctx>>, String> {
ctx.current_loc = expr.location;
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);
Ok(Some(match &expr.node { Ok(Some(match &expr.node {
@ -1368,26 +1369,26 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>(
unreachable!() unreachable!()
} }
}; };
// directly generate code for option.unwrap // // directly generate code for option.unwrap
// since it needs location information from ast // // since it needs location information from ast
if attr == &"unwrap".into() // if attr == &"unwrap".into()
&& id == ctx.primitives.option.get_obj_id(&ctx.unifier) // && id == ctx.primitives.option.get_obj_id(&ctx.unifier)
{ // {
if let BasicValueEnum::PointerValue(ptr) = val.to_basic_value_enum(ctx, generator)? { // if let BasicValueEnum::PointerValue(ptr) = val.to_basic_value_enum(ctx, generator)? {
let not_null = ctx.builder.build_is_not_null(ptr, "unwrap_not_null"); // let not_null = ctx.builder.build_is_not_null(ptr, "unwrap_not_null");
ctx.make_assert( // ctx.make_assert(
generator, // generator,
not_null, // not_null,
"0:UnwrapNoneError", // "0:UnwrapNoneError",
"", // "",
[None, None, None], // [None, None, None],
expr.location, // expr.location,
); // );
return Ok(Some(ctx.builder.build_load(ptr, "unwrap_some").into())) // return Ok(Some(ctx.builder.build_load(ptr, "unwrap_some").into()))
} else { // } else {
unreachable!("option must be ptr") // unreachable!("option must be ptr")
} // }
} // }
return Ok(generator return Ok(generator
.gen_call( .gen_call(
ctx, ctx,

View File

@ -20,7 +20,7 @@ use inkwell::{
values::{BasicValueEnum, FunctionValue, PhiValue, PointerValue} values::{BasicValueEnum, FunctionValue, PhiValue, PointerValue}
}; };
use itertools::Itertools; use itertools::Itertools;
use nac3parser::ast::{Stmt, StrRef}; use nac3parser::ast::{Stmt, StrRef, Location};
use parking_lot::{Condvar, Mutex}; use parking_lot::{Condvar, Mutex};
use std::collections::{HashMap, HashSet}; use std::collections::{HashMap, HashSet};
use std::sync::{ use std::sync::{
@ -77,6 +77,7 @@ pub struct CodeGenContext<'ctx, 'a> {
pub outer_catch_clauses: pub outer_catch_clauses:
Option<(Vec<Option<BasicValueEnum<'ctx>>>, BasicBlock<'ctx>, PhiValue<'ctx>)>, Option<(Vec<Option<BasicValueEnum<'ctx>>>, BasicBlock<'ctx>, PhiValue<'ctx>)>,
pub need_sret: bool, pub need_sret: bool,
pub current_loc: Location,
} }
impl<'ctx, 'a> CodeGenContext<'ctx, 'a> { impl<'ctx, 'a> CodeGenContext<'ctx, 'a> {
@ -570,7 +571,8 @@ pub fn gen_func_impl<'ctx, G: CodeGenerator, F: FnOnce(&mut G, &mut CodeGenConte
module, module,
unifier, unifier,
static_value_store, static_value_store,
need_sret: has_sret need_sret: has_sret,
current_loc: Default::default(),
}; };
let result = codegen_function(generator, &mut code_gen_context); let result = codegen_function(generator, &mut code_gen_context);

View File

@ -422,8 +422,8 @@ pub fn final_proxy<'ctx, 'a>(
final_paths.push(block); final_paths.push(block);
} }
pub fn get_builtins<'ctx, 'a, G: CodeGenerator>( pub fn get_builtins<'ctx, 'a>(
generator: &mut G, generator: &mut dyn CodeGenerator,
ctx: &mut CodeGenContext<'ctx, 'a>, ctx: &mut CodeGenContext<'ctx, 'a>,
symbol: &str, symbol: &str,
) -> FunctionValue<'ctx> { ) -> FunctionValue<'ctx> {
@ -519,8 +519,8 @@ pub fn exn_constructor<'ctx, 'a>(
Ok(Some(zelf.into())) Ok(Some(zelf.into()))
} }
pub fn gen_raise<'ctx, 'a, G: CodeGenerator>( pub fn gen_raise<'ctx, 'a>(
generator: &mut G, generator: &mut dyn CodeGenerator,
ctx: &mut CodeGenContext<'ctx, 'a>, ctx: &mut CodeGenContext<'ctx, 'a>,
exception: Option<&BasicValueEnum<'ctx>>, exception: Option<&BasicValueEnum<'ctx>>,
loc: Location, loc: Location,
@ -931,6 +931,7 @@ pub fn gen_stmt<'ctx, 'a, G: CodeGenerator>(
ctx: &mut CodeGenContext<'ctx, 'a>, ctx: &mut CodeGenContext<'ctx, 'a>,
stmt: &Stmt<Option<Type>>, stmt: &Stmt<Option<Type>>,
) -> Result<(), String> { ) -> Result<(), String> {
ctx.current_loc = stmt.location;
match &stmt.node { match &stmt.node {
StmtKind::Pass { .. } => {} StmtKind::Pass { .. } => {}
StmtKind::Expr { value, .. } => { StmtKind::Expr { value, .. } => {

View File

@ -263,8 +263,21 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
instance_to_stmt: Default::default(), instance_to_stmt: Default::default(),
resolver: None, resolver: None,
codegen_callback: Some(Arc::new(GenCall::new(Box::new( codegen_callback: Some(Arc::new(GenCall::new(Box::new(
|_, _, _, _, _| { |ctx, obj, _, _, generator| {
unreachable!("handled in gen_expr") if let BasicValueEnum::PointerValue(ptr) = obj.unwrap().1.to_basic_value_enum(ctx, generator)? {
let not_null = ctx.builder.build_is_not_null(ptr, "unwrap_not_null");
ctx.make_assert(
generator,
not_null,
"0:UnwrapNoneError",
"",
[None, None, None],
ctx.current_loc,
);
Ok(Some(ctx.builder.build_load(ptr, "unwrap_some")))
} else {
unreachable!("option must be ptr")
}
}, },
)))), )))),
loc: None, loc: None,