diff --git a/src/codegen/spirv.zig b/src/codegen/spirv.zig index 496bd0150b..11737943fe 100644 --- a/src/codegen/spirv.zig +++ b/src/codegen/spirv.zig @@ -694,24 +694,7 @@ pub const DeclGen = struct { .none => ty, else => ty.slicePtrFieldType(mod), }; - const ptr_id = switch (ptr.addr) { - .decl => |decl| try self.constructDeclRef(ptr_ty, decl), - .mut_decl => |mut_decl| try self.constructDeclRef(ptr_ty, mut_decl.decl), // TODO - .int => |int| blk: { - const ptr_id = self.spv.allocId(); - // TODO: This can probably be an OpSpecConstantOp Bitcast, but - // that is not implemented by Mesa yet. Therefore, just generate it - // as a runtime operation. - try self.func.body.emit(self.spv.gpa, .OpConvertUToPtr, .{ - .id_result_type = try self.resolveTypeId(ptr_ty), - .id_result = ptr_id, - .integer_value = try self.constant(Type.usize, int.toValue(), .direct), - }); - break :blk ptr_id; - }, - .comptime_field => unreachable, - else => |tag| return self.todo("pointer value of type {s}", .{@tagName(tag)}), - }; + const ptr_id = try self.constantPtr(ptr_ty, val); if (ptr.len == .none) { return ptr_id; } @@ -818,6 +801,38 @@ pub const DeclGen = struct { } } + fn constantPtr(self: *DeclGen, ptr_ty: Type, ptr_val: Value) !IdRef { + const result_ty_ref = try self.resolveType(ptr_ty, .direct); + const mod = self.module; + switch (mod.intern_pool.indexToKey(ptr_val.toIntern()).ptr.addr) { + .decl => |decl| return try self.constructDeclRef(ptr_ty, decl), + .mut_decl => |decl_mut| return try self.constructDeclRef(ptr_ty, decl_mut.decl), + .int => |int| { + const ptr_id = self.spv.allocId(); + // TODO: This can probably be an OpSpecConstantOp Bitcast, but + // that is not implemented by Mesa yet. Therefore, just generate it + // as a runtime operation. + try self.func.body.emit(self.spv.gpa, .OpConvertUToPtr, .{ + .id_result_type = self.typeId(result_ty_ref), + .id_result = ptr_id, + .integer_value = try self.constant(Type.usize, int.toValue(), .direct), + }); + return ptr_id; + }, + .eu_payload => unreachable, // TODO + .opt_payload => unreachable, // TODO + .comptime_field => unreachable, + .elem => |elem_ptr| { + const elem_ptr_ty = mod.intern_pool.typeOf(elem_ptr.base).toType(); + const parent_ptr_id = try self.constantPtr(elem_ptr_ty, elem_ptr.base.toValue()); + const size_ty_ref = try self.sizeType(); + const index_id = try self.constInt(size_ty_ref, elem_ptr.index); + return self.ptrAccessChain(result_ty_ref, parent_ptr_id, index_id, &.{}); + }, + .field => unreachable, // TODO + } + } + // Turn a Zig type's name into a cache reference. fn resolveTypeName(self: *DeclGen, ty: Type) !CacheString { var name = std.ArrayList(u8).init(self.gpa); diff --git a/test/behavior/pointers.zig b/test/behavior/pointers.zig index d007e7b480..2a878e89c9 100644 --- a/test/behavior/pointers.zig +++ b/test/behavior/pointers.zig @@ -141,7 +141,6 @@ test "peer type resolution with C pointers" { } test "peer type resolution with C pointer and const pointer" { - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; var ptr_c: [*c]u8 = undefined; const ptr_const: u8 = undefined; try expect(@TypeOf(ptr_c, &ptr_const) == [*c]const u8); @@ -314,7 +313,6 @@ test "allow any sentinel" { test "pointer sentinel with enums" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; const S = struct { const Number = enum { @@ -336,7 +334,6 @@ test "pointer sentinel with optional element" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; const S = struct { fn doTheTest() !void { @@ -353,7 +350,6 @@ test "pointer sentinel with +inf" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; const S = struct { fn doTheTest() !void { @@ -374,7 +370,6 @@ test "pointer to array at fixed address" { } test "pointer arithmetic affects the alignment" { - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; { var ptr: [*]align(8) u32 = undefined; var x: usize = 1; @@ -430,7 +425,6 @@ test "indexing array with sentinel returns correct type" { test "element pointer to slice" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; const S = struct { fn doTheTest() !void { @@ -453,7 +447,6 @@ test "element pointer to slice" { test "element pointer arithmetic to slice" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; const S = struct { fn doTheTest() !void { @@ -478,7 +471,6 @@ test "element pointer arithmetic to slice" { test "array slicing to slice" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; const S = struct { fn doTheTest() !void { diff --git a/test/behavior/slice.zig b/test/behavior/slice.zig index c04c018017..ce836eb337 100644 --- a/test/behavior/slice.zig +++ b/test/behavior/slice.zig @@ -121,7 +121,6 @@ test "slice of type" { test "generic malloc free" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; const a = memAlloc(u8, 10) catch unreachable; memFree(u8, a); @@ -302,7 +301,6 @@ test "slice type with custom alignment" { test "obtaining a null terminated slice" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // here we have a normal array var buf: [50]u8 = undefined; @@ -623,7 +621,6 @@ test "type coercion of pointer to anon struct literal to pointer to slice" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; const S = struct { const U = union {