authorgravatar for robin@voetter.nlRobin Voetter <robin@voetter.nl> 2021-05-18 13:31:22+02:00
committergravatar for robin@voetter.nlRobin Voetter <robin@voetter.nl> 2021-05-22 16:11:56+02:00
logc190b2ff83308a6680b9d4587d742c253dcdee5d
tree1a412788fafb029f010c9f5a4f80cacf9eb57503
parent9ddd7f4a60c70c1bf146c2fd0c35b32098755f77

SPIR-V: ResultId and Word aliases to improve code clarity


2 files changed, 65 insertions(+), 75 deletions(-)

src/codegen/spirv.zig+51-64
...@@ -14,16 +14,19 @@ const LazySrcLoc = Module.LazySrcLoc;...@@ -14,16 +14,19 @@ const LazySrcLoc = Module.LazySrcLoc;
14const ir = @import("../ir.zig");14const ir = @import("../ir.zig");
15const Inst = ir.Inst;15const Inst = ir.Inst;
1616
17pub const TypeMap = std.HashMap(Type, u32, Type.hash, Type.eql, std.hash_map.default_max_load_percentage);17pub const Word = u32;
18pub const InstMap = std.AutoHashMap(*Inst, u32);18pub const ResultId = u32;
1919
20pub fn writeOpcode(code: *std.ArrayList(u32), opcode: Opcode, arg_count: u32) !void {20pub const TypeMap = std.HashMap(Type, ResultId, Type.hash, Type.eql, std.hash_map.default_max_load_percentage);
21 const word_count = arg_count + 1;21pub const InstMap = std.AutoHashMap(*Inst, ResultId);
22
23pub fn writeOpcode(code: *std.ArrayList(Word), opcode: Opcode, arg_count: u16) !void {
24 const word_count: Word = arg_count + 1;
22 try code.append((word_count << 16) | @enumToInt(opcode));25 try code.append((word_count << 16) | @enumToInt(opcode));
23}26}
2427
25pub fn writeInstruction(code: *std.ArrayList(u32), opcode: Opcode, args: []const u32) !void {28pub fn writeInstruction(code: *std.ArrayList(Word), opcode: Opcode, args: []const Word) !void {
26 try writeOpcode(code, opcode, @intCast(u32, args.len));29 try writeOpcode(code, opcode, @intCast(u16, args.len));
27 try code.appendSlice(args);30 try code.appendSlice(args);
28}31}
2932
...@@ -31,11 +34,11 @@ pub fn writeInstruction(code: *std.ArrayList(u32), opcode: Opcode, args: []const...@@ -31,11 +34,11 @@ pub fn writeInstruction(code: *std.ArrayList(u32), opcode: Opcode, args: []const
31/// That includes the actual instructions, the current result-id bound, and data structures for querying result-id's34/// That includes the actual instructions, the current result-id bound, and data structures for querying result-id's
32/// of data which needs to be persistent over different calls to Decl code generation.35/// of data which needs to be persistent over different calls to Decl code generation.
33pub const SPIRVModule = struct {36pub const SPIRVModule = struct {
34 next_result_id: u32,37 next_result_id: ResultId,
3538
36 binary: struct {39 binary: struct {
37 types_globals_constants: std.ArrayList(u32),40 types_globals_constants: std.ArrayList(Word),
38 fn_decls: std.ArrayList(u32),41 fn_decls: std.ArrayList(Word),
39 },42 },
4043
41 types: TypeMap,44 types: TypeMap,
...@@ -44,8 +47,8 @@ pub const SPIRVModule = struct {...@@ -44,8 +47,8 @@ pub const SPIRVModule = struct {
44 return .{47 return .{
45 .next_result_id = 1, // 0 is an invalid SPIR-V result ID.48 .next_result_id = 1, // 0 is an invalid SPIR-V result ID.
46 .binary = .{49 .binary = .{
47 .types_globals_constants = std.ArrayList(u32).init(gpa),50 .types_globals_constants = std.ArrayList(Word).init(gpa),
48 .fn_decls = std.ArrayList(u32).init(gpa),51 .fn_decls = std.ArrayList(Word).init(gpa),
49 },52 },
50 .types = TypeMap.init(gpa),53 .types = TypeMap.init(gpa),
51 };54 };
...@@ -57,12 +60,12 @@ pub const SPIRVModule = struct {...@@ -57,12 +60,12 @@ pub const SPIRVModule = struct {
57 self.types.deinit();60 self.types.deinit();
58 }61 }
5962
60 pub fn allocResultId(self: *SPIRVModule) u32 {63 pub fn allocResultId(self: *SPIRVModule) Word {
61 defer self.next_result_id += 1;64 defer self.next_result_id += 1;
62 return self.next_result_id;65 return self.next_result_id;
63 }66 }
6467
65 pub fn resultIdBound(self: *SPIRVModule) u32 {68 pub fn resultIdBound(self: *SPIRVModule) Word {
66 return self.next_result_id;69 return self.next_result_id;
67 }70 }
68};71};
...@@ -76,7 +79,7 @@ pub const DeclGen = struct {...@@ -76,7 +79,7 @@ pub const DeclGen = struct {
76 spv: *SPIRVModule,79 spv: *SPIRVModule,
7780
78 /// An array of function argument result-ids. Each index corresponds with the function argument of the same index.81 /// An array of function argument result-ids. Each index corresponds with the function argument of the same index.
79 args: std.ArrayList(u32),82 args: std.ArrayList(ResultId),
8083
81 /// A counter to keep track of how many `arg` instructions we've seen yet.84 /// A counter to keep track of how many `arg` instructions we've seen yet.
82 next_arg_index: u32,85 next_arg_index: u32,
...@@ -145,7 +148,7 @@ pub const DeclGen = struct {...@@ -145,7 +148,7 @@ pub const DeclGen = struct {
145 return error.AnalysisFail;148 return error.AnalysisFail;
146 }149 }
147150
148 fn resolve(self: *DeclGen, inst: *Inst) !u32 {151 fn resolve(self: *DeclGen, inst: *Inst) !ResultId {
149 if (inst.value()) |val| {152 if (inst.value()) |val| {
150 return self.genConstant(inst.ty, val);153 return self.genConstant(inst.ty, val);
151 }154 }
...@@ -249,21 +252,21 @@ pub const DeclGen = struct {...@@ -249,21 +252,21 @@ pub const DeclGen = struct {
249252
250 /// Generate a constant representing `val`.253 /// Generate a constant representing `val`.
251 /// TODO: Deduplication?254 /// TODO: Deduplication?
252 fn genConstant(self: *DeclGen, ty: Type, val: Value) Error!u32 {255 fn genConstant(self: *DeclGen, ty: Type, val: Value) Error!ResultId {
253 const target = self.module.getTarget();256 const target = self.module.getTarget();
254 const code = &self.spv.binary.types_globals_constants;257 const code = &self.spv.binary.types_globals_constants;
255 const result_id = self.spv.allocResultId();258 const result_id = self.spv.allocResultId();
256 const result_type_id = try self.getOrGenType(ty);259 const result_type_id = try self.getOrGenType(ty);
257260
258 if (val.isUndef()) {261 if (val.isUndef()) {
259 try writeInstruction(code, .OpUndef, &[_]u32{ result_type_id, result_id });262 try writeInstruction(code, .OpUndef, &[_]Word{ result_type_id, result_id });
260 return result_id;263 return result_id;
261 }264 }
262265
263 switch (ty.zigTypeTag()) {266 switch (ty.zigTypeTag()) {
264 .Bool => {267 .Bool => {
265 const opcode: Opcode = if (val.toBool()) .OpConstantTrue else .OpConstantFalse;268 const opcode: Opcode = if (val.toBool()) .OpConstantTrue else .OpConstantFalse;
266 try writeInstruction(code, opcode, &[_]u32{ result_type_id, result_id });269 try writeInstruction(code, opcode, &[_]Word{ result_type_id, result_id });
267 },270 },
268 .Float => {271 .Float => {
269 // At this point we are guaranteed that the target floating point type is supported, otherwise the function272 // At this point we are guaranteed that the target floating point type is supported, otherwise the function
...@@ -272,15 +275,15 @@ pub const DeclGen = struct {...@@ -272,15 +275,15 @@ pub const DeclGen = struct {
272 // f16 and f32 require one word of storage. f64 requires 2, low-order first.275 // f16 and f32 require one word of storage. f64 requires 2, low-order first.
273276
274 switch (ty.floatBits(target)) {277 switch (ty.floatBits(target)) {
275 16 => try writeInstruction(code, .OpConstant, &[_]u32{ result_type_id, result_id, @bitCast(u16, val.toFloat(f16)) }),278 16 => try writeInstruction(code, .OpConstant, &[_]Word{ result_type_id, result_id, @bitCast(u16, val.toFloat(f16)) }),
276 32 => try writeInstruction(code, .OpConstant, &[_]u32{ result_type_id, result_id, @bitCast(u32, val.toFloat(f32)) }),279 32 => try writeInstruction(code, .OpConstant, &[_]Word{ result_type_id, result_id, @bitCast(u32, val.toFloat(f32)) }),
277 64 => {280 64 => {
278 const float_bits = @bitCast(u64, val.toFloat(f64));281 const float_bits = @bitCast(u64, val.toFloat(f64));
279 try writeInstruction(code, .OpConstant, &[_]u32{282 try writeInstruction(code, .OpConstant, &[_]Word{
280 result_type_id,283 result_type_id,
281 result_id,284 result_id,
282 @truncate(u32, float_bits),285 @truncate(Word, float_bits),
283 @truncate(u32, float_bits >> 32),286 @truncate(Word, float_bits >> 32),
284 });287 });
285 },288 },
286 128 => unreachable, // Filtered out in the call to getOrGenType.289 128 => unreachable, // Filtered out in the call to getOrGenType.
...@@ -294,7 +297,7 @@ pub const DeclGen = struct {...@@ -294,7 +297,7 @@ pub const DeclGen = struct {
294 return result_id;297 return result_id;
295 }298 }
296299
297 fn getOrGenType(self: *DeclGen, ty: Type) Error!u32 {300 fn getOrGenType(self: *DeclGen, ty: Type) Error!ResultId {
298 // We can't use getOrPut here so we can recursively generate types.301 // We can't use getOrPut here so we can recursively generate types.
299 if (self.spv.types.get(ty)) |already_generated| {302 if (self.spv.types.get(ty)) |already_generated| {
300 return already_generated;303 return already_generated;
...@@ -305,8 +308,8 @@ pub const DeclGen = struct {...@@ -305,8 +308,8 @@ pub const DeclGen = struct {
305 const result_id = self.spv.allocResultId();308 const result_id = self.spv.allocResultId();
306309
307 switch (ty.zigTypeTag()) {310 switch (ty.zigTypeTag()) {
308 .Void => try writeInstruction(code, .OpTypeVoid, &[_]u32{result_id}),311 .Void => try writeInstruction(code, .OpTypeVoid, &[_]Word{result_id}),
309 .Bool => try writeInstruction(code, .OpTypeBool, &[_]u32{result_id}),312 .Bool => try writeInstruction(code, .OpTypeBool, &[_]Word{result_id}),
310 .Int => {313 .Int => {
311 const int_info = ty.intInfo(target);314 const int_info = ty.intInfo(target);
312 const backing_bits = self.backingIntBits(int_info.bits) orelse {315 const backing_bits = self.backingIntBits(int_info.bits) orelse {
...@@ -315,7 +318,7 @@ pub const DeclGen = struct {...@@ -315,7 +318,7 @@ pub const DeclGen = struct {
315 };318 };
316319
317 // TODO: If backing_bits != int_info.bits, a duplicate type might be generated here.320 // TODO: If backing_bits != int_info.bits, a duplicate type might be generated here.
318 try writeInstruction(code, .OpTypeInt, &[_]u32{321 try writeInstruction(code, .OpTypeInt, &[_]Word{
319 result_id,322 result_id,
320 backing_bits,323 backing_bits,
321 switch (int_info.signedness) {324 switch (int_info.signedness) {
...@@ -340,7 +343,7 @@ pub const DeclGen = struct {...@@ -340,7 +343,7 @@ pub const DeclGen = struct {
340 return self.fail(.{ .node_offset = 0 }, "Floating point width of {} bits is not supported for the current SPIR-V feature set", .{bits});343 return self.fail(.{ .node_offset = 0 }, "Floating point width of {} bits is not supported for the current SPIR-V feature set", .{bits});
341 }344 }
342345
343 try writeInstruction(code, .OpTypeFloat, &[_]u32{ result_id, bits });346 try writeInstruction(code, .OpTypeFloat, &[_]Word{ result_id, bits });
344 },347 },
345 .Fn => {348 .Fn => {
346 // We only support zig-calling-convention functions, no varargs.349 // We only support zig-calling-convention functions, no varargs.
...@@ -360,7 +363,7 @@ pub const DeclGen = struct {...@@ -360,7 +363,7 @@ pub const DeclGen = struct {
360 const return_type_id = try self.getOrGenType(ty.fnReturnType());363 const return_type_id = try self.getOrGenType(ty.fnReturnType());
361364
362 // result id + result type id + parameter type ids.365 // result id + result type id + parameter type ids.
363 try writeOpcode(code, .OpTypeFunction, 2 + @intCast(u32, ty.fnParamLen()));366 try writeOpcode(code, .OpTypeFunction, 2 + @intCast(u16, ty.fnParamLen()));
364 try code.appendSlice(&.{ result_id, return_type_id });367 try code.appendSlice(&.{ result_id, return_type_id });
365368
366 i = 0;369 i = 0;
...@@ -397,7 +400,6 @@ pub const DeclGen = struct {...@@ -397,7 +400,6 @@ pub const DeclGen = struct {
397 return result_id;400 return result_id;
398 }401 }
399402
400<<<<<<< HEAD
401 pub fn gen(self: *DeclGen) !void {403 pub fn gen(self: *DeclGen) !void {
402 const decl = self.decl;404 const decl = self.decl;
403 const result_id = decl.fn_link.spirv.id;405 const result_id = decl.fn_link.spirv.id;
...@@ -405,21 +407,10 @@ pub const DeclGen = struct {...@@ -405,21 +407,10 @@ pub const DeclGen = struct {
405 if (decl.val.castTag(.function)) |func_payload| {407 if (decl.val.castTag(.function)) |func_payload| {
406 std.debug.assert(decl.ty.zigTypeTag() == .Fn);408 std.debug.assert(decl.ty.zigTypeTag() == .Fn);
407 const prototype_id = try self.getOrGenType(decl.ty);409 const prototype_id = try self.getOrGenType(decl.ty);
408 try writeInstruction(&self.spv.fn_decls, .OpFunction, &[_]u32{410 try writeInstruction(&self.spv.binary.fn_decls, .OpFunction, &[_]Word{
409 self.types.get(decl.ty.fnReturnType()).?, // This type should be generated along with the prototype.411 self.spv.types.get(decl.ty.fnReturnType()).?, // This type should be generated along with the prototype.
410=======
411 pub fn gen(self: *DeclGen) Error!void {
412 const result_id = self.decl.fn_link.spirv.id;
413 const tv = self.decl.typed_value.most_recent.typed_value;
414
415 if (tv.val.castTag(.function)) |func_payload| {
416 std.debug.assert(tv.ty.zigTypeTag() == .Fn);
417 const prototype_id = try self.getOrGenType(tv.ty);
418 try writeInstruction(&self.spv.binary.fn_decls, .OpFunction, &[_]u32{
419 self.spv.types.get(tv.ty.fnReturnType()).?, // This type should be generated along with the prototype.
420>>>>>>> 09e563b75 (SPIR-V: Put types in SPIRVModule, some general restructuring)
421 result_id,412 result_id,
422 @bitCast(u32, spec.FunctionControl{}), // TODO: We can set inline here if the type requires it.413 @bitCast(Word, spec.FunctionControl{}), // TODO: We can set inline here if the type requires it.
423 prototype_id,414 prototype_id,
424 });415 });
425416
...@@ -428,22 +419,18 @@ pub const DeclGen = struct {...@@ -428,22 +419,18 @@ pub const DeclGen = struct {
428419
429 try self.args.ensureCapacity(params);420 try self.args.ensureCapacity(params);
430 while (i < params) : (i += 1) {421 while (i < params) : (i += 1) {
431<<<<<<< HEAD422 const param_type_id = self.spv.types.get(decl.ty.fnParamType(i)).?;
432 const param_type_id = self.types.get(decl.ty.fnParamType(i)).?;
433=======
434 const param_type_id = self.spv.types.get(tv.ty.fnParamType(i)).?;
435>>>>>>> 09e563b75 (SPIR-V: Put types in SPIRVModule, some general restructuring)
436 const arg_result_id = self.spv.allocResultId();423 const arg_result_id = self.spv.allocResultId();
437 try writeInstruction(&self.spv.binary.fn_decls, .OpFunctionParameter, &[_]u32{ param_type_id, arg_result_id });424 try writeInstruction(&self.spv.binary.fn_decls, .OpFunctionParameter, &[_]Word{ param_type_id, arg_result_id });
438 self.args.appendAssumeCapacity(arg_result_id);425 self.args.appendAssumeCapacity(arg_result_id);
439 }426 }
440427
441 // TODO: This could probably be done in a better way...428 // TODO: This could probably be done in a better way...
442 const root_block_id = self.spv.allocResultId();429 const root_block_id = self.spv.allocResultId();
443 _ = try writeInstruction(&self.spv.binary.fn_decls, .OpLabel, &[_]u32{root_block_id});430 _ = try writeInstruction(&self.spv.binary.fn_decls, .OpLabel, &[_]Word{root_block_id});
444 try self.genBody(func_payload.data.body);431 try self.genBody(func_payload.data.body);
445432
446 try writeInstruction(&self.spv.binary.fn_decls, .OpFunctionEnd, &[_]u32{});433 try writeInstruction(&self.spv.binary.fn_decls, .OpFunctionEnd, &[_]Word{});
447 } else {434 } else {
448 return self.fail(.{ .node_offset = 0 }, "TODO: SPIR-V backend: generate decl type {}", .{decl.ty.zigTypeTag()});435 return self.fail(.{ .node_offset = 0 }, "TODO: SPIR-V backend: generate decl type {}", .{decl.ty.zigTypeTag()});
449 }436 }
...@@ -457,7 +444,7 @@ pub const DeclGen = struct {...@@ -457,7 +444,7 @@ pub const DeclGen = struct {
457 }444 }
458 }445 }
459446
460 fn genInst(self: *DeclGen, inst: *Inst) !?u32 {447 fn genInst(self: *DeclGen, inst: *Inst) !?ResultId {
461 return switch (inst.tag) {448 return switch (inst.tag) {
462 .add, .addwrap => try self.genBinOp(inst.castTag(.add).?),449 .add, .addwrap => try self.genBinOp(inst.castTag(.add).?),
463 .sub, .subwrap => try self.genBinOp(inst.castTag(.sub).?),450 .sub, .subwrap => try self.genBinOp(inst.castTag(.sub).?),
...@@ -487,7 +474,7 @@ pub const DeclGen = struct {...@@ -487,7 +474,7 @@ pub const DeclGen = struct {
487 };474 };
488 }475 }
489476
490 fn genBinOp(self: *DeclGen, inst: *Inst.BinOp) !u32 {477 fn genBinOp(self: *DeclGen, inst: *Inst.BinOp) !ResultId {
491 // TODO: Will lhs and rhs have the same type?478 // TODO: Will lhs and rhs have the same type?
492 const lhs_id = try self.resolve(inst.lhs);479 const lhs_id = try self.resolve(inst.lhs);
493 const rhs_id = try self.resolve(inst.rhs);480 const rhs_id = try self.resolve(inst.rhs);
...@@ -546,7 +533,7 @@ pub const DeclGen = struct {...@@ -546,7 +533,7 @@ pub const DeclGen = struct {
546 else => unreachable,533 else => unreachable,
547 };534 };
548535
549 try writeInstruction(&self.spv.binary.fn_decls, opcode, &[_]u32{ result_type_id, result_id, lhs_id, rhs_id });536 try writeInstruction(&self.spv.binary.fn_decls, opcode, &[_]Word{ result_type_id, result_id, lhs_id, rhs_id });
550537
551 // TODO: Trap on overflow? Probably going to be annoying.538 // TODO: Trap on overflow? Probably going to be annoying.
552 // TODO: Look into SPV_KHR_no_integer_wrap_decoration which provides NoSignedWrap/NoUnsignedWrap.539 // TODO: Look into SPV_KHR_no_integer_wrap_decoration which provides NoSignedWrap/NoUnsignedWrap.
...@@ -557,7 +544,7 @@ pub const DeclGen = struct {...@@ -557,7 +544,7 @@ pub const DeclGen = struct {
557 return self.fail(.{ .node_offset = 0 }, "TODO: SPIR-V backend: strange integer operation mask", .{});544 return self.fail(.{ .node_offset = 0 }, "TODO: SPIR-V backend: strange integer operation mask", .{});
558 }545 }
559546
560 fn genUnOp(self: *DeclGen, inst: *Inst.UnOp) !u32 {547 fn genUnOp(self: *DeclGen, inst: *Inst.UnOp) !ResultId {
561 const operand_id = try self.resolve(inst.operand);548 const operand_id = try self.resolve(inst.operand);
562549
563 const result_id = self.spv.allocResultId();550 const result_id = self.spv.allocResultId();
...@@ -571,32 +558,32 @@ pub const DeclGen = struct {...@@ -571,32 +558,32 @@ pub const DeclGen = struct {
571 else => unreachable,558 else => unreachable,
572 };559 };
573560
574 try writeInstruction(&self.spv.binary.fn_decls, opcode, &[_]u32{ result_type_id, result_id, operand_id });561 try writeInstruction(&self.spv.binary.fn_decls, opcode, &[_]Word{ result_type_id, result_id, operand_id });
575562
576 return result_id;563 return result_id;
577 }564 }
578565
579 fn genArg(self: *DeclGen) u32 {566 fn genArg(self: *DeclGen) ResultId {
580 defer self.next_arg_index += 1;567 defer self.next_arg_index += 1;
581 return self.args.items[self.next_arg_index];568 return self.args.items[self.next_arg_index];
582 }569 }
583570
584 fn genRet(self: *DeclGen, inst: *Inst.UnOp) !?u32 {571 fn genRet(self: *DeclGen, inst: *Inst.UnOp) !?ResultId {
585 const operand_id = try self.resolve(inst.operand);572 const operand_id = try self.resolve(inst.operand);
586 // TODO: This instruction needs to be the last in a block. Is that guaranteed?573 // TODO: This instruction needs to be the last in a block. Is that guaranteed?
587 try writeInstruction(&self.spv.binary.fn_decls, .OpReturnValue, &[_]u32{operand_id});574 try writeInstruction(&self.spv.binary.fn_decls, .OpReturnValue, &[_]Word{operand_id});
588 return null;575 return null;
589 }576 }
590577
591 fn genRetVoid(self: *DeclGen) !?u32 {578 fn genRetVoid(self: *DeclGen) !?ResultId {
592 // TODO: This instruction needs to be the last in a block. Is that guaranteed?579 // TODO: This instruction needs to be the last in a block. Is that guaranteed?
593 try writeInstruction(&self.spv.binary.fn_decls, .OpReturn, &[_]u32{});580 try writeInstruction(&self.spv.binary.fn_decls, .OpReturn, &[_]Word{});
594 return null;581 return null;
595 }582 }
596583
597 fn genUnreach(self: *DeclGen) !?u32 {584 fn genUnreach(self: *DeclGen) !?ResultId {
598 // TODO: This instruction needs to be the last in a block. Is that guaranteed?585 // TODO: This instruction needs to be the last in a block. Is that guaranteed?
599 try writeInstruction(&self.spv.binary.fn_decls, .OpUnreachable, &[_]u32{});586 try writeInstruction(&self.spv.binary.fn_decls, .OpUnreachable, &[_]Word{});
600 return null;587 return null;
601 }588 }
602};589};
src/link/SpirV.zig+14-11
...@@ -31,15 +31,18 @@ const Module = @import("../Module.zig");...@@ -31,15 +31,18 @@ const Module = @import("../Module.zig");
31const Compilation = @import("../Compilation.zig");31const Compilation = @import("../Compilation.zig");
32const link = @import("../link.zig");32const link = @import("../link.zig");
33const codegen = @import("../codegen/spirv.zig");33const codegen = @import("../codegen/spirv.zig");
34const Word = codegen.Word;
35const ResultId = codegen.ResultId;
34const trace = @import("../tracy.zig").trace;36const trace = @import("../tracy.zig").trace;
35const build_options = @import("build_options");37const build_options = @import("build_options");
36const spec = @import("../codegen/spirv/spec.zig");38const spec = @import("../codegen/spirv/spec.zig");
3739
38// TODO: Should this struct be used at all rather than just a hashmap of aux data for every decl?40// TODO: Should this struct be used at all rather than just a hashmap of aux data for every decl?
39pub const FnData = struct {41pub const FnData = struct {
40// We're going to fill these in flushModule, and we're going to fill them unconditionally,42 // We're going to fill these in flushModule, and we're going to fill them unconditionally,
41// so just set it to undefined.43 // so just set it to undefined.
42id: u32 = undefined };44 id: ResultId = undefined
45};
4346
44base: link.File,47base: link.File,
4548
...@@ -155,7 +158,7 @@ pub fn flushModule(self: *SpirV, comp: *Compilation) !void {...@@ -155,7 +158,7 @@ pub fn flushModule(self: *SpirV, comp: *Compilation) !void {
155 var decl_gen = codegen.DeclGen{158 var decl_gen = codegen.DeclGen{
156 .module = module,159 .module = module,
157 .spv = &spv,160 .spv = &spv,
158 .args = std.ArrayList(u32).init(self.base.allocator),161 .args = std.ArrayList(codegen.Word).init(self.base.allocator),
159 .next_arg_index = undefined,162 .next_arg_index = undefined,
160 .inst_results = codegen.InstMap.init(self.base.allocator),163 .inst_results = codegen.InstMap.init(self.base.allocator),
161 .decl = undefined,164 .decl = undefined,
...@@ -185,10 +188,10 @@ pub fn flushModule(self: *SpirV, comp: *Compilation) !void {...@@ -185,10 +188,10 @@ pub fn flushModule(self: *SpirV, comp: *Compilation) !void {
185 }188 }
186 }189 }
187190
188 var binary = std.ArrayList(u32).init(self.base.allocator);191 var binary = std.ArrayList(Word).init(self.base.allocator);
189 defer binary.deinit();192 defer binary.deinit();
190193
191 try binary.appendSlice(&[_]u32{194 try binary.appendSlice(&[_]Word{
192 spec.magic_number,195 spec.magic_number,
193 (spec.version.major << 16) | (spec.version.minor << 8),196 (spec.version.major << 16) | (spec.version.minor << 8),
194 0, // TODO: Register Zig compiler magic number.197 0, // TODO: Register Zig compiler magic number.
...@@ -220,7 +223,7 @@ pub fn flushModule(self: *SpirV, comp: *Compilation) !void {...@@ -220,7 +223,7 @@ pub fn flushModule(self: *SpirV, comp: *Compilation) !void {
220 try file.pwritevAll(&all_buffers, 0);223 try file.pwritevAll(&all_buffers, 0);
221}224}
222225
223fn writeCapabilities(binary: *std.ArrayList(u32), target: std.Target) !void {226fn writeCapabilities(binary: *std.ArrayList(Word), target: std.Target) !void {
224 // TODO: Integrate with a hypothetical feature system227 // TODO: Integrate with a hypothetical feature system
225 const cap: spec.Capability = switch (target.os.tag) {228 const cap: spec.Capability = switch (target.os.tag) {
226 .opencl => .Kernel,229 .opencl => .Kernel,
...@@ -229,10 +232,10 @@ fn writeCapabilities(binary: *std.ArrayList(u32), target: std.Target) !void {...@@ -229,10 +232,10 @@ fn writeCapabilities(binary: *std.ArrayList(u32), target: std.Target) !void {
229 else => unreachable, // TODO232 else => unreachable, // TODO
230 };233 };
231234
232 try codegen.writeInstruction(binary, .OpCapability, &[_]u32{@enumToInt(cap)});235 try codegen.writeInstruction(binary, .OpCapability, &[_]Word{@enumToInt(cap)});
233}236}
234237
235fn writeMemoryModel(binary: *std.ArrayList(u32), target: std.Target) !void {238fn writeMemoryModel(binary: *std.ArrayList(Word), target: std.Target) !void {
236 const addressing_model = switch (target.os.tag) {239 const addressing_model = switch (target.os.tag) {
237 .opencl => switch (target.cpu.arch) {240 .opencl => switch (target.cpu.arch) {
238 .spirv32 => spec.AddressingModel.Physical32,241 .spirv32 => spec.AddressingModel.Physical32,
...@@ -250,12 +253,12 @@ fn writeMemoryModel(binary: *std.ArrayList(u32), target: std.Target) !void {...@@ -250,12 +253,12 @@ fn writeMemoryModel(binary: *std.ArrayList(u32), target: std.Target) !void {
250 else => unreachable,253 else => unreachable,
251 };254 };
252255
253 try codegen.writeInstruction(binary, .OpMemoryModel, &[_]u32{256 try codegen.writeInstruction(binary, .OpMemoryModel, &[_]Word{
254 @enumToInt(addressing_model), @enumToInt(memory_model),257 @enumToInt(addressing_model), @enumToInt(memory_model),
255 });258 });
256}259}
257260
258fn wordsToIovConst(words: []const u32) std.os.iovec_const {261fn wordsToIovConst(words: []const Word) std.os.iovec_const {
259 const bytes = std.mem.sliceAsBytes(words);262 const bytes = std.mem.sliceAsBytes(words);
260 return .{263 return .{
261 .iov_base = bytes.ptr,264 .iov_base = bytes.ptr,