diff options
| author | Robin Voetter <robin@voetter.nl> | 2022-11-30 23:28:07 +0100 |
|---|---|---|
| committer | Robin Voetter <robin@voetter.nl> | 2023-04-09 01:51:51 +0200 |
| commit | caf8461af8df9a34abc5985042d98b8188575cd0 (patch) | |
| tree | 09db4533e38137d70c64c5aaccc62443916038e7 /src/codegen/spirv.zig | |
| parent | 2a8e784989b9053ce609a38a9d384a77ce5badaa (diff) | |
| download | zig-caf8461af8df9a34abc5985042d98b8188575cd0.tar.gz zig-caf8461af8df9a34abc5985042d98b8188575cd0.zip | |
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).
Diffstat (limited to 'src/codegen/spirv.zig')
| -rw-r--r-- | src/codegen/spirv.zig | 51 |
1 files changed, 36 insertions, 15 deletions
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; } |
