1
0
forked from M-Labs/nac3

core: pass resolver error ids to irrt

This commit is contained in:
lyken 2024-07-14 01:39:06 +08:00
parent 8863cd64a9
commit 2f7e75d7cf
5 changed files with 98 additions and 17 deletions

View File

@ -11,22 +11,38 @@ struct Str {
SizeT length;
};
// A limited set of errors IRRT could use.
typedef uint32_t ErrorId;
struct ErrorIds {
ErrorId index_error;
ErrorId value_error;
ErrorId assertion_error;
ErrorId runtime_error;
};
struct ErrorContext {
// Context
ErrorIds* error_ids;
// Error thrown by IRRT
ErrorId error_id;
const char* message_template; // MUST BE `&'static`
uint64_t param1;
uint64_t param2;
uint64_t param3;
void initialize() {
void initialize(ErrorIds* error_ids) {
this->error_ids = error_ids;
clear_error();
}
void clear_error() {
// Point the message_template to an empty str. Don't set it to nullptr as a sentinel
set_error("");
this->message_template = "";
}
void set_error(const char* message, uint64_t param1 = 0, uint64_t param2 = 0, uint64_t param3 = 0) {
void set_error(ErrorId error_id, const char* message, uint64_t param1 = 0, uint64_t param2 = 0, uint64_t param3 = 0) {
this->error_id = error_id;
this->message_template = message;
this->param1 = param1;
this->param2 = param2;
@ -47,8 +63,8 @@ struct ErrorContext {
extern "C" {
void __nac3_error_context_initialize(ErrorContext* errctx) {
errctx->initialize();
void __nac3_error_context_initialize(ErrorContext* errctx, ErrorIds* error_ids) {
errctx->initialize(error_ids);
}
uint8_t __nac3_error_context_has_no_error(ErrorContext* errctx) {
@ -64,6 +80,6 @@ void __nac3_error_context_get_error_str64(ErrorContext* errctx, Str<int64_t> *ds
}
void __nac3_error_dummy_raise(ErrorContext* errctx) {
errctx->set_error("THROWN FROM __nac3_error_dummy_raise!!!!!!");
errctx->set_error(errctx->error_ids->runtime_error, "THROWN FROM __nac3_error_dummy_raise!!!!!!");
}
}

View File

@ -576,6 +576,21 @@ impl<'ctx, 'a> CodeGenContext<'ctx, 'a> {
params: [Option<IntValue<'ctx>>; 3],
loc: Location,
) {
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);
}
pub fn raise_exn_impl<G: CodeGenerator + ?Sized>(
&mut self,
generator: &mut G,
error_id: IntValue<'ctx>,
msg: BasicValueEnum<'ctx>,
params: [Option<IntValue<'ctx>>; 3],
loc: Location,
) {
assert_eq!(error_id.get_type().get_bit_width(), 32);
let zelf = if let Some(exception_val) = self.exception_val {
exception_val
} else {
@ -588,8 +603,7 @@ impl<'ctx, 'a> CodeGenContext<'ctx, 'a> {
let zero = int32.const_zero();
unsafe {
let id_ptr = self.builder.build_in_bounds_gep(zelf, &[zero, zero], "exn.id").unwrap();
let id = self.resolver.get_string_id(name);
self.builder.build_store(id_ptr, int32.const_int(id as u64, false)).unwrap();
self.builder.build_store(id_ptr, error_id).unwrap();
let ptr = self
.builder
.build_in_bounds_gep(zelf, &[zero, int32.const_int(5, false)], "exn.msg")

View File

@ -93,7 +93,36 @@ impl<'ctx> StructureOptic<'ctx> for IrrtStringLens {
}
}
pub struct ErrorIdsFields<'ctx> {
pub index_error: GepGetter<IntLens<'ctx>>,
pub value_error: GepGetter<IntLens<'ctx>>,
pub assertion_error: GepGetter<IntLens<'ctx>>,
pub runtime_error: GepGetter<IntLens<'ctx>>,
}
#[derive(Debug, Clone)]
pub struct ErrorIdsLens;
impl<'ctx> StructureOptic<'ctx> for ErrorIdsLens {
type Fields = ErrorIdsFields<'ctx>;
fn struct_name(&self) -> &'static str {
"ErrorIds"
}
fn build_fields(&self, builder: &mut FieldBuilder<'ctx>) -> Self::Fields {
let i32_lens = IntLens(builder.ctx.i32_type());
ErrorIdsFields {
index_error: builder.add_field("index_error", i32_lens),
value_error: builder.add_field("value_error", i32_lens),
assertion_error: builder.add_field("assertion_error", i32_lens),
runtime_error: builder.add_field("runtime_error", i32_lens),
}
}
}
pub struct ErrorContextFields<'ctx> {
pub error_ids: GepGetter<AddressLens<ErrorIdsLens>>,
pub message_template: GepGetter<AddressLens<IntLens<'ctx>>>,
pub param1: GepGetter<IntLens<'ctx>>,
pub param2: GepGetter<IntLens<'ctx>>,
@ -115,6 +144,7 @@ impl<'ctx> StructureOptic<'ctx> for ErrorContextLens {
builder: &mut crate::codegen::optics::FieldBuilder<'ctx>,
) -> Self::Fields {
ErrorContextFields {
error_ids: builder.add_field("error_ids", AddressLens(ErrorIdsLens)),
message_template: builder
.add_field("message_template", AddressLens(IntLens(builder.ctx.i8_type()))),
param1: builder.add_field("param1", IntLens(builder.ctx.i64_type())),

View File

@ -3,15 +3,13 @@ use inkwell::{
values::{AnyValue, BasicMetadataValueEnum, IntValue},
};
use crate::{
codegen::{
optics::{Address, AddressLens, IntLens, Optic, OpticValue, Prism},
CodeGenContext, CodeGenerator,
},
util::SizeVariant,
use crate::codegen::{
optics::{Address, AddressLens, IntLens, Optic, OpticValue, Prism},
CodeGenContext, CodeGenerator,
};
use crate::util::SizeVariant;
use super::classes::{ErrorContextLens, StrLens};
use super::classes::{ErrorContextLens, ErrorIdsLens, StrLens};
fn get_size_variant(ty: IntType) -> SizeVariant {
match ty.get_bit_width() {
@ -82,12 +80,34 @@ impl<'ctx, 'a> FunctionBuilder<'ctx, 'a> {
}
}
fn build_error_ids<'ctx>(ctx: &CodeGenContext<'ctx, '_>) -> Address<'ctx, ErrorIdsLens> {
// ErrorIdsLens.get_fields(ctx.ctx).assertion_error.
let error_ids = ErrorIdsLens.alloca(ctx, "error_ids");
let llvm_i32 = ctx.ctx.i32_type();
let get_string_id =
|string_id| llvm_i32.const_int(ctx.resolver.get_string_id(string_id) as u64, false);
error_ids.view(ctx, |fields| &fields.index_error).store(ctx, &get_string_id("0:IndexError"));
error_ids.view(ctx, |fields| &fields.value_error).store(ctx, &get_string_id("0:ValueError"));
error_ids
.view(ctx, |fields| &fields.assertion_error)
.store(ctx, &get_string_id("0:AssertionError"));
error_ids
.view(ctx, |fields| &fields.runtime_error)
.store(ctx, &get_string_id("0:RuntimeError"));
error_ids
}
pub fn call_nac3_error_context_initialize<'ctx>(
ctx: &CodeGenContext<'ctx, '_>,
errctx: &Address<'ctx, ErrorContextLens>,
error_ids: &Address<'ctx, ErrorIdsLens>,
) {
FunctionBuilder::begin(ctx, "__nac3_error_context_initialize")
.arg("errctx", &AddressLens(ErrorContextLens), errctx)
.arg("error_ids", &AddressLens(ErrorIdsLens), error_ids)
.returning_void();
}
@ -130,9 +150,10 @@ pub fn test_dummy_raise<G: CodeGenerator + ?Sized>(
) {
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);
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);

View File

@ -172,7 +172,7 @@ impl<'ctx, AddresseeOptic: MemoryGetter<'ctx>> Address<'ctx, AddresseeOptic> {
// To make [`Address`] convenient to use
impl<'ctx, AddresseeOptic: MemorySetter<'ctx>> Address<'ctx, AddresseeOptic> {
pub fn set(&self, ctx: &CodeGenContext<'ctx, '_>, value: &AddresseeOptic::Value) {
pub fn store(&self, ctx: &CodeGenContext<'ctx, '_>, value: &AddresseeOptic::Value) {
self.addressee_optic.set(ctx, self.address, value);
}
}