authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-01-15 22:16:39-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-01-15 22:16:39-05:00
log8106f9846aea806350d319535e0181104299ba5d
treeef60cad5d8aa230cd7b5c34c6ef7c0db1d0bda88
parent0c1800a9c9507dd1b06c70cb8950b13afe09f758

fix enum codegen and implement comptime switch var on enums


3 files changed, 46 insertions(+), 9 deletions(-)

src/codegen.cpp+10-8
......@@ -677,9 +677,14 @@ static LLVMValueRef ir_llvm_value(CodeGen *g, IrInstruction *instruction) {
677677 assert(instruction->value.special != ConstValSpecialRuntime);
678678 assert(instruction->value.type);
679679 render_const_val(g, &instruction->value);
680 // we might have to do some pointer casting here due to the way union
681 // values are rendered with a type other than the one we expect
680682 if (handle_is_ptr(instruction->value.type)) {
681683 render_const_val_global(g, &instruction->value);
682 instruction->llvm_value = instruction->value.llvm_global;
684 TypeTableEntry *ptr_type = get_pointer_to_type(g, instruction->value.type, true);
685 instruction->llvm_value = LLVMBuildBitCast(g->builder, instruction->value.llvm_global, ptr_type->type_ref, "");
686 } else if (instruction->value.type->id == TypeTableEntryIdPointer) {
687 instruction->llvm_value = LLVMBuildBitCast(g->builder, instruction->value.llvm_value, instruction->value.type->type_ref, "");
683688 } else {
684689 instruction->llvm_value = instruction->value.llvm_value;
685690 }
......@@ -2540,7 +2545,7 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) {
25402545 tag_value,
25412546 union_value,
25422547 };
2543 return LLVMConstNamedStruct(canon_type->type_ref, fields, 2);
2548 return LLVMConstStruct(fields, 2, false);
25442549 }
25452550 }
25462551 case TypeTableEntryIdFn:
......@@ -2553,11 +2558,7 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) {
25532558 render_const_val(g, const_val->data.x_ptr.base_ptr);
25542559 render_const_val_global(g, const_val->data.x_ptr.base_ptr);
25552560 ConstExprValue *other_val = const_val->data.x_ptr.base_ptr;
2556 if (other_val->type == const_val->type->data.pointer.child_type) {
2557 const_val->llvm_value = other_val->llvm_global;
2558 } else {
2559 const_val->llvm_value = LLVMConstBitCast(other_val->llvm_global, const_val->type->type_ref);
2560 }
2561 const_val->llvm_value = LLVMConstBitCast(other_val->llvm_global, const_val->type->type_ref);
25612562 render_const_val_global(g, const_val);
25622563 return const_val->llvm_value;
25632564 } else {
......@@ -2636,7 +2637,8 @@ static void render_const_val(CodeGen *g, ConstExprValue *const_val) {
26362637
26372638static void render_const_val_global(CodeGen *g, ConstExprValue *const_val) {
26382639 if (!const_val->llvm_global) {
2639 LLVMValueRef global_value = LLVMAddGlobal(g->module, const_val->type->type_ref, "");
2640 LLVMTypeRef type_ref = const_val->llvm_value ? LLVMTypeOf(const_val->llvm_value) : const_val->type->type_ref;
2641 LLVMValueRef global_value = LLVMAddGlobal(g->module, type_ref, "");
26402642 LLVMSetLinkage(global_value, LLVMInternalLinkage);
26412643 LLVMSetGlobalConstant(global_value, true);
26422644 LLVMSetUnnamedAddr(global_value, true);
src/ir.cpp+14-1
......@@ -9565,7 +9565,20 @@ static TypeTableEntry *ir_analyze_instruction_switch_var(IrAnalyze *ira, IrInstr
95659565 }
95669566
95679567 if (instr_is_comptime(target_value_ptr)) {
9568 zig_panic("TODO comptime switch var");
9568 ConstExprValue *target_val_ptr = ir_resolve_const(ira, target_value_ptr, UndefBad);
9569 if (!target_value_ptr)
9570 return ira->codegen->builtin_types.entry_invalid;
9571
9572 ConstExprValue *pointee_val = const_ptr_pointee(target_val_ptr);
9573 if (pointee_val->type->id == TypeTableEntryIdEnum) {
9574 bool depends_on_compile_var = target_value_ptr->value.depends_on_compile_var;
9575 ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base, depends_on_compile_var);
9576 out_val->data.x_ptr.base_ptr = pointee_val->data.x_enum.payload;
9577 out_val->data.x_ptr.index = SIZE_MAX;
9578 return get_pointer_to_type(ira->codegen, pointee_val->type, target_value_ptr->value.type->data.pointer.is_const);
9579 } else {
9580 zig_panic("TODO comptime switch var");
9581 }
95699582 }
95709583
95719584 ir_build_enum_field_ptr_from(&ira->new_irb, &instruction->base, target_value_ptr, field);
test/cases/switch.zig+22
......@@ -129,3 +129,25 @@ fn switchWithMultipleExpressions() {
129129fn returnsFive() -> i32 {
130130 5
131131}
132
133
134const Number = enum {
135 One: u64,
136 Two: u8,
137 Three: f32,
138};
139
140const number = Number.Three { 1.23 };
141
142fn returnsFalse() -> bool {
143 switch (number) {
144 Number.One => |x| return x > 1234,
145 Number.Two => |x| return x == 'a',
146 Number.Three => |x| return x > 12.34,
147 }
148}
149fn switchOnConstEnumWithVar() {
150 @setFnTest(this);
151
152 assert(!returnsFalse());
153}