From caf8461af8df9a34abc5985042d98b8188575cd0 Mon Sep 17 00:00:00 2001 From: Robin Voetter Date: Wed, 30 Nov 2022 23:28:07 +0100 Subject: spirv: make locals generic pointers Taking the address of a local variable should result in a generic pointer - too much code breaks if we do not do this. We cannot lower locals into the generic storage class directly though, so instead, lower the variables into the Function storage class implicitly, and convert the pointer to a generic pointer. Also Correct OpInboundsAccessChain generation (we only need the one index). --- src/codegen/spirv.zig | 51 ++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 36 insertions(+), 15 deletions(-) (limited to 'src/codegen/spirv.zig') diff --git a/src/codegen/spirv.zig b/src/codegen/spirv.zig index 4deb9a225b..22c3791df0 100644 --- a/src/codegen/spirv.zig +++ b/src/codegen/spirv.zig @@ -1306,12 +1306,11 @@ pub const DeclGen = struct { }; const result_id = self.spv.allocId(); - const indexes = [_]IdRef{index}; - try self.func.body.emit(self.spv.gpa, .OpInBoundsAccessChain, .{ + try self.func.body.emit(self.spv.gpa, .OpInBoundsPtrAccessChain, .{ .id_result_type = spv_ptr_ty, .id_result = result_id, .base = slice_ptr, - .indexes = &indexes, + .element = index, }); return result_id; } @@ -1340,12 +1339,11 @@ pub const DeclGen = struct { const elem_ptr = blk: { const result_id = self.spv.allocId(); - const indexes = [_]IdRef{index}; - try self.func.body.emit(self.spv.gpa, .OpInBoundsAccessChain, .{ + try self.func.body.emit(self.spv.gpa, .OpInBoundsPtrAccessChain, .{ .id_result_type = ptr_ty_id, .id_result = result_id, .base = slice_ptr, - .indexes = &indexes, + .element = index, }); break :blk result_id; }; @@ -1448,22 +1446,45 @@ pub const DeclGen = struct { fn airAlloc(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { if (self.liveness.isUnused(inst)) return null; const ty = self.air.typeOfIndex(inst); - const result_type_id = try self.resolveTypeId(ty); + const result_ty_ref = try self.resolveType(ty, .direct); + const result_ty_id = self.typeId(result_ty_ref); const result_id = self.spv.allocId(); - // Rather than generating into code here, we're just going to generate directly into the functions section so that - // variable declarations appear in the first block of the function. const storage_class = spirvStorageClass(ty.ptrAddressSpace()); - const section = if (storage_class == .Function or storage_class == .Generic) - &self.func.prologue - else - &self.spv.sections.types_globals_constants; + const ptr_ty_id = switch (storage_class) { + .Generic => blk: { + const payload = try self.spv.arena.create(SpvType.Payload.Pointer); + payload.* = self.spv.typeRefType(result_ty_ref).payload(.pointer).*; + payload.storage_class = .Function; + break :blk try self.spv.resolveTypeId(SpvType.initPayload(&payload.base)); + }, + else => result_ty_id, + }; + const actual_storage_class = switch (storage_class) { + .Generic, .Function => .Function, + else => storage_class, + }; + const section = switch (storage_class) { + // SPIR-V requires that OpVariable declarations for locals go into the first block, so we are just going to + // directly generate them into func.prologue instead of the body. + .Generic, .Function => &self.func.prologue, + else => &self.spv.sections.types_globals_constants, + }; try section.emit(self.spv.gpa, .OpVariable, .{ - .id_result_type = result_type_id, + .id_result_type = ptr_ty_id, .id_result = result_id, - .storage_class = storage_class, + .storage_class = actual_storage_class, }); + if (storage_class == .Generic) { + const casted_result_id = self.spv.allocId(); + try self.func.body.emit(self.spv.gpa, .OpPtrCastToGeneric, .{ + .id_result_type = result_ty_id, + .id_result = casted_result_id, + .pointer = result_id, + }); + return casted_result_id; + } return result_id; } -- cgit v1.2.3