Commit 55ea855e2c

LemonBoy <thatlemon@gmail.com>
2020-02-25 13:10:29
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
1 parent 8981221
Changed files (3)
src
test
src/ir.cpp
@@ -27851,9 +27851,15 @@ static IrInstGen *ir_analyze_int_to_ptr(IrAnalyze *ira, IrInst* source_instr, Ir
         }
 
         IrInstGen *result = ir_const(ira, source_instr, ptr_type);
-        result->value->data.x_ptr.special = ConstPtrSpecialHardCodedAddr;
-        result->value->data.x_ptr.mut = ConstPtrMutRuntimeVar;
-        result->value->data.x_ptr.data.hard_coded_addr.addr = addr;
+        if (ptr_type->id == ZigTypeIdOptional && addr == 0) {
+            result->value->data.x_ptr.special = ConstPtrSpecialNull;
+            result->value->data.x_ptr.mut = ConstPtrMutComptimeConst;
+        } else {
+            result->value->data.x_ptr.special = ConstPtrSpecialHardCodedAddr;
+            result->value->data.x_ptr.mut = ConstPtrMutRuntimeVar;
+            result->value->data.x_ptr.data.hard_coded_addr.addr = addr;
+        }
+
         return result;
     }
 
@@ -27911,15 +27917,15 @@ static IrInstGen *ir_analyze_instruction_ptr_to_int(IrAnalyze *ira, IrInstSrcPtr
 
     ZigType *usize = ira->codegen->builtin_types.entry_usize;
 
-    // We check size explicitly so we can use get_src_ptr_type here.
-    if (get_src_ptr_type(target->value->type) == nullptr) {
+    ZigType *src_ptr_type = get_src_ptr_type(target->value->type);
+    if (src_ptr_type == nullptr) {
         ir_add_error(ira, &target->base,
                 buf_sprintf("expected pointer, found '%s'", buf_ptr(&target->value->type->name)));
         return ira->codegen->invalid_inst_gen;
     }
 
     bool has_bits;
-    if ((err = type_has_bits2(ira->codegen, target->value->type, &has_bits)))
+    if ((err = type_has_bits2(ira->codegen, src_ptr_type, &has_bits)))
         return ira->codegen->invalid_inst_gen;
 
     if (!has_bits) {
@@ -27932,11 +27938,19 @@ static IrInstGen *ir_analyze_instruction_ptr_to_int(IrAnalyze *ira, IrInstSrcPtr
         ZigValue *val = ir_resolve_const(ira, target, UndefBad);
         if (!val)
             return ira->codegen->invalid_inst_gen;
-        if (val->type->id == ZigTypeIdPointer && val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr) {
+
+        // Since we've already run this type trough get_codegen_ptr_type it is
+        // safe to access the x_ptr fields
+        if (val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr) {
             IrInstGen *result = ir_const(ira, &instruction->base.base, usize);
             bigint_init_unsigned(&result->value->data.x_bigint, val->data.x_ptr.data.hard_coded_addr.addr);
             result->value->type = usize;
             return result;
+        } else if (val->data.x_ptr.special == ConstPtrSpecialNull) {
+            IrInstGen *result = ir_const(ira, &instruction->base.base, usize);
+            bigint_init_unsigned(&result->value->data.x_bigint, 0);
+            result->value->type = usize;
+            return result;
         }
     }
 
test/stage1/behavior/pointers.zig
@@ -318,3 +318,15 @@ test "pointer arithmetic affects the alignment" {
         expect(@typeInfo(@TypeOf(ptr4)).Pointer.alignment == 4);
     }
 }
+
+test "@ptrToInt on null optional at comptime" {
+    {
+        const pointer = @intToPtr(?*u8, 0x000);
+        const x = @ptrToInt(pointer);
+        comptime expect(0 == @ptrToInt(pointer));
+    }
+    {
+        const pointer = @intToPtr(?*u8, 0xf00);
+        comptime expect(0xf00 == @ptrToInt(pointer));
+    }
+}
test/compile_errors.zig
@@ -3,6 +3,15 @@ const builtin = @import("builtin");
 const Target = @import("std").Target;
 
 pub fn addCases(cases: *tests.CompileErrorContext) void {
+    cases.addTest("@ptrToInt with pointer to zero-sized type",
+        \\export fn entry() void {
+        \\    var pointer: ?*u0 = null;
+        \\    var x = @ptrToInt(pointer);
+        \\}
+    , &[_][]const u8{
+        "tmp.zig:3:23: error: pointer to size 0 type has no address",
+    });
+
     cases.addTest("slice to pointer conversion mismatch",
         \\pub fn bytesAsSlice(bytes: var) [*]align(1) const u16 {
         \\    return @ptrCast([*]align(1) const u16, bytes.ptr)[0..1];