authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-09-21 18:47:12-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-09-21 18:47:12-04:00
log2e2740716103784334348c491a0e4d84052c5734
treef63b555951f38c8ff8272fcc6aac77f4fe7d4df8
parent9e5cd43e6d2caaaa2226be56c0886d73a200e78b
signaturelock-open Commit is signed but in an unrecognized format.

stage1: unify 2 implementations of pointer deref

I found out there were accidentally two code paths in zig ir for pointer dereference. So this should fix a few bugs. closes #1486

4 files changed, 59 insertions(+), 56 deletions(-)

src/ir.cpp+46-55
......@@ -153,6 +153,8 @@ static ZigType *adjust_ptr_align(CodeGen *g, ZigType *ptr_type, uint32_t new_ali
153153static ZigType *adjust_slice_align(CodeGen *g, ZigType *slice_type, uint32_t new_align);
154154static void buf_read_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue *val);
155155static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue *val);
156static Error ir_read_const_ptr(IrAnalyze *ira, AstNode *source_node,
157 ConstExprValue *out_val, ConstExprValue *ptr_val);
156158
157159static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *const_val) {
158160 assert(get_src_ptr_type(const_val->type) != nullptr);
......@@ -11205,34 +11207,42 @@ static IrInstruction *ir_implicit_cast(IrAnalyze *ira, IrInstruction *value, Zig
1120511207}
1120611208
1120711209static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruction, IrInstruction *ptr) {
11210 Error err;
1120811211 ZigType *type_entry = ptr->value.type;
1120911212 if (type_is_invalid(type_entry)) {
1121011213 return ira->codegen->invalid_instruction;
1121111214 } else if (type_entry->id == ZigTypeIdPointer) {
1121211215 ZigType *child_type = type_entry->data.pointer.child_type;
11216 // dereferencing a *u0 is comptime known to be 0
11217 if (child_type->id == ZigTypeIdInt && child_type->data.integral.bit_count == 0) {
11218 IrInstruction *result = ir_create_const(&ira->new_irb, source_instruction->scope,
11219 source_instruction->source_node, child_type);
11220 init_const_unsigned_negative(&result->value, child_type, 0, false);
11221 return result;
11222 }
1121311223 if (instr_is_comptime(ptr)) {
11224 if (ptr->value.special == ConstValSpecialUndef) {
11225 ir_add_error(ira, ptr, buf_sprintf("attempt to dereference undefined value"));
11226 return ira->codegen->invalid_instruction;
11227 }
1121411228 if (ptr->value.data.x_ptr.mut == ConstPtrMutComptimeConst ||
1121511229 ptr->value.data.x_ptr.mut == ConstPtrMutComptimeVar)
1121611230 {
11217 ConstExprValue *pointee = ir_const_ptr_pointee(ira, &ptr->value, source_instruction->source_node);
11218 if (pointee == nullptr)
11219 return ira->codegen->invalid_instruction;
11231 ConstExprValue *pointee = const_ptr_pointee_unchecked(ira->codegen, &ptr->value);
1122011232 if (pointee->special != ConstValSpecialRuntime) {
1122111233 IrInstruction *result = ir_create_const(&ira->new_irb, source_instruction->scope,
1122211234 source_instruction->source_node, child_type);
11223 copy_const_val(&result->value, pointee, ptr->value.data.x_ptr.mut == ConstPtrMutComptimeConst);
11235
11236 if ((err = ir_read_const_ptr(ira, source_instruction->source_node, &result->value,
11237 &ptr->value)))
11238 {
11239 return ira->codegen->invalid_instruction;
11240 }
1122411241 result->value.type = child_type;
1122511242 return result;
1122611243 }
1122711244 }
1122811245 }
11229 // dereferencing a *u0 is comptime known to be 0
11230 if (child_type->id == ZigTypeIdInt && child_type->data.integral.bit_count == 0) {
11231 IrInstruction *result = ir_create_const(&ira->new_irb, source_instruction->scope,
11232 source_instruction->source_node, child_type);
11233 init_const_unsigned_negative(&result->value, child_type, 0, false);
11234 return result;
11235 }
1123611246 // TODO if the instruction is a const ref instruction we can skip it
1123711247 IrInstruction *load_ptr_instruction = ir_build_load_ptr(&ira->new_irb, source_instruction->scope,
1123811248 source_instruction->source_node, ptr);
......@@ -13931,10 +13941,16 @@ static ZigType *ir_analyze_instruction_call(IrAnalyze *ira, IrInstructionCall *c
1393113941static Error ir_read_const_ptr(IrAnalyze *ira, AstNode *source_node,
1393213942 ConstExprValue *out_val, ConstExprValue *ptr_val)
1393313943{
13944 Error err;
1393413945 assert(out_val->type != nullptr);
1393513946
1393613947 ConstExprValue *pointee = const_ptr_pointee_unchecked(ira->codegen, ptr_val);
1393713948
13949 if ((err = type_resolve(ira->codegen, pointee->type, ResolveStatusSizeKnown)))
13950 return ErrorSemanticAnalyzeFail;
13951 if ((err = type_resolve(ira->codegen, out_val->type, ResolveStatusSizeKnown)))
13952 return ErrorSemanticAnalyzeFail;
13953
1393813954 size_t src_size = type_size(ira->codegen, pointee->type);
1393913955 size_t dst_size = type_size(ira->codegen, out_val->type);
1394013956
......@@ -13957,48 +13973,6 @@ static Error ir_read_const_ptr(IrAnalyze *ira, AstNode *source_node,
1395713973 return ErrorNone;
1395813974}
1395913975
13960static ZigType *ir_analyze_dereference(IrAnalyze *ira, IrInstructionUnOp *un_op_instruction) {
13961 Error err;
13962 IrInstruction *value = un_op_instruction->value->other;
13963
13964 ZigType *ptr_type = value->value.type;
13965 ZigType *child_type;
13966 if (type_is_invalid(ptr_type)) {
13967 return ira->codegen->builtin_types.entry_invalid;
13968 } else if (ptr_type->id == ZigTypeIdPointer) {
13969 if (ptr_type->data.pointer.ptr_len == PtrLenUnknown) {
13970 ir_add_error_node(ira, un_op_instruction->base.source_node,
13971 buf_sprintf("index syntax required for unknown-length pointer type '%s'",
13972 buf_ptr(&ptr_type->name)));
13973 return ira->codegen->builtin_types.entry_invalid;
13974 }
13975 child_type = ptr_type->data.pointer.child_type;
13976 } else {
13977 ir_add_error_node(ira, un_op_instruction->base.source_node,
13978 buf_sprintf("attempt to dereference non-pointer type '%s'",
13979 buf_ptr(&ptr_type->name)));
13980 return ira->codegen->builtin_types.entry_invalid;
13981 }
13982
13983 // this dereference is always an rvalue because in the IR gen we identify lvalue and emit
13984 // one of the ptr instructions
13985
13986 if (instr_is_comptime(value)) {
13987 ConstExprValue *comptime_value = ir_resolve_const(ira, value, UndefBad);
13988 if (comptime_value == nullptr)
13989 return ira->codegen->builtin_types.entry_invalid;
13990
13991 ConstExprValue *out_val = ir_build_const_from(ira, &un_op_instruction->base);
13992 out_val->type = child_type;
13993 if ((err = ir_read_const_ptr(ira, un_op_instruction->base.source_node, out_val, comptime_value)))
13994 return ira->codegen->builtin_types.entry_invalid;
13995 return child_type;
13996 }
13997
13998 ir_build_load_ptr_from(&ira->new_irb, &un_op_instruction->base, value);
13999 return child_type;
14000}
14001
1400213976static ZigType *ir_analyze_maybe(IrAnalyze *ira, IrInstructionUnOp *un_op_instruction) {
1400313977 Error err;
1400413978 IrInstruction *value = un_op_instruction->value->other;
......@@ -14131,8 +14105,25 @@ static ZigType *ir_analyze_instruction_un_op(IrAnalyze *ira, IrInstructionUnOp *
1413114105 case IrUnOpNegation:
1413214106 case IrUnOpNegationWrap:
1413314107 return ir_analyze_negation(ira, un_op_instruction);
14134 case IrUnOpDereference:
14135 return ir_analyze_dereference(ira, un_op_instruction);
14108 case IrUnOpDereference: {
14109 IrInstruction *ptr = un_op_instruction->value->other;
14110 if (type_is_invalid(ptr->value.type))
14111 return ira->codegen->builtin_types.entry_invalid;
14112 ZigType *ptr_type = ptr->value.type;
14113 if (ptr_type->id == ZigTypeIdPointer && ptr_type->data.pointer.ptr_len == PtrLenUnknown) {
14114 ir_add_error_node(ira, un_op_instruction->base.source_node,
14115 buf_sprintf("index syntax required for unknown-length pointer type '%s'",
14116 buf_ptr(&ptr_type->name)));
14117 return ira->codegen->builtin_types.entry_invalid;
14118 }
14119 // this dereference is always an rvalue because in the IR gen we identify lvalue and emit
14120 // one of the ptr instructions
14121 IrInstruction *result = ir_get_deref(ira, &un_op_instruction->base, ptr);
14122 if (result == ira->codegen->invalid_instruction)
14123 return ira->codegen->builtin_types.entry_invalid;
14124 ir_link_new_instruction(result, &un_op_instruction->base);
14125 return result->value.type;
14126 }
1413614127 case IrUnOpOptional:
1413714128 return ir_analyze_maybe(ira, un_op_instruction);
1413814129 }
test/behavior.zig+1
......@@ -15,6 +15,7 @@ comptime {
1515 _ = @import("cases/bugs/1381.zig");
1616 _ = @import("cases/bugs/1421.zig");
1717 _ = @import("cases/bugs/1442.zig");
18 _ = @import("cases/bugs/1486.zig");
1819 _ = @import("cases/bugs/394.zig");
1920 _ = @import("cases/bugs/655.zig");
2021 _ = @import("cases/bugs/656.zig");
test/cases/bugs/1486.zig created+11
......@@ -0,0 +1,11 @@
1const assert = @import("std").debug.assert;
2
3const ptr = &global;
4var global: u64 = 123;
5
6test "constant pointer to global variable causes runtime load" {
7 global = 1234;
8 assert(&global == ptr);
9 assert(ptr.* == 1234);
10}
11
test/compile_errors.zig+1-1
......@@ -2896,7 +2896,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
28962896 \\ _ = a.*;
28972897 \\}
28982898 ,
2899 ".tmp_source.zig:3:9: error: use of undefined value",
2899 ".tmp_source.zig:3:9: error: attempt to dereference undefined value",
29002900 );
29012901
29022902 cases.add(