mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
@@ -29,7 +29,7 @@
|
||||
- Fix bug where .min/.max would fail on a distinct int #1888.
|
||||
- Fix issue where compile time declarations in expression list would not be handled properly.
|
||||
- Issue where trailing body argument was allowed without type even though the definition specified it #1879.
|
||||
|
||||
- Fix issues with @jump on empty `default` or only `default` #1893 #1894
|
||||
### Stdlib changes
|
||||
- Added '%h' and '%H' for printing out binary data in hexadecimal using the formatter.
|
||||
- Added weakly linked `__powidf2`
|
||||
|
||||
@@ -777,6 +777,7 @@ static LLVMValueRef llvm_emit_switch_jump_stmt(GenContext *c,
|
||||
LLVMBasicBlockRef default_block,
|
||||
BEValue *switch_value)
|
||||
{
|
||||
ASSERT_SPAN(switch_ast, min_index > -1);
|
||||
unsigned case_count = vec_size(cases);
|
||||
BEValue min_val;
|
||||
llvm_emit_expr(c, &min_val, exprptr(cases[min_index]->case_stmt.expr));
|
||||
@@ -848,6 +849,7 @@ static void llvm_emit_switch_jump_table(GenContext *c,
|
||||
Ast *case_ast = cases[i];
|
||||
if (case_ast->ast_kind == AST_DEFAULT_STMT)
|
||||
{
|
||||
if (!case_ast->case_stmt.body) continue;
|
||||
default_block = case_ast->case_stmt.backend_block;
|
||||
default_index = i;
|
||||
continue;
|
||||
@@ -914,7 +916,7 @@ static void llvm_emit_switch_jump_table(GenContext *c,
|
||||
if (!case_stmt->case_stmt.body) continue;
|
||||
LLVMAddDestination(instr, block);
|
||||
}
|
||||
|
||||
if (!case_stmt->case_stmt.body) continue;
|
||||
llvm_emit_block(c, block);
|
||||
llvm_emit_stmt(c, case_stmt->case_stmt.body);
|
||||
llvm_emit_br(c, exit_block);
|
||||
|
||||
@@ -2533,7 +2533,11 @@ static bool sema_analyse_switch_body(SemaContext *context, Ast *statement, Sourc
|
||||
RETURN_SEMA_ERROR(statement, "The switch cannot use a jump table size of the table would exceed "
|
||||
"the maximum allowed (%u), please remove '@jump'.", compiler.build.switchjump_max_size);
|
||||
}
|
||||
|
||||
}
|
||||
// Do not generate a jump table if we only have a default statement.
|
||||
if (default_case && case_count == 1)
|
||||
{
|
||||
statement->flow.jump = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
70
test/test_suite/switch/jump_bugs.c3t
Normal file
70
test/test_suite/switch/jump_bugs.c3t
Normal file
@@ -0,0 +1,70 @@
|
||||
// #target: macos-aarch64
|
||||
module test;
|
||||
|
||||
fn void test1()
|
||||
{
|
||||
switch (0) @jump
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
enum Foo { A, B, }
|
||||
|
||||
fn void main()
|
||||
{
|
||||
test1();
|
||||
switch (Foo.A) @jump
|
||||
{
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* #expect: test.ll
|
||||
|
||||
@jumptable = private unnamed_addr constant [1 x ptr] [ptr blockaddress(@test.test1, %switch.case)], align 4
|
||||
|
||||
define void @test.test1() #0 {
|
||||
entry:
|
||||
%switch = alloca i32, align 4
|
||||
store i32 0, ptr %switch, align 4
|
||||
br label %switch.entry
|
||||
|
||||
switch.entry: ; preds = %entry
|
||||
%0 = load i32, ptr %switch, align 4
|
||||
%1 = icmp ugt i32 %0, 0
|
||||
br i1 %1, label %switch.exit, label %jumpblock
|
||||
|
||||
jumpblock: ; preds = %switch.entry
|
||||
%ptroffset = getelementptr inbounds [8 x i8], ptr @jumptable, i32 %0
|
||||
%target = load ptr, ptr %ptroffset, align 8
|
||||
indirectbr ptr %target, [label %switch.case]
|
||||
|
||||
switch.case: ; preds = %jumpblock
|
||||
br label %switch.exit
|
||||
|
||||
switch.exit: ; preds = %switch.case, %switch.entry
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @test.main() #0 {
|
||||
entry:
|
||||
%switch = alloca i32, align 4
|
||||
call void @test.test1()
|
||||
store i32 0, ptr %switch, align 4
|
||||
br label %switch.entry
|
||||
|
||||
switch.entry: ; preds = %entry
|
||||
%0 = load i32, ptr %switch, align 4
|
||||
switch i32 %0, label %switch.default [
|
||||
]
|
||||
|
||||
switch.default: ; preds = %switch.entry
|
||||
br label %switch.exit
|
||||
|
||||
switch.exit: ; preds = %switch.default
|
||||
ret void
|
||||
}
|
||||
Reference in New Issue
Block a user