diff --git a/nac3core/irrt/irrt_test.cpp b/nac3core/irrt/irrt_test.cpp index afc5be43..4d9c6181 100644 --- a/nac3core/irrt/irrt_test.cpp +++ b/nac3core/irrt/irrt_test.cpp @@ -13,7 +13,6 @@ int main() { run_test_core(); - run_test_print(); run_test_utils(); return 0; } \ No newline at end of file diff --git a/nac3core/src/codegen/expr.rs b/nac3core/src/codegen/expr.rs index c9f96385..c720470a 100644 --- a/nac3core/src/codegen/expr.rs +++ b/nac3core/src/codegen/expr.rs @@ -578,10 +578,10 @@ impl<'ctx, 'a> CodeGenContext<'ctx, 'a> { ) { let error_id = self.resolver.get_string_id(name); let error_id = self.ctx.i32_type().const_int(error_id as u64, false); - self.raise_exn_impl(generator, error_id, msg, params, loc); + self.raise_exn_by_id(generator, error_id, msg, params, loc); } - pub fn raise_exn_impl( + pub fn raise_exn_by_id( &mut self, generator: &mut G, error_id: IntValue<'ctx>, @@ -666,6 +666,32 @@ impl<'ctx, 'a> CodeGenContext<'ctx, 'a> { self.raise_exn(generator, err_name, err_msg, params, loc); self.builder.position_at_end(then_block); } + + pub fn make_assert_impl_by_id( + &mut self, + generator: &mut G, + cond: IntValue<'ctx>, + err_id: IntValue<'ctx>, + err_msg: BasicValueEnum<'ctx>, + params: [Option>; 3], + loc: Location, + ) { + let i1 = self.ctx.bool_type(); + let i1_true = i1.const_all_ones(); + // we assume that the condition is most probably true, so the normal path is the most + // probable path + // even if this assumption is violated, it does not matter as exception unwinding is + // slow anyway... + let cond = call_expect(self, cond, i1_true, Some("expect")); + let current_bb = self.builder.get_insert_block().unwrap(); + let current_fun = current_bb.get_parent().unwrap(); + let then_block = self.ctx.insert_basic_block_after(current_bb, "succ"); + let exn_block = self.ctx.append_basic_block(current_fun, "fail"); + self.builder.build_conditional_branch(cond, then_block, exn_block).unwrap(); + self.builder.position_at_end(exn_block); + self.raise_exn_by_id(generator, err_id, err_msg, params, loc); + self.builder.position_at_end(then_block); + } } /// See [`CodeGenerator::gen_constructor`]. diff --git a/nac3core/src/codegen/irrt/classes.rs b/nac3core/src/codegen/irrt/classes.rs index c1b12c6e..3b10e6f2 100644 --- a/nac3core/src/codegen/irrt/classes.rs +++ b/nac3core/src/codegen/irrt/classes.rs @@ -123,6 +123,7 @@ impl<'ctx> StructureOptic<'ctx> for ErrorIdsLens { pub struct ErrorContextFields<'ctx> { pub error_ids: GepGetter>, + pub error_id: GepGetter>, pub message_template: GepGetter>>, pub param1: GepGetter>, pub param2: GepGetter>, @@ -145,6 +146,7 @@ impl<'ctx> StructureOptic<'ctx> for ErrorContextLens { ) -> 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())), diff --git a/nac3core/src/codegen/irrt/new.rs b/nac3core/src/codegen/irrt/new.rs index 0dc78c62..4c7edb95 100644 --- a/nac3core/src/codegen/irrt/new.rs +++ b/nac3core/src/codegen/irrt/new.rs @@ -135,41 +135,48 @@ pub fn call_nac3_error_context_get_error_str<'ctx>( .returning("has_error", &IntLens(ctx.ctx.bool_type())) } -pub fn call_nac3_dummy_raise<'ctx>( +pub fn prepare_error_context<'ctx>( ctx: &CodeGenContext<'ctx, '_>, - errctx: &Address<'ctx, ErrorContextLens>, -) { - FunctionBuilder::begin(ctx, "__nac3_error_dummy_raise") - .arg("errctx", &AddressLens(ErrorContextLens), errctx) - .returning_void(); +) -> Address<'ctx, ErrorContextLens> { + let error_ids = build_error_ids(ctx); + let errctx_ptr = ErrorContextLens.alloca(ctx, "errctx"); + call_nac3_error_context_initialize(ctx, &errctx_ptr, &error_ids); + errctx_ptr } -pub fn test_dummy_raise( +pub fn check_error_context<'ctx, G: CodeGenerator + ?Sized>( generator: &mut G, - ctx: &mut CodeGenContext<'_, '_>, + ctx: &mut CodeGenContext<'ctx, '_>, + errctx_ptr: &Address<'ctx, ErrorContextLens>, ) { let size_type = generator.get_size_type(ctx.ctx); - let error_ids = build_error_ids(ctx); - let errctx_ptr = ErrorContextLens.alloca(ctx, "errctx"); - - call_nac3_error_context_initialize(ctx, &errctx_ptr, &error_ids); - call_nac3_dummy_raise(ctx, &errctx_ptr); - - let has_error = call_nac3_error_context_has_no_error(ctx, &errctx_ptr); + let has_error = call_nac3_error_context_has_no_error(ctx, errctx_ptr); let error_str_ptr = StrLens { size_type }.alloca(ctx, "error_str"); - call_nac3_error_context_get_error_str(size_type, ctx, &errctx_ptr, &error_str_ptr); + call_nac3_error_context_get_error_str(size_type, ctx, errctx_ptr, &error_str_ptr); + let error_id = errctx_ptr.view(ctx, |fields| &fields.error_id).load(ctx, "error_id"); let error_str = error_str_ptr.load(ctx, "error_str"); let param1 = errctx_ptr.view(ctx, |fields| &fields.param1).load(ctx, "param1"); let param2 = errctx_ptr.view(ctx, |fields| &fields.param2).load(ctx, "param2"); let param3 = errctx_ptr.view(ctx, |fields| &fields.param3).load(ctx, "param3"); - ctx.make_assert_impl( + ctx.make_assert_impl_by_id( generator, has_error, - "0:RuntimeError", // TODO: Make this dynamic (within IRRT), but this is probably not trivial + error_id, error_str.get_llvm_value(), [Some(param1), Some(param2), Some(param3)], ctx.current_loc, ); } + +pub fn call_nac3_dummy_raise( + generator: &mut G, + ctx: &mut CodeGenContext, +) { + let errctx = prepare_error_context(ctx); + FunctionBuilder::begin(ctx, "__nac3_error_dummy_raise") + .arg("errctx", &AddressLens(ErrorContextLens), &errctx) + .returning_void(); + check_error_context(generator, ctx, &errctx); +}