authorgravatar for thatlemon@gmail.comLemonBoy <thatlemon@gmail.com> 2020-02-25 13:10:29+01:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-02-25 17:38:56-05:00
log55ea855e2cefe8dcdb5fab9be66aa6ca3acd0370
tree8b08c867108b6e589ea5e6504728199a4482fbd5
parent89812217b4e5fee7e2851266c17c9d47204a1573

ir: Various fixes for comptime ptr handling

* Correctly fold ptrToInt on optional types * Generate null as ConstPtrSpecialNull in intToPtr * Correctly stop ptrToInt on ?*T where T is zero-sized Closes #4535

3 files changed, 42 insertions(+), 7 deletions(-)

src/ir.cpp+21-7
...@@ -27851,9 +27851,15 @@ static IrInstGen *ir_analyze_int_to_ptr(IrAnalyze *ira, IrInst* source_instr, Ir...@@ -27851,9 +27851,15 @@ static IrInstGen *ir_analyze_int_to_ptr(IrAnalyze *ira, IrInst* source_instr, Ir
27851 }27851 }
2785227852
27853 IrInstGen *result = ir_const(ira, source_instr, ptr_type);27853 IrInstGen *result = ir_const(ira, source_instr, ptr_type);
27854 result->value->data.x_ptr.special = ConstPtrSpecialHardCodedAddr;27854 if (ptr_type->id == ZigTypeIdOptional && addr == 0) {
27855 result->value->data.x_ptr.mut = ConstPtrMutRuntimeVar;27855 result->value->data.x_ptr.special = ConstPtrSpecialNull;
27856 result->value->data.x_ptr.data.hard_coded_addr.addr = addr;27856 result->value->data.x_ptr.mut = ConstPtrMutComptimeConst;
27857 } else {
27858 result->value->data.x_ptr.special = ConstPtrSpecialHardCodedAddr;
27859 result->value->data.x_ptr.mut = ConstPtrMutRuntimeVar;
27860 result->value->data.x_ptr.data.hard_coded_addr.addr = addr;
27861 }
27862
27857 return result;27863 return result;
27858 }27864 }
2785927865
...@@ -27911,15 +27917,15 @@ static IrInstGen *ir_analyze_instruction_ptr_to_int(IrAnalyze *ira, IrInstSrcPtr...@@ -27911,15 +27917,15 @@ static IrInstGen *ir_analyze_instruction_ptr_to_int(IrAnalyze *ira, IrInstSrcPtr
2791127917
27912 ZigType *usize = ira->codegen->builtin_types.entry_usize;27918 ZigType *usize = ira->codegen->builtin_types.entry_usize;
2791327919
27914 // We check size explicitly so we can use get_src_ptr_type here.27920 ZigType *src_ptr_type = get_src_ptr_type(target->value->type);
27915 if (get_src_ptr_type(target->value->type) == nullptr) {27921 if (src_ptr_type == nullptr) {
27916 ir_add_error(ira, &target->base,27922 ir_add_error(ira, &target->base,
27917 buf_sprintf("expected pointer, found '%s'", buf_ptr(&target->value->type->name)));27923 buf_sprintf("expected pointer, found '%s'", buf_ptr(&target->value->type->name)));
27918 return ira->codegen->invalid_inst_gen;27924 return ira->codegen->invalid_inst_gen;
27919 }27925 }
2792027926
27921 bool has_bits;27927 bool has_bits;
27922 if ((err = type_has_bits2(ira->codegen, target->value->type, &has_bits)))27928 if ((err = type_has_bits2(ira->codegen, src_ptr_type, &has_bits)))
27923 return ira->codegen->invalid_inst_gen;27929 return ira->codegen->invalid_inst_gen;
2792427930
27925 if (!has_bits) {27931 if (!has_bits) {
...@@ -27932,11 +27938,19 @@ static IrInstGen *ir_analyze_instruction_ptr_to_int(IrAnalyze *ira, IrInstSrcPtr...@@ -27932,11 +27938,19 @@ static IrInstGen *ir_analyze_instruction_ptr_to_int(IrAnalyze *ira, IrInstSrcPtr
27932 ZigValue *val = ir_resolve_const(ira, target, UndefBad);27938 ZigValue *val = ir_resolve_const(ira, target, UndefBad);
27933 if (!val)27939 if (!val)
27934 return ira->codegen->invalid_inst_gen;27940 return ira->codegen->invalid_inst_gen;
27935 if (val->type->id == ZigTypeIdPointer && val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr) {27941
27942 // Since we've already run this type trough get_codegen_ptr_type it is
27943 // safe to access the x_ptr fields
27944 if (val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr) {
27936 IrInstGen *result = ir_const(ira, &instruction->base.base, usize);27945 IrInstGen *result = ir_const(ira, &instruction->base.base, usize);
27937 bigint_init_unsigned(&result->value->data.x_bigint, val->data.x_ptr.data.hard_coded_addr.addr);27946 bigint_init_unsigned(&result->value->data.x_bigint, val->data.x_ptr.data.hard_coded_addr.addr);
27938 result->value->type = usize;27947 result->value->type = usize;
27939 return result;27948 return result;
27949 } else if (val->data.x_ptr.special == ConstPtrSpecialNull) {
27950 IrInstGen *result = ir_const(ira, &instruction->base.base, usize);
27951 bigint_init_unsigned(&result->value->data.x_bigint, 0);
27952 result->value->type = usize;
27953 return result;
27940 }27954 }
27941 }27955 }
2794227956
test/compile_errors.zig+9
...@@ -3,6 +3,15 @@ const builtin = @import("builtin");...@@ -3,6 +3,15 @@ const builtin = @import("builtin");
3const Target = @import("std").Target;3const Target = @import("std").Target;
44
5pub fn addCases(cases: *tests.CompileErrorContext) void {5pub fn addCases(cases: *tests.CompileErrorContext) void {
6 cases.addTest("@ptrToInt with pointer to zero-sized type",
7 \\export fn entry() void {
8 \\ var pointer: ?*u0 = null;
9 \\ var x = @ptrToInt(pointer);
10 \\}
11 , &[_][]const u8{
12 "tmp.zig:3:23: error: pointer to size 0 type has no address",
13 });
14
6 cases.addTest("slice to pointer conversion mismatch",15 cases.addTest("slice to pointer conversion mismatch",
7 \\pub fn bytesAsSlice(bytes: var) [*]align(1) const u16 {16 \\pub fn bytesAsSlice(bytes: var) [*]align(1) const u16 {
8 \\ return @ptrCast([*]align(1) const u16, bytes.ptr)[0..1];17 \\ return @ptrCast([*]align(1) const u16, bytes.ptr)[0..1];
test/stage1/behavior/pointers.zig+12
...@@ -318,3 +318,15 @@ test "pointer arithmetic affects the alignment" {...@@ -318,3 +318,15 @@ test "pointer arithmetic affects the alignment" {
318 expect(@typeInfo(@TypeOf(ptr4)).Pointer.alignment == 4);318 expect(@typeInfo(@TypeOf(ptr4)).Pointer.alignment == 4);
319 }319 }
320}320}
321
322test "@ptrToInt on null optional at comptime" {
323 {
324 const pointer = @intToPtr(?*u8, 0x000);
325 const x = @ptrToInt(pointer);
326 comptime expect(0 == @ptrToInt(pointer));
327 }
328 {
329 const pointer = @intToPtr(?*u8, 0xf00);
330 comptime expect(0xf00 == @ptrToInt(pointer));
331 }
332}