diff options
| author | Robin Voetter <robin@voetter.nl> | 2023-04-10 18:34:30 +0200 |
|---|---|---|
| committer | Robin Voetter <robin@voetter.nl> | 2023-05-11 20:31:50 +0200 |
| commit | dfecf89d06dc2caad41ff54b05240506ea2c47e8 (patch) | |
| tree | 46cb08a073d4e346188fc2c323d7b3dede446144 | |
| parent | 5d896a6cc6b7127dd4db0bd386ebe33da82d7824 (diff) | |
| download | zig-dfecf89d06dc2caad41ff54b05240506ea2c47e8.tar.gz zig-dfecf89d06dc2caad41ff54b05240506ea2c47e8.zip | |
spirv: fix OpFunctionCall parameters interleaving with insts
resolve() is now able to emit instructions. If usage of this function is
interleaved with calls to emitRaw() and writeOperand(), then an
instruction may get inserted between operands, causing an invalid module.
The solution here is to just perform a temporary allocation.
| -rw-r--r-- | src/codegen/spirv.zig | 20 |
1 files changed, 15 insertions, 5 deletions
diff --git a/src/codegen/spirv.zig b/src/codegen/spirv.zig index 87b72c6726..7c12335575 100644 --- a/src/codegen/spirv.zig +++ b/src/codegen/spirv.zig @@ -2717,19 +2717,29 @@ pub const DeclGen = struct { const result_id = self.spv.allocId(); const callee_id = try self.resolve(pl_op.operand); - try self.func.body.emitRaw(self.spv.gpa, .OpFunctionCall, 3 + args.len); - self.func.body.writeOperand(spec.IdResultType, result_type_id); - self.func.body.writeOperand(spec.IdResult, result_id); - self.func.body.writeOperand(spec.IdRef, callee_id); + const params = try self.gpa.alloc(spec.IdRef, args.len); + defer self.gpa.free(params); + var n_params: usize = 0; for (args) |arg| { + // Note: resolve() might emit instructions, so we need to call it + // before starting to emit OpFunctionCall instructions. Hence the + // temporary params buffer. const arg_id = try self.resolve(arg); const arg_ty = self.air.typeOf(arg); if (!arg_ty.hasRuntimeBitsIgnoreComptime()) continue; - self.func.body.writeOperand(spec.IdRef, arg_id); + params[n_params] = arg_id; + n_params += 1; } + try self.func.body.emit(self.spv.gpa, .OpFunctionCall, .{ + .id_result_type = result_type_id, + .id_result = result_id, + .function = callee_id, + .id_ref_3 = params[0..n_params], + }); + if (return_type.isNoReturn()) { try self.func.body.emit(self.spv.gpa, .OpUnreachable, {}); } |
