Commit cd9f6001af

Robin Voetter <robin@voetter.nl>
2021-08-20 02:53:29
Address Spaces: decl_ref, *?T => *T, and *(E!T) -> *T
1 parent 6023108
Changed files (3)
src/Module.zig
@@ -353,7 +353,7 @@ pub const Decl = struct {
         /// to require re-analysis.
         outdated,
     },
-    /// Whether `typed_value`, `align_val`, `linksection_val` and `has_addrspace` are populated.
+    /// Whether `typed_value`, `align_val`, `linksection_val` and `addrspace` are populated.
     has_tv: bool,
     /// If `true` it means the `Decl` is the resource owner of the type/value associated
     /// with it. That means when `Decl` is destroyed, the cleanup code should additionally
@@ -4401,6 +4401,34 @@ pub fn ptrType(
     });
 }
 
+/// Create a pointer type with an explicit address space. This function might return results
+/// of either simplePtrType or ptrType, depending on the address space.
+/// TODO(Snektron) unify ptrType functions.
+pub fn simplePtrTypeWithAddressSpace(
+    arena: *Allocator,
+    elem_ty: Type,
+    mutable: bool,
+    size: std.builtin.TypeInfo.Pointer.Size,
+    address_space: std.builtin.AddressSpace,
+) Allocator.Error!Type {
+    switch (address_space) {
+        .generic => return simplePtrType(arena, elem_ty, mutable, size),
+        else => return ptrType(
+            arena,
+            elem_ty,
+            null,
+            0,
+            address_space,
+            0,
+            0,
+            mutable,
+            false,
+            false,
+            size,
+        ),
+    }
+}
+
 pub fn optionalType(arena: *Allocator, child_type: Type) Allocator.Error!Type {
     switch (child_type.tag()) {
         .single_const_pointer => return Type.Tag.optional_single_const_pointer.create(
src/Sema.zig
@@ -3658,7 +3658,13 @@ fn zirOptionalPayloadPtr(
     }
 
     const child_type = try opt_type.optionalChildAlloc(sema.arena);
-    const child_pointer = try Module.simplePtrType(sema.arena, child_type, !optional_ptr_ty.isConstPtr(), .One);
+    const child_pointer = try Module.simplePtrTypeWithAddressSpace(
+        sema.arena,
+        child_type,
+        !optional_ptr_ty.isConstPtr(),
+        .One,
+        optional_ptr_ty.ptrAddressSpace(),
+    );
 
     if (try sema.resolveDefinedValue(block, src, optional_ptr)) |pointer_val| {
         if (try pointer_val.pointerDeref(sema.arena)) |val| {
@@ -3773,7 +3779,13 @@ fn zirErrUnionPayloadPtr(
         return sema.mod.fail(&block.base, src, "expected error union type, found {}", .{operand_ty.elemType()});
 
     const payload_ty = operand_ty.elemType().errorUnionPayload();
-    const operand_pointer_ty = try Module.simplePtrType(sema.arena, payload_ty, !operand_ty.isConstPtr(), .One);
+    const operand_pointer_ty = try Module.simplePtrTypeWithAddressSpace(
+        sema.arena,
+        payload_ty,
+        !operand_ty.isConstPtr(),
+        .One,
+        operand_ty.ptrAddressSpace(),
+    );
 
     if (try sema.resolveDefinedValue(block, src, operand)) |pointer_val| {
         if (try pointer_val.pointerDeref(sema.arena)) |val| {
@@ -9525,11 +9537,11 @@ fn analyzeDeclRef(sema: *Sema, decl: *Decl) CompileError!Air.Inst.Ref {
     const decl_tv = try decl.typedValue();
     if (decl_tv.val.castTag(.variable)) |payload| {
         const variable = payload.data;
-        const ty = try Module.simplePtrType(sema.arena, decl_tv.ty, variable.is_mutable, .One);
+        const ty = try Module.simplePtrTypeWithAddressSpace(sema.arena, decl_tv.ty, variable.is_mutable, .One, decl.@"addrspace");
         return sema.addConstant(ty, try Value.Tag.decl_ref.create(sema.arena, decl));
     }
     return sema.addConstant(
-        try Module.simplePtrType(sema.arena, decl_tv.ty, false, .One),
+        try Module.simplePtrTypeWithAddressSpace(sema.arena, decl_tv.ty, false, .One, decl.@"addrspace"),
         try Value.Tag.decl_ref.create(sema.arena, decl),
     );
 }
src/type.zig
@@ -1526,6 +1526,30 @@ pub const Type = extern union {
         }
     }
 
+    pub fn ptrAddressSpace(self: Type) std.builtin.AddressSpace {
+        return switch (self.tag()) {
+            .single_const_pointer_to_comptime_int,
+            .const_slice_u8,
+            .single_const_pointer,
+            .single_mut_pointer,
+            .many_const_pointer,
+            .many_mut_pointer,
+            .c_const_pointer,
+            .c_mut_pointer,
+            .const_slice,
+            .mut_slice,
+            .inferred_alloc_const,
+            .inferred_alloc_mut,
+            .manyptr_u8,
+            .manyptr_const_u8,
+            => .generic,
+
+            .pointer => self.castTag(.pointer).?.data.@"addrspace",
+
+            else => unreachable,
+        };
+    }
+
     /// Asserts that hasCodeGenBits() is true.
     pub fn abiAlignment(self: Type, target: Target) u32 {
         return switch (self.tag()) {