mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
- Fix bug with @jump miscompile
- Remove "panic" text from unreachable() when safe mode is turned off.
This commit is contained in:
@@ -143,7 +143,9 @@ fn void panicf(String fmt, String file, String function, uint line, args...)
|
||||
**/
|
||||
macro void unreachable(String string = "Unreachable statement reached.", ...) @builtin @noreturn
|
||||
{
|
||||
$if env::COMPILER_SAFE_MODE:
|
||||
panicf(string, $$FILE, $$FUNC, $$LINE, $vasplat());
|
||||
$endif;
|
||||
$$unreachable();
|
||||
}
|
||||
|
||||
|
||||
@@ -14,10 +14,12 @@
|
||||
- Fixed crash on certain recursive function definitions #1209.
|
||||
- Return the typekind "FUNC" for a function pointer.
|
||||
- No longer possible to dereference a function pointer.
|
||||
- Fix bug with @jump miscompile
|
||||
|
||||
### Stdlib changes
|
||||
- Added `remove_first_item` `remove_last_item` and `remove_item` as aliases for the `match` functions.
|
||||
- Added @str_hash, @str_upper, @str_lower, @str_find compile time macros.
|
||||
- Remove "panic" text from unreachable() when safe mode is turned off.
|
||||
|
||||
## 0.6.0 Change list
|
||||
|
||||
|
||||
@@ -886,8 +886,8 @@ opt_stmt_list
|
||||
switch_stmt
|
||||
: SWITCH optional_label '{' switch_body '}'
|
||||
| SWITCH optional_label '{' '}'
|
||||
| SWITCH optional_label paren_cond '{' switch_body '}'
|
||||
| SWITCH optional_label paren_cond '{' '}'
|
||||
| SWITCH optional_label paren_cond opt_attributes '{' switch_body '}'
|
||||
| SWITCH optional_label paren_cond opt_attributes '{' '}'
|
||||
;
|
||||
|
||||
expression_list
|
||||
|
||||
@@ -752,7 +752,13 @@ static LLVMValueRef llvm_emit_switch_jump_stmt(GenContext *c,
|
||||
BEValue min_val;
|
||||
llvm_emit_expr(c, &min_val, exprptr(cases[min_index]->case_stmt.expr));
|
||||
assert(llvm_value_is_const(&min_val));
|
||||
switch_value->value = LLVMBuildSub(c->builder, switch_value->value, min_val.value, "");
|
||||
llvm_value_rvalue(c, switch_value);
|
||||
llvm_value_rvalue(c, &min_val);
|
||||
LLVMValueRef min = min_val.value;
|
||||
if (!LLVMIsConstant(min) || !LLVMIsNull(min))
|
||||
{
|
||||
switch_value->value = LLVMBuildSub(c->builder, switch_value->value, min_val.value, "");
|
||||
}
|
||||
LLVMValueRef is_valid = LLVMBuildICmp(c->builder, LLVMIntUGT, switch_value->value, llvm_const_int(c, switch_value->type, count - 1), "");
|
||||
LLVMBasicBlockRef switch_block = llvm_basic_block_new(c, "jumpblock");
|
||||
LLVMBuildCondBr(c->builder, is_valid, default_block, switch_block);
|
||||
|
||||
@@ -17,7 +17,6 @@ fn void test()
|
||||
define void @unreachable.test() #0 {
|
||||
entry:
|
||||
%x = alloca i32, align 4
|
||||
%indirectarg = alloca %"any[]", align 8
|
||||
%0 = call i32 @unreachable.foo()
|
||||
store i32 %0, ptr %x, align 4
|
||||
%1 = load i32, ptr %x, align 4
|
||||
@@ -28,7 +27,5 @@ if.then: ; preds = %entry
|
||||
ret void
|
||||
|
||||
if.exit: ; preds = %entry
|
||||
store %"any[]" zeroinitializer, ptr %indirectarg, align 8
|
||||
call void @std.core.builtin.panicf(ptr @.str, i64 30, ptr @.str.1, i64 14, ptr @.str.2, i64 4, i32 10, ptr byval(%"any[]") align 8 %indirectarg)
|
||||
unreachable
|
||||
}
|
||||
65
test/test_suite/switch/jump_with_inc.c3t
Normal file
65
test/test_suite/switch/jump_with_inc.c3t
Normal file
@@ -0,0 +1,65 @@
|
||||
// #target: macos-aarch64
|
||||
module test;
|
||||
extern fn int b(int y);
|
||||
|
||||
fn int foo(int x) @export
|
||||
{
|
||||
switch (x) @jump
|
||||
{
|
||||
case 1:
|
||||
nextcase (b(x));
|
||||
case 0:
|
||||
x++;
|
||||
nextcase x;
|
||||
default:
|
||||
unreachable();
|
||||
}
|
||||
}
|
||||
/* #expect: test.ll
|
||||
|
||||
define i32 @test_foo(i32 %0) #0 {
|
||||
entry:
|
||||
%x = alloca i32, align 4
|
||||
%switch = alloca i32, align 4
|
||||
store i32 %0, ptr %x, align 4
|
||||
%1 = load i32, ptr %x, align 4
|
||||
store i32 %1, ptr %switch, align 4
|
||||
br label %switch.entry
|
||||
|
||||
switch.entry: ; preds = %entry
|
||||
%2 = load i32, ptr %switch, align 4
|
||||
%3 = icmp ugt i32 %2, 1
|
||||
br i1 %3, label %switch.default, label %jumpblock
|
||||
|
||||
jumpblock: ; preds = %switch.entry
|
||||
%ptroffset = getelementptr inbounds [8 x i8], ptr @jumptable, i32 %2
|
||||
%target = load ptr, ptr %ptroffset, align 8
|
||||
indirectbr ptr %target, [label %switch.case, label %switch.case4]
|
||||
|
||||
switch.case: ; preds = %jumpblock5, %jumpblock1, %jumpblock
|
||||
%4 = load i32, ptr %x, align 4
|
||||
%5 = call i32 @b(i32 %4)
|
||||
%6 = icmp ugt i32 %5, 1
|
||||
br i1 %6, label %switch.default, label %jumpblock1
|
||||
|
||||
jumpblock1: ; preds = %switch.case
|
||||
%ptroffset2 = getelementptr inbounds [8 x i8], ptr @jumptable, i32 %5
|
||||
%target3 = load ptr, ptr %ptroffset2, align 8
|
||||
indirectbr ptr %target3, [label %switch.case, label %switch.case4, label %switch.default]
|
||||
|
||||
switch.case4: ; preds = %jumpblock5, %jumpblock, %jumpblock1
|
||||
%7 = load i32, ptr %x, align 4
|
||||
%add = add i32 %7, 1
|
||||
store i32 %add, ptr %x, align 4
|
||||
%8 = load i32, ptr %x, align 4
|
||||
%9 = icmp ugt i32 %8, 1
|
||||
br i1 %9, label %switch.default, label %jumpblock5
|
||||
|
||||
jumpblock5: ; preds = %switch.case4
|
||||
%ptroffset6 = getelementptr inbounds [8 x i8], ptr @jumptable, i32 %8
|
||||
%target7 = load ptr, ptr %ptroffset6, align 8
|
||||
indirectbr ptr %target7, [label %switch.case, label %switch.case4, label %switch.default]
|
||||
|
||||
switch.default: ; preds = %jumpblock5, %switch.case4, %jumpblock1, %switch.case, %switch.entry
|
||||
unreachable
|
||||
}
|
||||
@@ -71,6 +71,8 @@ fn void test6(int a)
|
||||
@jumptable.2 = private constant [3 x ptr] [ptr blockaddress(@simple_jump.test3, %switch.case), ptr blockaddress(@simple_jump.test3, %switch.exit), ptr blockaddress(@simple_jump.test3, %switch.case1)], align 4
|
||||
@jumptable.3 = private constant [1 x ptr] [ptr blockaddress(@simple_jump.test4, %switch.case)], align 4
|
||||
@jumptable.4 = private constant [4 x ptr] [ptr blockaddress(@simple_jump.test5, %switch.case), ptr blockaddress(@simple_jump.test5, %switch.default), ptr blockaddress(@simple_jump.test5, %switch.default), ptr blockaddress(@simple_jump.test5, %switch.case1)], align 4
|
||||
@jumptable.5 = private constant [5 x ptr] [ptr blockaddress(@simple_jump.test6, %switch.case), ptr blockaddress(@simple_jump.test6, %switch.default), ptr blockaddress(@simple_jump.test6, %switch.default), ptr blockaddress(@simple_jump.test6, %switch.case1), ptr blockaddress(@simple_jump.test6, %switch.case2)], align 4
|
||||
|
||||
|
||||
after_check12: ; preds = %noerr_block8
|
||||
br label %noerr_block14
|
||||
@@ -87,7 +89,6 @@ voiderr: ; preds = %noerr_block14, %gua
|
||||
ret void
|
||||
}
|
||||
|
||||
; Function Attrs: nounwind uwtable
|
||||
define void @simple_jump.test1(i32 %0) #0 {
|
||||
entry:
|
||||
%switch = alloca i32, align 4
|
||||
@@ -96,12 +97,11 @@ entry:
|
||||
|
||||
switch.entry: ; preds = %entry
|
||||
%1 = load i32, ptr %switch, align 4
|
||||
%2 = sub i32 %1, 0
|
||||
%3 = icmp ugt i32 %2, 2
|
||||
br i1 %3, label %switch.exit, label %jumpblock
|
||||
%2 = icmp ugt i32 %1, 2
|
||||
br i1 %2, label %switch.exit, label %jumpblock
|
||||
|
||||
jumpblock: ; preds = %switch.entry
|
||||
%ptroffset = getelementptr inbounds [8 x i8], ptr @jumptable, i32 %2
|
||||
%ptroffset = getelementptr inbounds [8 x i8], ptr @jumptable, i32 %1
|
||||
%target = load ptr, ptr %ptroffset, align 8
|
||||
indirectbr ptr %target, [label %switch.case, label %switch.case1]
|
||||
|
||||
|
||||
Reference in New Issue
Block a user