authorgravatar for robin@voetter.nlRobin Voetter <robin@voetter.nl> 2023-04-10 18:34:30+02:00
committergravatar for robin@voetter.nlRobin Voetter <robin@voetter.nl> 2023-05-11 20:31:50+02:00
logdfecf89d06dc2caad41ff54b05240506ea2c47e8
tree46cb08a073d4e346188fc2c323d7b3dede446144
parent5d896a6cc6b7127dd4db0bd386ebe33da82d7824
signaturelock-open Commit is signed but in an unrecognized format.

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.

1 files changed, 15 insertions(+), 5 deletions(-)

src/codegen/spirv.zig+15-5
...@@ -2717,19 +2717,29 @@ pub const DeclGen = struct {...@@ -2717,19 +2717,29 @@ pub const DeclGen = struct {
2717 const result_id = self.spv.allocId();2717 const result_id = self.spv.allocId();
2718 const callee_id = try self.resolve(pl_op.operand);2718 const callee_id = try self.resolve(pl_op.operand);
27192719
2720 try self.func.body.emitRaw(self.spv.gpa, .OpFunctionCall, 3 + args.len);2720 const params = try self.gpa.alloc(spec.IdRef, args.len);
2721 self.func.body.writeOperand(spec.IdResultType, result_type_id);2721 defer self.gpa.free(params);
2722 self.func.body.writeOperand(spec.IdResult, result_id);
2723 self.func.body.writeOperand(spec.IdRef, callee_id);
27242722
2723 var n_params: usize = 0;
2725 for (args) |arg| {2724 for (args) |arg| {
2725 // Note: resolve() might emit instructions, so we need to call it
2726 // before starting to emit OpFunctionCall instructions. Hence the
2727 // temporary params buffer.
2726 const arg_id = try self.resolve(arg);2728 const arg_id = try self.resolve(arg);
2727 const arg_ty = self.air.typeOf(arg);2729 const arg_ty = self.air.typeOf(arg);
2728 if (!arg_ty.hasRuntimeBitsIgnoreComptime()) continue;2730 if (!arg_ty.hasRuntimeBitsIgnoreComptime()) continue;
27292731
2730 self.func.body.writeOperand(spec.IdRef, arg_id);2732 params[n_params] = arg_id;
2733 n_params += 1;
2731 }2734 }
27322735
2736 try self.func.body.emit(self.spv.gpa, .OpFunctionCall, .{
2737 .id_result_type = result_type_id,
2738 .id_result = result_id,
2739 .function = callee_id,
2740 .id_ref_3 = params[0..n_params],
2741 });
2742
2733 if (return_type.isNoReturn()) {2743 if (return_type.isNoReturn()) {
2734 try self.func.body.emit(self.spv.gpa, .OpUnreachable, {});2744 try self.func.body.emit(self.spv.gpa, .OpUnreachable, {});
2735 }2745 }