Implement unreachable
This commit is contained in:
parent
8b1013b3e7
commit
832baa7137
@ -81,13 +81,13 @@ os_reserve = fn (base: u64, size: u64, protection: OS_ProtectionFlags, map: OS_M
|
|||||||
>protection_flags = os_linux_protection_flags(protection);
|
>protection_flags = os_linux_protection_flags(protection);
|
||||||
>map_flags = os_linux_map_flags(map);
|
>map_flags = os_linux_map_flags(map);
|
||||||
>address = mmap(base, size, protection_flags, map_flags, -1, 0);
|
>address = mmap(base, size, protection_flags, map_flags, -1, 0);
|
||||||
//if (address == #integer_max(u64))
|
if (#int_from_pointer(address) == #integer_max(u64))
|
||||||
//{
|
{
|
||||||
// unreachable;
|
unreachable;
|
||||||
//}
|
}
|
||||||
//else
|
else
|
||||||
//{
|
{
|
||||||
//}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Arena = struct
|
Arena = struct
|
||||||
|
@ -114,6 +114,7 @@ const Module = struct {
|
|||||||
noreturn_type: *Type = undefined,
|
noreturn_type: *Type = undefined,
|
||||||
va_list_type: ?*Type = null,
|
va_list_type: ?*Type = null,
|
||||||
void_value: *Value = undefined,
|
void_value: *Value = undefined,
|
||||||
|
unreachable_value: *Value = undefined,
|
||||||
anonymous_pair_type_buffer: [64]u32 = undefined,
|
anonymous_pair_type_buffer: [64]u32 = undefined,
|
||||||
pointer_type_buffer: [128]u32 = undefined,
|
pointer_type_buffer: [128]u32 = undefined,
|
||||||
pointer_type_count: u32 = 0,
|
pointer_type_count: u32 = 0,
|
||||||
@ -778,10 +779,6 @@ const Module = struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_infer_or_ignore_value(module: *Module) *Value {
|
|
||||||
return &module.values.buffer[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_type(module: *Module, index: usize) *Type {
|
pub fn get_type(module: *Module, index: usize) *Type {
|
||||||
assert(index < module.types.count);
|
assert(index < module.types.count);
|
||||||
const result = &module.types.buffer[index];
|
const result = &module.types.buffer[index];
|
||||||
@ -965,6 +962,15 @@ const Module = struct {
|
|||||||
.dereference_to_assign = false,
|
.dereference_to_assign = false,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
module.unreachable_value = module.values.add();
|
||||||
|
module.unreachable_value.* = .{
|
||||||
|
.llvm = undefined,
|
||||||
|
.bb = .@"unreachable",
|
||||||
|
.type = module.noreturn_type,
|
||||||
|
.lvalue = false,
|
||||||
|
.dereference_to_assign = false,
|
||||||
|
};
|
||||||
|
|
||||||
return module;
|
return module;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1086,6 +1092,7 @@ pub const Value = struct {
|
|||||||
constant_integer: ConstantInteger,
|
constant_integer: ConstantInteger,
|
||||||
constant_array,
|
constant_array,
|
||||||
external_function,
|
external_function,
|
||||||
|
@"unreachable",
|
||||||
},
|
},
|
||||||
type: *Type,
|
type: *Type,
|
||||||
llvm: *llvm.Value,
|
llvm: *llvm.Value,
|
||||||
@ -2639,6 +2646,7 @@ const Converter = struct {
|
|||||||
extend,
|
extend,
|
||||||
integer_max,
|
integer_max,
|
||||||
int_from_enum,
|
int_from_enum,
|
||||||
|
int_from_pointer,
|
||||||
select,
|
select,
|
||||||
trap,
|
trap,
|
||||||
truncate,
|
truncate,
|
||||||
@ -2789,6 +2797,34 @@ const Converter = struct {
|
|||||||
value.type = target_type;
|
value.type = target_type;
|
||||||
return value;
|
return value;
|
||||||
},
|
},
|
||||||
|
.int_from_pointer => {
|
||||||
|
const source_value = converter.parse_value(module, null, .value);
|
||||||
|
converter.skip_space();
|
||||||
|
converter.expect_character(right_parenthesis);
|
||||||
|
if (source_value.type.bb != .pointer) {
|
||||||
|
converter.report_error();
|
||||||
|
}
|
||||||
|
const original_target_type = module.integer_type(64, false);
|
||||||
|
const target_type = expected_type orelse original_target_type;
|
||||||
|
|
||||||
|
if (target_type.bb != .integer) {
|
||||||
|
converter.report_error();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (target_type.get_bit_size() < original_target_type.get_bit_size()) {
|
||||||
|
converter.report_error();
|
||||||
|
}
|
||||||
|
|
||||||
|
const value = module.values.add();
|
||||||
|
value.* = .{
|
||||||
|
.llvm = module.llvm.builder.create_ptr_to_int(source_value.llvm, target_type.llvm.handle),
|
||||||
|
.type = target_type,
|
||||||
|
.lvalue = false,
|
||||||
|
.dereference_to_assign = false,
|
||||||
|
.bb = .instruction,
|
||||||
|
};
|
||||||
|
return value;
|
||||||
|
},
|
||||||
.select => {
|
.select => {
|
||||||
const condition_value = converter.parse_value(module, null, .value);
|
const condition_value = converter.parse_value(module, null, .value);
|
||||||
|
|
||||||
@ -3087,6 +3123,7 @@ const Converter = struct {
|
|||||||
const ValueKeyword = enum {
|
const ValueKeyword = enum {
|
||||||
@"_",
|
@"_",
|
||||||
undefined,
|
undefined,
|
||||||
|
@"unreachable",
|
||||||
zero,
|
zero,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -3176,6 +3213,7 @@ const Converter = struct {
|
|||||||
if (string_to_enum(ValueKeyword, identifier)) |value_keyword| switch (value_keyword) {
|
if (string_to_enum(ValueKeyword, identifier)) |value_keyword| switch (value_keyword) {
|
||||||
._ => converter.report_error(),
|
._ => converter.report_error(),
|
||||||
.undefined => @trap(),
|
.undefined => @trap(),
|
||||||
|
.@"unreachable" => @trap(),
|
||||||
.zero => {
|
.zero => {
|
||||||
zero = true;
|
zero = true;
|
||||||
converter.skip_space();
|
converter.skip_space();
|
||||||
@ -3345,6 +3383,7 @@ const Converter = struct {
|
|||||||
// We need to break here otherwise `field_count` would be incremented
|
// We need to break here otherwise `field_count` would be incremented
|
||||||
break;
|
break;
|
||||||
},
|
},
|
||||||
|
.@"unreachable" => @trap(),
|
||||||
} else {
|
} else {
|
||||||
converter.report_error();
|
converter.report_error();
|
||||||
}
|
}
|
||||||
@ -3495,7 +3534,7 @@ const Converter = struct {
|
|||||||
const identifier = converter.parse_identifier();
|
const identifier = converter.parse_identifier();
|
||||||
|
|
||||||
if (string_to_enum(ValueKeyword, identifier)) |value_keyword| switch (value_keyword) {
|
if (string_to_enum(ValueKeyword, identifier)) |value_keyword| switch (value_keyword) {
|
||||||
._ => return module.get_infer_or_ignore_value(),
|
._ => return module.void_value,
|
||||||
.undefined => {
|
.undefined => {
|
||||||
const expected_ty = expected_type orelse converter.report_error();
|
const expected_ty = expected_type orelse converter.report_error();
|
||||||
// TODO: cache poison
|
// TODO: cache poison
|
||||||
@ -3514,6 +3553,11 @@ const Converter = struct {
|
|||||||
|
|
||||||
return module.get_zero_value(ty);
|
return module.get_zero_value(ty);
|
||||||
},
|
},
|
||||||
|
.@"unreachable" => {
|
||||||
|
_ = module.llvm.builder.create_unreachable();
|
||||||
|
module.llvm.builder.clear_insertion_position();
|
||||||
|
return module.unreachable_value;
|
||||||
|
},
|
||||||
} else {
|
} else {
|
||||||
const variable = if (current_function.value.bb.function.locals.find(identifier)) |local| local else if (current_function.value.bb.function.arguments.find(identifier)) |argument| argument else if (module.globals.find(identifier)) |global| global else converter.report_error();
|
const variable = if (current_function.value.bb.function.locals.find(identifier)) |local| local else if (current_function.value.bb.function.arguments.find(identifier)) |argument| argument else if (module.globals.find(identifier)) |global| global else converter.report_error();
|
||||||
|
|
||||||
|
@ -404,3 +404,7 @@ test "bits_return_u1" {
|
|||||||
test "integer_max" {
|
test "integer_max" {
|
||||||
try invsrc(@src());
|
try invsrc(@src());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "unreachable" {
|
||||||
|
try invsrc(@src());
|
||||||
|
}
|
||||||
|
9
tests/unreachable.bbb
Normal file
9
tests/unreachable.bbb
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
[export] main = fn [cc(c)] () s32
|
||||||
|
{
|
||||||
|
>result: s32 = 0;
|
||||||
|
if (result != 0)
|
||||||
|
{
|
||||||
|
unreachable;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user