authorgravatar for vasyapulopapik@gmail.comKleshzz <vasyapulopapik@gmail.com> 2026-07-23 15:05:18+03:00
committergravatar for alichraghi@noreply.codeberg.orgAli Cheraghi <alichraghi@noreply.codeberg.org> 2026-07-26 21:07:52+02:00
log2aa8f3d3f5bf98d1a6a7396c608e24203cf094be
treef2d2715b792c1822129c09ad3480df48cea0d1f3
parentd552433946de375430a339e245b5ea0af1b79ca6

spirv: improve assembler capacity allocation, error locations


1 files changed, 22 insertions(+), 20 deletions(-)

src/codegen/spirv/Assembler.zig+22-20
......@@ -26,7 +26,7 @@ inst: struct {
2626 string_bytes: std.ArrayList(u8) = .empty,
2727 inst_offset: u32 = 0,
2828
29 fn result(ass: @This()) ?AsmValue.Ref {
29 fn result(ass: *const @This()) ?AsmValue.Ref {
3030 for (ass.operands.items[0..@min(ass.operands.items.len, 2)]) |op| {
3131 switch (op) {
3232 .result_id => |index| return index,
......@@ -179,19 +179,19 @@ fn processInstruction(ass: *Assembler) !void {
179179 const cg = ass.cg;
180180 const result: AsmValue = switch (ass.inst.opcode) {
181181 .OpEntryPoint => {
182 return ass.fail(ass.currentToken().start, "cannot export entry points in assembly", .{});
182 return ass.fail(ass.inst.inst_offset, "cannot export entry points in assembly", .{});
183183 },
184184 .OpExecutionMode, .OpExecutionModeId => {
185 return ass.fail(ass.currentToken().start, "cannot set execution mode in assembly", .{});
185 return ass.fail(ass.inst.inst_offset, "cannot set execution mode in assembly", .{});
186186 },
187187 .OpCapability, .OpExtension => {
188 return ass.fail(ass.currentToken().start, "cannot declare capabilities or extensions in assembly; use -mcpu instead", .{});
188 return ass.fail(ass.inst.inst_offset, "cannot declare capabilities or extensions in assembly; use -mcpu instead", .{});
189189 },
190190 .OpExtInstImport => blk: {
191191 const set_name_offset = ass.inst.operands.items[1].string;
192192 const set_name = std.mem.sliceTo(ass.inst.string_bytes.items[set_name_offset..], 0);
193193 const set_tag = std.meta.stringToEnum(spec.InstructionSet, set_name) orelse {
194 return ass.fail(set_name_offset, "unknown instruction set: {s}", .{set_name});
194 return ass.fail(ass.inst.inst_offset, "unknown instruction set: {s}", .{set_name});
195195 };
196196 break :blk .{ .value = try cg.importInstructionSet(set_tag) };
197197 },
......@@ -366,38 +366,40 @@ fn processGenericInstruction(ass: *Assembler) !?AsmValue {
366366
367367 var maybe_result_id: ?Id = null;
368368 const first_word = section.instructions.items.len;
369 // At this point we're not quite sure how many operands this instruction is
370 // going to have, so insert 0 and patch up the actual opcode word later.
371 try section.ensureUnusedCapacity(cg.gpa, 1);
369
370 // Pre-calculate exact instruction size to avoid per-operand capacity checks.
371 var total_words: usize = 1; // 1 word for the opcode itself
372 for (operands) |operand| {
373 total_words += switch (operand) {
374 .value, .literal32, .result_id, .ref_id => 1,
375 .literal64 => 2,
376 .string => |offset| blk: {
377 const text = std.mem.sliceTo(ass.inst.string_bytes.items[offset..], 0);
378 break :blk @divCeil(text.len + 1, @sizeOf(Word));
379 },
380 };
381 }
382
383 try section.ensureUnusedCapacity(cg.gpa, total_words);
372384 section.writeWord(0);
373385
374386 for (operands) |operand| {
375387 switch (operand) {
376 .value, .literal32 => |word| {
377 try section.ensureUnusedCapacity(cg.gpa, 1);
378 section.writeWord(word);
379 },
380 .literal64 => |dword| {
381 try section.ensureUnusedCapacity(cg.gpa, 2);
382 section.writeDoubleWord(dword);
383 },
388 .value, .literal32 => |word| section.writeWord(word),
389 .literal64 => |dword| section.writeDoubleWord(dword),
384390 .result_id => {
385391 maybe_result_id = if (maybe_spv_decl_index) |spv_decl_index|
386392 cg.declPtr(spv_decl_index).result_id
387393 else
388394 cg.allocId();
389 try section.ensureUnusedCapacity(cg.gpa, 1);
390395 section.writeOperand(Id, maybe_result_id.?);
391396 },
392397 .ref_id => |index| {
393398 const result = try ass.resolveRef(index);
394 try section.ensureUnusedCapacity(cg.gpa, 1);
395399 section.writeOperand(spec.Id, result.resultId());
396400 },
397401 .string => |offset| {
398402 const text = std.mem.sliceTo(ass.inst.string_bytes.items[offset..], 0);
399 const size = @divCeil(text.len + 1, @sizeOf(Word));
400 try section.ensureUnusedCapacity(cg.gpa, size);
401403 section.writeOperand(spec.LiteralString, text);
402404 },
403405 }