aboutsummaryrefslogtreecommitdiff
path: root/src/ir.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/ir.cpp')
-rw-r--r--src/ir.cpp46
1 files changed, 39 insertions, 7 deletions
diff --git a/src/ir.cpp b/src/ir.cpp
index ad05c8e23e..ae629e0910 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -4324,6 +4324,13 @@ static ErrorMsg *ir_add_error(IrAnalyze *ira, IrInstruction *source_instruction,
return ir_add_error_node(ira, source_instruction->source_node, msg);
}
+static void ir_add_typedef_err_note(IrAnalyze *ira, ErrorMsg *msg, TypeTableEntry *type_entry) {
+ if (type_entry->id == TypeTableEntryIdTypeDecl) {
+ // requires tracking source_node in the typedecl type
+ zig_panic("TODO add error note about typedecls");
+ }
+}
+
static IrInstruction *ir_exec_const_result(IrExecutable *exec) {
if (exec->basic_block_list.length != 1)
return nullptr;
@@ -5451,8 +5458,7 @@ static TypeTableEntry *ir_analyze_ref(IrAnalyze *ira, IrInstruction *source_inst
if (value->type_entry->id == TypeTableEntryIdInvalid)
return ira->codegen->builtin_types.entry_invalid;
- bool is_inline = ir_should_inline(&ira->new_irb);
- if (is_inline || instr_is_comptime(value)) {
+ if (instr_is_comptime(value)) {
ConstExprValue *val = ir_resolve_const(ira, value, UndefBad);
if (!val)
return ira->codegen->builtin_types.entry_invalid;
@@ -8223,7 +8229,7 @@ static TypeTableEntry *ir_analyze_instruction_switch_target(IrAnalyze *ira,
case TypeTableEntryIdUnion:
case TypeTableEntryIdBlock:
case TypeTableEntryIdBoundFn:
- ir_add_error_node(ira, switch_target_instruction->base.source_node,
+ ir_add_error(ira, &switch_target_instruction->base,
buf_sprintf("invalid switch target type '%s'", buf_ptr(&target_type->name)));
// TODO if this is a typedecl, add error note showing the declaration of the type decl
return ira->codegen->builtin_types.entry_invalid;
@@ -8231,10 +8237,36 @@ static TypeTableEntry *ir_analyze_instruction_switch_target(IrAnalyze *ira,
zig_unreachable();
}
-static TypeTableEntry *ir_analyze_instruction_switch_var(IrAnalyze *ira,
- IrInstructionSwitchVar *switch_var_instruction)
-{
- zig_panic("TODO switch var analyze");
+static TypeTableEntry *ir_analyze_instruction_switch_var(IrAnalyze *ira, IrInstructionSwitchVar *instruction) {
+ IrInstruction *target_value_ptr = instruction->target_value_ptr->other;
+ if (target_value_ptr->type_entry->id == TypeTableEntryIdInvalid)
+ return ira->codegen->builtin_types.entry_invalid;
+
+ IrInstruction *prong_value = instruction->prong_value->other;
+ if (prong_value->type_entry->id == TypeTableEntryIdInvalid)
+ return ira->codegen->builtin_types.entry_invalid;
+
+ assert(target_value_ptr->type_entry->id == TypeTableEntryIdPointer);
+ TypeTableEntry *target_type = target_value_ptr->type_entry->data.pointer.child_type;
+ if (target_type->id == TypeTableEntryIdEnum) {
+ ConstExprValue *prong_val = ir_resolve_const(ira, prong_value, UndefBad);
+ if (!prong_val)
+ return ira->codegen->builtin_types.entry_invalid;
+
+ TypeEnumField *field = &target_type->data.enumeration.fields[prong_val->data.x_bignum.data.x_uint];
+ if (instr_is_comptime(target_value_ptr)) {
+ zig_panic("TODO comptime switch var");
+ }
+
+ ir_build_enum_field_ptr_from(&ira->new_irb, &instruction->base, target_value_ptr, field);
+ return get_pointer_to_type(ira->codegen, field->type_entry,
+ target_value_ptr->type_entry->data.pointer.is_const);
+ } else {
+ ErrorMsg *msg = ir_add_error(ira, &instruction->base,
+ buf_sprintf("switch on type '%s' provides no expression parameter", buf_ptr(&target_type->name)));
+ ir_add_typedef_err_note(ira, msg, target_type);
+ return ira->codegen->builtin_types.entry_invalid;
+ }
}
static TypeTableEntry *ir_analyze_instruction_enum_tag(IrAnalyze *ira, IrInstructionEnumTag *enum_tag_instruction) {