aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/codegen.cpp22
-rw-r--r--src/ir.cpp12
2 files changed, 31 insertions, 3 deletions
diff --git a/src/codegen.cpp b/src/codegen.cpp
index fd36e15f82..d64c191c93 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -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;
}
diff --git a/src/ir.cpp b/src/ir.cpp
index a5561e9bfd..bbf56fd08d 100644
--- a/src/ir.cpp
+++ b/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) {