mirror of
https://github.com/ziglang/zig.git
synced 2026-02-13 04:48:20 +00:00
Merge pull request #4172 from LemonBoy/swish
Two switch-related patches
This commit is contained in:
commit
d3e67d9921
@ -4876,14 +4876,30 @@ static LLVMValueRef ir_render_pop_count(CodeGen *g, IrExecutable *executable, Ir
|
||||
}
|
||||
|
||||
static LLVMValueRef ir_render_switch_br(CodeGen *g, IrExecutable *executable, IrInstructionSwitchBr *instruction) {
|
||||
LLVMValueRef target_value = ir_llvm_value(g, instruction->target_value);
|
||||
ZigType *target_type = instruction->target_value->value->type;
|
||||
LLVMBasicBlockRef else_block = instruction->else_block->llvm_block;
|
||||
|
||||
LLVMValueRef target_value = ir_llvm_value(g, instruction->target_value);
|
||||
if (target_type->id == ZigTypeIdPointer) {
|
||||
const ZigType *usize = g->builtin_types.entry_usize;
|
||||
target_value = LLVMBuildPtrToInt(g->builder, target_value, usize->llvm_type, "");
|
||||
}
|
||||
|
||||
LLVMValueRef switch_instr = LLVMBuildSwitch(g->builder, target_value, else_block,
|
||||
(unsigned)instruction->case_count);
|
||||
(unsigned)instruction->case_count);
|
||||
|
||||
for (size_t i = 0; i < instruction->case_count; i += 1) {
|
||||
IrInstructionSwitchBrCase *this_case = &instruction->cases[i];
|
||||
LLVMAddCase(switch_instr, ir_llvm_value(g, this_case->value), this_case->block->llvm_block);
|
||||
|
||||
LLVMValueRef case_value = ir_llvm_value(g, this_case->value);
|
||||
if (target_type->id == ZigTypeIdPointer) {
|
||||
const ZigType *usize = g->builtin_types.entry_usize;
|
||||
case_value = LLVMBuildPtrToInt(g->builder, case_value, usize->llvm_type, "");
|
||||
}
|
||||
|
||||
LLVMAddCase(switch_instr, case_value, this_case->block->llvm_block);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
12
src/ir.cpp
12
src/ir.cpp
@ -26394,6 +26394,7 @@ static IrInstruction *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira,
|
||||
if (type_is_invalid(end_value->value->type))
|
||||
return ira->codegen->invalid_instruction;
|
||||
|
||||
assert(start_value->value->type->id == ZigTypeIdEnum);
|
||||
BigInt start_index;
|
||||
bigint_init_bigint(&start_index, &start_value->value->data.x_enum_tag);
|
||||
|
||||
@ -26401,6 +26402,11 @@ static IrInstruction *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira,
|
||||
BigInt end_index;
|
||||
bigint_init_bigint(&end_index, &end_value->value->data.x_enum_tag);
|
||||
|
||||
if (bigint_cmp(&start_index, &end_index) == CmpGT) {
|
||||
ir_add_error(ira, start_value,
|
||||
buf_sprintf("range start value is greater than the end value"));
|
||||
}
|
||||
|
||||
BigInt field_index;
|
||||
bigint_init_bigint(&field_index, &start_index);
|
||||
for (;;) {
|
||||
@ -26530,6 +26536,12 @@ static IrInstruction *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira,
|
||||
|
||||
assert(start_val->type->id == ZigTypeIdInt || start_val->type->id == ZigTypeIdComptimeInt);
|
||||
assert(end_val->type->id == ZigTypeIdInt || end_val->type->id == ZigTypeIdComptimeInt);
|
||||
|
||||
if (bigint_cmp(&start_val->data.x_bigint, &end_val->data.x_bigint) == CmpGT) {
|
||||
ir_add_error(ira, start_value,
|
||||
buf_sprintf("range start value is greater than the end value"));
|
||||
}
|
||||
|
||||
AstNode *prev_node = rangeset_add_range(&rs, &start_val->data.x_bigint, &end_val->data.x_bigint,
|
||||
start_value->source_node);
|
||||
if (prev_node != nullptr) {
|
||||
|
||||
@ -2,6 +2,20 @@ const tests = @import("tests.zig");
|
||||
const builtin = @import("builtin");
|
||||
|
||||
pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||
cases.addTest("switch ranges endpoints are validated",
|
||||
\\pub export fn entry() void {
|
||||
\\ var x: i32 = 0;
|
||||
\\ switch (x) {
|
||||
\\ 6...1 => {},
|
||||
\\ -1...-5 => {},
|
||||
\\ else => unreachable,
|
||||
\\ }
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
"tmp.zig:4:9: error: range start value is greater than the end value",
|
||||
"tmp.zig:5:9: error: range start value is greater than the end value",
|
||||
});
|
||||
|
||||
cases.addTest("errors in for loop bodies are propagated",
|
||||
\\pub export fn entry() void {
|
||||
\\ var arr: [100]u8 = undefined;
|
||||
|
||||
@ -452,3 +452,30 @@ test "switch on global mutable var isn't constant-folded" {
|
||||
poll();
|
||||
}
|
||||
}
|
||||
|
||||
test "switch on pointer type" {
|
||||
const S = struct {
|
||||
const X = struct {
|
||||
field: u32,
|
||||
};
|
||||
|
||||
const P1 = @intToPtr(*X, 0x400);
|
||||
const P2 = @intToPtr(*X, 0x800);
|
||||
const P3 = @intToPtr(*X, 0xC00);
|
||||
|
||||
fn doTheTest(arg: *X) i32 {
|
||||
switch (arg) {
|
||||
P1 => return 1,
|
||||
P2 => return 2,
|
||||
else => return 3,
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
expect(1 == S.doTheTest(S.P1));
|
||||
expect(2 == S.doTheTest(S.P2));
|
||||
expect(3 == S.doTheTest(S.P3));
|
||||
comptime expect(1 == S.doTheTest(S.P1));
|
||||
comptime expect(2 == S.doTheTest(S.P2));
|
||||
comptime expect(3 == S.doTheTest(S.P3));
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user