fix enum codegen and implement comptime switch var on enums
parent
0c1800a9c9
commit
8106f9846a
|
@ -677,9 +677,14 @@ static LLVMValueRef ir_llvm_value(CodeGen *g, IrInstruction *instruction) {
|
||||||
assert(instruction->value.special != ConstValSpecialRuntime);
|
assert(instruction->value.special != ConstValSpecialRuntime);
|
||||||
assert(instruction->value.type);
|
assert(instruction->value.type);
|
||||||
render_const_val(g, &instruction->value);
|
render_const_val(g, &instruction->value);
|
||||||
|
// we might have to do some pointer casting here due to the way union
|
||||||
|
// values are rendered with a type other than the one we expect
|
||||||
if (handle_is_ptr(instruction->value.type)) {
|
if (handle_is_ptr(instruction->value.type)) {
|
||||||
render_const_val_global(g, &instruction->value);
|
render_const_val_global(g, &instruction->value);
|
||||||
instruction->llvm_value = instruction->value.llvm_global;
|
TypeTableEntry *ptr_type = get_pointer_to_type(g, instruction->value.type, true);
|
||||||
|
instruction->llvm_value = LLVMBuildBitCast(g->builder, instruction->value.llvm_global, ptr_type->type_ref, "");
|
||||||
|
} else if (instruction->value.type->id == TypeTableEntryIdPointer) {
|
||||||
|
instruction->llvm_value = LLVMBuildBitCast(g->builder, instruction->value.llvm_value, instruction->value.type->type_ref, "");
|
||||||
} else {
|
} else {
|
||||||
instruction->llvm_value = instruction->value.llvm_value;
|
instruction->llvm_value = instruction->value.llvm_value;
|
||||||
}
|
}
|
||||||
|
@ -2540,7 +2545,7 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) {
|
||||||
tag_value,
|
tag_value,
|
||||||
union_value,
|
union_value,
|
||||||
};
|
};
|
||||||
return LLVMConstNamedStruct(canon_type->type_ref, fields, 2);
|
return LLVMConstStruct(fields, 2, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case TypeTableEntryIdFn:
|
case TypeTableEntryIdFn:
|
||||||
|
@ -2553,11 +2558,7 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) {
|
||||||
render_const_val(g, const_val->data.x_ptr.base_ptr);
|
render_const_val(g, const_val->data.x_ptr.base_ptr);
|
||||||
render_const_val_global(g, const_val->data.x_ptr.base_ptr);
|
render_const_val_global(g, const_val->data.x_ptr.base_ptr);
|
||||||
ConstExprValue *other_val = const_val->data.x_ptr.base_ptr;
|
ConstExprValue *other_val = const_val->data.x_ptr.base_ptr;
|
||||||
if (other_val->type == const_val->type->data.pointer.child_type) {
|
const_val->llvm_value = LLVMConstBitCast(other_val->llvm_global, const_val->type->type_ref);
|
||||||
const_val->llvm_value = other_val->llvm_global;
|
|
||||||
} else {
|
|
||||||
const_val->llvm_value = LLVMConstBitCast(other_val->llvm_global, const_val->type->type_ref);
|
|
||||||
}
|
|
||||||
render_const_val_global(g, const_val);
|
render_const_val_global(g, const_val);
|
||||||
return const_val->llvm_value;
|
return const_val->llvm_value;
|
||||||
} else {
|
} else {
|
||||||
|
@ -2636,7 +2637,8 @@ static void render_const_val(CodeGen *g, ConstExprValue *const_val) {
|
||||||
|
|
||||||
static void render_const_val_global(CodeGen *g, ConstExprValue *const_val) {
|
static void render_const_val_global(CodeGen *g, ConstExprValue *const_val) {
|
||||||
if (!const_val->llvm_global) {
|
if (!const_val->llvm_global) {
|
||||||
LLVMValueRef global_value = LLVMAddGlobal(g->module, const_val->type->type_ref, "");
|
LLVMTypeRef type_ref = const_val->llvm_value ? LLVMTypeOf(const_val->llvm_value) : const_val->type->type_ref;
|
||||||
|
LLVMValueRef global_value = LLVMAddGlobal(g->module, type_ref, "");
|
||||||
LLVMSetLinkage(global_value, LLVMInternalLinkage);
|
LLVMSetLinkage(global_value, LLVMInternalLinkage);
|
||||||
LLVMSetGlobalConstant(global_value, true);
|
LLVMSetGlobalConstant(global_value, true);
|
||||||
LLVMSetUnnamedAddr(global_value, true);
|
LLVMSetUnnamedAddr(global_value, true);
|
||||||
|
|
15
src/ir.cpp
15
src/ir.cpp
|
@ -9565,7 +9565,20 @@ static TypeTableEntry *ir_analyze_instruction_switch_var(IrAnalyze *ira, IrInstr
|
||||||
}
|
}
|
||||||
|
|
||||||
if (instr_is_comptime(target_value_ptr)) {
|
if (instr_is_comptime(target_value_ptr)) {
|
||||||
zig_panic("TODO comptime switch var");
|
ConstExprValue *target_val_ptr = ir_resolve_const(ira, target_value_ptr, UndefBad);
|
||||||
|
if (!target_value_ptr)
|
||||||
|
return ira->codegen->builtin_types.entry_invalid;
|
||||||
|
|
||||||
|
ConstExprValue *pointee_val = const_ptr_pointee(target_val_ptr);
|
||||||
|
if (pointee_val->type->id == TypeTableEntryIdEnum) {
|
||||||
|
bool depends_on_compile_var = target_value_ptr->value.depends_on_compile_var;
|
||||||
|
ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base, depends_on_compile_var);
|
||||||
|
out_val->data.x_ptr.base_ptr = pointee_val->data.x_enum.payload;
|
||||||
|
out_val->data.x_ptr.index = SIZE_MAX;
|
||||||
|
return get_pointer_to_type(ira->codegen, pointee_val->type, target_value_ptr->value.type->data.pointer.is_const);
|
||||||
|
} else {
|
||||||
|
zig_panic("TODO comptime switch var");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ir_build_enum_field_ptr_from(&ira->new_irb, &instruction->base, target_value_ptr, field);
|
ir_build_enum_field_ptr_from(&ira->new_irb, &instruction->base, target_value_ptr, field);
|
||||||
|
|
|
@ -129,3 +129,25 @@ fn switchWithMultipleExpressions() {
|
||||||
fn returnsFive() -> i32 {
|
fn returnsFive() -> i32 {
|
||||||
5
|
5
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const Number = enum {
|
||||||
|
One: u64,
|
||||||
|
Two: u8,
|
||||||
|
Three: f32,
|
||||||
|
};
|
||||||
|
|
||||||
|
const number = Number.Three { 1.23 };
|
||||||
|
|
||||||
|
fn returnsFalse() -> bool {
|
||||||
|
switch (number) {
|
||||||
|
Number.One => |x| return x > 1234,
|
||||||
|
Number.Two => |x| return x == 'a',
|
||||||
|
Number.Three => |x| return x > 12.34,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn switchOnConstEnumWithVar() {
|
||||||
|
@setFnTest(this);
|
||||||
|
|
||||||
|
assert(!returnsFalse());
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue