aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobin Voetter <robin@voetter.nl>2023-04-10 18:34:30 +0200
committerRobin Voetter <robin@voetter.nl>2023-05-11 20:31:50 +0200
commitdfecf89d06dc2caad41ff54b05240506ea2c47e8 (patch)
tree46cb08a073d4e346188fc2c323d7b3dede446144
parent5d896a6cc6b7127dd4db0bd386ebe33da82d7824 (diff)
downloadzig-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.zig20
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, {});
}