forked from M-Labs/nac3
core: pass resolver error ids to irrt
This commit is contained in:
parent
8863cd64a9
commit
2f7e75d7cf
|
@ -11,22 +11,38 @@ struct Str {
|
||||||
SizeT length;
|
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 {
|
struct ErrorContext {
|
||||||
|
// Context
|
||||||
|
ErrorIds* error_ids;
|
||||||
|
|
||||||
|
// Error thrown by IRRT
|
||||||
|
ErrorId error_id;
|
||||||
const char* message_template; // MUST BE `&'static`
|
const char* message_template; // MUST BE `&'static`
|
||||||
uint64_t param1;
|
uint64_t param1;
|
||||||
uint64_t param2;
|
uint64_t param2;
|
||||||
uint64_t param3;
|
uint64_t param3;
|
||||||
|
|
||||||
void initialize() {
|
void initialize(ErrorIds* error_ids) {
|
||||||
|
this->error_ids = error_ids;
|
||||||
clear_error();
|
clear_error();
|
||||||
}
|
}
|
||||||
|
|
||||||
void clear_error() {
|
void clear_error() {
|
||||||
// Point the message_template to an empty str. Don't set it to nullptr as a sentinel
|
// 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->message_template = message;
|
||||||
this->param1 = param1;
|
this->param1 = param1;
|
||||||
this->param2 = param2;
|
this->param2 = param2;
|
||||||
|
@ -47,8 +63,8 @@ struct ErrorContext {
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
||||||
void __nac3_error_context_initialize(ErrorContext* errctx) {
|
void __nac3_error_context_initialize(ErrorContext* errctx, ErrorIds* error_ids) {
|
||||||
errctx->initialize();
|
errctx->initialize(error_ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t __nac3_error_context_has_no_error(ErrorContext* errctx) {
|
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) {
|
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!!!!!!");
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -576,6 +576,21 @@ impl<'ctx, 'a> CodeGenContext<'ctx, 'a> {
|
||||||
params: [Option<IntValue<'ctx>>; 3],
|
params: [Option<IntValue<'ctx>>; 3],
|
||||||
loc: Location,
|
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 {
|
let zelf = if let Some(exception_val) = self.exception_val {
|
||||||
exception_val
|
exception_val
|
||||||
} else {
|
} else {
|
||||||
|
@ -588,8 +603,7 @@ impl<'ctx, 'a> CodeGenContext<'ctx, 'a> {
|
||||||
let zero = int32.const_zero();
|
let zero = int32.const_zero();
|
||||||
unsafe {
|
unsafe {
|
||||||
let id_ptr = self.builder.build_in_bounds_gep(zelf, &[zero, zero], "exn.id").unwrap();
|
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, error_id).unwrap();
|
||||||
self.builder.build_store(id_ptr, int32.const_int(id as u64, false)).unwrap();
|
|
||||||
let ptr = self
|
let ptr = self
|
||||||
.builder
|
.builder
|
||||||
.build_in_bounds_gep(zelf, &[zero, int32.const_int(5, false)], "exn.msg")
|
.build_in_bounds_gep(zelf, &[zero, int32.const_int(5, false)], "exn.msg")
|
||||||
|
|
|
@ -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 struct ErrorContextFields<'ctx> {
|
||||||
|
pub error_ids: GepGetter<AddressLens<ErrorIdsLens>>,
|
||||||
pub message_template: GepGetter<AddressLens<IntLens<'ctx>>>,
|
pub message_template: GepGetter<AddressLens<IntLens<'ctx>>>,
|
||||||
pub param1: GepGetter<IntLens<'ctx>>,
|
pub param1: GepGetter<IntLens<'ctx>>,
|
||||||
pub param2: 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>,
|
builder: &mut crate::codegen::optics::FieldBuilder<'ctx>,
|
||||||
) -> Self::Fields {
|
) -> Self::Fields {
|
||||||
ErrorContextFields {
|
ErrorContextFields {
|
||||||
|
error_ids: builder.add_field("error_ids", AddressLens(ErrorIdsLens)),
|
||||||
message_template: builder
|
message_template: builder
|
||||||
.add_field("message_template", AddressLens(IntLens(builder.ctx.i8_type()))),
|
.add_field("message_template", AddressLens(IntLens(builder.ctx.i8_type()))),
|
||||||
param1: builder.add_field("param1", IntLens(builder.ctx.i64_type())),
|
param1: builder.add_field("param1", IntLens(builder.ctx.i64_type())),
|
||||||
|
|
|
@ -3,15 +3,13 @@ use inkwell::{
|
||||||
values::{AnyValue, BasicMetadataValueEnum, IntValue},
|
values::{AnyValue, BasicMetadataValueEnum, IntValue},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::codegen::{
|
||||||
codegen::{
|
optics::{Address, AddressLens, IntLens, Optic, OpticValue, Prism},
|
||||||
optics::{Address, AddressLens, IntLens, Optic, OpticValue, Prism},
|
CodeGenContext, CodeGenerator,
|
||||||
CodeGenContext, CodeGenerator,
|
|
||||||
},
|
|
||||||
util::SizeVariant,
|
|
||||||
};
|
};
|
||||||
|
use crate::util::SizeVariant;
|
||||||
|
|
||||||
use super::classes::{ErrorContextLens, StrLens};
|
use super::classes::{ErrorContextLens, ErrorIdsLens, StrLens};
|
||||||
|
|
||||||
fn get_size_variant(ty: IntType) -> SizeVariant {
|
fn get_size_variant(ty: IntType) -> SizeVariant {
|
||||||
match ty.get_bit_width() {
|
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>(
|
pub fn call_nac3_error_context_initialize<'ctx>(
|
||||||
ctx: &CodeGenContext<'ctx, '_>,
|
ctx: &CodeGenContext<'ctx, '_>,
|
||||||
errctx: &Address<'ctx, ErrorContextLens>,
|
errctx: &Address<'ctx, ErrorContextLens>,
|
||||||
|
error_ids: &Address<'ctx, ErrorIdsLens>,
|
||||||
) {
|
) {
|
||||||
FunctionBuilder::begin(ctx, "__nac3_error_context_initialize")
|
FunctionBuilder::begin(ctx, "__nac3_error_context_initialize")
|
||||||
.arg("errctx", &AddressLens(ErrorContextLens), errctx)
|
.arg("errctx", &AddressLens(ErrorContextLens), errctx)
|
||||||
|
.arg("error_ids", &AddressLens(ErrorIdsLens), error_ids)
|
||||||
.returning_void();
|
.returning_void();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,9 +150,10 @@ pub fn test_dummy_raise<G: CodeGenerator + ?Sized>(
|
||||||
) {
|
) {
|
||||||
let size_type = generator.get_size_type(ctx.ctx);
|
let size_type = generator.get_size_type(ctx.ctx);
|
||||||
|
|
||||||
|
let error_ids = build_error_ids(ctx);
|
||||||
let errctx_ptr = ErrorContextLens.alloca(ctx, "errctx");
|
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);
|
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);
|
||||||
|
|
|
@ -172,7 +172,7 @@ impl<'ctx, AddresseeOptic: MemoryGetter<'ctx>> Address<'ctx, AddresseeOptic> {
|
||||||
|
|
||||||
// To make [`Address`] convenient to use
|
// To make [`Address`] convenient to use
|
||||||
impl<'ctx, AddresseeOptic: MemorySetter<'ctx>> Address<'ctx, AddresseeOptic> {
|
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);
|
self.addressee_optic.set(ctx, self.address, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue