forked from M-Labs/nac3
core: irrt error context mechanism
This commit is contained in:
parent
1f2bb80812
commit
51a099b602
84
nac3core/irrt/irrt/error_context.hpp
Normal file
84
nac3core/irrt/irrt/error_context.hpp
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <irrt/int_defs.hpp>
|
||||||
|
#include <irrt/utils.hpp>
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
// nac3core's "str" struct type definition
|
||||||
|
template <typename SizeT>
|
||||||
|
struct Str {
|
||||||
|
const char* content;
|
||||||
|
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(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
|
||||||
|
this->message_template = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
this->param3 = param3;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool has_error() {
|
||||||
|
return !cstr_utils::is_empty(message_template);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename SizeT>
|
||||||
|
void get_error_str(Str<SizeT> *dst_str) {
|
||||||
|
dst_str->content = message_template;
|
||||||
|
dst_str->length = (SizeT) cstr_utils::length(message_template);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
void __nac3_error_context_initialize(ErrorContext* errctx, ErrorIds* error_ids) {
|
||||||
|
errctx->initialize(error_ids);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool __nac3_error_context_has_no_error(ErrorContext* errctx) {
|
||||||
|
return !errctx->has_error();
|
||||||
|
}
|
||||||
|
|
||||||
|
void __nac3_error_context_get_error_str(ErrorContext* errctx, Str<int32_t> *dst_str) {
|
||||||
|
errctx->get_error_str<int32_t>(dst_str);
|
||||||
|
}
|
||||||
|
|
||||||
|
void __nac3_error_context_get_error_str64(ErrorContext* errctx, Str<int64_t> *dst_str) {
|
||||||
|
errctx->get_error_str<int64_t>(dst_str);
|
||||||
|
}
|
||||||
|
|
||||||
|
void __nac3_error_dummy_raise(ErrorContext* errctx) {
|
||||||
|
errctx->set_error(errctx->error_ids->runtime_error, "THROWN FROM __nac3_error_dummy_raise!!!!!!");
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <irrt/int_defs.hpp>
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
template <typename T>
|
template <typename T>
|
||||||
const T& max(const T& a, const T& b) {
|
const T& max(const T& a, const T& b) {
|
||||||
@ -18,4 +20,59 @@ bool arrays_match(int len, T* as, T* bs) {
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace cstr_utils {
|
||||||
|
bool is_empty(const char* str) {
|
||||||
|
return str[0] == '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
int8_t compare(const char* a, const char* b) {
|
||||||
|
uint32_t i = 0;
|
||||||
|
while (true) {
|
||||||
|
if (a[i] < b[i]) {
|
||||||
|
return -1;
|
||||||
|
} else if (a[i] > b[i]) {
|
||||||
|
return 1;
|
||||||
|
} else { // a[i] == b[i]
|
||||||
|
if (a[i] == '\0') {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int8_t equal(const char* a, const char* b) {
|
||||||
|
return compare(a, b) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t length(const char* str) {
|
||||||
|
uint32_t length = 0;
|
||||||
|
while (*str != '\0') {
|
||||||
|
length++;
|
||||||
|
str++;
|
||||||
|
}
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool copy(const char* src, char* dst, uint32_t dst_max_size) {
|
||||||
|
for (uint32_t i = 0; i < dst_max_size; i++) {
|
||||||
|
bool is_last = i + 1 == dst_max_size;
|
||||||
|
if (is_last && src[i] != '\0') {
|
||||||
|
dst[i] = '\0';
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (src[i] == '\0') {
|
||||||
|
dst[i] = '\0';
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
dst[i] = src[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
__builtin_unreachable();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@ -3,3 +3,4 @@
|
|||||||
#include <irrt/core.hpp>
|
#include <irrt/core.hpp>
|
||||||
#include <irrt/int_defs.hpp>
|
#include <irrt/int_defs.hpp>
|
||||||
#include <irrt/utils.hpp>
|
#include <irrt/utils.hpp>
|
||||||
|
#include <irrt/error_context.hpp>
|
@ -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_by_id(generator, error_id, msg, params, loc);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn raise_exn_by_id<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")
|
||||||
@ -652,6 +666,32 @@ impl<'ctx, 'a> CodeGenContext<'ctx, 'a> {
|
|||||||
self.raise_exn(generator, err_name, err_msg, params, loc);
|
self.raise_exn(generator, err_name, err_msg, params, loc);
|
||||||
self.builder.position_at_end(then_block);
|
self.builder.position_at_end(then_block);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn make_assert_impl_by_id<G: CodeGenerator + ?Sized>(
|
||||||
|
&mut self,
|
||||||
|
generator: &mut G,
|
||||||
|
cond: IntValue<'ctx>,
|
||||||
|
err_id: IntValue<'ctx>,
|
||||||
|
err_msg: BasicValueEnum<'ctx>,
|
||||||
|
params: [Option<IntValue<'ctx>>; 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`].
|
/// See [`CodeGenerator::gen_constructor`].
|
||||||
|
@ -1,13 +1,15 @@
|
|||||||
use crate::codegen::model::*;
|
use crate::codegen::{model::*, CodeGenContext, CodeGenerator};
|
||||||
|
|
||||||
|
use super::util::{get_sized_dependent_function_name, FunctionBuilder};
|
||||||
|
|
||||||
pub struct StrFields<'ctx> {
|
pub struct StrFields<'ctx> {
|
||||||
content: Field<PointerModel<FixedIntModel<Byte>>>,
|
pub content: Field<PointerModel<FixedIntModel<Byte>>>,
|
||||||
length: Field<IntModel<'ctx>>,
|
pub length: Field<IntModel<'ctx>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Str<'ctx> {
|
pub struct Str<'ctx> {
|
||||||
sizet: IntModel<'ctx>,
|
pub sizet: IntModel<'ctx>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'ctx> IsStruct<'ctx> for Str<'ctx> {
|
impl<'ctx> IsStruct<'ctx> for Str<'ctx> {
|
||||||
@ -27,10 +29,10 @@ impl<'ctx> IsStruct<'ctx> for Str<'ctx> {
|
|||||||
|
|
||||||
type ErrorId = Int32;
|
type ErrorId = Int32;
|
||||||
pub struct ErrorIdsFields {
|
pub struct ErrorIdsFields {
|
||||||
index_error: Field<FixedIntModel<ErrorId>>,
|
pub index_error: Field<FixedIntModel<ErrorId>>,
|
||||||
value_error: Field<FixedIntModel<ErrorId>>,
|
pub value_error: Field<FixedIntModel<ErrorId>>,
|
||||||
assertion_error: Field<FixedIntModel<ErrorId>>,
|
pub assertion_error: Field<FixedIntModel<ErrorId>>,
|
||||||
runtime_error: Field<FixedIntModel<ErrorId>>,
|
pub runtime_error: Field<FixedIntModel<ErrorId>>,
|
||||||
}
|
}
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct ErrorIds;
|
pub struct ErrorIds;
|
||||||
@ -53,11 +55,11 @@ impl<'ctx> IsStruct<'ctx> for ErrorIds {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct ErrorContextFields {
|
pub struct ErrorContextFields {
|
||||||
error_id: Field<FixedIntModel<ErrorId>>,
|
pub error_id: Field<FixedIntModel<ErrorId>>,
|
||||||
message_template: Field<PointerModel<FixedIntModel<Byte>>>,
|
pub message_template: Field<PointerModel<FixedIntModel<Byte>>>,
|
||||||
param1: Field<FixedIntModel<Int64>>,
|
pub param1: Field<FixedIntModel<Int64>>,
|
||||||
param2: Field<FixedIntModel<Int64>>,
|
pub param2: Field<FixedIntModel<Int64>>,
|
||||||
param3: Field<FixedIntModel<Int64>>,
|
pub param3: Field<FixedIntModel<Int64>>,
|
||||||
}
|
}
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct ErrorContext;
|
pub struct ErrorContext;
|
||||||
@ -79,3 +81,102 @@ impl<'ctx> IsStruct<'ctx> for ErrorContext {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Prepare ErrorIds
|
||||||
|
fn build_error_ids<'ctx>(ctx: &CodeGenContext<'ctx, '_>) -> Pointer<'ctx, StructModel<ErrorIds>> {
|
||||||
|
// ErrorIdsLens.get_fields(ctx.ctx).assertion_error.
|
||||||
|
let error_ids = StructModel(ErrorIds).alloca(ctx, "error_ids");
|
||||||
|
let i32_model = FixedIntModel(Int32);
|
||||||
|
// i32_model.make_constant()
|
||||||
|
|
||||||
|
let get_string_id =
|
||||||
|
|string_id| i32_model.constant(ctx.ctx, ctx.resolver.get_string_id(string_id) as u64);
|
||||||
|
|
||||||
|
error_ids.gep(ctx, |f| f.index_error).store(ctx, &get_string_id("0:IndexError"));
|
||||||
|
error_ids.gep(ctx, |f| f.value_error).store(ctx, &get_string_id("0:ValueError"));
|
||||||
|
error_ids.gep(ctx, |f| f.assertion_error).store(ctx, &get_string_id("0:AssertionError"));
|
||||||
|
error_ids.gep(ctx, |f| f.runtime_error).store(ctx, &get_string_id("0:RuntimeError"));
|
||||||
|
|
||||||
|
error_ids
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn call_nac3_error_context_initialize<'ctx>(
|
||||||
|
ctx: &CodeGenContext<'ctx, '_>,
|
||||||
|
perrctx: &Pointer<'ctx, StructModel<ErrorContext>>,
|
||||||
|
perror_ids: &Pointer<'ctx, StructModel<ErrorIds>>,
|
||||||
|
) {
|
||||||
|
FunctionBuilder::begin(ctx, "__nac3_error_context_initialize")
|
||||||
|
.arg("errctx", &PointerModel(StructModel(ErrorContext)), perrctx)
|
||||||
|
.arg("error_ids", &PointerModel(StructModel(ErrorIds)), perror_ids)
|
||||||
|
.returning_void();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn call_nac3_error_context_has_no_error<'ctx>(
|
||||||
|
ctx: &CodeGenContext<'ctx, '_>,
|
||||||
|
errctx: &Pointer<'ctx, StructModel<ErrorContext>>,
|
||||||
|
) -> FixedInt<'ctx, Bool> {
|
||||||
|
FunctionBuilder::begin(ctx, "__nac3_error_context_has_no_error")
|
||||||
|
.arg("errctx", &PointerModel(StructModel(ErrorContext)), errctx)
|
||||||
|
.returning("has_error", &FixedIntModel(Bool))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn call_nac3_error_context_get_error_str<'ctx>(
|
||||||
|
sizet: IntModel<'ctx>,
|
||||||
|
ctx: &CodeGenContext<'ctx, '_>,
|
||||||
|
errctx: &Pointer<'ctx, StructModel<ErrorContext>>,
|
||||||
|
dst_str: &Pointer<'ctx, StructModel<Str<'ctx>>>,
|
||||||
|
) {
|
||||||
|
FunctionBuilder::begin(
|
||||||
|
ctx,
|
||||||
|
&get_sized_dependent_function_name(sizet, "__nac3_error_context_get_error_str"),
|
||||||
|
)
|
||||||
|
.arg("errctx", &PointerModel(StructModel(ErrorContext)), errctx)
|
||||||
|
.arg("dst_str", &PointerModel(StructModel(Str { sizet })), dst_str)
|
||||||
|
.returning_void();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn prepare_error_context<'ctx>(
|
||||||
|
ctx: &CodeGenContext<'ctx, '_>,
|
||||||
|
) -> Pointer<'ctx, StructModel<ErrorContext>> {
|
||||||
|
let error_ids = build_error_ids(ctx);
|
||||||
|
let errctx_ptr = StructModel(ErrorContext).alloca(ctx, "errctx");
|
||||||
|
call_nac3_error_context_initialize(ctx, &errctx_ptr, &error_ids);
|
||||||
|
errctx_ptr
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn check_error_context<'ctx, G: CodeGenerator + ?Sized>(
|
||||||
|
generator: &mut G,
|
||||||
|
ctx: &mut CodeGenContext<'ctx, '_>,
|
||||||
|
errctx_ptr: &Pointer<'ctx, StructModel<ErrorContext>>,
|
||||||
|
) {
|
||||||
|
let sizet = IntModel(generator.get_size_type(ctx.ctx));
|
||||||
|
|
||||||
|
let has_error = call_nac3_error_context_has_no_error(ctx, errctx_ptr);
|
||||||
|
let pstr = StructModel(Str { sizet }).alloca(ctx, "error_str");
|
||||||
|
call_nac3_error_context_get_error_str(sizet, ctx, errctx_ptr, &pstr);
|
||||||
|
|
||||||
|
let error_id = errctx_ptr.gep(ctx, |f| f.error_id).load(ctx, "error_id");
|
||||||
|
let error_str = pstr.load(ctx, "error_str");
|
||||||
|
let param1 = errctx_ptr.gep(ctx, |f| f.param1).load(ctx, "param1");
|
||||||
|
let param2 = errctx_ptr.gep(ctx, |f| f.param2).load(ctx, "param2");
|
||||||
|
let param3 = errctx_ptr.gep(ctx, |f| f.param3).load(ctx, "param3");
|
||||||
|
ctx.make_assert_impl_by_id(
|
||||||
|
generator,
|
||||||
|
has_error.value,
|
||||||
|
error_id.value,
|
||||||
|
error_str.get_llvm_value(),
|
||||||
|
[Some(param1.value), Some(param2.value), Some(param3.value)],
|
||||||
|
ctx.current_loc,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn call_nac3_dummy_raise<G: CodeGenerator + ?Sized>(
|
||||||
|
generator: &mut G,
|
||||||
|
ctx: &mut CodeGenContext,
|
||||||
|
) {
|
||||||
|
let errctx = prepare_error_context(ctx);
|
||||||
|
FunctionBuilder::begin(ctx, "__nac3_error_dummy_raise")
|
||||||
|
.arg("errctx", &PointerModel(StructModel(ErrorContext)), &errctx)
|
||||||
|
.returning_void();
|
||||||
|
check_error_context(generator, ctx, &errctx);
|
||||||
|
}
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
use crate::typecheck::typedef::Type;
|
use crate::typecheck::typedef::Type;
|
||||||
|
|
||||||
|
pub mod error_context;
|
||||||
mod test;
|
mod test;
|
||||||
|
mod util;
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
classes::{
|
classes::{
|
||||||
|
@ -17,9 +17,9 @@ fn get_size_variant(ty: IntType) -> SizeVariant {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn get_sized_dependent_function_name(ty: IntType, fn_name: &str) -> String {
|
pub fn get_sized_dependent_function_name(ty: IntModel, fn_name: &str) -> String {
|
||||||
let mut fn_name = fn_name.to_owned();
|
let mut fn_name = fn_name.to_owned();
|
||||||
match get_size_variant(ty) {
|
match get_size_variant(ty.0) {
|
||||||
SizeVariant::Bits32 => {
|
SizeVariant::Bits32 => {
|
||||||
// Do nothing, `fn_name` already has the correct name
|
// Do nothing, `fn_name` already has the correct name
|
||||||
}
|
}
|
||||||
@ -51,7 +51,7 @@ impl<'ctx, 'a> FunctionBuilder<'ctx, 'a> {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn returning<M: Model<'ctx>>(self, name: &'static str, return_model: &M) -> S::MemoryValue {
|
pub fn returning<M: Model<'ctx>>(self, name: &'static str, return_model: &M) -> M::Value {
|
||||||
let (param_tys, param_vals): (Vec<_>, Vec<_>) = self.arguments.into_iter().unzip();
|
let (param_tys, param_vals): (Vec<_>, Vec<_>) = self.arguments.into_iter().unzip();
|
||||||
|
|
||||||
let function = self.ctx.module.get_function(self.fn_name).unwrap_or_else(|| {
|
let function = self.ctx.module.get_function(self.fn_name).unwrap_or_else(|| {
|
||||||
|
@ -23,7 +23,9 @@ use inkwell::{
|
|||||||
values::{BasicValueEnum, FunctionValue, IntValue, PhiValue, PointerValue},
|
values::{BasicValueEnum, FunctionValue, IntValue, PhiValue, PointerValue},
|
||||||
AddressSpace, IntPredicate, OptimizationLevel,
|
AddressSpace, IntPredicate, OptimizationLevel,
|
||||||
};
|
};
|
||||||
|
use irrt::error_context::Str;
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
|
use model::{IntModel, Model, StructModel};
|
||||||
use nac3parser::ast::{Location, Stmt, StrRef};
|
use nac3parser::ast::{Location, Stmt, StrRef};
|
||||||
use parking_lot::{Condvar, Mutex};
|
use parking_lot::{Condvar, Mutex};
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{HashMap, HashSet};
|
||||||
@ -647,7 +649,7 @@ pub fn gen_func_impl<
|
|||||||
..primitives
|
..primitives
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut type_cache: HashMap<_, _> = [
|
let mut type_cache: HashMap<_, BasicTypeEnum<'_>> = [
|
||||||
(primitives.int32, context.i32_type().into()),
|
(primitives.int32, context.i32_type().into()),
|
||||||
(primitives.int64, context.i64_type().into()),
|
(primitives.int64, context.i64_type().into()),
|
||||||
(primitives.uint32, context.i32_type().into()),
|
(primitives.uint32, context.i32_type().into()),
|
||||||
@ -655,19 +657,8 @@ pub fn gen_func_impl<
|
|||||||
(primitives.float, context.f64_type().into()),
|
(primitives.float, context.f64_type().into()),
|
||||||
(primitives.bool, context.i8_type().into()),
|
(primitives.bool, context.i8_type().into()),
|
||||||
(primitives.str, {
|
(primitives.str, {
|
||||||
let name = "str";
|
let sizet = IntModel(generator.get_size_type(context));
|
||||||
match module.get_struct_type(name) {
|
StructModel(Str { sizet }).get_llvm_type(context)
|
||||||
None => {
|
|
||||||
let str_type = context.opaque_struct_type("str");
|
|
||||||
let fields = [
|
|
||||||
context.i8_type().ptr_type(AddressSpace::default()).into(),
|
|
||||||
generator.get_size_type(context).into(),
|
|
||||||
];
|
|
||||||
str_type.set_body(&fields, false);
|
|
||||||
str_type.into()
|
|
||||||
}
|
|
||||||
Some(t) => t.as_basic_type_enum(),
|
|
||||||
}
|
|
||||||
}),
|
}),
|
||||||
(primitives.range, RangeType::new(context).as_base_type().into()),
|
(primitives.range, RangeType::new(context).as_base_type().into()),
|
||||||
(primitives.exception, {
|
(primitives.exception, {
|
||||||
@ -675,10 +666,12 @@ pub fn gen_func_impl<
|
|||||||
if let Some(t) = module.get_struct_type(name) {
|
if let Some(t) = module.get_struct_type(name) {
|
||||||
t.ptr_type(AddressSpace::default()).as_basic_type_enum()
|
t.ptr_type(AddressSpace::default()).as_basic_type_enum()
|
||||||
} else {
|
} else {
|
||||||
|
let sizet = IntModel(generator.get_size_type(context));
|
||||||
|
let str_ty = StructModel(Str { sizet }).get_llvm_type(context);
|
||||||
|
|
||||||
let exception = context.opaque_struct_type("Exception");
|
let exception = context.opaque_struct_type("Exception");
|
||||||
let int32 = context.i32_type().into();
|
let int32 = context.i32_type().into();
|
||||||
let int64 = context.i64_type().into();
|
let int64 = context.i64_type().into();
|
||||||
let str_ty = module.get_struct_type("str").unwrap().as_basic_type_enum();
|
|
||||||
let fields = [int32, str_ty, int32, int32, str_ty, str_ty, int64, int64, int64];
|
let fields = [int32, str_ty, int32, int32, str_ty, str_ty, int64, int64, int64];
|
||||||
exception.set_body(&fields, false);
|
exception.set_body(&fields, false);
|
||||||
exception.ptr_type(AddressSpace::default()).as_basic_type_enum()
|
exception.ptr_type(AddressSpace::default()).as_basic_type_enum()
|
||||||
|
@ -9,7 +9,7 @@ use crate::{
|
|||||||
irrt::{
|
irrt::{
|
||||||
calculate_len_for_slice_range, call_ndarray_calc_broadcast,
|
calculate_len_for_slice_range, call_ndarray_calc_broadcast,
|
||||||
call_ndarray_calc_broadcast_index, call_ndarray_calc_nd_indices,
|
call_ndarray_calc_broadcast_index, call_ndarray_calc_nd_indices,
|
||||||
call_ndarray_calc_size,
|
call_ndarray_calc_size, error_context::call_nac3_dummy_raise,
|
||||||
},
|
},
|
||||||
llvm_intrinsics::{self, call_memcpy_generic},
|
llvm_intrinsics::{self, call_memcpy_generic},
|
||||||
stmt::{gen_for_callback_incrementing, gen_for_range_callback, gen_if_else_expr_callback},
|
stmt::{gen_for_callback_incrementing, gen_for_range_callback, gen_if_else_expr_callback},
|
||||||
@ -538,6 +538,8 @@ fn call_ndarray_zeros_impl<'ctx, G: CodeGenerator + ?Sized>(
|
|||||||
elem_ty: Type,
|
elem_ty: Type,
|
||||||
shape: BasicValueEnum<'ctx>,
|
shape: BasicValueEnum<'ctx>,
|
||||||
) -> Result<NDArrayValue<'ctx>, String> {
|
) -> Result<NDArrayValue<'ctx>, String> {
|
||||||
|
call_nac3_dummy_raise(generator, ctx);
|
||||||
|
|
||||||
let supported_types = [
|
let supported_types = [
|
||||||
ctx.primitives.int32,
|
ctx.primitives.int32,
|
||||||
ctx.primitives.int64,
|
ctx.primitives.int64,
|
||||||
|
Loading…
Reference in New Issue
Block a user