| ... | ... | @@ -26,7 +26,7 @@ inst: struct { |
| 26 | 26 | string_bytes: std.ArrayList(u8) = .empty, |
| 27 | 27 | inst_offset: u32 = 0, |
| 28 | 28 | |
| 29 | | fn result(ass: @This()) ?AsmValue.Ref { |
| 29 | fn result(ass: *const @This()) ?AsmValue.Ref { |
| 30 | 30 | for (ass.operands.items[0..@min(ass.operands.items.len, 2)]) |op| { |
| 31 | 31 | switch (op) { |
| 32 | 32 | .result_id => |index| return index, |
| ... | ... | @@ -179,19 +179,19 @@ fn processInstruction(ass: *Assembler) !void { |
| 179 | 179 | const cg = ass.cg; |
| 180 | 180 | const result: AsmValue = switch (ass.inst.opcode) { |
| 181 | 181 | .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", .{}); |
| 183 | 183 | }, |
| 184 | 184 | .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", .{}); |
| 186 | 186 | }, |
| 187 | 187 | .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", .{}); |
| 189 | 189 | }, |
| 190 | 190 | .OpExtInstImport => blk: { |
| 191 | 191 | const set_name_offset = ass.inst.operands.items[1].string; |
| 192 | 192 | const set_name = std.mem.sliceTo(ass.inst.string_bytes.items[set_name_offset..], 0); |
| 193 | 193 | 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}); |
| 195 | 195 | }; |
| 196 | 196 | break :blk .{ .value = try cg.importInstructionSet(set_tag) }; |
| 197 | 197 | }, |
| ... | ... | @@ -366,38 +366,40 @@ fn processGenericInstruction(ass: *Assembler) !?AsmValue { |
| 366 | 366 | |
| 367 | 367 | var maybe_result_id: ?Id = null; |
| 368 | 368 | 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); |
| 372 | 384 | section.writeWord(0); |
| 373 | 385 | |
| 374 | 386 | for (operands) |operand| { |
| 375 | 387 | 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), |
| 384 | 390 | .result_id => { |
| 385 | 391 | maybe_result_id = if (maybe_spv_decl_index) |spv_decl_index| |
| 386 | 392 | cg.declPtr(spv_decl_index).result_id |
| 387 | 393 | else |
| 388 | 394 | cg.allocId(); |
| 389 | | try section.ensureUnusedCapacity(cg.gpa, 1); |
| 390 | 395 | section.writeOperand(Id, maybe_result_id.?); |
| 391 | 396 | }, |
| 392 | 397 | .ref_id => |index| { |
| 393 | 398 | const result = try ass.resolveRef(index); |
| 394 | | try section.ensureUnusedCapacity(cg.gpa, 1); |
| 395 | 399 | section.writeOperand(spec.Id, result.resultId()); |
| 396 | 400 | }, |
| 397 | 401 | .string => |offset| { |
| 398 | 402 | 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); |
| 401 | 403 | section.writeOperand(spec.LiteralString, text); |
| 402 | 404 | }, |
| 403 | 405 | } |