| author | |
| committer | |
| log | 9b18125562b2402cae8450253decd906f09e4dc6 |
| tree | 5525843896ccb333dfeb4fe832c565f4e1cd3b49 |
| parent | 20d7bb68ac7043e7d4ec8f0653ec73a1090187da |
| signature |
10 files changed, 1255 insertions(+), 771 deletions(-)
src/codegen/spirv.zig+240-208| ... | @@ -30,6 +30,8 @@ const SpvAssembler = @import("spirv/Assembler.zig"); | ... | @@ -30,6 +30,8 @@ const SpvAssembler = @import("spirv/Assembler.zig"); |
| 30 | 30 | ||
| 31 | const InstMap = std.AutoHashMapUnmanaged(Air.Inst.Index, IdRef); | 31 | const InstMap = std.AutoHashMapUnmanaged(Air.Inst.Index, IdRef); |
| 32 | 32 | ||
| 33 | pub const zig_call_abi_ver = 3; | ||
| 34 | |||
| 33 | /// We want to store some extra facts about types as mapped from Zig to SPIR-V. | 35 | /// We want to store some extra facts about types as mapped from Zig to SPIR-V. |
| 34 | /// This structure is used to keep that extra information, as well as | 36 | /// This structure is used to keep that extra information, as well as |
| 35 | /// the cached reference to the type. | 37 | /// the cached reference to the type. |
| ... | @@ -252,15 +254,18 @@ pub const Object = struct { | ... | @@ -252,15 +254,18 @@ pub const Object = struct { |
| 252 | /// Note: Function does not actually generate the decl, it just allocates an index. | 254 | /// Note: Function does not actually generate the decl, it just allocates an index. |
| 253 | pub fn resolveDecl(self: *Object, mod: *Module, decl_index: InternPool.DeclIndex) !SpvModule.Decl.Index { | 255 | pub fn resolveDecl(self: *Object, mod: *Module, decl_index: InternPool.DeclIndex) !SpvModule.Decl.Index { |
| 254 | const decl = mod.declPtr(decl_index); | 256 | const decl = mod.declPtr(decl_index); |
| 257 | assert(decl.has_tv); // TODO: Do we need to handle a situation where this is false? | ||
| 255 | try mod.markDeclAlive(decl); | 258 | try mod.markDeclAlive(decl); |
| 256 | 259 | ||
| 257 | const entry = try self.decl_link.getOrPut(self.gpa, decl_index); | 260 | const entry = try self.decl_link.getOrPut(self.gpa, decl_index); |
| 258 | if (!entry.found_existing) { | 261 | if (!entry.found_existing) { |
| 259 | // TODO: Extern fn? | 262 | // TODO: Extern fn? |
| 260 | const kind: SpvModule.DeclKind = if (decl.val.isFuncBody(mod)) | 263 | const kind: SpvModule.Decl.Kind = if (decl.val.isFuncBody(mod)) |
| 261 | .func | 264 | .func |
| 262 | else | 265 | else switch (decl.@"addrspace") { |
| 263 | .global; | 266 | .generic => .invocation_global, |
| 267 | else => .global, | ||
| 268 | }; | ||
| 264 | 269 | ||
| 265 | entry.value_ptr.* = try self.spv.allocDecl(kind); | 270 | entry.value_ptr.* = try self.spv.allocDecl(kind); |
| 266 | } | 271 | } |
| ... | @@ -443,87 +448,90 @@ const DeclGen = struct { | ... | @@ -443,87 +448,90 @@ const DeclGen = struct { |
| 443 | return self.inst_results.get(index).?; // Assertion means instruction does not dominate usage. | 448 | return self.inst_results.get(index).?; // Assertion means instruction does not dominate usage. |
| 444 | } | 449 | } |
| 445 | 450 | ||
| 446 | fn resolveAnonDecl(self: *DeclGen, val: InternPool.Index, storage_class: StorageClass) !IdRef { | 451 | fn resolveAnonDecl(self: *DeclGen, val: InternPool.Index) !IdRef { |
| 447 | // TODO: This cannot be a function at this point, but it should probably be handled anyway. | 452 | // TODO: This cannot be a function at this point, but it should probably be handled anyway. |
| 453 | |||
| 454 | const mod = self.module; | ||
| 455 | const ty = Type.fromInterned(mod.intern_pool.typeOf(val)); | ||
| 456 | const decl_ptr_ty_ref = try self.ptrType(ty, .Generic); | ||
| 457 | |||
| 448 | const spv_decl_index = blk: { | 458 | const spv_decl_index = blk: { |
| 449 | const entry = try self.object.anon_decl_link.getOrPut(self.object.gpa, .{ val, storage_class }); | 459 | const entry = try self.object.anon_decl_link.getOrPut(self.object.gpa, .{ val, .Function }); |
| 450 | if (entry.found_existing) { | 460 | if (entry.found_existing) { |
| 451 | try self.addFunctionDep(entry.value_ptr.*, storage_class); | 461 | try self.addFunctionDep(entry.value_ptr.*, .Function); |
| 452 | return self.spv.declPtr(entry.value_ptr.*).result_id; | 462 | |
| 463 | const result_id = self.spv.declPtr(entry.value_ptr.*).result_id; | ||
| 464 | return try self.castToGeneric(self.typeId(decl_ptr_ty_ref), result_id); | ||
| 453 | } | 465 | } |
| 454 | 466 | ||
| 455 | const spv_decl_index = try self.spv.allocDecl(.global); | 467 | const spv_decl_index = try self.spv.allocDecl(.invocation_global); |
| 456 | try self.addFunctionDep(spv_decl_index, storage_class); | 468 | try self.addFunctionDep(spv_decl_index, .Function); |
| 457 | entry.value_ptr.* = spv_decl_index; | 469 | entry.value_ptr.* = spv_decl_index; |
| 458 | break :blk spv_decl_index; | 470 | break :blk spv_decl_index; |
| 459 | }; | 471 | }; |
| 460 | 472 | ||
| 461 | const mod = self.module; | ||
| 462 | const ty = Type.fromInterned(mod.intern_pool.typeOf(val)); | ||
| 463 | const ptr_ty_ref = try self.ptrType(ty, storage_class); | ||
| 464 | |||
| 465 | const var_id = self.spv.declPtr(spv_decl_index).result_id; | ||
| 466 | |||
| 467 | const section = &self.spv.sections.types_globals_constants; | ||
| 468 | try section.emit(self.spv.gpa, .OpVariable, .{ | ||
| 469 | .id_result_type = self.typeId(ptr_ty_ref), | ||
| 470 | .id_result = var_id, | ||
| 471 | .storage_class = storage_class, | ||
| 472 | }); | ||
| 473 | |||
| 474 | // TODO: At some point we will be able to generate this all constant here, but then all of | 473 | // TODO: At some point we will be able to generate this all constant here, but then all of |
| 475 | // constant() will need to be implemented such that it doesn't generate any at-runtime code. | 474 | // constant() will need to be implemented such that it doesn't generate any at-runtime code. |
| 476 | // NOTE: Because this is a global, we really only want to initialize it once. Therefore the | 475 | // NOTE: Because this is a global, we really only want to initialize it once. Therefore the |
| 477 | // constant lowering of this value will need to be deferred to some other function, which | 476 | // constant lowering of this value will need to be deferred to an initializer similar to |
| 478 | // is then added to the list of initializers using endGlobal(). | 477 | // other globals. |
| 479 | 478 | ||
| 480 | // Save the current state so that we can temporarily generate into a different function. | 479 | const result_id = self.spv.declPtr(spv_decl_index).result_id; |
| 481 | // TODO: This should probably be made a little more robust. | ||
| 482 | const func = self.func; | ||
| 483 | defer self.func = func; | ||
| 484 | const block_label = self.current_block_label; | ||
| 485 | defer self.current_block_label = block_label; | ||
| 486 | 480 | ||
| 487 | self.func = .{}; | 481 | { |
| 488 | defer self.func.deinit(self.gpa); | 482 | // Save the current state so that we can temporarily generate into a different function. |
| 483 | // TODO: This should probably be made a little more robust. | ||
| 484 | const func = self.func; | ||
| 485 | defer self.func = func; | ||
| 486 | const block_label = self.current_block_label; | ||
| 487 | defer self.current_block_label = block_label; | ||
| 489 | 488 | ||
| 490 | // TODO: Merge this with genDecl? | 489 | self.func = .{}; |
| 491 | const begin = self.spv.beginGlobal(); | 490 | defer self.func.deinit(self.gpa); |
| 492 | 491 | ||
| 493 | const void_ty_ref = try self.resolveType(Type.void, .direct); | 492 | const void_ty_ref = try self.resolveType(Type.void, .direct); |
| 494 | const initializer_proto_ty_ref = try self.spv.resolve(.{ .function_type = .{ | 493 | const initializer_proto_ty_ref = try self.spv.resolve(.{ .function_type = .{ |
| 495 | .return_type = void_ty_ref, | 494 | .return_type = void_ty_ref, |
| 496 | .parameters = &.{}, | 495 | .parameters = &.{}, |
| 497 | } }); | 496 | } }); |
| 498 | 497 | ||
| 499 | const initializer_id = self.spv.allocId(); | 498 | const initializer_id = self.spv.allocId(); |
| 500 | try self.func.prologue.emit(self.spv.gpa, .OpFunction, .{ | ||
| 501 | .id_result_type = self.typeId(void_ty_ref), | ||
| 502 | .id_result = initializer_id, | ||
| 503 | .function_control = .{}, | ||
| 504 | .function_type = self.typeId(initializer_proto_ty_ref), | ||
| 505 | }); | ||
| 506 | const root_block_id = self.spv.allocId(); | ||
| 507 | try self.func.prologue.emit(self.spv.gpa, .OpLabel, .{ | ||
| 508 | .id_result = root_block_id, | ||
| 509 | }); | ||
| 510 | self.current_block_label = root_block_id; | ||
| 511 | 499 | ||
| 512 | const val_id = try self.constant(ty, Value.fromInterned(val), .indirect); | 500 | try self.func.prologue.emit(self.spv.gpa, .OpFunction, .{ |
| 513 | try self.func.body.emit(self.spv.gpa, .OpStore, .{ | 501 | .id_result_type = self.typeId(void_ty_ref), |
| 514 | .pointer = var_id, | 502 | .id_result = initializer_id, |
| 515 | .object = val_id, | 503 | .function_control = .{}, |
| 516 | }); | 504 | .function_type = self.typeId(initializer_proto_ty_ref), |
| 505 | }); | ||
| 506 | const root_block_id = self.spv.allocId(); | ||
| 507 | try self.func.prologue.emit(self.spv.gpa, .OpLabel, .{ | ||
| 508 | .id_result = root_block_id, | ||
| 509 | }); | ||
| 510 | self.current_block_label = root_block_id; | ||
| 517 | 511 | ||
| 518 | self.spv.endGlobal(spv_decl_index, begin, var_id, initializer_id); | 512 | const val_id = try self.constant(ty, Value.fromInterned(val), .indirect); |
| 519 | try self.func.body.emit(self.spv.gpa, .OpReturn, {}); | 513 | try self.func.body.emit(self.spv.gpa, .OpStore, .{ |
| 520 | try self.func.body.emit(self.spv.gpa, .OpFunctionEnd, {}); | 514 | .pointer = result_id, |
| 521 | try self.spv.addFunction(spv_decl_index, self.func); | 515 | .object = val_id, |
| 516 | }); | ||
| 522 | 517 | ||
| 523 | try self.spv.debugNameFmt(var_id, "__anon_{d}", .{@intFromEnum(val)}); | 518 | try self.func.body.emit(self.spv.gpa, .OpReturn, {}); |
| 524 | try self.spv.debugNameFmt(initializer_id, "initializer of __anon_{d}", .{@intFromEnum(val)}); | 519 | try self.func.body.emit(self.spv.gpa, .OpFunctionEnd, {}); |
| 520 | try self.spv.addFunction(spv_decl_index, self.func); | ||
| 521 | |||
| 522 | try self.spv.debugNameFmt(initializer_id, "initializer of __anon_{d}", .{@intFromEnum(val)}); | ||
| 525 | 523 | ||
| 526 | return var_id; | 524 | const fn_decl_ptr_ty_ref = try self.ptrType(ty, .Function); |
| 525 | try self.spv.sections.types_globals_constants.emit(self.spv.gpa, .OpExtInst, .{ | ||
| 526 | .id_result_type = self.typeId(fn_decl_ptr_ty_ref), | ||
| 527 | .id_result = result_id, | ||
| 528 | .set = try self.spv.importInstructionSet(.zig), | ||
| 529 | .instruction = .{ .inst = 0 }, // TODO: Put this definition somewhere... | ||
| 530 | .id_ref_4 = &.{initializer_id}, | ||
| 531 | }); | ||
| 532 | } | ||
| 533 | |||
| 534 | return try self.castToGeneric(self.typeId(decl_ptr_ty_ref), result_id); | ||
| 527 | } | 535 | } |
| 528 | 536 | ||
| 529 | fn addFunctionDep(self: *DeclGen, decl_index: SpvModule.Decl.Index, storage_class: StorageClass) !void { | 537 | fn addFunctionDep(self: *DeclGen, decl_index: SpvModule.Decl.Index, storage_class: StorageClass) !void { |
| ... | @@ -1179,19 +1187,10 @@ const DeclGen = struct { | ... | @@ -1179,19 +1187,10 @@ const DeclGen = struct { |
| 1179 | unreachable; // TODO | 1187 | unreachable; // TODO |
| 1180 | } | 1188 | } |
| 1181 | 1189 | ||
| 1182 | const final_storage_class = self.spvStorageClass(ty.ptrAddressSpace(mod)); | 1190 | // Anon decl refs are always generic. |
| 1183 | const actual_storage_class = switch (final_storage_class) { | 1191 | assert(ty.ptrAddressSpace(mod) == .generic); |
| 1184 | .Generic => .CrossWorkgroup, | 1192 | const decl_ptr_ty_ref = try self.ptrType(decl_ty, .Generic); |
| 1185 | else => |other| other, | 1193 | const ptr_id = try self.resolveAnonDecl(decl_val); |
| 1186 | }; | ||
| 1187 | |||
| 1188 | const decl_id = try self.resolveAnonDecl(decl_val, actual_storage_class); | ||
| 1189 | const decl_ptr_ty_ref = try self.ptrType(decl_ty, final_storage_class); | ||
| 1190 | |||
| 1191 | const ptr_id = switch (final_storage_class) { | ||
| 1192 | .Generic => try self.castToGeneric(self.typeId(decl_ptr_ty_ref), decl_id), | ||
| 1193 | else => decl_id, | ||
| 1194 | }; | ||
| 1195 | 1194 | ||
| 1196 | if (decl_ptr_ty_ref != ty_ref) { | 1195 | if (decl_ptr_ty_ref != ty_ref) { |
| 1197 | // Differing pointer types, insert a cast. | 1196 | // Differing pointer types, insert a cast. |
| ... | @@ -1229,8 +1228,13 @@ const DeclGen = struct { | ... | @@ -1229,8 +1228,13 @@ const DeclGen = struct { |
| 1229 | } | 1228 | } |
| 1230 | 1229 | ||
| 1231 | const spv_decl_index = try self.object.resolveDecl(mod, decl_index); | 1230 | const spv_decl_index = try self.object.resolveDecl(mod, decl_index); |
| 1231 | const spv_decl = self.spv.declPtr(spv_decl_index); | ||
| 1232 | |||
| 1233 | const decl_id = switch (spv_decl.kind) { | ||
| 1234 | .func => unreachable, // TODO: Is this possible? | ||
| 1235 | .global, .invocation_global => spv_decl.result_id, | ||
| 1236 | }; | ||
| 1232 | 1237 | ||
| 1233 | const decl_id = self.spv.declPtr(spv_decl_index).result_id; | ||
| 1234 | const final_storage_class = self.spvStorageClass(decl.@"addrspace"); | 1238 | const final_storage_class = self.spvStorageClass(decl.@"addrspace"); |
| 1235 | try self.addFunctionDep(spv_decl_index, final_storage_class); | 1239 | try self.addFunctionDep(spv_decl_index, final_storage_class); |
| 1236 | 1240 | ||
| ... | @@ -1509,6 +1513,13 @@ const DeclGen = struct { | ... | @@ -1509,6 +1513,13 @@ const DeclGen = struct { |
| 1509 | if (self.type_map.get(ty.toIntern())) |info| return info.ty_ref; | 1513 | if (self.type_map.get(ty.toIntern())) |info| return info.ty_ref; |
| 1510 | 1514 | ||
| 1511 | const fn_info = mod.typeToFunc(ty).?; | 1515 | const fn_info = mod.typeToFunc(ty).?; |
| 1516 | |||
| 1517 | comptime assert(zig_call_abi_ver == 3); | ||
| 1518 | switch (fn_info.cc) { | ||
| 1519 | .Unspecified, .Kernel, .Fragment, .Vertex, .C => {}, | ||
| 1520 | else => unreachable, // TODO | ||
| 1521 | } | ||
| 1522 | |||
| 1512 | // TODO: Put this somewhere in Sema.zig | 1523 | // TODO: Put this somewhere in Sema.zig |
| 1513 | if (fn_info.is_var_args) | 1524 | if (fn_info.is_var_args) |
| 1514 | return self.fail("VarArgs functions are unsupported for SPIR-V", .{}); | 1525 | return self.fail("VarArgs functions are unsupported for SPIR-V", .{}); |
| ... | @@ -1956,13 +1967,15 @@ const DeclGen = struct { | ... | @@ -1956,13 +1967,15 @@ const DeclGen = struct { |
| 1956 | /// (anyerror!void has the same layout as anyerror). | 1967 | /// (anyerror!void has the same layout as anyerror). |
| 1957 | /// Each test declaration generates a function like. | 1968 | /// Each test declaration generates a function like. |
| 1958 | /// %anyerror = OpTypeInt 0 16 | 1969 | /// %anyerror = OpTypeInt 0 16 |
| 1970 | /// %p_invocation_globals_struct_ty = ... | ||
| 1959 | /// %p_anyerror = OpTypePointer CrossWorkgroup %anyerror | 1971 | /// %p_anyerror = OpTypePointer CrossWorkgroup %anyerror |
| 1960 | /// %K = OpTypeFunction %void %p_anyerror | 1972 | /// %K = OpTypeFunction %void %p_invocation_globals_struct_ty %p_anyerror |
| 1961 | /// | 1973 | /// |
| 1962 | /// %test = OpFunction %void %K | 1974 | /// %test = OpFunction %void %K |
| 1975 | /// %p_invocation_globals = OpFunctionParameter p_invocation_globals_struct_ty | ||
| 1963 | /// %p_err = OpFunctionParameter %p_anyerror | 1976 | /// %p_err = OpFunctionParameter %p_anyerror |
| 1964 | /// %lbl = OpLabel | 1977 | /// %lbl = OpLabel |
| 1965 | /// %result = OpFunctionCall %anyerror %func | 1978 | /// %result = OpFunctionCall %anyerror %func %p_invocation_globals |
| 1966 | /// OpStore %p_err %result | 1979 | /// OpStore %p_err %result |
| 1967 | /// OpFunctionEnd | 1980 | /// OpFunctionEnd |
| 1968 | /// TODO is to also write out the error as a function call parameter, and to somehow fetch | 1981 | /// TODO is to also write out the error as a function call parameter, and to somehow fetch |
| ... | @@ -1972,10 +1985,12 @@ const DeclGen = struct { | ... | @@ -1972,10 +1985,12 @@ const DeclGen = struct { |
| 1972 | const ptr_anyerror_ty_ref = try self.ptrType(Type.anyerror, .CrossWorkgroup); | 1985 | const ptr_anyerror_ty_ref = try self.ptrType(Type.anyerror, .CrossWorkgroup); |
| 1973 | const void_ty_ref = try self.resolveType(Type.void, .direct); | 1986 | const void_ty_ref = try self.resolveType(Type.void, .direct); |
| 1974 | 1987 | ||
| 1975 | const kernel_proto_ty_ref = try self.spv.resolve(.{ .function_type = .{ | 1988 | const kernel_proto_ty_ref = try self.spv.resolve(.{ |
| 1976 | .return_type = void_ty_ref, | 1989 | .function_type = .{ |
| 1977 | .parameters = &.{ptr_anyerror_ty_ref}, | 1990 | .return_type = void_ty_ref, |
| 1978 | } }); | 1991 | .parameters = &.{ptr_anyerror_ty_ref}, |
| 1992 | }, | ||
| 1993 | }); | ||
| 1979 | 1994 | ||
| 1980 | const test_id = self.spv.declPtr(spv_test_decl_index).result_id; | 1995 | const test_id = self.spv.declPtr(spv_test_decl_index).result_id; |
| 1981 | 1996 | ||
| ... | @@ -2026,147 +2041,164 @@ const DeclGen = struct { | ... | @@ -2026,147 +2041,164 @@ const DeclGen = struct { |
| 2026 | const ip = &mod.intern_pool; | 2041 | const ip = &mod.intern_pool; |
| 2027 | const decl = mod.declPtr(self.decl_index); | 2042 | const decl = mod.declPtr(self.decl_index); |
| 2028 | const spv_decl_index = try self.object.resolveDecl(mod, self.decl_index); | 2043 | const spv_decl_index = try self.object.resolveDecl(mod, self.decl_index); |
| 2029 | const target = self.getTarget(); | 2044 | const result_id = self.spv.declPtr(spv_decl_index).result_id; |
| 2030 | 2045 | ||
| 2031 | const decl_id = self.spv.declPtr(spv_decl_index).result_id; | 2046 | switch (self.spv.declPtr(spv_decl_index).kind) { |
| 2047 | .func => { | ||
| 2048 | assert(decl.ty.zigTypeTag(mod) == .Fn); | ||
| 2049 | const fn_info = mod.typeToFunc(decl.ty).?; | ||
| 2050 | const return_ty_ref = try self.resolveFnReturnType(Type.fromInterned(fn_info.return_type)); | ||
| 2032 | 2051 | ||
| 2033 | if (decl.val.getFunction(mod)) |_| { | 2052 | const prototype_ty_ref = try self.resolveType(decl.ty, .direct); |
| 2034 | assert(decl.ty.zigTypeTag(mod) == .Fn); | 2053 | try self.func.prologue.emit(self.spv.gpa, .OpFunction, .{ |
| 2035 | const fn_info = mod.typeToFunc(decl.ty).?; | 2054 | .id_result_type = self.typeId(return_ty_ref), |
| 2036 | const return_ty_ref = try self.resolveFnReturnType(Type.fromInterned(fn_info.return_type)); | 2055 | .id_result = result_id, |
| 2056 | .function_control = switch (fn_info.cc) { | ||
| 2057 | .Inline => .{ .Inline = true }, | ||
| 2058 | else => .{}, | ||
| 2059 | }, | ||
| 2060 | .function_type = self.typeId(prototype_ty_ref), | ||
| 2061 | }); | ||
| 2037 | 2062 | ||
| 2038 | const prototype_id = try self.resolveTypeId(decl.ty); | 2063 | comptime assert(zig_call_abi_ver == 3); |
| 2039 | try self.func.prologue.emit(self.spv.gpa, .OpFunction, .{ | 2064 | try self.args.ensureUnusedCapacity(self.gpa, fn_info.param_types.len); |
| 2040 | .id_result_type = self.typeId(return_ty_ref), | 2065 | for (fn_info.param_types.get(ip)) |param_ty_index| { |
| 2041 | .id_result = decl_id, | 2066 | const param_ty = Type.fromInterned(param_ty_index); |
| 2042 | .function_control = switch (fn_info.cc) { | 2067 | if (!param_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; |
| 2043 | .Inline => .{ .Inline = true }, | 2068 | |
| 2044 | else => .{}, | 2069 | const param_type_id = try self.resolveTypeId(param_ty); |
| 2045 | }, | 2070 | const arg_result_id = self.spv.allocId(); |
| 2046 | .function_type = prototype_id, | 2071 | try self.func.prologue.emit(self.spv.gpa, .OpFunctionParameter, .{ |
| 2047 | }); | 2072 | .id_result_type = param_type_id, |
| 2073 | .id_result = arg_result_id, | ||
| 2074 | }); | ||
| 2075 | self.args.appendAssumeCapacity(arg_result_id); | ||
| 2076 | } | ||
| 2048 | 2077 | ||
| 2049 | try self.args.ensureUnusedCapacity(self.gpa, fn_info.param_types.len); | 2078 | // TODO: This could probably be done in a better way... |
| 2050 | for (fn_info.param_types.get(ip)) |param_ty_index| { | 2079 | const root_block_id = self.spv.allocId(); |
| 2051 | const param_ty = Type.fromInterned(param_ty_index); | ||
| 2052 | if (!param_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; | ||
| 2053 | 2080 | ||
| 2054 | const param_type_id = try self.resolveTypeId(param_ty); | 2081 | // The root block of a function declaration should appear before OpVariable instructions, |
| 2055 | const arg_result_id = self.spv.allocId(); | 2082 | // so it is generated into the function's prologue. |
| 2056 | try self.func.prologue.emit(self.spv.gpa, .OpFunctionParameter, .{ | 2083 | try self.func.prologue.emit(self.spv.gpa, .OpLabel, .{ |
| 2057 | .id_result_type = param_type_id, | 2084 | .id_result = root_block_id, |
| 2058 | .id_result = arg_result_id, | ||
| 2059 | }); | 2085 | }); |
| 2060 | self.args.appendAssumeCapacity(arg_result_id); | 2086 | self.current_block_label = root_block_id; |
| 2061 | } | ||
| 2062 | 2087 | ||
| 2063 | // TODO: This could probably be done in a better way... | 2088 | const main_body = self.air.getMainBody(); |
| 2064 | const root_block_id = self.spv.allocId(); | 2089 | switch (self.control_flow) { |
| 2090 | .structured => { | ||
| 2091 | _ = try self.genStructuredBody(.selection, main_body); | ||
| 2092 | // We always expect paths to here to end, but we still need the block | ||
| 2093 | // to act as a dummy merge block. | ||
| 2094 | try self.func.body.emit(self.spv.gpa, .OpUnreachable, {}); | ||
| 2095 | }, | ||
| 2096 | .unstructured => { | ||
| 2097 | try self.genBody(main_body); | ||
| 2098 | }, | ||
| 2099 | } | ||
| 2100 | try self.func.body.emit(self.spv.gpa, .OpFunctionEnd, {}); | ||
| 2101 | // Append the actual code into the functions section. | ||
| 2102 | try self.spv.addFunction(spv_decl_index, self.func); | ||
| 2065 | 2103 | ||
| 2066 | // The root block of a function declaration should appear before OpVariable instructions, | 2104 | const fqn = ip.stringToSlice(try decl.fullyQualifiedName(self.module)); |
| 2067 | // so it is generated into the function's prologue. | 2105 | try self.spv.debugName(result_id, fqn); |
| 2068 | try self.func.prologue.emit(self.spv.gpa, .OpLabel, .{ | ||
| 2069 | .id_result = root_block_id, | ||
| 2070 | }); | ||
| 2071 | self.current_block_label = root_block_id; | ||
| 2072 | 2106 | ||
| 2073 | const main_body = self.air.getMainBody(); | 2107 | // Temporarily generate a test kernel declaration if this is a test function. |
| 2074 | switch (self.control_flow) { | 2108 | if (self.module.test_functions.contains(self.decl_index)) { |
| 2075 | .structured => { | 2109 | try self.generateTestEntryPoint(fqn, spv_decl_index); |
| 2076 | _ = try self.genStructuredBody(.selection, main_body); | 2110 | } |
| 2077 | // We always expect paths to here to end, but we still need the block | 2111 | }, |
| 2078 | // to act as a dummy merge block. | 2112 | .global => { |
| 2079 | try self.func.body.emit(self.spv.gpa, .OpUnreachable, {}); | 2113 | const maybe_init_val: ?Value = blk: { |
| 2080 | }, | 2114 | if (decl.val.getVariable(mod)) |payload| { |
| 2081 | .unstructured => { | 2115 | if (payload.is_extern) break :blk null; |
| 2082 | try self.genBody(main_body); | 2116 | break :blk Value.fromInterned(payload.init); |
| 2083 | }, | 2117 | } |
| 2084 | } | 2118 | break :blk decl.val; |
| 2085 | try self.func.body.emit(self.spv.gpa, .OpFunctionEnd, {}); | 2119 | }; |
| 2086 | // Append the actual code into the functions section. | 2120 | assert(maybe_init_val == null); // TODO |
| 2087 | try self.spv.addFunction(spv_decl_index, self.func); | ||
| 2088 | 2121 | ||
| 2089 | const fqn = ip.stringToSlice(try decl.fullyQualifiedName(self.module)); | 2122 | const final_storage_class = self.spvStorageClass(decl.@"addrspace"); |
| 2090 | try self.spv.debugName(decl_id, fqn); | 2123 | assert(final_storage_class != .Generic); // These should be instance globals |
| 2091 | 2124 | ||
| 2092 | // Temporarily generate a test kernel declaration if this is a test function. | 2125 | const ptr_ty_ref = try self.ptrType(decl.ty, final_storage_class); |
| 2093 | if (self.module.test_functions.contains(self.decl_index)) { | ||
| 2094 | try self.generateTestEntryPoint(fqn, spv_decl_index); | ||
| 2095 | } | ||
| 2096 | } else { | ||
| 2097 | const opt_init_val: ?Value = blk: { | ||
| 2098 | if (decl.val.getVariable(mod)) |payload| { | ||
| 2099 | if (payload.is_extern) break :blk null; | ||
| 2100 | break :blk Value.fromInterned(payload.init); | ||
| 2101 | } | ||
| 2102 | break :blk decl.val; | ||
| 2103 | }; | ||
| 2104 | 2126 | ||
| 2105 | // Generate the actual variable for the global... | 2127 | try self.spv.sections.types_globals_constants.emit(self.spv.gpa, .OpVariable, .{ |
| 2106 | const final_storage_class = self.spvStorageClass(decl.@"addrspace"); | 2128 | .id_result_type = self.typeId(ptr_ty_ref), |
| 2107 | const actual_storage_class = blk: { | 2129 | .id_result = result_id, |
| 2108 | if (target.os.tag != .vulkan) { | 2130 | .storage_class = final_storage_class, |
| 2109 | break :blk switch (final_storage_class) { | 2131 | }); |
| 2110 | .Generic => .CrossWorkgroup, | ||
| 2111 | else => final_storage_class, | ||
| 2112 | }; | ||
| 2113 | } | ||
| 2114 | break :blk final_storage_class; | ||
| 2115 | }; | ||
| 2116 | 2132 | ||
| 2117 | const ptr_ty_ref = try self.ptrType(decl.ty, actual_storage_class); | 2133 | const fqn = ip.stringToSlice(try decl.fullyQualifiedName(self.module)); |
| 2134 | try self.spv.debugName(result_id, fqn); | ||
| 2135 | try self.spv.declareDeclDeps(spv_decl_index, &.{}); | ||
| 2136 | }, | ||
| 2137 | .invocation_global => { | ||
| 2138 | const maybe_init_val: ?Value = blk: { | ||
| 2139 | if (decl.val.getVariable(mod)) |payload| { | ||
| 2140 | if (payload.is_extern) break :blk null; | ||
| 2141 | break :blk Value.fromInterned(payload.init); | ||
| 2142 | } | ||
| 2143 | break :blk decl.val; | ||
| 2144 | }; | ||
| 2118 | 2145 | ||
| 2119 | const begin = self.spv.beginGlobal(); | 2146 | try self.spv.declareDeclDeps(spv_decl_index, &.{}); |
| 2120 | try self.spv.globals.section.emit(self.spv.gpa, .OpVariable, .{ | ||
| 2121 | .id_result_type = self.typeId(ptr_ty_ref), | ||
| 2122 | .id_result = decl_id, | ||
| 2123 | .storage_class = actual_storage_class, | ||
| 2124 | }); | ||
| 2125 | const fqn = ip.stringToSlice(try decl.fullyQualifiedName(self.module)); | ||
| 2126 | try self.spv.debugName(decl_id, fqn); | ||
| 2127 | 2147 | ||
| 2128 | if (opt_init_val) |init_val| { | 2148 | const ptr_ty_ref = try self.ptrType(decl.ty, .Function); |
| 2129 | // Currently, initializers for CrossWorkgroup variables is not implemented | ||
| 2130 | // in Mesa. Therefore we generate an initialization kernel instead. | ||
| 2131 | const void_ty_ref = try self.resolveType(Type.void, .direct); | ||
| 2132 | 2149 | ||
| 2133 | const initializer_proto_ty_ref = try self.spv.resolve(.{ .function_type = .{ | 2150 | if (maybe_init_val) |init_val| { |
| 2134 | .return_type = void_ty_ref, | 2151 | // TODO: Combine with resolveAnonDecl? |
| 2135 | .parameters = &.{}, | 2152 | const void_ty_ref = try self.resolveType(Type.void, .direct); |
| 2136 | } }); | 2153 | const initializer_proto_ty_ref = try self.spv.resolve(.{ .function_type = .{ |
| 2154 | .return_type = void_ty_ref, | ||
| 2155 | .parameters = &.{}, | ||
| 2156 | } }); | ||
| 2137 | 2157 | ||
| 2138 | // Now emit the instructions that initialize the variable. | 2158 | const initializer_id = self.spv.allocId(); |
| 2139 | const initializer_id = self.spv.allocId(); | 2159 | try self.func.prologue.emit(self.spv.gpa, .OpFunction, .{ |
| 2140 | try self.func.prologue.emit(self.spv.gpa, .OpFunction, .{ | 2160 | .id_result_type = self.typeId(void_ty_ref), |
| 2141 | .id_result_type = self.typeId(void_ty_ref), | 2161 | .id_result = initializer_id, |
| 2142 | .id_result = initializer_id, | 2162 | .function_control = .{}, |
| 2143 | .function_control = .{}, | 2163 | .function_type = self.typeId(initializer_proto_ty_ref), |
| 2144 | .function_type = self.typeId(initializer_proto_ty_ref), | 2164 | }); |
| 2145 | }); | ||
| 2146 | const root_block_id = self.spv.allocId(); | ||
| 2147 | try self.func.prologue.emit(self.spv.gpa, .OpLabel, .{ | ||
| 2148 | .id_result = root_block_id, | ||
| 2149 | }); | ||
| 2150 | self.current_block_label = root_block_id; | ||
| 2151 | 2165 | ||
| 2152 | const val_id = try self.constant(decl.ty, init_val, .indirect); | 2166 | const root_block_id = self.spv.allocId(); |
| 2153 | try self.func.body.emit(self.spv.gpa, .OpStore, .{ | 2167 | try self.func.prologue.emit(self.spv.gpa, .OpLabel, .{ |
| 2154 | .pointer = decl_id, | 2168 | .id_result = root_block_id, |
| 2155 | .object = val_id, | 2169 | }); |
| 2156 | }); | 2170 | self.current_block_label = root_block_id; |
| 2157 | 2171 | ||
| 2158 | // TODO: We should be able to get rid of this by now... | 2172 | const val_id = try self.constant(decl.ty, init_val, .indirect); |
| 2159 | self.spv.endGlobal(spv_decl_index, begin, decl_id, initializer_id); | 2173 | try self.func.body.emit(self.spv.gpa, .OpStore, .{ |
| 2174 | .pointer = result_id, | ||
| 2175 | .object = val_id, | ||
| 2176 | }); | ||
| 2160 | 2177 | ||
| 2161 | try self.func.body.emit(self.spv.gpa, .OpReturn, {}); | 2178 | try self.func.body.emit(self.spv.gpa, .OpReturn, {}); |
| 2162 | try self.func.body.emit(self.spv.gpa, .OpFunctionEnd, {}); | 2179 | try self.func.body.emit(self.spv.gpa, .OpFunctionEnd, {}); |
| 2163 | try self.spv.addFunction(spv_decl_index, self.func); | 2180 | try self.spv.addFunction(spv_decl_index, self.func); |
| 2164 | 2181 | ||
| 2165 | try self.spv.debugNameFmt(initializer_id, "initializer of {s}", .{fqn}); | 2182 | const fqn = ip.stringToSlice(try decl.fullyQualifiedName(self.module)); |
| 2166 | } else { | 2183 | try self.spv.debugNameFmt(initializer_id, "initializer of {s}", .{fqn}); |
| 2167 | self.spv.endGlobal(spv_decl_index, begin, decl_id, null); | 2184 | |
| 2168 | try self.spv.declareDeclDeps(spv_decl_index, &.{}); | 2185 | try self.spv.sections.types_globals_constants.emit(self.spv.gpa, .OpExtInst, .{ |
| 2169 | } | 2186 | .id_result_type = self.typeId(ptr_ty_ref), |
| 2187 | .id_result = result_id, | ||
| 2188 | .set = try self.spv.importInstructionSet(.zig), | ||
| 2189 | .instruction = .{ .inst = 0 }, // TODO: Put this definition somewhere... | ||
| 2190 | .id_ref_4 = &.{initializer_id}, | ||
| 2191 | }); | ||
| 2192 | } else { | ||
| 2193 | try self.spv.sections.types_globals_constants.emit(self.spv.gpa, .OpExtInst, .{ | ||
| 2194 | .id_result_type = self.typeId(ptr_ty_ref), | ||
| 2195 | .id_result = result_id, | ||
| 2196 | .set = try self.spv.importInstructionSet(.zig), | ||
| 2197 | .instruction = .{ .inst = 0 }, // TODO: Put this definition somewhere... | ||
| 2198 | .id_ref_4 = &.{}, | ||
| 2199 | }); | ||
| 2200 | } | ||
| 2201 | }, | ||
| 2170 | } | 2202 | } |
| 2171 | } | 2203 | } |
| 2172 | 2204 | ||
| ... | @@ -2559,8 +2591,8 @@ const DeclGen = struct { | ... | @@ -2559,8 +2591,8 @@ const DeclGen = struct { |
| 2559 | else => unreachable, | 2591 | else => unreachable, |
| 2560 | }; | 2592 | }; |
| 2561 | const set_id = switch (target.os.tag) { | 2593 | const set_id = switch (target.os.tag) { |
| 2562 | .opencl => try self.spv.importInstructionSet(.opencl), | 2594 | .opencl => try self.spv.importInstructionSet(.@"OpenCL.std"), |
| 2563 | .vulkan => try self.spv.importInstructionSet(.glsl), | 2595 | .vulkan => try self.spv.importInstructionSet(.@"GLSL.std.450"), |
| 2564 | else => unreachable, | 2596 | else => unreachable, |
| 2565 | }; | 2597 | }; |
| 2566 | 2598 | ||
| ... | @@ -2734,8 +2766,8 @@ const DeclGen = struct { | ... | @@ -2734,8 +2766,8 @@ const DeclGen = struct { |
| 2734 | else => unreachable, | 2766 | else => unreachable, |
| 2735 | }; | 2767 | }; |
| 2736 | const set_id = switch (target.os.tag) { | 2768 | const set_id = switch (target.os.tag) { |
| 2737 | .opencl => try self.spv.importInstructionSet(.opencl), | 2769 | .opencl => try self.spv.importInstructionSet(.@"OpenCL.std"), |
| 2738 | .vulkan => try self.spv.importInstructionSet(.glsl), | 2770 | .vulkan => try self.spv.importInstructionSet(.@"GLSL.std.450"), |
| 2739 | else => unreachable, | 2771 | else => unreachable, |
| 2740 | }; | 2772 | }; |
| 2741 | 2773 | ||
| ... | @@ -5427,9 +5459,9 @@ const DeclGen = struct { | ... | @@ -5427,9 +5459,9 @@ const DeclGen = struct { |
| 5427 | const result_id = self.spv.allocId(); | 5459 | const result_id = self.spv.allocId(); |
| 5428 | const callee_id = try self.resolve(pl_op.operand); | 5460 | const callee_id = try self.resolve(pl_op.operand); |
| 5429 | 5461 | ||
| 5462 | comptime assert(zig_call_abi_ver == 3); | ||
| 5430 | const params = try self.gpa.alloc(spec.IdRef, args.len); | 5463 | const params = try self.gpa.alloc(spec.IdRef, args.len); |
| 5431 | defer self.gpa.free(params); | 5464 | defer self.gpa.free(params); |
| 5432 | |||
| 5433 | var n_params: usize = 0; | 5465 | var n_params: usize = 0; |
| 5434 | for (args) |arg| { | 5466 | for (args) |arg| { |
| 5435 | // Note: resolve() might emit instructions, so we need to call it | 5467 | // Note: resolve() might emit instructions, so we need to call it |
src/codegen/spirv/Cache.zig+10-21| ... | @@ -134,7 +134,10 @@ const Tag = enum { | ... | @@ -134,7 +134,10 @@ const Tag = enum { |
| 134 | /// data is (bool) type | 134 | /// data is (bool) type |
| 135 | bool_false, | 135 | bool_false, |
| 136 | 136 | ||
| 137 | const SimpleType = enum { void, bool }; | 137 | const SimpleType = enum { |
| 138 | void, | ||
| 139 | bool, | ||
| 140 | }; | ||
| 138 | 141 | ||
| 139 | const VectorType = Key.VectorType; | 142 | const VectorType = Key.VectorType; |
| 140 | const ArrayType = Key.ArrayType; | 143 | const ArrayType = Key.ArrayType; |
| ... | @@ -287,11 +290,12 @@ pub const Key = union(enum) { | ... | @@ -287,11 +290,12 @@ pub const Key = union(enum) { |
| 287 | pub const PointerType = struct { | 290 | pub const PointerType = struct { |
| 288 | storage_class: StorageClass, | 291 | storage_class: StorageClass, |
| 289 | child_type: Ref, | 292 | child_type: Ref, |
| 293 | /// Ref to a .fwd_ptr_type. | ||
| 290 | fwd: Ref, | 294 | fwd: Ref, |
| 291 | // TODO: Decorations: | 295 | // TODO: Decorations: |
| 292 | // - Alignment | 296 | // - Alignment |
| 293 | // - ArrayStride, | 297 | // - ArrayStride |
| 294 | // - MaxByteOffset, | 298 | // - MaxByteOffset |
| 295 | }; | 299 | }; |
| 296 | 300 | ||
| 297 | pub const ForwardPointerType = struct { | 301 | pub const ForwardPointerType = struct { |
| ... | @@ -728,6 +732,9 @@ pub fn resolve(self: *Self, spv: *Module, key: Key) !Ref { | ... | @@ -728,6 +732,9 @@ pub fn resolve(self: *Self, spv: *Module, key: Key) !Ref { |
| 728 | // }, | 732 | // }, |
| 729 | .ptr_type => |ptr| Item{ | 733 | .ptr_type => |ptr| Item{ |
| 730 | .tag = .type_ptr_simple, | 734 | .tag = .type_ptr_simple, |
| 735 | // For this variant we need to steal the ID of the forward-declaration, instead | ||
| 736 | // of allocating one manually. This will make sure that we get a single result-id | ||
| 737 | // any possibly forward declared pointer type. | ||
| 731 | .result_id = self.resultId(ptr.fwd), | 738 | .result_id = self.resultId(ptr.fwd), |
| 732 | .data = try self.addExtra(spv, Tag.SimplePointerType{ | 739 | .data = try self.addExtra(spv, Tag.SimplePointerType{ |
| 733 | .storage_class = ptr.storage_class, | 740 | .storage_class = ptr.storage_class, |
| ... | @@ -896,24 +903,6 @@ pub fn lookup(self: *const Self, ref: Ref) Key { | ... | @@ -896,24 +903,6 @@ pub fn lookup(self: *const Self, ref: Ref) Key { |
| 896 | }, | 903 | }, |
| 897 | }; | 904 | }; |
| 898 | }, | 905 | }, |
| 899 | // .type_ptr_generic => .{ | ||
| 900 | // .ptr_type = .{ | ||
| 901 | // .storage_class = .Generic, | ||
| 902 | // .child_type = @enumFromInt(data), | ||
| 903 | // }, | ||
| 904 | // }, | ||
| 905 | // .type_ptr_crosswgp => .{ | ||
| 906 | // .ptr_type = .{ | ||
| 907 | // .storage_class = .CrossWorkgroup, | ||
| 908 | // .child_type = @enumFromInt(data), | ||
| 909 | // }, | ||
| 910 | // }, | ||
| 911 | // .type_ptr_function => .{ | ||
| 912 | // .ptr_type = .{ | ||
| 913 | // .storage_class = .Function, | ||
| 914 | // .child_type = @enumFromInt(data), | ||
| 915 | // }, | ||
| 916 | // }, | ||
| 917 | .type_ptr_simple => { | 906 | .type_ptr_simple => { |
| 918 | const payload = self.extraData(Tag.SimplePointerType, data); | 907 | const payload = self.extraData(Tag.SimplePointerType, data); |
| 919 | return .{ | 908 | return .{ |
src/codegen/spirv/Module.zig+43-227| ... | @@ -72,9 +72,20 @@ pub const Decl = struct { | ... | @@ -72,9 +72,20 @@ pub const Decl = struct { |
| 72 | /// Index to refer to a Decl by. | 72 | /// Index to refer to a Decl by. |
| 73 | pub const Index = enum(u32) { _ }; | 73 | pub const Index = enum(u32) { _ }; |
| 74 | 74 | ||
| 75 | /// The result-id to be used for this declaration. This is the final result-id | 75 | /// Useful to tell what kind of decl this is, and hold the result-id or field index |
| 76 | /// of the decl, which may be an OpFunction, OpVariable, or the result of a sequence | 76 | /// to be used for this decl. |
| 77 | /// of OpSpecConstantOp operations. | 77 | pub const Kind = enum { |
| 78 | func, | ||
| 79 | global, | ||
| 80 | invocation_global, | ||
| 81 | }; | ||
| 82 | |||
| 83 | /// See comment on Kind | ||
| 84 | kind: Kind, | ||
| 85 | /// The result-id associated to this decl. The specific meaning of this depends on `kind`: | ||
| 86 | /// - For `func`, this is the result-id of the associated OpFunction instruction. | ||
| 87 | /// - For `global`, this is the result-id of the associated OpVariable instruction. | ||
| 88 | /// - For `invocation_global`, this is the result-id of the associated InvocationGlobal instruction. | ||
| 78 | result_id: IdRef, | 89 | result_id: IdRef, |
| 79 | /// The offset of the first dependency of this decl in the `decl_deps` array. | 90 | /// The offset of the first dependency of this decl in the `decl_deps` array. |
| 80 | begin_dep: u32, | 91 | begin_dep: u32, |
| ... | @@ -82,20 +93,6 @@ pub const Decl = struct { | ... | @@ -82,20 +93,6 @@ pub const Decl = struct { |
| 82 | end_dep: u32, | 93 | end_dep: u32, |
| 83 | }; | 94 | }; |
| 84 | 95 | ||
| 85 | /// Globals must be kept in order: operations involving globals must be ordered | ||
| 86 | /// so that the global declaration precedes any usage. | ||
| 87 | pub const Global = struct { | ||
| 88 | /// This is the result-id of the OpVariable instruction that declares the global. | ||
| 89 | result_id: IdRef, | ||
| 90 | /// The offset into `self.globals.section` of the first instruction of this global | ||
| 91 | /// declaration. | ||
| 92 | begin_inst: u32, | ||
| 93 | /// The past-end offset into `self.flobals.section`. | ||
| 94 | end_inst: u32, | ||
| 95 | /// The result-id of the function that initializes this value. | ||
| 96 | initializer_id: ?IdRef, | ||
| 97 | }; | ||
| 98 | |||
| 99 | /// This models a kernel entry point. | 96 | /// This models a kernel entry point. |
| 100 | pub const EntryPoint = struct { | 97 | pub const EntryPoint = struct { |
| 101 | /// The declaration that should be exported. | 98 | /// The declaration that should be exported. |
| ... | @@ -165,18 +162,8 @@ decl_deps: std.ArrayListUnmanaged(Decl.Index) = .{}, | ... | @@ -165,18 +162,8 @@ decl_deps: std.ArrayListUnmanaged(Decl.Index) = .{}, |
| 165 | /// The list of entry points that should be exported from this module. | 162 | /// The list of entry points that should be exported from this module. |
| 166 | entry_points: std.ArrayListUnmanaged(EntryPoint) = .{}, | 163 | entry_points: std.ArrayListUnmanaged(EntryPoint) = .{}, |
| 167 | 164 | ||
| 168 | /// The fields in this structure help to maintain the required order for global variables. | ||
| 169 | globals: struct { | ||
| 170 | /// Set of globals, referred to by Decl.Index. | ||
| 171 | globals: std.AutoArrayHashMapUnmanaged(Decl.Index, Global) = .{}, | ||
| 172 | /// This pseudo-section contains the initialization code for all the globals. Instructions from | ||
| 173 | /// here are reordered when flushing the module. Its contents should be part of the | ||
| 174 | /// `types_globals_constants` SPIR-V section when the module is emitted. | ||
| 175 | section: Section = .{}, | ||
| 176 | } = .{}, | ||
| 177 | |||
| 178 | /// The list of extended instruction sets that should be imported. | 165 | /// The list of extended instruction sets that should be imported. |
| 179 | extended_instruction_set: std.AutoHashMapUnmanaged(ExtendedInstructionSet, IdRef) = .{}, | 166 | extended_instruction_set: std.AutoHashMapUnmanaged(spec.InstructionSet, IdRef) = .{}, |
| 180 | 167 | ||
| 181 | pub fn init(gpa: Allocator) Module { | 168 | pub fn init(gpa: Allocator) Module { |
| 182 | return .{ | 169 | return .{ |
| ... | @@ -205,9 +192,6 @@ pub fn deinit(self: *Module) void { | ... | @@ -205,9 +192,6 @@ pub fn deinit(self: *Module) void { |
| 205 | 192 | ||
| 206 | self.entry_points.deinit(self.gpa); | 193 | self.entry_points.deinit(self.gpa); |
| 207 | 194 | ||
| 208 | self.globals.globals.deinit(self.gpa); | ||
| 209 | self.globals.section.deinit(self.gpa); | ||
| 210 | |||
| 211 | self.extended_instruction_set.deinit(self.gpa); | 195 | self.extended_instruction_set.deinit(self.gpa); |
| 212 | 196 | ||
| 213 | self.* = undefined; | 197 | self.* = undefined; |
| ... | @@ -243,46 +227,6 @@ pub fn resolveString(self: *Module, str: []const u8) !CacheString { | ... | @@ -243,46 +227,6 @@ pub fn resolveString(self: *Module, str: []const u8) !CacheString { |
| 243 | return try self.cache.addString(self, str); | 227 | return try self.cache.addString(self, str); |
| 244 | } | 228 | } |
| 245 | 229 | ||
| 246 | fn orderGlobalsInto( | ||
| 247 | self: *Module, | ||
| 248 | decl_index: Decl.Index, | ||
| 249 | section: *Section, | ||
| 250 | seen: *std.DynamicBitSetUnmanaged, | ||
| 251 | ) !void { | ||
| 252 | const decl = self.declPtr(decl_index); | ||
| 253 | const deps = self.decl_deps.items[decl.begin_dep..decl.end_dep]; | ||
| 254 | const global = self.globalPtr(decl_index).?; | ||
| 255 | const insts = self.globals.section.instructions.items[global.begin_inst..global.end_inst]; | ||
| 256 | |||
| 257 | seen.set(@intFromEnum(decl_index)); | ||
| 258 | |||
| 259 | for (deps) |dep| { | ||
| 260 | if (!seen.isSet(@intFromEnum(dep))) { | ||
| 261 | try self.orderGlobalsInto(dep, section, seen); | ||
| 262 | } | ||
| 263 | } | ||
| 264 | |||
| 265 | try section.instructions.appendSlice(self.gpa, insts); | ||
| 266 | } | ||
| 267 | |||
| 268 | fn orderGlobals(self: *Module) !Section { | ||
| 269 | const globals = self.globals.globals.keys(); | ||
| 270 | |||
| 271 | var seen = try std.DynamicBitSetUnmanaged.initEmpty(self.gpa, self.decls.items.len); | ||
| 272 | defer seen.deinit(self.gpa); | ||
| 273 | |||
| 274 | var ordered_globals = Section{}; | ||
| 275 | errdefer ordered_globals.deinit(self.gpa); | ||
| 276 | |||
| 277 | for (globals) |decl_index| { | ||
| 278 | if (!seen.isSet(@intFromEnum(decl_index))) { | ||
| 279 | try self.orderGlobalsInto(decl_index, &ordered_globals, &seen); | ||
| 280 | } | ||
| 281 | } | ||
| 282 | |||
| 283 | return ordered_globals; | ||
| 284 | } | ||
| 285 | |||
| 286 | fn addEntryPointDeps( | 230 | fn addEntryPointDeps( |
| 287 | self: *Module, | 231 | self: *Module, |
| 288 | decl_index: Decl.Index, | 232 | decl_index: Decl.Index, |
| ... | @@ -298,8 +242,8 @@ fn addEntryPointDeps( | ... | @@ -298,8 +242,8 @@ fn addEntryPointDeps( |
| 298 | 242 | ||
| 299 | seen.set(@intFromEnum(decl_index)); | 243 | seen.set(@intFromEnum(decl_index)); |
| 300 | 244 | ||
| 301 | if (self.globalPtr(decl_index)) |global| { | 245 | if (decl.kind == .global) { |
| 302 | try interface.append(global.result_id); | 246 | try interface.append(decl.result_id); |
| 303 | } | 247 | } |
| 304 | 248 | ||
| 305 | for (deps) |dep| { | 249 | for (deps) |dep| { |
| ... | @@ -335,81 +279,9 @@ fn entryPoints(self: *Module) !Section { | ... | @@ -335,81 +279,9 @@ fn entryPoints(self: *Module) !Section { |
| 335 | return entry_points; | 279 | return entry_points; |
| 336 | } | 280 | } |
| 337 | 281 | ||
| 338 | /// Generate a function that calls all initialization functions, | 282 | pub fn finalize(self: *Module, a: Allocator, target: std.Target) ![]Word { |
| 339 | /// in unspecified order (an order should not be required here). | ||
| 340 | /// It generated as follows: | ||
| 341 | /// %init = OpFunction %void None | ||
| 342 | /// foreach %initializer: | ||
| 343 | /// OpFunctionCall %initializer | ||
| 344 | /// OpReturn | ||
| 345 | /// OpFunctionEnd | ||
| 346 | fn initializer(self: *Module, entry_points: *Section) !Section { | ||
| 347 | var section = Section{}; | ||
| 348 | errdefer section.deinit(self.gpa); | ||
| 349 | |||
| 350 | // const void_ty_ref = try self.resolveType(Type.void, .direct); | ||
| 351 | const void_ty_ref = try self.resolve(.void_type); | ||
| 352 | const void_ty_id = self.resultId(void_ty_ref); | ||
| 353 | const init_proto_ty_ref = try self.resolve(.{ .function_type = .{ | ||
| 354 | .return_type = void_ty_ref, | ||
| 355 | .parameters = &.{}, | ||
| 356 | } }); | ||
| 357 | |||
| 358 | const init_id = self.allocId(); | ||
| 359 | try section.emit(self.gpa, .OpFunction, .{ | ||
| 360 | .id_result_type = void_ty_id, | ||
| 361 | .id_result = init_id, | ||
| 362 | .function_control = .{}, | ||
| 363 | .function_type = self.resultId(init_proto_ty_ref), | ||
| 364 | }); | ||
| 365 | try section.emit(self.gpa, .OpLabel, .{ | ||
| 366 | .id_result = self.allocId(), | ||
| 367 | }); | ||
| 368 | |||
| 369 | var seen = try std.DynamicBitSetUnmanaged.initEmpty(self.gpa, self.decls.items.len); | ||
| 370 | defer seen.deinit(self.gpa); | ||
| 371 | |||
| 372 | var interface = std.ArrayList(IdRef).init(self.gpa); | ||
| 373 | defer interface.deinit(); | ||
| 374 | |||
| 375 | for (self.globals.globals.keys(), self.globals.globals.values()) |decl_index, global| { | ||
| 376 | try self.addEntryPointDeps(decl_index, &seen, &interface); | ||
| 377 | if (global.initializer_id) |initializer_id| { | ||
| 378 | try section.emit(self.gpa, .OpFunctionCall, .{ | ||
| 379 | .id_result_type = void_ty_id, | ||
| 380 | .id_result = self.allocId(), | ||
| 381 | .function = initializer_id, | ||
| 382 | }); | ||
| 383 | } | ||
| 384 | } | ||
| 385 | |||
| 386 | try section.emit(self.gpa, .OpReturn, {}); | ||
| 387 | try section.emit(self.gpa, .OpFunctionEnd, {}); | ||
| 388 | |||
| 389 | try entry_points.emit(self.gpa, .OpEntryPoint, .{ | ||
| 390 | // TODO: Rusticl does not support this because its poorly defined. | ||
| 391 | // Do we need to generate a workaround here? | ||
| 392 | .execution_model = .Kernel, | ||
| 393 | .entry_point = init_id, | ||
| 394 | .name = "zig global initializer", | ||
| 395 | .interface = interface.items, | ||
| 396 | }); | ||
| 397 | |||
| 398 | try self.sections.execution_modes.emit(self.gpa, .OpExecutionMode, .{ | ||
| 399 | .entry_point = init_id, | ||
| 400 | .mode = .Initializer, | ||
| 401 | }); | ||
| 402 | |||
| 403 | return section; | ||
| 404 | } | ||
| 405 | |||
| 406 | /// Emit this module as a spir-v binary. | ||
| 407 | pub fn flush(self: *Module, file: std.fs.File, target: std.Target) !void { | ||
| 408 | // See SPIR-V Spec section 2.3, "Physical Layout of a SPIR-V Module and Instruction" | 283 | // See SPIR-V Spec section 2.3, "Physical Layout of a SPIR-V Module and Instruction" |
| 409 | 284 | // TODO: Audit calls to allocId() in this function to make it idempotent. | |
| 410 | // TODO: Perform topological sort on the globals. | ||
| 411 | var globals = try self.orderGlobals(); | ||
| 412 | defer globals.deinit(self.gpa); | ||
| 413 | 285 | ||
| 414 | var entry_points = try self.entryPoints(); | 286 | var entry_points = try self.entryPoints(); |
| 415 | defer entry_points.deinit(self.gpa); | 287 | defer entry_points.deinit(self.gpa); |
| ... | @@ -417,13 +289,6 @@ pub fn flush(self: *Module, file: std.fs.File, target: std.Target) !void { | ... | @@ -417,13 +289,6 @@ pub fn flush(self: *Module, file: std.fs.File, target: std.Target) !void { |
| 417 | var types_constants = try self.cache.materialize(self); | 289 | var types_constants = try self.cache.materialize(self); |
| 418 | defer types_constants.deinit(self.gpa); | 290 | defer types_constants.deinit(self.gpa); |
| 419 | 291 | ||
| 420 | // // TODO: Pass global variables as function parameters | ||
| 421 | // var init_func = if (target.os.tag != .vulkan) | ||
| 422 | // try self.initializer(&entry_points) | ||
| 423 | // else | ||
| 424 | // Section{}; | ||
| 425 | // defer init_func.deinit(self.gpa); | ||
| 426 | |||
| 427 | const header = [_]Word{ | 292 | const header = [_]Word{ |
| 428 | spec.magic_number, | 293 | spec.magic_number, |
| 429 | // TODO: From cpu features | 294 | // TODO: From cpu features |
| ... | @@ -436,7 +301,7 @@ pub fn flush(self: *Module, file: std.fs.File, target: std.Target) !void { | ... | @@ -436,7 +301,7 @@ pub fn flush(self: *Module, file: std.fs.File, target: std.Target) !void { |
| 436 | else => 4, | 301 | else => 4, |
| 437 | }, | 302 | }, |
| 438 | }), | 303 | }), |
| 439 | 0, // TODO: Register Zig compiler magic number. | 304 | spec.zig_generator_id, |
| 440 | self.idBound(), | 305 | self.idBound(), |
| 441 | 0, // Schema (currently reserved for future use) | 306 | 0, // Schema (currently reserved for future use) |
| 442 | }; | 307 | }; |
| ... | @@ -468,30 +333,23 @@ pub fn flush(self: *Module, file: std.fs.File, target: std.Target) !void { | ... | @@ -468,30 +333,23 @@ pub fn flush(self: *Module, file: std.fs.File, target: std.Target) !void { |
| 468 | self.sections.annotations.toWords(), | 333 | self.sections.annotations.toWords(), |
| 469 | types_constants.toWords(), | 334 | types_constants.toWords(), |
| 470 | self.sections.types_globals_constants.toWords(), | 335 | self.sections.types_globals_constants.toWords(), |
| 471 | globals.toWords(), | ||
| 472 | self.sections.functions.toWords(), | 336 | self.sections.functions.toWords(), |
| 473 | }; | 337 | }; |
| 474 | 338 | ||
| 475 | if (builtin.zig_backend == .stage2_x86_64) { | 339 | var total_result_size: usize = 0; |
| 476 | for (buffers) |buf| { | 340 | for (buffers) |buffer| { |
| 477 | try file.writeAll(std.mem.sliceAsBytes(buf)); | 341 | total_result_size += buffer.len; |
| 478 | } | 342 | } |
| 479 | } else { | 343 | const result = try a.alloc(Word, total_result_size); |
| 480 | // miscompiles with x86_64 backend | 344 | errdefer a.free(result); |
| 481 | var iovc_buffers: [buffers.len]std.os.iovec_const = undefined; | 345 | |
| 482 | var file_size: u64 = 0; | 346 | var offset: usize = 0; |
| 483 | for (&iovc_buffers, 0..) |*iovc, i| { | 347 | for (buffers) |buffer| { |
| 484 | // Note, since spir-v supports both little and big endian we can ignore byte order here and | 348 | @memcpy(result[offset..][0..buffer.len], buffer); |
| 485 | // just treat the words as a sequence of bytes. | 349 | offset += buffer.len; |
| 486 | const bytes = std.mem.sliceAsBytes(buffers[i]); | ||
| 487 | iovc.* = .{ .iov_base = bytes.ptr, .iov_len = bytes.len }; | ||
| 488 | file_size += bytes.len; | ||
| 489 | } | ||
| 490 | |||
| 491 | try file.seekTo(0); | ||
| 492 | try file.setEndPos(file_size); | ||
| 493 | try file.pwritevAll(&iovc_buffers, 0); | ||
| 494 | } | 350 | } |
| 351 | |||
| 352 | return result; | ||
| 495 | } | 353 | } |
| 496 | 354 | ||
| 497 | /// Merge the sections making up a function declaration into this module. | 355 | /// Merge the sections making up a function declaration into this module. |
| ... | @@ -501,23 +359,17 @@ pub fn addFunction(self: *Module, decl_index: Decl.Index, func: Fn) !void { | ... | @@ -501,23 +359,17 @@ pub fn addFunction(self: *Module, decl_index: Decl.Index, func: Fn) !void { |
| 501 | try self.declareDeclDeps(decl_index, func.decl_deps.keys()); | 359 | try self.declareDeclDeps(decl_index, func.decl_deps.keys()); |
| 502 | } | 360 | } |
| 503 | 361 | ||
| 504 | pub const ExtendedInstructionSet = enum { | ||
| 505 | glsl, | ||
| 506 | opencl, | ||
| 507 | }; | ||
| 508 | |||
| 509 | /// Imports or returns the existing id of an extended instruction set | 362 | /// Imports or returns the existing id of an extended instruction set |
| 510 | pub fn importInstructionSet(self: *Module, set: ExtendedInstructionSet) !IdRef { | 363 | pub fn importInstructionSet(self: *Module, set: spec.InstructionSet) !IdRef { |
| 364 | assert(set != .core); | ||
| 365 | |||
| 511 | const gop = try self.extended_instruction_set.getOrPut(self.gpa, set); | 366 | const gop = try self.extended_instruction_set.getOrPut(self.gpa, set); |
| 512 | if (gop.found_existing) return gop.value_ptr.*; | 367 | if (gop.found_existing) return gop.value_ptr.*; |
| 513 | 368 | ||
| 514 | const result_id = self.allocId(); | 369 | const result_id = self.allocId(); |
| 515 | try self.sections.extended_instruction_set.emit(self.gpa, .OpExtInstImport, .{ | 370 | try self.sections.extended_instruction_set.emit(self.gpa, .OpExtInstImport, .{ |
| 516 | .id_result = result_id, | 371 | .id_result = result_id, |
| 517 | .name = switch (set) { | 372 | .name = @tagName(set), |
| 518 | .glsl => "GLSL.std.450", | ||
| 519 | .opencl => "OpenCL.std", | ||
| 520 | }, | ||
| 521 | }); | 373 | }); |
| 522 | gop.value_ptr.* = result_id; | 374 | gop.value_ptr.* = result_id; |
| 523 | 375 | ||
| ... | @@ -631,40 +483,21 @@ pub fn decorateMember( | ... | @@ -631,40 +483,21 @@ pub fn decorateMember( |
| 631 | }); | 483 | }); |
| 632 | } | 484 | } |
| 633 | 485 | ||
| 634 | pub const DeclKind = enum { | 486 | pub fn allocDecl(self: *Module, kind: Decl.Kind) !Decl.Index { |
| 635 | func, | ||
| 636 | global, | ||
| 637 | }; | ||
| 638 | |||
| 639 | pub fn allocDecl(self: *Module, kind: DeclKind) !Decl.Index { | ||
| 640 | try self.decls.append(self.gpa, .{ | 487 | try self.decls.append(self.gpa, .{ |
| 488 | .kind = kind, | ||
| 641 | .result_id = self.allocId(), | 489 | .result_id = self.allocId(), |
| 642 | .begin_dep = undefined, | 490 | .begin_dep = undefined, |
| 643 | .end_dep = undefined, | 491 | .end_dep = undefined, |
| 644 | }); | 492 | }); |
| 645 | const index = @as(Decl.Index, @enumFromInt(@as(u32, @intCast(self.decls.items.len - 1)))); | ||
| 646 | switch (kind) { | ||
| 647 | .func => {}, | ||
| 648 | // If the decl represents a global, also allocate a global node. | ||
| 649 | .global => try self.globals.globals.putNoClobber(self.gpa, index, .{ | ||
| 650 | .result_id = undefined, | ||
| 651 | .begin_inst = undefined, | ||
| 652 | .end_inst = undefined, | ||
| 653 | .initializer_id = undefined, | ||
| 654 | }), | ||
| 655 | } | ||
| 656 | 493 | ||
| 657 | return index; | 494 | return @as(Decl.Index, @enumFromInt(@as(u32, @intCast(self.decls.items.len - 1)))); |
| 658 | } | 495 | } |
| 659 | 496 | ||
| 660 | pub fn declPtr(self: *Module, index: Decl.Index) *Decl { | 497 | pub fn declPtr(self: *Module, index: Decl.Index) *Decl { |
| 661 | return &self.decls.items[@intFromEnum(index)]; | 498 | return &self.decls.items[@intFromEnum(index)]; |
| 662 | } | 499 | } |
| 663 | 500 | ||
| 664 | pub fn globalPtr(self: *Module, index: Decl.Index) ?*Global { | ||
| 665 | return self.globals.globals.getPtr(index); | ||
| 666 | } | ||
| 667 | |||
| 668 | /// Declare ALL dependencies for a decl. | 501 | /// Declare ALL dependencies for a decl. |
| 669 | pub fn declareDeclDeps(self: *Module, decl_index: Decl.Index, deps: []const Decl.Index) !void { | 502 | pub fn declareDeclDeps(self: *Module, decl_index: Decl.Index, deps: []const Decl.Index) !void { |
| 670 | const begin_dep = @as(u32, @intCast(self.decl_deps.items.len)); | 503 | const begin_dep = @as(u32, @intCast(self.decl_deps.items.len)); |
| ... | @@ -676,26 +509,9 @@ pub fn declareDeclDeps(self: *Module, decl_index: Decl.Index, deps: []const Decl | ... | @@ -676,26 +509,9 @@ pub fn declareDeclDeps(self: *Module, decl_index: Decl.Index, deps: []const Decl |
| 676 | decl.end_dep = end_dep; | 509 | decl.end_dep = end_dep; |
| 677 | } | 510 | } |
| 678 | 511 | ||
| 679 | pub fn beginGlobal(self: *Module) u32 { | 512 | /// Declare a SPIR-V function as an entry point. This causes an extra wrapper |
| 680 | return @as(u32, @intCast(self.globals.section.instructions.items.len)); | 513 | /// function to be generated, which is then exported as the real entry point. The purpose of this |
| 681 | } | 514 | /// wrapper is to allocate and initialize the structure holding the instance globals. |
| 682 | |||
| 683 | pub fn endGlobal( | ||
| 684 | self: *Module, | ||
| 685 | global_index: Decl.Index, | ||
| 686 | begin_inst: u32, | ||
| 687 | result_id: IdRef, | ||
| 688 | initializer_id: ?IdRef, | ||
| 689 | ) void { | ||
| 690 | const global = self.globalPtr(global_index).?; | ||
| 691 | global.* = .{ | ||
| 692 | .result_id = result_id, | ||
| 693 | .begin_inst = begin_inst, | ||
| 694 | .end_inst = @intCast(self.globals.section.instructions.items.len), | ||
| 695 | .initializer_id = initializer_id, | ||
| 696 | }; | ||
| 697 | } | ||
| 698 | |||
| 699 | pub fn declareEntryPoint( | 515 | pub fn declareEntryPoint( |
| 700 | self: *Module, | 516 | self: *Module, |
| 701 | decl_index: Decl.Index, | 517 | decl_index: Decl.Index, |
src/codegen/spirv/Section.zig+11| ... | @@ -53,6 +53,17 @@ pub fn emitRaw( | ... | @@ -53,6 +53,17 @@ pub fn emitRaw( |
| 53 | section.writeWord((@as(Word, @intCast(word_count << 16))) | @intFromEnum(opcode)); | 53 | section.writeWord((@as(Word, @intCast(word_count << 16))) | @intFromEnum(opcode)); |
| 54 | } | 54 | } |
| 55 | 55 | ||
| 56 | /// Write an entire instruction, including all operands | ||
| 57 | pub fn emitRawInstruction( | ||
| 58 | section: *Section, | ||
| 59 | allocator: Allocator, | ||
| 60 | opcode: Opcode, | ||
| 61 | operands: []const Word, | ||
| 62 | ) !void { | ||
| 63 | try section.emitRaw(allocator, opcode, operands.len); | ||
| 64 | section.writeWords(operands); | ||
| 65 | } | ||
| 66 | |||
| 56 | pub fn emit( | 67 | pub fn emit( |
| 57 | section: *Section, | 68 | section: *Section, |
| 58 | allocator: Allocator, | 69 | allocator: Allocator, |
src/codegen/spirv/spec.zig+147-132| ... | @@ -1,5 +1,7 @@ | ... | @@ -1,5 +1,7 @@ |
| 1 | //! This file is auto-generated by tools/gen_spirv_spec.zig. | 1 | //! This file is auto-generated by tools/gen_spirv_spec.zig. |
| 2 | 2 | ||
| 3 | const std = @import("std"); | ||
| 4 | |||
| 3 | pub const Version = packed struct(Word) { | 5 | pub const Version = packed struct(Word) { |
| 4 | padding: u8 = 0, | 6 | padding: u8 = 0, |
| 5 | minor: u8, | 7 | minor: u8, |
| ... | @@ -15,6 +17,18 @@ pub const Word = u32; | ... | @@ -15,6 +17,18 @@ pub const Word = u32; |
| 15 | pub const IdResult = enum(Word) { | 17 | pub const IdResult = enum(Word) { |
| 16 | none, | 18 | none, |
| 17 | _, | 19 | _, |
| 20 | |||
| 21 | pub fn format( | ||
| 22 | self: IdResult, | ||
| 23 | comptime _: []const u8, | ||
| 24 | _: std.fmt.FormatOptions, | ||
| 25 | writer: anytype, | ||
| 26 | ) @TypeOf(writer).Error!void { | ||
| 27 | switch (self) { | ||
| 28 | .none => try writer.writeAll("(none)"), | ||
| 29 | else => try writer.print("%{}", .{@intFromEnum(self)}), | ||
| 30 | } | ||
| 31 | } | ||
| 18 | }; | 32 | }; |
| 19 | pub const IdResultType = IdResult; | 33 | pub const IdResultType = IdResult; |
| 20 | pub const IdRef = IdResult; | 34 | pub const IdRef = IdResult; |
| ... | @@ -70,6 +84,7 @@ pub const Instruction = struct { | ... | @@ -70,6 +84,7 @@ pub const Instruction = struct { |
| 70 | operands: []const Operand, | 84 | operands: []const Operand, |
| 71 | }; | 85 | }; |
| 72 | 86 | ||
| 87 | pub const zig_generator_id: Word = 41; | ||
| 73 | pub const version = Version{ .major = 1, .minor = 6, .patch = 1 }; | 88 | pub const version = Version{ .major = 1, .minor = 6, .patch = 1 }; |
| 74 | pub const magic_number: Word = 0x07230203; | 89 | pub const magic_number: Word = 0x07230203; |
| 75 | 90 | ||
| ... | @@ -166,25 +181,25 @@ pub const OperandKind = enum { | ... | @@ -166,25 +181,25 @@ pub const OperandKind = enum { |
| 166 | PairLiteralIntegerIdRef, | 181 | PairLiteralIntegerIdRef, |
| 167 | PairIdRefLiteralInteger, | 182 | PairIdRefLiteralInteger, |
| 168 | PairIdRefIdRef, | 183 | PairIdRefIdRef, |
| 169 | @"opencl.debuginfo.100.DebugInfoFlags", | 184 | @"OpenCL.DebugInfo.100.DebugInfoFlags", |
| 170 | @"opencl.debuginfo.100.DebugBaseTypeAttributeEncoding", | 185 | @"OpenCL.DebugInfo.100.DebugBaseTypeAttributeEncoding", |
| 171 | @"opencl.debuginfo.100.DebugCompositeType", | 186 | @"OpenCL.DebugInfo.100.DebugCompositeType", |
| 172 | @"opencl.debuginfo.100.DebugTypeQualifier", | 187 | @"OpenCL.DebugInfo.100.DebugTypeQualifier", |
| 173 | @"opencl.debuginfo.100.DebugOperation", | 188 | @"OpenCL.DebugInfo.100.DebugOperation", |
| 174 | @"opencl.debuginfo.100.DebugImportedEntity", | 189 | @"OpenCL.DebugInfo.100.DebugImportedEntity", |
| 175 | @"nonsemantic.shader.debuginfo.100.DebugInfoFlags", | 190 | @"NonSemantic.Shader.DebugInfo.100.DebugInfoFlags", |
| 176 | @"nonsemantic.shader.debuginfo.100.BuildIdentifierFlags", | 191 | @"NonSemantic.Shader.DebugInfo.100.BuildIdentifierFlags", |
| 177 | @"nonsemantic.shader.debuginfo.100.DebugBaseTypeAttributeEncoding", | 192 | @"NonSemantic.Shader.DebugInfo.100.DebugBaseTypeAttributeEncoding", |
| 178 | @"nonsemantic.shader.debuginfo.100.DebugCompositeType", | 193 | @"NonSemantic.Shader.DebugInfo.100.DebugCompositeType", |
| 179 | @"nonsemantic.shader.debuginfo.100.DebugTypeQualifier", | 194 | @"NonSemantic.Shader.DebugInfo.100.DebugTypeQualifier", |
| 180 | @"nonsemantic.shader.debuginfo.100.DebugOperation", | 195 | @"NonSemantic.Shader.DebugInfo.100.DebugOperation", |
| 181 | @"nonsemantic.shader.debuginfo.100.DebugImportedEntity", | 196 | @"NonSemantic.Shader.DebugInfo.100.DebugImportedEntity", |
| 182 | @"nonsemantic.clspvreflection.KernelPropertyFlags", | 197 | @"NonSemantic.ClspvReflection.6.KernelPropertyFlags", |
| 183 | @"debuginfo.DebugInfoFlags", | 198 | @"DebugInfo.DebugInfoFlags", |
| 184 | @"debuginfo.DebugBaseTypeAttributeEncoding", | 199 | @"DebugInfo.DebugBaseTypeAttributeEncoding", |
| 185 | @"debuginfo.DebugCompositeType", | 200 | @"DebugInfo.DebugCompositeType", |
| 186 | @"debuginfo.DebugTypeQualifier", | 201 | @"DebugInfo.DebugTypeQualifier", |
| 187 | @"debuginfo.DebugOperation", | 202 | @"DebugInfo.DebugOperation", |
| 188 | 203 | ||
| 189 | pub fn category(self: OperandKind) OperandCategory { | 204 | pub fn category(self: OperandKind) OperandCategory { |
| 190 | return switch (self) { | 205 | return switch (self) { |
| ... | @@ -252,25 +267,25 @@ pub const OperandKind = enum { | ... | @@ -252,25 +267,25 @@ pub const OperandKind = enum { |
| 252 | .PairLiteralIntegerIdRef => .composite, | 267 | .PairLiteralIntegerIdRef => .composite, |
| 253 | .PairIdRefLiteralInteger => .composite, | 268 | .PairIdRefLiteralInteger => .composite, |
| 254 | .PairIdRefIdRef => .composite, | 269 | .PairIdRefIdRef => .composite, |
| 255 | .@"opencl.debuginfo.100.DebugInfoFlags" => .bit_enum, | 270 | .@"OpenCL.DebugInfo.100.DebugInfoFlags" => .bit_enum, |
| 256 | .@"opencl.debuginfo.100.DebugBaseTypeAttributeEncoding" => .value_enum, | 271 | .@"OpenCL.DebugInfo.100.DebugBaseTypeAttributeEncoding" => .value_enum, |
| 257 | .@"opencl.debuginfo.100.DebugCompositeType" => .value_enum, | 272 | .@"OpenCL.DebugInfo.100.DebugCompositeType" => .value_enum, |
| 258 | .@"opencl.debuginfo.100.DebugTypeQualifier" => .value_enum, | 273 | .@"OpenCL.DebugInfo.100.DebugTypeQualifier" => .value_enum, |
| 259 | .@"opencl.debuginfo.100.DebugOperation" => .value_enum, | 274 | .@"OpenCL.DebugInfo.100.DebugOperation" => .value_enum, |
| 260 | .@"opencl.debuginfo.100.DebugImportedEntity" => .value_enum, | 275 | .@"OpenCL.DebugInfo.100.DebugImportedEntity" => .value_enum, |
| 261 | .@"nonsemantic.shader.debuginfo.100.DebugInfoFlags" => .bit_enum, | 276 | .@"NonSemantic.Shader.DebugInfo.100.DebugInfoFlags" => .bit_enum, |
| 262 | .@"nonsemantic.shader.debuginfo.100.BuildIdentifierFlags" => .bit_enum, | 277 | .@"NonSemantic.Shader.DebugInfo.100.BuildIdentifierFlags" => .bit_enum, |
| 263 | .@"nonsemantic.shader.debuginfo.100.DebugBaseTypeAttributeEncoding" => .value_enum, | 278 | .@"NonSemantic.Shader.DebugInfo.100.DebugBaseTypeAttributeEncoding" => .value_enum, |
| 264 | .@"nonsemantic.shader.debuginfo.100.DebugCompositeType" => .value_enum, | 279 | .@"NonSemantic.Shader.DebugInfo.100.DebugCompositeType" => .value_enum, |
| 265 | .@"nonsemantic.shader.debuginfo.100.DebugTypeQualifier" => .value_enum, | 280 | .@"NonSemantic.Shader.DebugInfo.100.DebugTypeQualifier" => .value_enum, |
| 266 | .@"nonsemantic.shader.debuginfo.100.DebugOperation" => .value_enum, | 281 | .@"NonSemantic.Shader.DebugInfo.100.DebugOperation" => .value_enum, |
| 267 | .@"nonsemantic.shader.debuginfo.100.DebugImportedEntity" => .value_enum, | 282 | .@"NonSemantic.Shader.DebugInfo.100.DebugImportedEntity" => .value_enum, |
| 268 | .@"nonsemantic.clspvreflection.KernelPropertyFlags" => .bit_enum, | 283 | .@"NonSemantic.ClspvReflection.6.KernelPropertyFlags" => .bit_enum, |
| 269 | .@"debuginfo.DebugInfoFlags" => .bit_enum, | 284 | .@"DebugInfo.DebugInfoFlags" => .bit_enum, |
| 270 | .@"debuginfo.DebugBaseTypeAttributeEncoding" => .value_enum, | 285 | .@"DebugInfo.DebugBaseTypeAttributeEncoding" => .value_enum, |
| 271 | .@"debuginfo.DebugCompositeType" => .value_enum, | 286 | .@"DebugInfo.DebugCompositeType" => .value_enum, |
| 272 | .@"debuginfo.DebugTypeQualifier" => .value_enum, | 287 | .@"DebugInfo.DebugTypeQualifier" => .value_enum, |
| 273 | .@"debuginfo.DebugOperation" => .value_enum, | 288 | .@"DebugInfo.DebugOperation" => .value_enum, |
| 274 | }; | 289 | }; |
| 275 | } | 290 | } |
| 276 | pub fn enumerants(self: OperandKind) []const Enumerant { | 291 | pub fn enumerants(self: OperandKind) []const Enumerant { |
| ... | @@ -1395,7 +1410,7 @@ pub const OperandKind = enum { | ... | @@ -1395,7 +1410,7 @@ pub const OperandKind = enum { |
| 1395 | .PairLiteralIntegerIdRef => unreachable, | 1410 | .PairLiteralIntegerIdRef => unreachable, |
| 1396 | .PairIdRefLiteralInteger => unreachable, | 1411 | .PairIdRefLiteralInteger => unreachable, |
| 1397 | .PairIdRefIdRef => unreachable, | 1412 | .PairIdRefIdRef => unreachable, |
| 1398 | .@"opencl.debuginfo.100.DebugInfoFlags" => &[_]Enumerant{ | 1413 | .@"OpenCL.DebugInfo.100.DebugInfoFlags" => &[_]Enumerant{ |
| 1399 | .{ .name = "FlagIsProtected", .value = 0x01, .parameters = &[_]OperandKind{} }, | 1414 | .{ .name = "FlagIsProtected", .value = 0x01, .parameters = &[_]OperandKind{} }, |
| 1400 | .{ .name = "FlagIsPrivate", .value = 0x02, .parameters = &[_]OperandKind{} }, | 1415 | .{ .name = "FlagIsPrivate", .value = 0x02, .parameters = &[_]OperandKind{} }, |
| 1401 | .{ .name = "FlagIsPublic", .value = 0x03, .parameters = &[_]OperandKind{} }, | 1416 | .{ .name = "FlagIsPublic", .value = 0x03, .parameters = &[_]OperandKind{} }, |
| ... | @@ -1415,7 +1430,7 @@ pub const OperandKind = enum { | ... | @@ -1415,7 +1430,7 @@ pub const OperandKind = enum { |
| 1415 | .{ .name = "FlagTypePassByValue", .value = 0x8000, .parameters = &[_]OperandKind{} }, | 1430 | .{ .name = "FlagTypePassByValue", .value = 0x8000, .parameters = &[_]OperandKind{} }, |
| 1416 | .{ .name = "FlagTypePassByReference", .value = 0x10000, .parameters = &[_]OperandKind{} }, | 1431 | .{ .name = "FlagTypePassByReference", .value = 0x10000, .parameters = &[_]OperandKind{} }, |
| 1417 | }, | 1432 | }, |
| 1418 | .@"opencl.debuginfo.100.DebugBaseTypeAttributeEncoding" => &[_]Enumerant{ | 1433 | .@"OpenCL.DebugInfo.100.DebugBaseTypeAttributeEncoding" => &[_]Enumerant{ |
| 1419 | .{ .name = "Unspecified", .value = 0, .parameters = &[_]OperandKind{} }, | 1434 | .{ .name = "Unspecified", .value = 0, .parameters = &[_]OperandKind{} }, |
| 1420 | .{ .name = "Address", .value = 1, .parameters = &[_]OperandKind{} }, | 1435 | .{ .name = "Address", .value = 1, .parameters = &[_]OperandKind{} }, |
| 1421 | .{ .name = "Boolean", .value = 2, .parameters = &[_]OperandKind{} }, | 1436 | .{ .name = "Boolean", .value = 2, .parameters = &[_]OperandKind{} }, |
| ... | @@ -1425,18 +1440,18 @@ pub const OperandKind = enum { | ... | @@ -1425,18 +1440,18 @@ pub const OperandKind = enum { |
| 1425 | .{ .name = "Unsigned", .value = 6, .parameters = &[_]OperandKind{} }, | 1440 | .{ .name = "Unsigned", .value = 6, .parameters = &[_]OperandKind{} }, |
| 1426 | .{ .name = "UnsignedChar", .value = 7, .parameters = &[_]OperandKind{} }, | 1441 | .{ .name = "UnsignedChar", .value = 7, .parameters = &[_]OperandKind{} }, |
| 1427 | }, | 1442 | }, |
| 1428 | .@"opencl.debuginfo.100.DebugCompositeType" => &[_]Enumerant{ | 1443 | .@"OpenCL.DebugInfo.100.DebugCompositeType" => &[_]Enumerant{ |
| 1429 | .{ .name = "Class", .value = 0, .parameters = &[_]OperandKind{} }, | 1444 | .{ .name = "Class", .value = 0, .parameters = &[_]OperandKind{} }, |
| 1430 | .{ .name = "Structure", .value = 1, .parameters = &[_]OperandKind{} }, | 1445 | .{ .name = "Structure", .value = 1, .parameters = &[_]OperandKind{} }, |
| 1431 | .{ .name = "Union", .value = 2, .parameters = &[_]OperandKind{} }, | 1446 | .{ .name = "Union", .value = 2, .parameters = &[_]OperandKind{} }, |
| 1432 | }, | 1447 | }, |
| 1433 | .@"opencl.debuginfo.100.DebugTypeQualifier" => &[_]Enumerant{ | 1448 | .@"OpenCL.DebugInfo.100.DebugTypeQualifier" => &[_]Enumerant{ |
| 1434 | .{ .name = "ConstType", .value = 0, .parameters = &[_]OperandKind{} }, | 1449 | .{ .name = "ConstType", .value = 0, .parameters = &[_]OperandKind{} }, |
| 1435 | .{ .name = "VolatileType", .value = 1, .parameters = &[_]OperandKind{} }, | 1450 | .{ .name = "VolatileType", .value = 1, .parameters = &[_]OperandKind{} }, |
| 1436 | .{ .name = "RestrictType", .value = 2, .parameters = &[_]OperandKind{} }, | 1451 | .{ .name = "RestrictType", .value = 2, .parameters = &[_]OperandKind{} }, |
| 1437 | .{ .name = "AtomicType", .value = 3, .parameters = &[_]OperandKind{} }, | 1452 | .{ .name = "AtomicType", .value = 3, .parameters = &[_]OperandKind{} }, |
| 1438 | }, | 1453 | }, |
| 1439 | .@"opencl.debuginfo.100.DebugOperation" => &[_]Enumerant{ | 1454 | .@"OpenCL.DebugInfo.100.DebugOperation" => &[_]Enumerant{ |
| 1440 | .{ .name = "Deref", .value = 0, .parameters = &[_]OperandKind{} }, | 1455 | .{ .name = "Deref", .value = 0, .parameters = &[_]OperandKind{} }, |
| 1441 | .{ .name = "Plus", .value = 1, .parameters = &[_]OperandKind{} }, | 1456 | .{ .name = "Plus", .value = 1, .parameters = &[_]OperandKind{} }, |
| 1442 | .{ .name = "Minus", .value = 2, .parameters = &[_]OperandKind{} }, | 1457 | .{ .name = "Minus", .value = 2, .parameters = &[_]OperandKind{} }, |
| ... | @@ -1448,11 +1463,11 @@ pub const OperandKind = enum { | ... | @@ -1448,11 +1463,11 @@ pub const OperandKind = enum { |
| 1448 | .{ .name = "Constu", .value = 8, .parameters = &[_]OperandKind{.LiteralInteger} }, | 1463 | .{ .name = "Constu", .value = 8, .parameters = &[_]OperandKind{.LiteralInteger} }, |
| 1449 | .{ .name = "Fragment", .value = 9, .parameters = &[_]OperandKind{ .LiteralInteger, .LiteralInteger } }, | 1464 | .{ .name = "Fragment", .value = 9, .parameters = &[_]OperandKind{ .LiteralInteger, .LiteralInteger } }, |
| 1450 | }, | 1465 | }, |
| 1451 | .@"opencl.debuginfo.100.DebugImportedEntity" => &[_]Enumerant{ | 1466 | .@"OpenCL.DebugInfo.100.DebugImportedEntity" => &[_]Enumerant{ |
| 1452 | .{ .name = "ImportedModule", .value = 0, .parameters = &[_]OperandKind{} }, | 1467 | .{ .name = "ImportedModule", .value = 0, .parameters = &[_]OperandKind{} }, |
| 1453 | .{ .name = "ImportedDeclaration", .value = 1, .parameters = &[_]OperandKind{} }, | 1468 | .{ .name = "ImportedDeclaration", .value = 1, .parameters = &[_]OperandKind{} }, |
| 1454 | }, | 1469 | }, |
| 1455 | .@"nonsemantic.shader.debuginfo.100.DebugInfoFlags" => &[_]Enumerant{ | 1470 | .@"NonSemantic.Shader.DebugInfo.100.DebugInfoFlags" => &[_]Enumerant{ |
| 1456 | .{ .name = "FlagIsProtected", .value = 0x01, .parameters = &[_]OperandKind{} }, | 1471 | .{ .name = "FlagIsProtected", .value = 0x01, .parameters = &[_]OperandKind{} }, |
| 1457 | .{ .name = "FlagIsPrivate", .value = 0x02, .parameters = &[_]OperandKind{} }, | 1472 | .{ .name = "FlagIsPrivate", .value = 0x02, .parameters = &[_]OperandKind{} }, |
| 1458 | .{ .name = "FlagIsPublic", .value = 0x03, .parameters = &[_]OperandKind{} }, | 1473 | .{ .name = "FlagIsPublic", .value = 0x03, .parameters = &[_]OperandKind{} }, |
| ... | @@ -1473,10 +1488,10 @@ pub const OperandKind = enum { | ... | @@ -1473,10 +1488,10 @@ pub const OperandKind = enum { |
| 1473 | .{ .name = "FlagTypePassByReference", .value = 0x10000, .parameters = &[_]OperandKind{} }, | 1488 | .{ .name = "FlagTypePassByReference", .value = 0x10000, .parameters = &[_]OperandKind{} }, |
| 1474 | .{ .name = "FlagUnknownPhysicalLayout", .value = 0x20000, .parameters = &[_]OperandKind{} }, | 1489 | .{ .name = "FlagUnknownPhysicalLayout", .value = 0x20000, .parameters = &[_]OperandKind{} }, |
| 1475 | }, | 1490 | }, |
| 1476 | .@"nonsemantic.shader.debuginfo.100.BuildIdentifierFlags" => &[_]Enumerant{ | 1491 | .@"NonSemantic.Shader.DebugInfo.100.BuildIdentifierFlags" => &[_]Enumerant{ |
| 1477 | .{ .name = "IdentifierPossibleDuplicates", .value = 0x01, .parameters = &[_]OperandKind{} }, | 1492 | .{ .name = "IdentifierPossibleDuplicates", .value = 0x01, .parameters = &[_]OperandKind{} }, |
| 1478 | }, | 1493 | }, |
| 1479 | .@"nonsemantic.shader.debuginfo.100.DebugBaseTypeAttributeEncoding" => &[_]Enumerant{ | 1494 | .@"NonSemantic.Shader.DebugInfo.100.DebugBaseTypeAttributeEncoding" => &[_]Enumerant{ |
| 1480 | .{ .name = "Unspecified", .value = 0, .parameters = &[_]OperandKind{} }, | 1495 | .{ .name = "Unspecified", .value = 0, .parameters = &[_]OperandKind{} }, |
| 1481 | .{ .name = "Address", .value = 1, .parameters = &[_]OperandKind{} }, | 1496 | .{ .name = "Address", .value = 1, .parameters = &[_]OperandKind{} }, |
| 1482 | .{ .name = "Boolean", .value = 2, .parameters = &[_]OperandKind{} }, | 1497 | .{ .name = "Boolean", .value = 2, .parameters = &[_]OperandKind{} }, |
| ... | @@ -1486,18 +1501,18 @@ pub const OperandKind = enum { | ... | @@ -1486,18 +1501,18 @@ pub const OperandKind = enum { |
| 1486 | .{ .name = "Unsigned", .value = 6, .parameters = &[_]OperandKind{} }, | 1501 | .{ .name = "Unsigned", .value = 6, .parameters = &[_]OperandKind{} }, |
| 1487 | .{ .name = "UnsignedChar", .value = 7, .parameters = &[_]OperandKind{} }, | 1502 | .{ .name = "UnsignedChar", .value = 7, .parameters = &[_]OperandKind{} }, |
| 1488 | }, | 1503 | }, |
| 1489 | .@"nonsemantic.shader.debuginfo.100.DebugCompositeType" => &[_]Enumerant{ | 1504 | .@"NonSemantic.Shader.DebugInfo.100.DebugCompositeType" => &[_]Enumerant{ |
| 1490 | .{ .name = "Class", .value = 0, .parameters = &[_]OperandKind{} }, | 1505 | .{ .name = "Class", .value = 0, .parameters = &[_]OperandKind{} }, |
| 1491 | .{ .name = "Structure", .value = 1, .parameters = &[_]OperandKind{} }, | 1506 | .{ .name = "Structure", .value = 1, .parameters = &[_]OperandKind{} }, |
| 1492 | .{ .name = "Union", .value = 2, .parameters = &[_]OperandKind{} }, | 1507 | .{ .name = "Union", .value = 2, .parameters = &[_]OperandKind{} }, |
| 1493 | }, | 1508 | }, |
| 1494 | .@"nonsemantic.shader.debuginfo.100.DebugTypeQualifier" => &[_]Enumerant{ | 1509 | .@"NonSemantic.Shader.DebugInfo.100.DebugTypeQualifier" => &[_]Enumerant{ |
| 1495 | .{ .name = "ConstType", .value = 0, .parameters = &[_]OperandKind{} }, | 1510 | .{ .name = "ConstType", .value = 0, .parameters = &[_]OperandKind{} }, |
| 1496 | .{ .name = "VolatileType", .value = 1, .parameters = &[_]OperandKind{} }, | 1511 | .{ .name = "VolatileType", .value = 1, .parameters = &[_]OperandKind{} }, |
| 1497 | .{ .name = "RestrictType", .value = 2, .parameters = &[_]OperandKind{} }, | 1512 | .{ .name = "RestrictType", .value = 2, .parameters = &[_]OperandKind{} }, |
| 1498 | .{ .name = "AtomicType", .value = 3, .parameters = &[_]OperandKind{} }, | 1513 | .{ .name = "AtomicType", .value = 3, .parameters = &[_]OperandKind{} }, |
| 1499 | }, | 1514 | }, |
| 1500 | .@"nonsemantic.shader.debuginfo.100.DebugOperation" => &[_]Enumerant{ | 1515 | .@"NonSemantic.Shader.DebugInfo.100.DebugOperation" => &[_]Enumerant{ |
| 1501 | .{ .name = "Deref", .value = 0, .parameters = &[_]OperandKind{} }, | 1516 | .{ .name = "Deref", .value = 0, .parameters = &[_]OperandKind{} }, |
| 1502 | .{ .name = "Plus", .value = 1, .parameters = &[_]OperandKind{} }, | 1517 | .{ .name = "Plus", .value = 1, .parameters = &[_]OperandKind{} }, |
| 1503 | .{ .name = "Minus", .value = 2, .parameters = &[_]OperandKind{} }, | 1518 | .{ .name = "Minus", .value = 2, .parameters = &[_]OperandKind{} }, |
| ... | @@ -1509,14 +1524,14 @@ pub const OperandKind = enum { | ... | @@ -1509,14 +1524,14 @@ pub const OperandKind = enum { |
| 1509 | .{ .name = "Constu", .value = 8, .parameters = &[_]OperandKind{.IdRef} }, | 1524 | .{ .name = "Constu", .value = 8, .parameters = &[_]OperandKind{.IdRef} }, |
| 1510 | .{ .name = "Fragment", .value = 9, .parameters = &[_]OperandKind{ .IdRef, .IdRef } }, | 1525 | .{ .name = "Fragment", .value = 9, .parameters = &[_]OperandKind{ .IdRef, .IdRef } }, |
| 1511 | }, | 1526 | }, |
| 1512 | .@"nonsemantic.shader.debuginfo.100.DebugImportedEntity" => &[_]Enumerant{ | 1527 | .@"NonSemantic.Shader.DebugInfo.100.DebugImportedEntity" => &[_]Enumerant{ |
| 1513 | .{ .name = "ImportedModule", .value = 0, .parameters = &[_]OperandKind{} }, | 1528 | .{ .name = "ImportedModule", .value = 0, .parameters = &[_]OperandKind{} }, |
| 1514 | .{ .name = "ImportedDeclaration", .value = 1, .parameters = &[_]OperandKind{} }, | 1529 | .{ .name = "ImportedDeclaration", .value = 1, .parameters = &[_]OperandKind{} }, |
| 1515 | }, | 1530 | }, |
| 1516 | .@"nonsemantic.clspvreflection.KernelPropertyFlags" => &[_]Enumerant{ | 1531 | .@"NonSemantic.ClspvReflection.6.KernelPropertyFlags" => &[_]Enumerant{ |
| 1517 | .{ .name = "MayUsePrintf", .value = 0x1, .parameters = &[_]OperandKind{} }, | 1532 | .{ .name = "MayUsePrintf", .value = 0x1, .parameters = &[_]OperandKind{} }, |
| 1518 | }, | 1533 | }, |
| 1519 | .@"debuginfo.DebugInfoFlags" => &[_]Enumerant{ | 1534 | .@"DebugInfo.DebugInfoFlags" => &[_]Enumerant{ |
| 1520 | .{ .name = "FlagIsProtected", .value = 0x01, .parameters = &[_]OperandKind{} }, | 1535 | .{ .name = "FlagIsProtected", .value = 0x01, .parameters = &[_]OperandKind{} }, |
| 1521 | .{ .name = "FlagIsPrivate", .value = 0x02, .parameters = &[_]OperandKind{} }, | 1536 | .{ .name = "FlagIsPrivate", .value = 0x02, .parameters = &[_]OperandKind{} }, |
| 1522 | .{ .name = "FlagIsPublic", .value = 0x03, .parameters = &[_]OperandKind{} }, | 1537 | .{ .name = "FlagIsPublic", .value = 0x03, .parameters = &[_]OperandKind{} }, |
| ... | @@ -1533,7 +1548,7 @@ pub const OperandKind = enum { | ... | @@ -1533,7 +1548,7 @@ pub const OperandKind = enum { |
| 1533 | .{ .name = "FlagRValueReference", .value = 0x1000, .parameters = &[_]OperandKind{} }, | 1548 | .{ .name = "FlagRValueReference", .value = 0x1000, .parameters = &[_]OperandKind{} }, |
| 1534 | .{ .name = "FlagIsOptimized", .value = 0x2000, .parameters = &[_]OperandKind{} }, | 1549 | .{ .name = "FlagIsOptimized", .value = 0x2000, .parameters = &[_]OperandKind{} }, |
| 1535 | }, | 1550 | }, |
| 1536 | .@"debuginfo.DebugBaseTypeAttributeEncoding" => &[_]Enumerant{ | 1551 | .@"DebugInfo.DebugBaseTypeAttributeEncoding" => &[_]Enumerant{ |
| 1537 | .{ .name = "Unspecified", .value = 0, .parameters = &[_]OperandKind{} }, | 1552 | .{ .name = "Unspecified", .value = 0, .parameters = &[_]OperandKind{} }, |
| 1538 | .{ .name = "Address", .value = 1, .parameters = &[_]OperandKind{} }, | 1553 | .{ .name = "Address", .value = 1, .parameters = &[_]OperandKind{} }, |
| 1539 | .{ .name = "Boolean", .value = 2, .parameters = &[_]OperandKind{} }, | 1554 | .{ .name = "Boolean", .value = 2, .parameters = &[_]OperandKind{} }, |
| ... | @@ -1543,17 +1558,17 @@ pub const OperandKind = enum { | ... | @@ -1543,17 +1558,17 @@ pub const OperandKind = enum { |
| 1543 | .{ .name = "Unsigned", .value = 7, .parameters = &[_]OperandKind{} }, | 1558 | .{ .name = "Unsigned", .value = 7, .parameters = &[_]OperandKind{} }, |
| 1544 | .{ .name = "UnsignedChar", .value = 8, .parameters = &[_]OperandKind{} }, | 1559 | .{ .name = "UnsignedChar", .value = 8, .parameters = &[_]OperandKind{} }, |
| 1545 | }, | 1560 | }, |
| 1546 | .@"debuginfo.DebugCompositeType" => &[_]Enumerant{ | 1561 | .@"DebugInfo.DebugCompositeType" => &[_]Enumerant{ |
| 1547 | .{ .name = "Class", .value = 0, .parameters = &[_]OperandKind{} }, | 1562 | .{ .name = "Class", .value = 0, .parameters = &[_]OperandKind{} }, |
| 1548 | .{ .name = "Structure", .value = 1, .parameters = &[_]OperandKind{} }, | 1563 | .{ .name = "Structure", .value = 1, .parameters = &[_]OperandKind{} }, |
| 1549 | .{ .name = "Union", .value = 2, .parameters = &[_]OperandKind{} }, | 1564 | .{ .name = "Union", .value = 2, .parameters = &[_]OperandKind{} }, |
| 1550 | }, | 1565 | }, |
| 1551 | .@"debuginfo.DebugTypeQualifier" => &[_]Enumerant{ | 1566 | .@"DebugInfo.DebugTypeQualifier" => &[_]Enumerant{ |
| 1552 | .{ .name = "ConstType", .value = 0, .parameters = &[_]OperandKind{} }, | 1567 | .{ .name = "ConstType", .value = 0, .parameters = &[_]OperandKind{} }, |
| 1553 | .{ .name = "VolatileType", .value = 1, .parameters = &[_]OperandKind{} }, | 1568 | .{ .name = "VolatileType", .value = 1, .parameters = &[_]OperandKind{} }, |
| 1554 | .{ .name = "RestrictType", .value = 2, .parameters = &[_]OperandKind{} }, | 1569 | .{ .name = "RestrictType", .value = 2, .parameters = &[_]OperandKind{} }, |
| 1555 | }, | 1570 | }, |
| 1556 | .@"debuginfo.DebugOperation" => &[_]Enumerant{ | 1571 | .@"DebugInfo.DebugOperation" => &[_]Enumerant{ |
| 1557 | .{ .name = "Deref", .value = 0, .parameters = &[_]OperandKind{} }, | 1572 | .{ .name = "Deref", .value = 0, .parameters = &[_]OperandKind{} }, |
| 1558 | .{ .name = "Plus", .value = 1, .parameters = &[_]OperandKind{} }, | 1573 | .{ .name = "Plus", .value = 1, .parameters = &[_]OperandKind{} }, |
| 1559 | .{ .name = "Minus", .value = 2, .parameters = &[_]OperandKind{} }, | 1574 | .{ .name = "Minus", .value = 2, .parameters = &[_]OperandKind{} }, |
| ... | @@ -4952,7 +4967,7 @@ pub const StoreCacheControl = enum(u32) { | ... | @@ -4952,7 +4967,7 @@ pub const StoreCacheControl = enum(u32) { |
| 4952 | pub const NamedMaximumNumberOfRegisters = enum(u32) { | 4967 | pub const NamedMaximumNumberOfRegisters = enum(u32) { |
| 4953 | AutoINTEL = 0, | 4968 | AutoINTEL = 0, |
| 4954 | }; | 4969 | }; |
| 4955 | pub const @"opencl.debuginfo.100.DebugInfoFlags" = packed struct { | 4970 | pub const @"OpenCL.DebugInfo.100.DebugInfoFlags" = packed struct { |
| 4956 | FlagIsProtected: bool = false, | 4971 | FlagIsProtected: bool = false, |
| 4957 | FlagIsPrivate: bool = false, | 4972 | FlagIsPrivate: bool = false, |
| 4958 | FlagIsLocal: bool = false, | 4973 | FlagIsLocal: bool = false, |
| ... | @@ -4986,7 +5001,7 @@ pub const @"opencl.debuginfo.100.DebugInfoFlags" = packed struct { | ... | @@ -4986,7 +5001,7 @@ pub const @"opencl.debuginfo.100.DebugInfoFlags" = packed struct { |
| 4986 | _reserved_bit_30: bool = false, | 5001 | _reserved_bit_30: bool = false, |
| 4987 | _reserved_bit_31: bool = false, | 5002 | _reserved_bit_31: bool = false, |
| 4988 | }; | 5003 | }; |
| 4989 | pub const @"opencl.debuginfo.100.DebugBaseTypeAttributeEncoding" = enum(u32) { | 5004 | pub const @"OpenCL.DebugInfo.100.DebugBaseTypeAttributeEncoding" = enum(u32) { |
| 4990 | Unspecified = 0, | 5005 | Unspecified = 0, |
| 4991 | Address = 1, | 5006 | Address = 1, |
| 4992 | Boolean = 2, | 5007 | Boolean = 2, |
| ... | @@ -4996,18 +5011,18 @@ pub const @"opencl.debuginfo.100.DebugBaseTypeAttributeEncoding" = enum(u32) { | ... | @@ -4996,18 +5011,18 @@ pub const @"opencl.debuginfo.100.DebugBaseTypeAttributeEncoding" = enum(u32) { |
| 4996 | Unsigned = 6, | 5011 | Unsigned = 6, |
| 4997 | UnsignedChar = 7, | 5012 | UnsignedChar = 7, |
| 4998 | }; | 5013 | }; |
| 4999 | pub const @"opencl.debuginfo.100.DebugCompositeType" = enum(u32) { | 5014 | pub const @"OpenCL.DebugInfo.100.DebugCompositeType" = enum(u32) { |
| 5000 | Class = 0, | 5015 | Class = 0, |
| 5001 | Structure = 1, | 5016 | Structure = 1, |
| 5002 | Union = 2, | 5017 | Union = 2, |
| 5003 | }; | 5018 | }; |
| 5004 | pub const @"opencl.debuginfo.100.DebugTypeQualifier" = enum(u32) { | 5019 | pub const @"OpenCL.DebugInfo.100.DebugTypeQualifier" = enum(u32) { |
| 5005 | ConstType = 0, | 5020 | ConstType = 0, |
| 5006 | VolatileType = 1, | 5021 | VolatileType = 1, |
| 5007 | RestrictType = 2, | 5022 | RestrictType = 2, |
| 5008 | AtomicType = 3, | 5023 | AtomicType = 3, |
| 5009 | }; | 5024 | }; |
| 5010 | pub const @"opencl.debuginfo.100.DebugOperation" = enum(u32) { | 5025 | pub const @"OpenCL.DebugInfo.100.DebugOperation" = enum(u32) { |
| 5011 | Deref = 0, | 5026 | Deref = 0, |
| 5012 | Plus = 1, | 5027 | Plus = 1, |
| 5013 | Minus = 2, | 5028 | Minus = 2, |
| ... | @@ -5019,7 +5034,7 @@ pub const @"opencl.debuginfo.100.DebugOperation" = enum(u32) { | ... | @@ -5019,7 +5034,7 @@ pub const @"opencl.debuginfo.100.DebugOperation" = enum(u32) { |
| 5019 | Constu = 8, | 5034 | Constu = 8, |
| 5020 | Fragment = 9, | 5035 | Fragment = 9, |
| 5021 | 5036 | ||
| 5022 | pub const Extended = union(@"opencl.debuginfo.100.DebugOperation") { | 5037 | pub const Extended = union(@"OpenCL.DebugInfo.100.DebugOperation") { |
| 5023 | Deref, | 5038 | Deref, |
| 5024 | Plus, | 5039 | Plus, |
| 5025 | Minus, | 5040 | Minus, |
| ... | @@ -5032,11 +5047,11 @@ pub const @"opencl.debuginfo.100.DebugOperation" = enum(u32) { | ... | @@ -5032,11 +5047,11 @@ pub const @"opencl.debuginfo.100.DebugOperation" = enum(u32) { |
| 5032 | Fragment: struct { literal_integer_0: LiteralInteger, literal_integer_1: LiteralInteger }, | 5047 | Fragment: struct { literal_integer_0: LiteralInteger, literal_integer_1: LiteralInteger }, |
| 5033 | }; | 5048 | }; |
| 5034 | }; | 5049 | }; |
| 5035 | pub const @"opencl.debuginfo.100.DebugImportedEntity" = enum(u32) { | 5050 | pub const @"OpenCL.DebugInfo.100.DebugImportedEntity" = enum(u32) { |
| 5036 | ImportedModule = 0, | 5051 | ImportedModule = 0, |
| 5037 | ImportedDeclaration = 1, | 5052 | ImportedDeclaration = 1, |
| 5038 | }; | 5053 | }; |
| 5039 | pub const @"nonsemantic.shader.debuginfo.100.DebugInfoFlags" = packed struct { | 5054 | pub const @"NonSemantic.Shader.DebugInfo.100.DebugInfoFlags" = packed struct { |
| 5040 | FlagIsProtected: bool = false, | 5055 | FlagIsProtected: bool = false, |
| 5041 | FlagIsPrivate: bool = false, | 5056 | FlagIsPrivate: bool = false, |
| 5042 | FlagIsLocal: bool = false, | 5057 | FlagIsLocal: bool = false, |
| ... | @@ -5070,7 +5085,7 @@ pub const @"nonsemantic.shader.debuginfo.100.DebugInfoFlags" = packed struct { | ... | @@ -5070,7 +5085,7 @@ pub const @"nonsemantic.shader.debuginfo.100.DebugInfoFlags" = packed struct { |
| 5070 | _reserved_bit_30: bool = false, | 5085 | _reserved_bit_30: bool = false, |
| 5071 | _reserved_bit_31: bool = false, | 5086 | _reserved_bit_31: bool = false, |
| 5072 | }; | 5087 | }; |
| 5073 | pub const @"nonsemantic.shader.debuginfo.100.BuildIdentifierFlags" = packed struct { | 5088 | pub const @"NonSemantic.Shader.DebugInfo.100.BuildIdentifierFlags" = packed struct { |
| 5074 | IdentifierPossibleDuplicates: bool = false, | 5089 | IdentifierPossibleDuplicates: bool = false, |
| 5075 | _reserved_bit_1: bool = false, | 5090 | _reserved_bit_1: bool = false, |
| 5076 | _reserved_bit_2: bool = false, | 5091 | _reserved_bit_2: bool = false, |
| ... | @@ -5104,7 +5119,7 @@ pub const @"nonsemantic.shader.debuginfo.100.BuildIdentifierFlags" = packed stru | ... | @@ -5104,7 +5119,7 @@ pub const @"nonsemantic.shader.debuginfo.100.BuildIdentifierFlags" = packed stru |
| 5104 | _reserved_bit_30: bool = false, | 5119 | _reserved_bit_30: bool = false, |
| 5105 | _reserved_bit_31: bool = false, | 5120 | _reserved_bit_31: bool = false, |
| 5106 | }; | 5121 | }; |
| 5107 | pub const @"nonsemantic.shader.debuginfo.100.DebugBaseTypeAttributeEncoding" = enum(u32) { | 5122 | pub const @"NonSemantic.Shader.DebugInfo.100.DebugBaseTypeAttributeEncoding" = enum(u32) { |
| 5108 | Unspecified = 0, | 5123 | Unspecified = 0, |
| 5109 | Address = 1, | 5124 | Address = 1, |
| 5110 | Boolean = 2, | 5125 | Boolean = 2, |
| ... | @@ -5114,18 +5129,18 @@ pub const @"nonsemantic.shader.debuginfo.100.DebugBaseTypeAttributeEncoding" = e | ... | @@ -5114,18 +5129,18 @@ pub const @"nonsemantic.shader.debuginfo.100.DebugBaseTypeAttributeEncoding" = e |
| 5114 | Unsigned = 6, | 5129 | Unsigned = 6, |
| 5115 | UnsignedChar = 7, | 5130 | UnsignedChar = 7, |
| 5116 | }; | 5131 | }; |
| 5117 | pub const @"nonsemantic.shader.debuginfo.100.DebugCompositeType" = enum(u32) { | 5132 | pub const @"NonSemantic.Shader.DebugInfo.100.DebugCompositeType" = enum(u32) { |
| 5118 | Class = 0, | 5133 | Class = 0, |
| 5119 | Structure = 1, | 5134 | Structure = 1, |
| 5120 | Union = 2, | 5135 | Union = 2, |
| 5121 | }; | 5136 | }; |
| 5122 | pub const @"nonsemantic.shader.debuginfo.100.DebugTypeQualifier" = enum(u32) { | 5137 | pub const @"NonSemantic.Shader.DebugInfo.100.DebugTypeQualifier" = enum(u32) { |
| 5123 | ConstType = 0, | 5138 | ConstType = 0, |
| 5124 | VolatileType = 1, | 5139 | VolatileType = 1, |
| 5125 | RestrictType = 2, | 5140 | RestrictType = 2, |
| 5126 | AtomicType = 3, | 5141 | AtomicType = 3, |
| 5127 | }; | 5142 | }; |
| 5128 | pub const @"nonsemantic.shader.debuginfo.100.DebugOperation" = enum(u32) { | 5143 | pub const @"NonSemantic.Shader.DebugInfo.100.DebugOperation" = enum(u32) { |
| 5129 | Deref = 0, | 5144 | Deref = 0, |
| 5130 | Plus = 1, | 5145 | Plus = 1, |
| 5131 | Minus = 2, | 5146 | Minus = 2, |
| ... | @@ -5137,7 +5152,7 @@ pub const @"nonsemantic.shader.debuginfo.100.DebugOperation" = enum(u32) { | ... | @@ -5137,7 +5152,7 @@ pub const @"nonsemantic.shader.debuginfo.100.DebugOperation" = enum(u32) { |
| 5137 | Constu = 8, | 5152 | Constu = 8, |
| 5138 | Fragment = 9, | 5153 | Fragment = 9, |
| 5139 | 5154 | ||
| 5140 | pub const Extended = union(@"nonsemantic.shader.debuginfo.100.DebugOperation") { | 5155 | pub const Extended = union(@"NonSemantic.Shader.DebugInfo.100.DebugOperation") { |
| 5141 | Deref, | 5156 | Deref, |
| 5142 | Plus, | 5157 | Plus, |
| 5143 | Minus, | 5158 | Minus, |
| ... | @@ -5150,11 +5165,11 @@ pub const @"nonsemantic.shader.debuginfo.100.DebugOperation" = enum(u32) { | ... | @@ -5150,11 +5165,11 @@ pub const @"nonsemantic.shader.debuginfo.100.DebugOperation" = enum(u32) { |
| 5150 | Fragment: struct { id_ref_0: IdRef, id_ref_1: IdRef }, | 5165 | Fragment: struct { id_ref_0: IdRef, id_ref_1: IdRef }, |
| 5151 | }; | 5166 | }; |
| 5152 | }; | 5167 | }; |
| 5153 | pub const @"nonsemantic.shader.debuginfo.100.DebugImportedEntity" = enum(u32) { | 5168 | pub const @"NonSemantic.Shader.DebugInfo.100.DebugImportedEntity" = enum(u32) { |
| 5154 | ImportedModule = 0, | 5169 | ImportedModule = 0, |
| 5155 | ImportedDeclaration = 1, | 5170 | ImportedDeclaration = 1, |
| 5156 | }; | 5171 | }; |
| 5157 | pub const @"nonsemantic.clspvreflection.KernelPropertyFlags" = packed struct { | 5172 | pub const @"NonSemantic.ClspvReflection.6.KernelPropertyFlags" = packed struct { |
| 5158 | MayUsePrintf: bool = false, | 5173 | MayUsePrintf: bool = false, |
| 5159 | _reserved_bit_1: bool = false, | 5174 | _reserved_bit_1: bool = false, |
| 5160 | _reserved_bit_2: bool = false, | 5175 | _reserved_bit_2: bool = false, |
| ... | @@ -5188,7 +5203,7 @@ pub const @"nonsemantic.clspvreflection.KernelPropertyFlags" = packed struct { | ... | @@ -5188,7 +5203,7 @@ pub const @"nonsemantic.clspvreflection.KernelPropertyFlags" = packed struct { |
| 5188 | _reserved_bit_30: bool = false, | 5203 | _reserved_bit_30: bool = false, |
| 5189 | _reserved_bit_31: bool = false, | 5204 | _reserved_bit_31: bool = false, |
| 5190 | }; | 5205 | }; |
| 5191 | pub const @"debuginfo.DebugInfoFlags" = packed struct { | 5206 | pub const @"DebugInfo.DebugInfoFlags" = packed struct { |
| 5192 | FlagIsProtected: bool = false, | 5207 | FlagIsProtected: bool = false, |
| 5193 | FlagIsPrivate: bool = false, | 5208 | FlagIsPrivate: bool = false, |
| 5194 | FlagIsLocal: bool = false, | 5209 | FlagIsLocal: bool = false, |
| ... | @@ -5222,7 +5237,7 @@ pub const @"debuginfo.DebugInfoFlags" = packed struct { | ... | @@ -5222,7 +5237,7 @@ pub const @"debuginfo.DebugInfoFlags" = packed struct { |
| 5222 | _reserved_bit_30: bool = false, | 5237 | _reserved_bit_30: bool = false, |
| 5223 | _reserved_bit_31: bool = false, | 5238 | _reserved_bit_31: bool = false, |
| 5224 | }; | 5239 | }; |
| 5225 | pub const @"debuginfo.DebugBaseTypeAttributeEncoding" = enum(u32) { | 5240 | pub const @"DebugInfo.DebugBaseTypeAttributeEncoding" = enum(u32) { |
| 5226 | Unspecified = 0, | 5241 | Unspecified = 0, |
| 5227 | Address = 1, | 5242 | Address = 1, |
| 5228 | Boolean = 2, | 5243 | Boolean = 2, |
| ... | @@ -5232,17 +5247,17 @@ pub const @"debuginfo.DebugBaseTypeAttributeEncoding" = enum(u32) { | ... | @@ -5232,17 +5247,17 @@ pub const @"debuginfo.DebugBaseTypeAttributeEncoding" = enum(u32) { |
| 5232 | Unsigned = 7, | 5247 | Unsigned = 7, |
| 5233 | UnsignedChar = 8, | 5248 | UnsignedChar = 8, |
| 5234 | }; | 5249 | }; |
| 5235 | pub const @"debuginfo.DebugCompositeType" = enum(u32) { | 5250 | pub const @"DebugInfo.DebugCompositeType" = enum(u32) { |
| 5236 | Class = 0, | 5251 | Class = 0, |
| 5237 | Structure = 1, | 5252 | Structure = 1, |
| 5238 | Union = 2, | 5253 | Union = 2, |
| 5239 | }; | 5254 | }; |
| 5240 | pub const @"debuginfo.DebugTypeQualifier" = enum(u32) { | 5255 | pub const @"DebugInfo.DebugTypeQualifier" = enum(u32) { |
| 5241 | ConstType = 0, | 5256 | ConstType = 0, |
| 5242 | VolatileType = 1, | 5257 | VolatileType = 1, |
| 5243 | RestrictType = 2, | 5258 | RestrictType = 2, |
| 5244 | }; | 5259 | }; |
| 5245 | pub const @"debuginfo.DebugOperation" = enum(u32) { | 5260 | pub const @"DebugInfo.DebugOperation" = enum(u32) { |
| 5246 | Deref = 0, | 5261 | Deref = 0, |
| 5247 | Plus = 1, | 5262 | Plus = 1, |
| 5248 | Minus = 2, | 5263 | Minus = 2, |
| ... | @@ -5253,7 +5268,7 @@ pub const @"debuginfo.DebugOperation" = enum(u32) { | ... | @@ -5253,7 +5268,7 @@ pub const @"debuginfo.DebugOperation" = enum(u32) { |
| 5253 | StackValue = 7, | 5268 | StackValue = 7, |
| 5254 | Constu = 8, | 5269 | Constu = 8, |
| 5255 | 5270 | ||
| 5256 | pub const Extended = union(@"debuginfo.DebugOperation") { | 5271 | pub const Extended = union(@"DebugInfo.DebugOperation") { |
| 5257 | Deref, | 5272 | Deref, |
| 5258 | Plus, | 5273 | Plus, |
| 5259 | Minus, | 5274 | Minus, |
| ... | @@ -5267,19 +5282,19 @@ pub const @"debuginfo.DebugOperation" = enum(u32) { | ... | @@ -5267,19 +5282,19 @@ pub const @"debuginfo.DebugOperation" = enum(u32) { |
| 5267 | }; | 5282 | }; |
| 5268 | pub const InstructionSet = enum { | 5283 | pub const InstructionSet = enum { |
| 5269 | core, | 5284 | core, |
| 5270 | @"opencl.std.100", | 5285 | @"OpenCL.std", |
| 5271 | @"glsl.std.450", | 5286 | @"GLSL.std.450", |
| 5272 | @"opencl.debuginfo.100", | 5287 | @"OpenCL.DebugInfo.100", |
| 5273 | @"spv-amd-shader-ballot", | 5288 | SPV_AMD_shader_ballot, |
| 5274 | @"nonsemantic.shader.debuginfo.100", | 5289 | @"NonSemantic.Shader.DebugInfo.100", |
| 5275 | @"nonsemantic.vkspreflection", | 5290 | @"NonSemantic.VkspReflection", |
| 5276 | @"nonsemantic.clspvreflection", | 5291 | @"NonSemantic.ClspvReflection.6", |
| 5277 | @"spv-amd-gcn-shader", | 5292 | SPV_AMD_gcn_shader, |
| 5278 | @"spv-amd-shader-trinary-minmax", | 5293 | SPV_AMD_shader_trinary_minmax, |
| 5279 | debuginfo, | 5294 | DebugInfo, |
| 5280 | @"nonsemantic.debugprintf", | 5295 | @"NonSemantic.DebugPrintf", |
| 5281 | @"spv-amd-shader-explicit-vertex-parameter", | 5296 | SPV_AMD_shader_explicit_vertex_parameter, |
| 5282 | @"nonsemantic.debugbreak", | 5297 | @"NonSemantic.DebugBreak", |
| 5283 | zig, | 5298 | zig, |
| 5284 | 5299 | ||
| 5285 | pub fn instructions(self: InstructionSet) []const Instruction { | 5300 | pub fn instructions(self: InstructionSet) []const Instruction { |
| ... | @@ -12775,7 +12790,7 @@ pub const InstructionSet = enum { | ... | @@ -12775,7 +12790,7 @@ pub const InstructionSet = enum { |
| 12775 | }, | 12790 | }, |
| 12776 | }, | 12791 | }, |
| 12777 | }, | 12792 | }, |
| 12778 | .@"opencl.std.100" => &[_]Instruction{ | 12793 | .@"OpenCL.std" => &[_]Instruction{ |
| 12779 | .{ | 12794 | .{ |
| 12780 | .name = "acos", | 12795 | .name = "acos", |
| 12781 | .opcode = 0, | 12796 | .opcode = 0, |
| ... | @@ -14025,7 +14040,7 @@ pub const InstructionSet = enum { | ... | @@ -14025,7 +14040,7 @@ pub const InstructionSet = enum { |
| 14025 | }, | 14040 | }, |
| 14026 | }, | 14041 | }, |
| 14027 | }, | 14042 | }, |
| 14028 | .@"glsl.std.450" => &[_]Instruction{ | 14043 | .@"GLSL.std.450" => &[_]Instruction{ |
| 14029 | .{ | 14044 | .{ |
| 14030 | .name = "Round", | 14045 | .name = "Round", |
| 14031 | .opcode = 1, | 14046 | .opcode = 1, |
| ... | @@ -14633,7 +14648,7 @@ pub const InstructionSet = enum { | ... | @@ -14633,7 +14648,7 @@ pub const InstructionSet = enum { |
| 14633 | }, | 14648 | }, |
| 14634 | }, | 14649 | }, |
| 14635 | }, | 14650 | }, |
| 14636 | .@"opencl.debuginfo.100" => &[_]Instruction{ | 14651 | .@"OpenCL.DebugInfo.100" => &[_]Instruction{ |
| 14637 | .{ | 14652 | .{ |
| 14638 | .name = "DebugInfoNone", | 14653 | .name = "DebugInfoNone", |
| 14639 | .opcode = 0, | 14654 | .opcode = 0, |
| ... | @@ -14655,7 +14670,7 @@ pub const InstructionSet = enum { | ... | @@ -14655,7 +14670,7 @@ pub const InstructionSet = enum { |
| 14655 | .operands = &[_]Operand{ | 14670 | .operands = &[_]Operand{ |
| 14656 | .{ .kind = .IdRef, .quantifier = .required }, | 14671 | .{ .kind = .IdRef, .quantifier = .required }, |
| 14657 | .{ .kind = .IdRef, .quantifier = .required }, | 14672 | .{ .kind = .IdRef, .quantifier = .required }, |
| 14658 | .{ .kind = .@"opencl.debuginfo.100.DebugBaseTypeAttributeEncoding", .quantifier = .required }, | 14673 | .{ .kind = .@"OpenCL.DebugInfo.100.DebugBaseTypeAttributeEncoding", .quantifier = .required }, |
| 14659 | }, | 14674 | }, |
| 14660 | }, | 14675 | }, |
| 14661 | .{ | 14676 | .{ |
| ... | @@ -14664,7 +14679,7 @@ pub const InstructionSet = enum { | ... | @@ -14664,7 +14679,7 @@ pub const InstructionSet = enum { |
| 14664 | .operands = &[_]Operand{ | 14679 | .operands = &[_]Operand{ |
| 14665 | .{ .kind = .IdRef, .quantifier = .required }, | 14680 | .{ .kind = .IdRef, .quantifier = .required }, |
| 14666 | .{ .kind = .StorageClass, .quantifier = .required }, | 14681 | .{ .kind = .StorageClass, .quantifier = .required }, |
| 14667 | .{ .kind = .@"opencl.debuginfo.100.DebugInfoFlags", .quantifier = .required }, | 14682 | .{ .kind = .@"OpenCL.DebugInfo.100.DebugInfoFlags", .quantifier = .required }, |
| 14668 | }, | 14683 | }, |
| 14669 | }, | 14684 | }, |
| 14670 | .{ | 14685 | .{ |
| ... | @@ -14672,7 +14687,7 @@ pub const InstructionSet = enum { | ... | @@ -14672,7 +14687,7 @@ pub const InstructionSet = enum { |
| 14672 | .opcode = 4, | 14687 | .opcode = 4, |
| 14673 | .operands = &[_]Operand{ | 14688 | .operands = &[_]Operand{ |
| 14674 | .{ .kind = .IdRef, .quantifier = .required }, | 14689 | .{ .kind = .IdRef, .quantifier = .required }, |
| 14675 | .{ .kind = .@"opencl.debuginfo.100.DebugTypeQualifier", .quantifier = .required }, | 14690 | .{ .kind = .@"OpenCL.DebugInfo.100.DebugTypeQualifier", .quantifier = .required }, |
| 14676 | }, | 14691 | }, |
| 14677 | }, | 14692 | }, |
| 14678 | .{ | 14693 | .{ |
| ... | @@ -14707,7 +14722,7 @@ pub const InstructionSet = enum { | ... | @@ -14707,7 +14722,7 @@ pub const InstructionSet = enum { |
| 14707 | .name = "DebugTypeFunction", | 14722 | .name = "DebugTypeFunction", |
| 14708 | .opcode = 8, | 14723 | .opcode = 8, |
| 14709 | .operands = &[_]Operand{ | 14724 | .operands = &[_]Operand{ |
| 14710 | .{ .kind = .@"opencl.debuginfo.100.DebugInfoFlags", .quantifier = .required }, | 14725 | .{ .kind = .@"OpenCL.DebugInfo.100.DebugInfoFlags", .quantifier = .required }, |
| 14711 | .{ .kind = .IdRef, .quantifier = .required }, | 14726 | .{ .kind = .IdRef, .quantifier = .required }, |
| 14712 | .{ .kind = .IdRef, .quantifier = .variadic }, | 14727 | .{ .kind = .IdRef, .quantifier = .variadic }, |
| 14713 | }, | 14728 | }, |
| ... | @@ -14723,7 +14738,7 @@ pub const InstructionSet = enum { | ... | @@ -14723,7 +14738,7 @@ pub const InstructionSet = enum { |
| 14723 | .{ .kind = .LiteralInteger, .quantifier = .required }, | 14738 | .{ .kind = .LiteralInteger, .quantifier = .required }, |
| 14724 | .{ .kind = .IdRef, .quantifier = .required }, | 14739 | .{ .kind = .IdRef, .quantifier = .required }, |
| 14725 | .{ .kind = .IdRef, .quantifier = .required }, | 14740 | .{ .kind = .IdRef, .quantifier = .required }, |
| 14726 | .{ .kind = .@"opencl.debuginfo.100.DebugInfoFlags", .quantifier = .required }, | 14741 | .{ .kind = .@"OpenCL.DebugInfo.100.DebugInfoFlags", .quantifier = .required }, |
| 14727 | .{ .kind = .PairIdRefIdRef, .quantifier = .variadic }, | 14742 | .{ .kind = .PairIdRefIdRef, .quantifier = .variadic }, |
| 14728 | }, | 14743 | }, |
| 14729 | }, | 14744 | }, |
| ... | @@ -14732,14 +14747,14 @@ pub const InstructionSet = enum { | ... | @@ -14732,14 +14747,14 @@ pub const InstructionSet = enum { |
| 14732 | .opcode = 10, | 14747 | .opcode = 10, |
| 14733 | .operands = &[_]Operand{ | 14748 | .operands = &[_]Operand{ |
| 14734 | .{ .kind = .IdRef, .quantifier = .required }, | 14749 | .{ .kind = .IdRef, .quantifier = .required }, |
| 14735 | .{ .kind = .@"opencl.debuginfo.100.DebugCompositeType", .quantifier = .required }, | 14750 | .{ .kind = .@"OpenCL.DebugInfo.100.DebugCompositeType", .quantifier = .required }, |
| 14736 | .{ .kind = .IdRef, .quantifier = .required }, | 14751 | .{ .kind = .IdRef, .quantifier = .required }, |
| 14737 | .{ .kind = .LiteralInteger, .quantifier = .required }, | 14752 | .{ .kind = .LiteralInteger, .quantifier = .required }, |
| 14738 | .{ .kind = .LiteralInteger, .quantifier = .required }, | 14753 | .{ .kind = .LiteralInteger, .quantifier = .required }, |
| 14739 | .{ .kind = .IdRef, .quantifier = .required }, | 14754 | .{ .kind = .IdRef, .quantifier = .required }, |
| 14740 | .{ .kind = .IdRef, .quantifier = .required }, | 14755 | .{ .kind = .IdRef, .quantifier = .required }, |
| 14741 | .{ .kind = .IdRef, .quantifier = .required }, | 14756 | .{ .kind = .IdRef, .quantifier = .required }, |
| 14742 | .{ .kind = .@"opencl.debuginfo.100.DebugInfoFlags", .quantifier = .required }, | 14757 | .{ .kind = .@"OpenCL.DebugInfo.100.DebugInfoFlags", .quantifier = .required }, |
| 14743 | .{ .kind = .IdRef, .quantifier = .variadic }, | 14758 | .{ .kind = .IdRef, .quantifier = .variadic }, |
| 14744 | }, | 14759 | }, |
| 14745 | }, | 14760 | }, |
| ... | @@ -14755,7 +14770,7 @@ pub const InstructionSet = enum { | ... | @@ -14755,7 +14770,7 @@ pub const InstructionSet = enum { |
| 14755 | .{ .kind = .IdRef, .quantifier = .required }, | 14770 | .{ .kind = .IdRef, .quantifier = .required }, |
| 14756 | .{ .kind = .IdRef, .quantifier = .required }, | 14771 | .{ .kind = .IdRef, .quantifier = .required }, |
| 14757 | .{ .kind = .IdRef, .quantifier = .required }, | 14772 | .{ .kind = .IdRef, .quantifier = .required }, |
| 14758 | .{ .kind = .@"opencl.debuginfo.100.DebugInfoFlags", .quantifier = .required }, | 14773 | .{ .kind = .@"OpenCL.DebugInfo.100.DebugInfoFlags", .quantifier = .required }, |
| 14759 | .{ .kind = .IdRef, .quantifier = .optional }, | 14774 | .{ .kind = .IdRef, .quantifier = .optional }, |
| 14760 | }, | 14775 | }, |
| 14761 | }, | 14776 | }, |
| ... | @@ -14767,7 +14782,7 @@ pub const InstructionSet = enum { | ... | @@ -14767,7 +14782,7 @@ pub const InstructionSet = enum { |
| 14767 | .{ .kind = .IdRef, .quantifier = .required }, | 14782 | .{ .kind = .IdRef, .quantifier = .required }, |
| 14768 | .{ .kind = .IdRef, .quantifier = .required }, | 14783 | .{ .kind = .IdRef, .quantifier = .required }, |
| 14769 | .{ .kind = .IdRef, .quantifier = .required }, | 14784 | .{ .kind = .IdRef, .quantifier = .required }, |
| 14770 | .{ .kind = .@"opencl.debuginfo.100.DebugInfoFlags", .quantifier = .required }, | 14785 | .{ .kind = .@"OpenCL.DebugInfo.100.DebugInfoFlags", .quantifier = .required }, |
| 14771 | }, | 14786 | }, |
| 14772 | }, | 14787 | }, |
| 14773 | .{ | 14788 | .{ |
| ... | @@ -14832,7 +14847,7 @@ pub const InstructionSet = enum { | ... | @@ -14832,7 +14847,7 @@ pub const InstructionSet = enum { |
| 14832 | .{ .kind = .IdRef, .quantifier = .required }, | 14847 | .{ .kind = .IdRef, .quantifier = .required }, |
| 14833 | .{ .kind = .IdRef, .quantifier = .required }, | 14848 | .{ .kind = .IdRef, .quantifier = .required }, |
| 14834 | .{ .kind = .IdRef, .quantifier = .required }, | 14849 | .{ .kind = .IdRef, .quantifier = .required }, |
| 14835 | .{ .kind = .@"opencl.debuginfo.100.DebugInfoFlags", .quantifier = .required }, | 14850 | .{ .kind = .@"OpenCL.DebugInfo.100.DebugInfoFlags", .quantifier = .required }, |
| 14836 | .{ .kind = .IdRef, .quantifier = .optional }, | 14851 | .{ .kind = .IdRef, .quantifier = .optional }, |
| 14837 | }, | 14852 | }, |
| 14838 | }, | 14853 | }, |
| ... | @@ -14847,7 +14862,7 @@ pub const InstructionSet = enum { | ... | @@ -14847,7 +14862,7 @@ pub const InstructionSet = enum { |
| 14847 | .{ .kind = .LiteralInteger, .quantifier = .required }, | 14862 | .{ .kind = .LiteralInteger, .quantifier = .required }, |
| 14848 | .{ .kind = .IdRef, .quantifier = .required }, | 14863 | .{ .kind = .IdRef, .quantifier = .required }, |
| 14849 | .{ .kind = .IdRef, .quantifier = .required }, | 14864 | .{ .kind = .IdRef, .quantifier = .required }, |
| 14850 | .{ .kind = .@"opencl.debuginfo.100.DebugInfoFlags", .quantifier = .required }, | 14865 | .{ .kind = .@"OpenCL.DebugInfo.100.DebugInfoFlags", .quantifier = .required }, |
| 14851 | }, | 14866 | }, |
| 14852 | }, | 14867 | }, |
| 14853 | .{ | 14868 | .{ |
| ... | @@ -14861,7 +14876,7 @@ pub const InstructionSet = enum { | ... | @@ -14861,7 +14876,7 @@ pub const InstructionSet = enum { |
| 14861 | .{ .kind = .LiteralInteger, .quantifier = .required }, | 14876 | .{ .kind = .LiteralInteger, .quantifier = .required }, |
| 14862 | .{ .kind = .IdRef, .quantifier = .required }, | 14877 | .{ .kind = .IdRef, .quantifier = .required }, |
| 14863 | .{ .kind = .IdRef, .quantifier = .required }, | 14878 | .{ .kind = .IdRef, .quantifier = .required }, |
| 14864 | .{ .kind = .@"opencl.debuginfo.100.DebugInfoFlags", .quantifier = .required }, | 14879 | .{ .kind = .@"OpenCL.DebugInfo.100.DebugInfoFlags", .quantifier = .required }, |
| 14865 | .{ .kind = .LiteralInteger, .quantifier = .required }, | 14880 | .{ .kind = .LiteralInteger, .quantifier = .required }, |
| 14866 | .{ .kind = .IdRef, .quantifier = .required }, | 14881 | .{ .kind = .IdRef, .quantifier = .required }, |
| 14867 | .{ .kind = .IdRef, .quantifier = .optional }, | 14882 | .{ .kind = .IdRef, .quantifier = .optional }, |
| ... | @@ -14919,7 +14934,7 @@ pub const InstructionSet = enum { | ... | @@ -14919,7 +14934,7 @@ pub const InstructionSet = enum { |
| 14919 | .{ .kind = .LiteralInteger, .quantifier = .required }, | 14934 | .{ .kind = .LiteralInteger, .quantifier = .required }, |
| 14920 | .{ .kind = .LiteralInteger, .quantifier = .required }, | 14935 | .{ .kind = .LiteralInteger, .quantifier = .required }, |
| 14921 | .{ .kind = .IdRef, .quantifier = .required }, | 14936 | .{ .kind = .IdRef, .quantifier = .required }, |
| 14922 | .{ .kind = .@"opencl.debuginfo.100.DebugInfoFlags", .quantifier = .required }, | 14937 | .{ .kind = .@"OpenCL.DebugInfo.100.DebugInfoFlags", .quantifier = .required }, |
| 14923 | .{ .kind = .LiteralInteger, .quantifier = .optional }, | 14938 | .{ .kind = .LiteralInteger, .quantifier = .optional }, |
| 14924 | }, | 14939 | }, |
| 14925 | }, | 14940 | }, |
| ... | @@ -14954,7 +14969,7 @@ pub const InstructionSet = enum { | ... | @@ -14954,7 +14969,7 @@ pub const InstructionSet = enum { |
| 14954 | .name = "DebugOperation", | 14969 | .name = "DebugOperation", |
| 14955 | .opcode = 30, | 14970 | .opcode = 30, |
| 14956 | .operands = &[_]Operand{ | 14971 | .operands = &[_]Operand{ |
| 14957 | .{ .kind = .@"opencl.debuginfo.100.DebugOperation", .quantifier = .required }, | 14972 | .{ .kind = .@"OpenCL.DebugInfo.100.DebugOperation", .quantifier = .required }, |
| 14958 | .{ .kind = .LiteralInteger, .quantifier = .variadic }, | 14973 | .{ .kind = .LiteralInteger, .quantifier = .variadic }, |
| 14959 | }, | 14974 | }, |
| 14960 | }, | 14975 | }, |
| ... | @@ -14989,7 +15004,7 @@ pub const InstructionSet = enum { | ... | @@ -14989,7 +15004,7 @@ pub const InstructionSet = enum { |
| 14989 | .opcode = 34, | 15004 | .opcode = 34, |
| 14990 | .operands = &[_]Operand{ | 15005 | .operands = &[_]Operand{ |
| 14991 | .{ .kind = .IdRef, .quantifier = .required }, | 15006 | .{ .kind = .IdRef, .quantifier = .required }, |
| 14992 | .{ .kind = .@"opencl.debuginfo.100.DebugImportedEntity", .quantifier = .required }, | 15007 | .{ .kind = .@"OpenCL.DebugInfo.100.DebugImportedEntity", .quantifier = .required }, |
| 14993 | .{ .kind = .IdRef, .quantifier = .required }, | 15008 | .{ .kind = .IdRef, .quantifier = .required }, |
| 14994 | .{ .kind = .IdRef, .quantifier = .required }, | 15009 | .{ .kind = .IdRef, .quantifier = .required }, |
| 14995 | .{ .kind = .LiteralInteger, .quantifier = .required }, | 15010 | .{ .kind = .LiteralInteger, .quantifier = .required }, |
| ... | @@ -15020,7 +15035,7 @@ pub const InstructionSet = enum { | ... | @@ -15020,7 +15035,7 @@ pub const InstructionSet = enum { |
| 15020 | }, | 15035 | }, |
| 15021 | }, | 15036 | }, |
| 15022 | }, | 15037 | }, |
| 15023 | .@"spv-amd-shader-ballot" => &[_]Instruction{ | 15038 | .SPV_AMD_shader_ballot => &[_]Instruction{ |
| 15024 | .{ | 15039 | .{ |
| 15025 | .name = "SwizzleInvocationsAMD", | 15040 | .name = "SwizzleInvocationsAMD", |
| 15026 | .opcode = 1, | 15041 | .opcode = 1, |
| ... | @@ -15054,7 +15069,7 @@ pub const InstructionSet = enum { | ... | @@ -15054,7 +15069,7 @@ pub const InstructionSet = enum { |
| 15054 | }, | 15069 | }, |
| 15055 | }, | 15070 | }, |
| 15056 | }, | 15071 | }, |
| 15057 | .@"nonsemantic.shader.debuginfo.100" => &[_]Instruction{ | 15072 | .@"NonSemantic.Shader.DebugInfo.100" => &[_]Instruction{ |
| 15058 | .{ | 15073 | .{ |
| 15059 | .name = "DebugInfoNone", | 15074 | .name = "DebugInfoNone", |
| 15060 | .opcode = 0, | 15075 | .opcode = 0, |
| ... | @@ -15491,7 +15506,7 @@ pub const InstructionSet = enum { | ... | @@ -15491,7 +15506,7 @@ pub const InstructionSet = enum { |
| 15491 | }, | 15506 | }, |
| 15492 | }, | 15507 | }, |
| 15493 | }, | 15508 | }, |
| 15494 | .@"nonsemantic.vkspreflection" => &[_]Instruction{ | 15509 | .@"NonSemantic.VkspReflection" => &[_]Instruction{ |
| 15495 | .{ | 15510 | .{ |
| 15496 | .name = "Configuration", | 15511 | .name = "Configuration", |
| 15497 | .opcode = 1, | 15512 | .opcode = 1, |
| ... | @@ -15623,7 +15638,7 @@ pub const InstructionSet = enum { | ... | @@ -15623,7 +15638,7 @@ pub const InstructionSet = enum { |
| 15623 | }, | 15638 | }, |
| 15624 | }, | 15639 | }, |
| 15625 | }, | 15640 | }, |
| 15626 | .@"nonsemantic.clspvreflection" => &[_]Instruction{ | 15641 | .@"NonSemantic.ClspvReflection.6" => &[_]Instruction{ |
| 15627 | .{ | 15642 | .{ |
| 15628 | .name = "Kernel", | 15643 | .name = "Kernel", |
| 15629 | .opcode = 1, | 15644 | .opcode = 1, |
| ... | @@ -16030,7 +16045,7 @@ pub const InstructionSet = enum { | ... | @@ -16030,7 +16045,7 @@ pub const InstructionSet = enum { |
| 16030 | }, | 16045 | }, |
| 16031 | }, | 16046 | }, |
| 16032 | }, | 16047 | }, |
| 16033 | .@"spv-amd-gcn-shader" => &[_]Instruction{ | 16048 | .SPV_AMD_gcn_shader => &[_]Instruction{ |
| 16034 | .{ | 16049 | .{ |
| 16035 | .name = "CubeFaceIndexAMD", | 16050 | .name = "CubeFaceIndexAMD", |
| 16036 | .opcode = 1, | 16051 | .opcode = 1, |
| ... | @@ -16051,7 +16066,7 @@ pub const InstructionSet = enum { | ... | @@ -16051,7 +16066,7 @@ pub const InstructionSet = enum { |
| 16051 | .operands = &[_]Operand{}, | 16066 | .operands = &[_]Operand{}, |
| 16052 | }, | 16067 | }, |
| 16053 | }, | 16068 | }, |
| 16054 | .@"spv-amd-shader-trinary-minmax" => &[_]Instruction{ | 16069 | .SPV_AMD_shader_trinary_minmax => &[_]Instruction{ |
| 16055 | .{ | 16070 | .{ |
| 16056 | .name = "FMin3AMD", | 16071 | .name = "FMin3AMD", |
| 16057 | .opcode = 1, | 16072 | .opcode = 1, |
| ... | @@ -16134,7 +16149,7 @@ pub const InstructionSet = enum { | ... | @@ -16134,7 +16149,7 @@ pub const InstructionSet = enum { |
| 16134 | }, | 16149 | }, |
| 16135 | }, | 16150 | }, |
| 16136 | }, | 16151 | }, |
| 16137 | .debuginfo => &[_]Instruction{ | 16152 | .DebugInfo => &[_]Instruction{ |
| 16138 | .{ | 16153 | .{ |
| 16139 | .name = "DebugInfoNone", | 16154 | .name = "DebugInfoNone", |
| 16140 | .opcode = 0, | 16155 | .opcode = 0, |
| ... | @@ -16155,7 +16170,7 @@ pub const InstructionSet = enum { | ... | @@ -16155,7 +16170,7 @@ pub const InstructionSet = enum { |
| 16155 | .operands = &[_]Operand{ | 16170 | .operands = &[_]Operand{ |
| 16156 | .{ .kind = .IdRef, .quantifier = .required }, | 16171 | .{ .kind = .IdRef, .quantifier = .required }, |
| 16157 | .{ .kind = .IdRef, .quantifier = .required }, | 16172 | .{ .kind = .IdRef, .quantifier = .required }, |
| 16158 | .{ .kind = .@"debuginfo.DebugBaseTypeAttributeEncoding", .quantifier = .required }, | 16173 | .{ .kind = .@"DebugInfo.DebugBaseTypeAttributeEncoding", .quantifier = .required }, |
| 16159 | }, | 16174 | }, |
| 16160 | }, | 16175 | }, |
| 16161 | .{ | 16176 | .{ |
| ... | @@ -16164,7 +16179,7 @@ pub const InstructionSet = enum { | ... | @@ -16164,7 +16179,7 @@ pub const InstructionSet = enum { |
| 16164 | .operands = &[_]Operand{ | 16179 | .operands = &[_]Operand{ |
| 16165 | .{ .kind = .IdRef, .quantifier = .required }, | 16180 | .{ .kind = .IdRef, .quantifier = .required }, |
| 16166 | .{ .kind = .StorageClass, .quantifier = .required }, | 16181 | .{ .kind = .StorageClass, .quantifier = .required }, |
| 16167 | .{ .kind = .@"debuginfo.DebugInfoFlags", .quantifier = .required }, | 16182 | .{ .kind = .@"DebugInfo.DebugInfoFlags", .quantifier = .required }, |
| 16168 | }, | 16183 | }, |
| 16169 | }, | 16184 | }, |
| 16170 | .{ | 16185 | .{ |
| ... | @@ -16172,7 +16187,7 @@ pub const InstructionSet = enum { | ... | @@ -16172,7 +16187,7 @@ pub const InstructionSet = enum { |
| 16172 | .opcode = 4, | 16187 | .opcode = 4, |
| 16173 | .operands = &[_]Operand{ | 16188 | .operands = &[_]Operand{ |
| 16174 | .{ .kind = .IdRef, .quantifier = .required }, | 16189 | .{ .kind = .IdRef, .quantifier = .required }, |
| 16175 | .{ .kind = .@"debuginfo.DebugTypeQualifier", .quantifier = .required }, | 16190 | .{ .kind = .@"DebugInfo.DebugTypeQualifier", .quantifier = .required }, |
| 16176 | }, | 16191 | }, |
| 16177 | }, | 16192 | }, |
| 16178 | .{ | 16193 | .{ |
| ... | @@ -16222,7 +16237,7 @@ pub const InstructionSet = enum { | ... | @@ -16222,7 +16237,7 @@ pub const InstructionSet = enum { |
| 16222 | .{ .kind = .LiteralInteger, .quantifier = .required }, | 16237 | .{ .kind = .LiteralInteger, .quantifier = .required }, |
| 16223 | .{ .kind = .IdRef, .quantifier = .required }, | 16238 | .{ .kind = .IdRef, .quantifier = .required }, |
| 16224 | .{ .kind = .IdRef, .quantifier = .required }, | 16239 | .{ .kind = .IdRef, .quantifier = .required }, |
| 16225 | .{ .kind = .@"debuginfo.DebugInfoFlags", .quantifier = .required }, | 16240 | .{ .kind = .@"DebugInfo.DebugInfoFlags", .quantifier = .required }, |
| 16226 | .{ .kind = .PairIdRefIdRef, .quantifier = .variadic }, | 16241 | .{ .kind = .PairIdRefIdRef, .quantifier = .variadic }, |
| 16227 | }, | 16242 | }, |
| 16228 | }, | 16243 | }, |
| ... | @@ -16231,13 +16246,13 @@ pub const InstructionSet = enum { | ... | @@ -16231,13 +16246,13 @@ pub const InstructionSet = enum { |
| 16231 | .opcode = 10, | 16246 | .opcode = 10, |
| 16232 | .operands = &[_]Operand{ | 16247 | .operands = &[_]Operand{ |
| 16233 | .{ .kind = .IdRef, .quantifier = .required }, | 16248 | .{ .kind = .IdRef, .quantifier = .required }, |
| 16234 | .{ .kind = .@"debuginfo.DebugCompositeType", .quantifier = .required }, | 16249 | .{ .kind = .@"DebugInfo.DebugCompositeType", .quantifier = .required }, |
| 16235 | .{ .kind = .IdRef, .quantifier = .required }, | 16250 | .{ .kind = .IdRef, .quantifier = .required }, |
| 16236 | .{ .kind = .LiteralInteger, .quantifier = .required }, | 16251 | .{ .kind = .LiteralInteger, .quantifier = .required }, |
| 16237 | .{ .kind = .LiteralInteger, .quantifier = .required }, | 16252 | .{ .kind = .LiteralInteger, .quantifier = .required }, |
| 16238 | .{ .kind = .IdRef, .quantifier = .required }, | 16253 | .{ .kind = .IdRef, .quantifier = .required }, |
| 16239 | .{ .kind = .IdRef, .quantifier = .required }, | 16254 | .{ .kind = .IdRef, .quantifier = .required }, |
| 16240 | .{ .kind = .@"debuginfo.DebugInfoFlags", .quantifier = .required }, | 16255 | .{ .kind = .@"DebugInfo.DebugInfoFlags", .quantifier = .required }, |
| 16241 | .{ .kind = .IdRef, .quantifier = .variadic }, | 16256 | .{ .kind = .IdRef, .quantifier = .variadic }, |
| 16242 | }, | 16257 | }, |
| 16243 | }, | 16258 | }, |
| ... | @@ -16253,7 +16268,7 @@ pub const InstructionSet = enum { | ... | @@ -16253,7 +16268,7 @@ pub const InstructionSet = enum { |
| 16253 | .{ .kind = .IdRef, .quantifier = .required }, | 16268 | .{ .kind = .IdRef, .quantifier = .required }, |
| 16254 | .{ .kind = .IdRef, .quantifier = .required }, | 16269 | .{ .kind = .IdRef, .quantifier = .required }, |
| 16255 | .{ .kind = .IdRef, .quantifier = .required }, | 16270 | .{ .kind = .IdRef, .quantifier = .required }, |
| 16256 | .{ .kind = .@"debuginfo.DebugInfoFlags", .quantifier = .required }, | 16271 | .{ .kind = .@"DebugInfo.DebugInfoFlags", .quantifier = .required }, |
| 16257 | .{ .kind = .IdRef, .quantifier = .optional }, | 16272 | .{ .kind = .IdRef, .quantifier = .optional }, |
| 16258 | }, | 16273 | }, |
| 16259 | }, | 16274 | }, |
| ... | @@ -16265,7 +16280,7 @@ pub const InstructionSet = enum { | ... | @@ -16265,7 +16280,7 @@ pub const InstructionSet = enum { |
| 16265 | .{ .kind = .IdRef, .quantifier = .required }, | 16280 | .{ .kind = .IdRef, .quantifier = .required }, |
| 16266 | .{ .kind = .IdRef, .quantifier = .required }, | 16281 | .{ .kind = .IdRef, .quantifier = .required }, |
| 16267 | .{ .kind = .IdRef, .quantifier = .required }, | 16282 | .{ .kind = .IdRef, .quantifier = .required }, |
| 16268 | .{ .kind = .@"debuginfo.DebugInfoFlags", .quantifier = .required }, | 16283 | .{ .kind = .@"DebugInfo.DebugInfoFlags", .quantifier = .required }, |
| 16269 | }, | 16284 | }, |
| 16270 | }, | 16285 | }, |
| 16271 | .{ | 16286 | .{ |
| ... | @@ -16330,7 +16345,7 @@ pub const InstructionSet = enum { | ... | @@ -16330,7 +16345,7 @@ pub const InstructionSet = enum { |
| 16330 | .{ .kind = .IdRef, .quantifier = .required }, | 16345 | .{ .kind = .IdRef, .quantifier = .required }, |
| 16331 | .{ .kind = .IdRef, .quantifier = .required }, | 16346 | .{ .kind = .IdRef, .quantifier = .required }, |
| 16332 | .{ .kind = .IdRef, .quantifier = .required }, | 16347 | .{ .kind = .IdRef, .quantifier = .required }, |
| 16333 | .{ .kind = .@"debuginfo.DebugInfoFlags", .quantifier = .required }, | 16348 | .{ .kind = .@"DebugInfo.DebugInfoFlags", .quantifier = .required }, |
| 16334 | .{ .kind = .IdRef, .quantifier = .optional }, | 16349 | .{ .kind = .IdRef, .quantifier = .optional }, |
| 16335 | }, | 16350 | }, |
| 16336 | }, | 16351 | }, |
| ... | @@ -16345,7 +16360,7 @@ pub const InstructionSet = enum { | ... | @@ -16345,7 +16360,7 @@ pub const InstructionSet = enum { |
| 16345 | .{ .kind = .LiteralInteger, .quantifier = .required }, | 16360 | .{ .kind = .LiteralInteger, .quantifier = .required }, |
| 16346 | .{ .kind = .IdRef, .quantifier = .required }, | 16361 | .{ .kind = .IdRef, .quantifier = .required }, |
| 16347 | .{ .kind = .IdRef, .quantifier = .required }, | 16362 | .{ .kind = .IdRef, .quantifier = .required }, |
| 16348 | .{ .kind = .@"debuginfo.DebugInfoFlags", .quantifier = .required }, | 16363 | .{ .kind = .@"DebugInfo.DebugInfoFlags", .quantifier = .required }, |
| 16349 | }, | 16364 | }, |
| 16350 | }, | 16365 | }, |
| 16351 | .{ | 16366 | .{ |
| ... | @@ -16359,7 +16374,7 @@ pub const InstructionSet = enum { | ... | @@ -16359,7 +16374,7 @@ pub const InstructionSet = enum { |
| 16359 | .{ .kind = .LiteralInteger, .quantifier = .required }, | 16374 | .{ .kind = .LiteralInteger, .quantifier = .required }, |
| 16360 | .{ .kind = .IdRef, .quantifier = .required }, | 16375 | .{ .kind = .IdRef, .quantifier = .required }, |
| 16361 | .{ .kind = .IdRef, .quantifier = .required }, | 16376 | .{ .kind = .IdRef, .quantifier = .required }, |
| 16362 | .{ .kind = .@"debuginfo.DebugInfoFlags", .quantifier = .required }, | 16377 | .{ .kind = .@"DebugInfo.DebugInfoFlags", .quantifier = .required }, |
| 16363 | .{ .kind = .LiteralInteger, .quantifier = .required }, | 16378 | .{ .kind = .LiteralInteger, .quantifier = .required }, |
| 16364 | .{ .kind = .IdRef, .quantifier = .required }, | 16379 | .{ .kind = .IdRef, .quantifier = .required }, |
| 16365 | .{ .kind = .IdRef, .quantifier = .optional }, | 16380 | .{ .kind = .IdRef, .quantifier = .optional }, |
| ... | @@ -16450,7 +16465,7 @@ pub const InstructionSet = enum { | ... | @@ -16450,7 +16465,7 @@ pub const InstructionSet = enum { |
| 16450 | .name = "DebugOperation", | 16465 | .name = "DebugOperation", |
| 16451 | .opcode = 30, | 16466 | .opcode = 30, |
| 16452 | .operands = &[_]Operand{ | 16467 | .operands = &[_]Operand{ |
| 16453 | .{ .kind = .@"debuginfo.DebugOperation", .quantifier = .required }, | 16468 | .{ .kind = .@"DebugInfo.DebugOperation", .quantifier = .required }, |
| 16454 | .{ .kind = .LiteralInteger, .quantifier = .variadic }, | 16469 | .{ .kind = .LiteralInteger, .quantifier = .variadic }, |
| 16455 | }, | 16470 | }, |
| 16456 | }, | 16471 | }, |
| ... | @@ -16481,7 +16496,7 @@ pub const InstructionSet = enum { | ... | @@ -16481,7 +16496,7 @@ pub const InstructionSet = enum { |
| 16481 | }, | 16496 | }, |
| 16482 | }, | 16497 | }, |
| 16483 | }, | 16498 | }, |
| 16484 | .@"nonsemantic.debugprintf" => &[_]Instruction{ | 16499 | .@"NonSemantic.DebugPrintf" => &[_]Instruction{ |
| 16485 | .{ | 16500 | .{ |
| 16486 | .name = "DebugPrintf", | 16501 | .name = "DebugPrintf", |
| 16487 | .opcode = 1, | 16502 | .opcode = 1, |
| ... | @@ -16491,7 +16506,7 @@ pub const InstructionSet = enum { | ... | @@ -16491,7 +16506,7 @@ pub const InstructionSet = enum { |
| 16491 | }, | 16506 | }, |
| 16492 | }, | 16507 | }, |
| 16493 | }, | 16508 | }, |
| 16494 | .@"spv-amd-shader-explicit-vertex-parameter" => &[_]Instruction{ | 16509 | .SPV_AMD_shader_explicit_vertex_parameter => &[_]Instruction{ |
| 16495 | .{ | 16510 | .{ |
| 16496 | .name = "InterpolateAtVertexAMD", | 16511 | .name = "InterpolateAtVertexAMD", |
| 16497 | .opcode = 1, | 16512 | .opcode = 1, |
| ... | @@ -16501,7 +16516,7 @@ pub const InstructionSet = enum { | ... | @@ -16501,7 +16516,7 @@ pub const InstructionSet = enum { |
| 16501 | }, | 16516 | }, |
| 16502 | }, | 16517 | }, |
| 16503 | }, | 16518 | }, |
| 16504 | .@"nonsemantic.debugbreak" => &[_]Instruction{ | 16519 | .@"NonSemantic.DebugBreak" => &[_]Instruction{ |
| 16505 | .{ | 16520 | .{ |
| 16506 | .name = "DebugBreak", | 16521 | .name = "DebugBreak", |
| 16507 | .opcode = 1, | 16522 | .opcode = 1, |
src/link/SpirV.zig+31-6| ... | @@ -39,8 +39,12 @@ const Liveness = @import("../Liveness.zig"); | ... | @@ -39,8 +39,12 @@ const Liveness = @import("../Liveness.zig"); |
| 39 | const Value = @import("../Value.zig"); | 39 | const Value = @import("../Value.zig"); |
| 40 | 40 | ||
| 41 | const SpvModule = @import("../codegen/spirv/Module.zig"); | 41 | const SpvModule = @import("../codegen/spirv/Module.zig"); |
| 42 | const Section = @import("../codegen/spirv/Section.zig"); | ||
| 42 | const spec = @import("../codegen/spirv/spec.zig"); | 43 | const spec = @import("../codegen/spirv/spec.zig"); |
| 43 | const IdResult = spec.IdResult; | 44 | const IdResult = spec.IdResult; |
| 45 | const Word = spec.Word; | ||
| 46 | |||
| 47 | const BinaryModule = @import("SpirV/BinaryModule.zig"); | ||
| 44 | 48 | ||
| 45 | base: link.File, | 49 | base: link.File, |
| 46 | 50 | ||
| ... | @@ -163,6 +167,7 @@ pub fn updateExports( | ... | @@ -163,6 +167,7 @@ pub fn updateExports( |
| 163 | .Vertex => spec.ExecutionModel.Vertex, | 167 | .Vertex => spec.ExecutionModel.Vertex, |
| 164 | .Fragment => spec.ExecutionModel.Fragment, | 168 | .Fragment => spec.ExecutionModel.Fragment, |
| 165 | .Kernel => spec.ExecutionModel.Kernel, | 169 | .Kernel => spec.ExecutionModel.Kernel, |
| 170 | .C => return, // TODO: What to do here? | ||
| 166 | else => unreachable, | 171 | else => unreachable, |
| 167 | }; | 172 | }; |
| 168 | const is_vulkan = target.os.tag == .vulkan; | 173 | const is_vulkan = target.os.tag == .vulkan; |
| ... | @@ -197,8 +202,6 @@ pub fn flushModule(self: *SpirV, arena: Allocator, prog_node: *std.Progress.Node | ... | @@ -197,8 +202,6 @@ pub fn flushModule(self: *SpirV, arena: Allocator, prog_node: *std.Progress.Node |
| 197 | @panic("Attempted to compile for architecture that was disabled by build configuration"); | 202 | @panic("Attempted to compile for architecture that was disabled by build configuration"); |
| 198 | } | 203 | } |
| 199 | 204 | ||
| 200 | _ = arena; // Has the same lifetime as the call to Compilation.update. | ||
| 201 | |||
| 202 | const tracy = trace(@src()); | 205 | const tracy = trace(@src()); |
| 203 | defer tracy.end(); | 206 | defer tracy.end(); |
| 204 | 207 | ||
| ... | @@ -223,9 +226,9 @@ pub fn flushModule(self: *SpirV, arena: Allocator, prog_node: *std.Progress.Node | ... | @@ -223,9 +226,9 @@ pub fn flushModule(self: *SpirV, arena: Allocator, prog_node: *std.Progress.Node |
| 223 | defer error_info.deinit(); | 226 | defer error_info.deinit(); |
| 224 | 227 | ||
| 225 | try error_info.appendSlice("zig_errors"); | 228 | try error_info.appendSlice("zig_errors"); |
| 226 | const module = self.base.comp.module.?; | 229 | const mod = self.base.comp.module.?; |
| 227 | for (module.global_error_set.keys()) |name_nts| { | 230 | for (mod.global_error_set.keys()) |name_nts| { |
| 228 | const name = module.intern_pool.stringToSlice(name_nts); | 231 | const name = mod.intern_pool.stringToSlice(name_nts); |
| 229 | // Errors can contain pretty much any character - to encode them in a string we must escape | 232 | // Errors can contain pretty much any character - to encode them in a string we must escape |
| 230 | // them somehow. Easiest here is to use some established scheme, one which also preseves the | 233 | // them somehow. Easiest here is to use some established scheme, one which also preseves the |
| 231 | // name if it contains no strange characters is nice for debugging. URI encoding fits the bill. | 234 | // name if it contains no strange characters is nice for debugging. URI encoding fits the bill. |
| ... | @@ -239,7 +242,29 @@ pub fn flushModule(self: *SpirV, arena: Allocator, prog_node: *std.Progress.Node | ... | @@ -239,7 +242,29 @@ pub fn flushModule(self: *SpirV, arena: Allocator, prog_node: *std.Progress.Node |
| 239 | .extension = error_info.items, | 242 | .extension = error_info.items, |
| 240 | }); | 243 | }); |
| 241 | 244 | ||
| 242 | try spv.flush(self.base.file.?, target); | 245 | const module = try spv.finalize(arena, target); |
| 246 | errdefer arena.free(module); | ||
| 247 | |||
| 248 | const new_module = self.lowerInstanceGlobals(arena, module) catch |err| switch (err) { | ||
| 249 | error.OutOfMemory => return error.OutOfMemory, | ||
| 250 | else => |other| { | ||
| 251 | std.debug.print("error while lowering instance globals: {s}\n", .{@errorName(other)}); | ||
| 252 | return error.FlushFailure; | ||
| 253 | }, | ||
| 254 | }; | ||
| 255 | defer arena.free(new_module); | ||
| 256 | |||
| 257 | try self.base.file.?.writeAll(std.mem.sliceAsBytes(new_module)); | ||
| 258 | } | ||
| 259 | |||
| 260 | fn lowerInstanceGlobals(self: *SpirV, a: Allocator, module: []Word) ![]Word { | ||
| 261 | _ = self; | ||
| 262 | |||
| 263 | var parser = try BinaryModule.Parser.init(a); | ||
| 264 | defer parser.deinit(); | ||
| 265 | const binary = try parser.parse(module); | ||
| 266 | const lower_invocation_globals = @import("SpirV/lower_invocation_globals.zig"); | ||
| 267 | return try lower_invocation_globals.run(&parser, binary); | ||
| 243 | } | 268 | } |
| 244 | 269 | ||
| 245 | fn writeCapabilities(spv: *SpvModule, target: std.Target) !void { | 270 | fn writeCapabilities(spv: *SpvModule, target: std.Target) !void { |
src/link/SpirV/BinaryModule.zig+20-174| ... | @@ -33,6 +33,11 @@ ext_inst_map: std.AutoHashMapUnmanaged(ResultId, InstructionSet), | ... | @@ -33,6 +33,11 @@ ext_inst_map: std.AutoHashMapUnmanaged(ResultId, InstructionSet), |
| 33 | /// of Op(Spec)Constant and OpSwitch. | 33 | /// of Op(Spec)Constant and OpSwitch. |
| 34 | arith_type_width: std.AutoHashMapUnmanaged(ResultId, u16), | 34 | arith_type_width: std.AutoHashMapUnmanaged(ResultId, u16), |
| 35 | 35 | ||
| 36 | /// The starting offsets of some sections | ||
| 37 | sections: struct { | ||
| 38 | functions: usize, | ||
| 39 | }, | ||
| 40 | |||
| 36 | pub fn deinit(self: *BinaryModule, a: Allocator) void { | 41 | pub fn deinit(self: *BinaryModule, a: Allocator) void { |
| 37 | self.ext_inst_map.deinit(a); | 42 | self.ext_inst_map.deinit(a); |
| 38 | self.arith_type_width.deinit(a); | 43 | self.arith_type_width.deinit(a); |
| ... | @@ -43,6 +48,10 @@ pub fn iterateInstructions(self: BinaryModule) Instruction.Iterator { | ... | @@ -43,6 +48,10 @@ pub fn iterateInstructions(self: BinaryModule) Instruction.Iterator { |
| 43 | return Instruction.Iterator.init(self.instructions); | 48 | return Instruction.Iterator.init(self.instructions); |
| 44 | } | 49 | } |
| 45 | 50 | ||
| 51 | pub fn iterateInstructionsFrom(self: BinaryModule, offset: usize) Instruction.Iterator { | ||
| 52 | return Instruction.Iterator.init(self.instructions[offset..]); | ||
| 53 | } | ||
| 54 | |||
| 46 | /// Errors that can be raised when the module is not correct. | 55 | /// Errors that can be raised when the module is not correct. |
| 47 | /// Note that the parser doesn't validate SPIR-V modules by a | 56 | /// Note that the parser doesn't validate SPIR-V modules by a |
| 48 | /// long shot. It only yields errors that critically prevent | 57 | /// long shot. It only yields errors that critically prevent |
| ... | @@ -107,97 +116,6 @@ pub const Instruction = struct { | ... | @@ -107,97 +116,6 @@ pub const Instruction = struct { |
| 107 | operands: []const Word, | 116 | operands: []const Word, |
| 108 | }; | 117 | }; |
| 109 | 118 | ||
| 110 | /// This struct is used to return information about | ||
| 111 | /// a module's functions - entry points, functions, | ||
| 112 | /// list of callees. | ||
| 113 | pub const FunctionInfo = struct { | ||
| 114 | /// Information that is gathered about a particular function. | ||
| 115 | pub const Fn = struct { | ||
| 116 | /// The word-offset of the first word (of the OpFunction instruction) | ||
| 117 | /// of this instruction. | ||
| 118 | begin_offset: usize, | ||
| 119 | /// The past-end offset of the end (including operands) of the last | ||
| 120 | /// instruction of the function. | ||
| 121 | end_offset: usize, | ||
| 122 | /// The index of the first callee in `callee_store`. | ||
| 123 | first_callee: usize, | ||
| 124 | /// The module offset of the OpTypeFunction instruction corresponding | ||
| 125 | /// to this function. | ||
| 126 | /// We use an offset so that we don't need to keep a separate map. | ||
| 127 | type_offset: usize, | ||
| 128 | }; | ||
| 129 | |||
| 130 | /// Maps function result-id -> Function information structure. | ||
| 131 | functions: std.AutoArrayHashMapUnmanaged(ResultId, Fn), | ||
| 132 | /// List of entry points in this module. Contains OpFunction result-ids. | ||
| 133 | entry_points: []const ResultId, | ||
| 134 | /// For each function, a list of function result-ids that it calls. | ||
| 135 | callee_store: []const ResultId, | ||
| 136 | |||
| 137 | pub fn deinit(self: *FunctionInfo, a: Allocator) void { | ||
| 138 | self.functions.deinit(a); | ||
| 139 | a.free(self.entry_points); | ||
| 140 | a.free(self.callee_store); | ||
| 141 | self.* = undefined; | ||
| 142 | } | ||
| 143 | |||
| 144 | /// Fetch the list of callees per function. Guaranteed to contain only unique IDs. | ||
| 145 | pub fn callees(self: FunctionInfo, fn_id: ResultId) []const ResultId { | ||
| 146 | const fn_index = self.functions.getIndex(fn_id).?; | ||
| 147 | const values = self.functions.values(); | ||
| 148 | const first_callee = values[fn_index].first_callee; | ||
| 149 | if (fn_index == values.len - 1) { | ||
| 150 | return self.callee_store[first_callee..]; | ||
| 151 | } else { | ||
| 152 | const next_first_callee = values[fn_index + 1].first_callee; | ||
| 153 | return self.callee_store[first_callee..next_first_callee]; | ||
| 154 | } | ||
| 155 | } | ||
| 156 | |||
| 157 | /// Returns a topological ordering of the functions: For each item | ||
| 158 | /// in the returned list of OpFunction result-ids, it is guaranteed that | ||
| 159 | /// the callees have a lower index. Note that SPIR-V does not support | ||
| 160 | /// any recursion, so this always works. | ||
| 161 | pub fn topologicalSort(self: FunctionInfo, a: Allocator) ![]const ResultId { | ||
| 162 | var sort = std.ArrayList(ResultId).init(a); | ||
| 163 | defer sort.deinit(); | ||
| 164 | |||
| 165 | var seen = try std.DynamicBitSetUnmanaged.initEmpty(a, self.functions.count()); | ||
| 166 | defer seen.deinit(a); | ||
| 167 | |||
| 168 | var stack = std.ArrayList(ResultId).init(a); | ||
| 169 | defer stack.deinit(); | ||
| 170 | |||
| 171 | for (self.functions.keys()) |id| { | ||
| 172 | try self.topologicalSortStep(id, &sort, &seen); | ||
| 173 | } | ||
| 174 | |||
| 175 | return try sort.toOwnedSlice(); | ||
| 176 | } | ||
| 177 | |||
| 178 | fn topologicalSortStep( | ||
| 179 | self: FunctionInfo, | ||
| 180 | id: ResultId, | ||
| 181 | sort: *std.ArrayList(ResultId), | ||
| 182 | seen: *std.DynamicBitSetUnmanaged, | ||
| 183 | ) !void { | ||
| 184 | const fn_index = self.functions.getIndex(id) orelse { | ||
| 185 | log.err("function calls invalid callee-id {}", .{@intFromEnum(id)}); | ||
| 186 | return error.InvalidId; | ||
| 187 | }; | ||
| 188 | if (seen.isSet(fn_index)) { | ||
| 189 | return; | ||
| 190 | } | ||
| 191 | |||
| 192 | seen.set(fn_index); | ||
| 193 | for (self.callees(id)) |callee| { | ||
| 194 | try self.topologicalSortStep(callee, sort, seen); | ||
| 195 | } | ||
| 196 | |||
| 197 | try sort.append(id); | ||
| 198 | } | ||
| 199 | }; | ||
| 200 | |||
| 201 | /// This parser contains information (acceleration tables) | 119 | /// This parser contains information (acceleration tables) |
| 202 | /// that can be persisted across different modules. This is | 120 | /// that can be persisted across different modules. This is |
| 203 | /// used to initialize the module, and is also used when | 121 | /// used to initialize the module, and is also used when |
| ... | @@ -256,8 +174,11 @@ pub const Parser = struct { | ... | @@ -256,8 +174,11 @@ pub const Parser = struct { |
| 256 | .instructions = module[header_words..], | 174 | .instructions = module[header_words..], |
| 257 | .ext_inst_map = .{}, | 175 | .ext_inst_map = .{}, |
| 258 | .arith_type_width = .{}, | 176 | .arith_type_width = .{}, |
| 177 | .sections = undefined, | ||
| 259 | }; | 178 | }; |
| 260 | 179 | ||
| 180 | var maybe_function_section: ?usize = null; | ||
| 181 | |||
| 261 | // First pass through the module to verify basic structure and | 182 | // First pass through the module to verify basic structure and |
| 262 | // to gather some initial stuff for more detailed analysis. | 183 | // to gather some initial stuff for more detailed analysis. |
| 263 | // We want to check some stuff that Instruction.Iterator is no good for, | 184 | // We want to check some stuff that Instruction.Iterator is no good for, |
| ... | @@ -297,6 +218,9 @@ pub const Parser = struct { | ... | @@ -297,6 +218,9 @@ pub const Parser = struct { |
| 297 | if (entry.found_existing) return error.DuplicateId; | 218 | if (entry.found_existing) return error.DuplicateId; |
| 298 | entry.value_ptr.* = std.math.cast(u16, operands[1]) orelse return error.InvalidOperands; | 219 | entry.value_ptr.* = std.math.cast(u16, operands[1]) orelse return error.InvalidOperands; |
| 299 | }, | 220 | }, |
| 221 | .OpFunction => if (maybe_function_section == null) { | ||
| 222 | maybe_function_section = offset; | ||
| 223 | }, | ||
| 300 | else => {}, | 224 | else => {}, |
| 301 | } | 225 | } |
| 302 | 226 | ||
| ... | @@ -317,89 +241,11 @@ pub const Parser = struct { | ... | @@ -317,89 +241,11 @@ pub const Parser = struct { |
| 317 | } | 241 | } |
| 318 | } | 242 | } |
| 319 | 243 | ||
| 320 | return binary; | 244 | binary.sections = .{ |
| 321 | } | 245 | .functions = maybe_function_section orelse binary.instructions.len, |
| 322 | |||
| 323 | pub fn parseFunctionInfo(self: *Parser, binary: BinaryModule) ParseError!FunctionInfo { | ||
| 324 | var entry_points = std.AutoArrayHashMap(ResultId, void).init(self.a); | ||
| 325 | defer entry_points.deinit(); | ||
| 326 | |||
| 327 | var functions = std.AutoArrayHashMap(ResultId, FunctionInfo.Fn).init(self.a); | ||
| 328 | errdefer functions.deinit(); | ||
| 329 | |||
| 330 | var fn_ty_decls = std.AutoHashMap(ResultId, usize).init(self.a); | ||
| 331 | defer fn_ty_decls.deinit(); | ||
| 332 | |||
| 333 | var calls = std.AutoArrayHashMap(ResultId, void).init(self.a); | ||
| 334 | defer calls.deinit(); | ||
| 335 | |||
| 336 | var callee_store = std.ArrayList(ResultId).init(self.a); | ||
| 337 | defer callee_store.deinit(); | ||
| 338 | |||
| 339 | var maybe_current_function: ?ResultId = null; | ||
| 340 | var begin: usize = undefined; | ||
| 341 | var fn_ty_id: ResultId = undefined; | ||
| 342 | |||
| 343 | var it = binary.iterateInstructions(); | ||
| 344 | while (it.next()) |inst| { | ||
| 345 | switch (inst.opcode) { | ||
| 346 | .OpEntryPoint => { | ||
| 347 | const entry = try entry_points.getOrPut(@enumFromInt(inst.operands[1])); | ||
| 348 | if (entry.found_existing) return error.DuplicateId; | ||
| 349 | }, | ||
| 350 | .OpTypeFunction => { | ||
| 351 | const entry = try fn_ty_decls.getOrPut(@enumFromInt(inst.operands[0])); | ||
| 352 | if (entry.found_existing) return error.DuplicateId; | ||
| 353 | entry.value_ptr.* = inst.offset; | ||
| 354 | }, | ||
| 355 | .OpFunction => { | ||
| 356 | maybe_current_function = @enumFromInt(inst.operands[1]); | ||
| 357 | begin = inst.offset; | ||
| 358 | fn_ty_id = @enumFromInt(inst.operands[3]); | ||
| 359 | }, | ||
| 360 | .OpFunctionCall => { | ||
| 361 | const callee: ResultId = @enumFromInt(inst.operands[2]); | ||
| 362 | try calls.put(callee, {}); | ||
| 363 | }, | ||
| 364 | .OpFunctionEnd => { | ||
| 365 | const current_function = maybe_current_function orelse { | ||
| 366 | log.err("encountered OpFunctionEnd without corresponding OpFunction", .{}); | ||
| 367 | return error.InvalidPhysicalFormat; | ||
| 368 | }; | ||
| 369 | const entry = try functions.getOrPut(current_function); | ||
| 370 | if (entry.found_existing) return error.DuplicateId; | ||
| 371 | |||
| 372 | const first_callee = callee_store.items.len; | ||
| 373 | try callee_store.appendSlice(calls.keys()); | ||
| 374 | |||
| 375 | const type_offset = fn_ty_decls.get(fn_ty_id) orelse { | ||
| 376 | log.err("Invalid OpFunction type", .{}); | ||
| 377 | return error.InvalidId; | ||
| 378 | }; | ||
| 379 | |||
| 380 | entry.value_ptr.* = .{ | ||
| 381 | .begin_offset = begin, | ||
| 382 | .end_offset = it.offset, // Use past-end offset | ||
| 383 | .first_callee = first_callee, | ||
| 384 | .type_offset = type_offset, | ||
| 385 | }; | ||
| 386 | maybe_current_function = null; | ||
| 387 | calls.clearRetainingCapacity(); | ||
| 388 | }, | ||
| 389 | else => {}, | ||
| 390 | } | ||
| 391 | } | ||
| 392 | |||
| 393 | if (maybe_current_function != null) { | ||
| 394 | log.err("final OpFunction does not have an OpFunctionEnd", .{}); | ||
| 395 | return error.InvalidPhysicalFormat; | ||
| 396 | } | ||
| 397 | |||
| 398 | return FunctionInfo{ | ||
| 399 | .functions = functions.unmanaged, | ||
| 400 | .entry_points = try self.a.dupe(ResultId, entry_points.keys()), | ||
| 401 | .callee_store = try callee_store.toOwnedSlice(), | ||
| 402 | }; | 246 | }; |
| 247 | |||
| 248 | return binary; | ||
| 403 | } | 249 | } |
| 404 | 250 | ||
| 405 | /// Parse offsets in the instruction that contain result-ids. | 251 | /// Parse offsets in the instruction that contain result-ids. |
| ... | @@ -438,7 +284,7 @@ pub const Parser = struct { | ... | @@ -438,7 +284,7 @@ pub const Parser = struct { |
| 438 | if (offset + 1 >= inst.operands.len) return error.InvalidPhysicalFormat; | 284 | if (offset + 1 >= inst.operands.len) return error.InvalidPhysicalFormat; |
| 439 | const set_id: ResultId = @enumFromInt(inst.operands[offset]); | 285 | const set_id: ResultId = @enumFromInt(inst.operands[offset]); |
| 440 | const set = binary.ext_inst_map.get(set_id) orelse { | 286 | const set = binary.ext_inst_map.get(set_id) orelse { |
| 441 | log.err("Invalid instruction set {}", .{@intFromEnum(set_id)}); | 287 | log.err("invalid instruction set {}", .{@intFromEnum(set_id)}); |
| 442 | return error.InvalidId; | 288 | return error.InvalidId; |
| 443 | }; | 289 | }; |
| 444 | const ext_opcode = std.math.cast(u16, inst.operands[offset + 1]) orelse return error.InvalidPhysicalFormat; | 290 | const ext_opcode = std.math.cast(u16, inst.operands[offset + 1]) orelse return error.InvalidPhysicalFormat; |
src/link/SpirV/lower_invocation_globals.zig created+714| ... | @@ -0,0 +1,714 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const Allocator = std.mem.Allocator; | ||
| 3 | const assert = std.debug.assert; | ||
| 4 | const log = std.log.scoped(.spirv_link); | ||
| 5 | |||
| 6 | const BinaryModule = @import("BinaryModule.zig"); | ||
| 7 | const Section = @import("../../codegen/spirv/Section.zig"); | ||
| 8 | const spec = @import("../../codegen/spirv/spec.zig"); | ||
| 9 | const ResultId = spec.IdResult; | ||
| 10 | const Word = spec.Word; | ||
| 11 | |||
| 12 | /// This structure contains all the stuff that we need to parse from the module in | ||
| 13 | /// order to run this pass, as well as some functions to ease its use. | ||
| 14 | const ModuleInfo = struct { | ||
| 15 | /// Information about a particular function. | ||
| 16 | const Fn = struct { | ||
| 17 | /// The index of the first callee in `callee_store`. | ||
| 18 | first_callee: usize, | ||
| 19 | /// The return type id of this function | ||
| 20 | return_type: ResultId, | ||
| 21 | /// The parameter types of this function | ||
| 22 | param_types: []const ResultId, | ||
| 23 | /// The set of (result-id's of) invocation globals that are accessed | ||
| 24 | /// in this function, or after resolution, that are accessed in this | ||
| 25 | /// function or any of it's callees. | ||
| 26 | invocation_globals: std.AutoArrayHashMapUnmanaged(ResultId, void), | ||
| 27 | }; | ||
| 28 | |||
| 29 | /// Information about a particular invocation global | ||
| 30 | const InvocationGlobal = struct { | ||
| 31 | /// The list of invocation globals that this invocation global | ||
| 32 | /// depends on. | ||
| 33 | dependencies: std.AutoArrayHashMapUnmanaged(ResultId, void), | ||
| 34 | /// The invocation global's type | ||
| 35 | ty: ResultId, | ||
| 36 | /// Initializer function. May be `none`. | ||
| 37 | /// Note that if the initializer is `none`, then `dependencies` is empty. | ||
| 38 | initializer: ResultId, | ||
| 39 | }; | ||
| 40 | |||
| 41 | /// Maps function result-id -> Fn information structure. | ||
| 42 | functions: std.AutoArrayHashMapUnmanaged(ResultId, Fn), | ||
| 43 | /// Set of OpFunction result-ids in this module. | ||
| 44 | entry_points: std.AutoArrayHashMapUnmanaged(ResultId, void), | ||
| 45 | /// For each function, a list of function result-ids that it calls. | ||
| 46 | callee_store: []const ResultId, | ||
| 47 | /// Maps each invocation global result-id to a type-id. | ||
| 48 | invocation_globals: std.AutoArrayHashMapUnmanaged(ResultId, InvocationGlobal), | ||
| 49 | |||
| 50 | /// Fetch the list of callees per function. Guaranteed to contain only unique IDs. | ||
| 51 | fn callees(self: ModuleInfo, fn_id: ResultId) []const ResultId { | ||
| 52 | const fn_index = self.functions.getIndex(fn_id).?; | ||
| 53 | const values = self.functions.values(); | ||
| 54 | const first_callee = values[fn_index].first_callee; | ||
| 55 | if (fn_index == values.len - 1) { | ||
| 56 | return self.callee_store[first_callee..]; | ||
| 57 | } else { | ||
| 58 | const next_first_callee = values[fn_index + 1].first_callee; | ||
| 59 | return self.callee_store[first_callee..next_first_callee]; | ||
| 60 | } | ||
| 61 | } | ||
| 62 | |||
| 63 | /// Extract most of the required information from the binary. The remaining info is | ||
| 64 | /// constructed by `resolve()`. | ||
| 65 | fn parse( | ||
| 66 | arena: Allocator, | ||
| 67 | parser: *BinaryModule.Parser, | ||
| 68 | binary: BinaryModule, | ||
| 69 | ) BinaryModule.ParseError!ModuleInfo { | ||
| 70 | var entry_points = std.AutoArrayHashMap(ResultId, void).init(arena); | ||
| 71 | var functions = std.AutoArrayHashMap(ResultId, Fn).init(arena); | ||
| 72 | var fn_types = std.AutoHashMap(ResultId, struct { | ||
| 73 | return_type: ResultId, | ||
| 74 | param_types: []const ResultId, | ||
| 75 | }).init(arena); | ||
| 76 | var calls = std.AutoArrayHashMap(ResultId, void).init(arena); | ||
| 77 | var callee_store = std.ArrayList(ResultId).init(arena); | ||
| 78 | var function_invocation_globals = std.AutoArrayHashMap(ResultId, void).init(arena); | ||
| 79 | var result_id_offsets = std.ArrayList(u16).init(arena); | ||
| 80 | var invocation_globals = std.AutoArrayHashMap(ResultId, InvocationGlobal).init(arena); | ||
| 81 | |||
| 82 | var maybe_current_function: ?ResultId = null; | ||
| 83 | var fn_ty_id: ResultId = undefined; | ||
| 84 | |||
| 85 | var it = binary.iterateInstructions(); | ||
| 86 | while (it.next()) |inst| { | ||
| 87 | result_id_offsets.items.len = 0; | ||
| 88 | try parser.parseInstructionResultIds(binary, inst, &result_id_offsets); | ||
| 89 | |||
| 90 | switch (inst.opcode) { | ||
| 91 | .OpEntryPoint => { | ||
| 92 | const entry_point: ResultId = @enumFromInt(inst.operands[1]); | ||
| 93 | const entry = try entry_points.getOrPut(entry_point); | ||
| 94 | if (entry.found_existing) { | ||
| 95 | log.err("Entry point type {} has duplicate definition", .{entry_point}); | ||
| 96 | return error.DuplicateId; | ||
| 97 | } | ||
| 98 | }, | ||
| 99 | .OpTypeFunction => { | ||
| 100 | const fn_type: ResultId = @enumFromInt(inst.operands[0]); | ||
| 101 | const return_type: ResultId = @enumFromInt(inst.operands[1]); | ||
| 102 | const param_types: []const ResultId = @ptrCast(inst.operands[2..]); | ||
| 103 | |||
| 104 | const entry = try fn_types.getOrPut(fn_type); | ||
| 105 | if (entry.found_existing) { | ||
| 106 | log.err("Function type {} has duplicate definition", .{fn_type}); | ||
| 107 | return error.DuplicateId; | ||
| 108 | } | ||
| 109 | |||
| 110 | entry.value_ptr.* = .{ | ||
| 111 | .return_type = return_type, | ||
| 112 | .param_types = param_types, | ||
| 113 | }; | ||
| 114 | }, | ||
| 115 | .OpExtInst => { | ||
| 116 | // Note: format and set are already verified by parseInstructionResultIds(). | ||
| 117 | const global_type: ResultId = @enumFromInt(inst.operands[0]); | ||
| 118 | const result_id: ResultId = @enumFromInt(inst.operands[1]); | ||
| 119 | const set_id: ResultId = @enumFromInt(inst.operands[2]); | ||
| 120 | const set_inst = inst.operands[3]; | ||
| 121 | |||
| 122 | const set = binary.ext_inst_map.get(set_id).?; | ||
| 123 | if (set == .zig and set_inst == 0) { | ||
| 124 | const initializer: ResultId = if (inst.operands.len >= 5) | ||
| 125 | @enumFromInt(inst.operands[4]) | ||
| 126 | else | ||
| 127 | .none; | ||
| 128 | |||
| 129 | try invocation_globals.put(result_id, .{ | ||
| 130 | .dependencies = .{}, | ||
| 131 | .ty = global_type, | ||
| 132 | .initializer = initializer, | ||
| 133 | }); | ||
| 134 | } | ||
| 135 | }, | ||
| 136 | .OpFunction => { | ||
| 137 | if (maybe_current_function) |current_function| { | ||
| 138 | log.err("OpFunction {} does not have an OpFunctionEnd", .{current_function}); | ||
| 139 | return error.InvalidPhysicalFormat; | ||
| 140 | } | ||
| 141 | |||
| 142 | maybe_current_function = @enumFromInt(inst.operands[1]); | ||
| 143 | fn_ty_id = @enumFromInt(inst.operands[3]); | ||
| 144 | function_invocation_globals.clearRetainingCapacity(); | ||
| 145 | }, | ||
| 146 | .OpFunctionCall => { | ||
| 147 | const callee: ResultId = @enumFromInt(inst.operands[2]); | ||
| 148 | try calls.put(callee, {}); | ||
| 149 | }, | ||
| 150 | .OpFunctionEnd => { | ||
| 151 | const current_function = maybe_current_function orelse { | ||
| 152 | log.err("encountered OpFunctionEnd without corresponding OpFunction", .{}); | ||
| 153 | return error.InvalidPhysicalFormat; | ||
| 154 | }; | ||
| 155 | const entry = try functions.getOrPut(current_function); | ||
| 156 | if (entry.found_existing) { | ||
| 157 | log.err("Function {} has duplicate definition", .{current_function}); | ||
| 158 | return error.DuplicateId; | ||
| 159 | } | ||
| 160 | |||
| 161 | const first_callee = callee_store.items.len; | ||
| 162 | try callee_store.appendSlice(calls.keys()); | ||
| 163 | |||
| 164 | const fn_type = fn_types.get(fn_ty_id) orelse { | ||
| 165 | log.err("Function {} has invalid OpFunction type", .{current_function}); | ||
| 166 | return error.InvalidId; | ||
| 167 | }; | ||
| 168 | |||
| 169 | entry.value_ptr.* = .{ | ||
| 170 | .first_callee = first_callee, | ||
| 171 | .return_type = fn_type.return_type, | ||
| 172 | .param_types = fn_type.param_types, | ||
| 173 | .invocation_globals = try function_invocation_globals.unmanaged.clone(arena), | ||
| 174 | }; | ||
| 175 | maybe_current_function = null; | ||
| 176 | calls.clearRetainingCapacity(); | ||
| 177 | }, | ||
| 178 | else => {}, | ||
| 179 | } | ||
| 180 | |||
| 181 | for (result_id_offsets.items) |off| { | ||
| 182 | const result_id: ResultId = @enumFromInt(inst.operands[off]); | ||
| 183 | if (invocation_globals.contains(result_id)) { | ||
| 184 | try function_invocation_globals.put(result_id, {}); | ||
| 185 | } | ||
| 186 | } | ||
| 187 | } | ||
| 188 | |||
| 189 | if (maybe_current_function) |current_function| { | ||
| 190 | log.err("OpFunction {} does not have an OpFunctionEnd", .{current_function}); | ||
| 191 | return error.InvalidPhysicalFormat; | ||
| 192 | } | ||
| 193 | |||
| 194 | return ModuleInfo{ | ||
| 195 | .functions = functions.unmanaged, | ||
| 196 | .entry_points = entry_points.unmanaged, | ||
| 197 | .callee_store = callee_store.items, | ||
| 198 | .invocation_globals = invocation_globals.unmanaged, | ||
| 199 | }; | ||
| 200 | } | ||
| 201 | |||
| 202 | /// Derive the remaining info from the structures filled in by parsing. | ||
| 203 | fn resolve(self: *ModuleInfo, arena: Allocator) !void { | ||
| 204 | try self.resolveInvocationGlobalUsage(arena); | ||
| 205 | try self.resolveInvocationGlobalDependencies(arena); | ||
| 206 | } | ||
| 207 | |||
| 208 | /// For each function, extend the list of `invocation_globals` with the | ||
| 209 | /// invocation globals that ALL of its dependencies use. | ||
| 210 | fn resolveInvocationGlobalUsage(self: *ModuleInfo, arena: Allocator) !void { | ||
| 211 | var seen = try std.DynamicBitSetUnmanaged.initEmpty(arena, self.functions.count()); | ||
| 212 | |||
| 213 | for (self.functions.keys()) |id| { | ||
| 214 | try self.resolveInvocationGlobalUsageStep(arena, id, &seen); | ||
| 215 | } | ||
| 216 | } | ||
| 217 | |||
| 218 | fn resolveInvocationGlobalUsageStep( | ||
| 219 | self: *ModuleInfo, | ||
| 220 | arena: Allocator, | ||
| 221 | id: ResultId, | ||
| 222 | seen: *std.DynamicBitSetUnmanaged, | ||
| 223 | ) !void { | ||
| 224 | const index = self.functions.getIndex(id) orelse { | ||
| 225 | log.err("function calls invalid function {}", .{id}); | ||
| 226 | return error.InvalidId; | ||
| 227 | }; | ||
| 228 | |||
| 229 | if (seen.isSet(index)) { | ||
| 230 | return; | ||
| 231 | } | ||
| 232 | seen.set(index); | ||
| 233 | |||
| 234 | const info = &self.functions.values()[index]; | ||
| 235 | for (self.callees(id)) |callee| { | ||
| 236 | try self.resolveInvocationGlobalUsageStep(arena, callee, seen); | ||
| 237 | const callee_info = self.functions.get(callee).?; | ||
| 238 | for (callee_info.invocation_globals.keys()) |global| { | ||
| 239 | try info.invocation_globals.put(arena, global, {}); | ||
| 240 | } | ||
| 241 | } | ||
| 242 | } | ||
| 243 | |||
| 244 | /// For each invocation global, populate and fully resolve the `dependencies` set. | ||
| 245 | /// This requires `resolveInvocationGlobalUsage()` to be already done. | ||
| 246 | fn resolveInvocationGlobalDependencies( | ||
| 247 | self: *ModuleInfo, | ||
| 248 | arena: Allocator, | ||
| 249 | ) !void { | ||
| 250 | var seen = try std.DynamicBitSetUnmanaged.initEmpty(arena, self.invocation_globals.count()); | ||
| 251 | |||
| 252 | for (self.invocation_globals.keys()) |id| { | ||
| 253 | try self.resolveInvocationGlobalDependenciesStep(arena, id, &seen); | ||
| 254 | } | ||
| 255 | } | ||
| 256 | |||
| 257 | fn resolveInvocationGlobalDependenciesStep( | ||
| 258 | self: *ModuleInfo, | ||
| 259 | arena: Allocator, | ||
| 260 | id: ResultId, | ||
| 261 | seen: *std.DynamicBitSetUnmanaged, | ||
| 262 | ) !void { | ||
| 263 | const index = self.invocation_globals.getIndex(id) orelse { | ||
| 264 | log.err("invalid invocation global {}", .{id}); | ||
| 265 | return error.InvalidId; | ||
| 266 | }; | ||
| 267 | |||
| 268 | if (seen.isSet(index)) { | ||
| 269 | return; | ||
| 270 | } | ||
| 271 | seen.set(index); | ||
| 272 | |||
| 273 | const info = &self.invocation_globals.values()[index]; | ||
| 274 | if (info.initializer == .none) { | ||
| 275 | return; | ||
| 276 | } | ||
| 277 | |||
| 278 | const initializer = self.functions.get(info.initializer) orelse { | ||
| 279 | log.err("invocation global {} has invalid initializer {}", .{ id, info.initializer }); | ||
| 280 | return error.InvalidId; | ||
| 281 | }; | ||
| 282 | |||
| 283 | for (initializer.invocation_globals.keys()) |dependency| { | ||
| 284 | if (dependency == id) { | ||
| 285 | // The set of invocation global dependencies includes the dependency itself, | ||
| 286 | // so we need to skip that case. | ||
| 287 | continue; | ||
| 288 | } | ||
| 289 | |||
| 290 | try info.dependencies.put(arena, dependency, {}); | ||
| 291 | try self.resolveInvocationGlobalDependenciesStep(arena, dependency, seen); | ||
| 292 | |||
| 293 | const dep_info = self.invocation_globals.getPtr(dependency).?; | ||
| 294 | |||
| 295 | for (dep_info.dependencies.keys()) |global| { | ||
| 296 | try info.dependencies.put(arena, global, {}); | ||
| 297 | } | ||
| 298 | } | ||
| 299 | } | ||
| 300 | }; | ||
| 301 | |||
| 302 | const ModuleBuilder = struct { | ||
| 303 | const FunctionType = struct { | ||
| 304 | return_type: ResultId, | ||
| 305 | param_types: []const ResultId, | ||
| 306 | |||
| 307 | const Context = struct { | ||
| 308 | pub fn hash(_: @This(), ty: FunctionType) u32 { | ||
| 309 | var hasher = std.hash.Wyhash.init(0); | ||
| 310 | hasher.update(std.mem.asBytes(&ty.return_type)); | ||
| 311 | hasher.update(std.mem.sliceAsBytes(ty.param_types)); | ||
| 312 | return @truncate(hasher.final()); | ||
| 313 | } | ||
| 314 | |||
| 315 | pub fn eql(_: @This(), a: FunctionType, b: FunctionType, _: usize) bool { | ||
| 316 | if (a.return_type != b.return_type) return false; | ||
| 317 | return std.mem.eql(ResultId, a.param_types, b.param_types); | ||
| 318 | } | ||
| 319 | }; | ||
| 320 | }; | ||
| 321 | |||
| 322 | const FunctionNewInfo = struct { | ||
| 323 | /// This is here just so that we don't need to allocate the new | ||
| 324 | /// param_types multiple times. | ||
| 325 | new_function_type: ResultId, | ||
| 326 | /// The first ID of the parameters for the invocation globals. | ||
| 327 | /// Each global is allocate here according to the index in | ||
| 328 | /// `ModuleInfo.Fn.invocation_globals`. | ||
| 329 | global_id_base: u32, | ||
| 330 | |||
| 331 | fn invocationGlobalId(self: FunctionNewInfo, index: usize) ResultId { | ||
| 332 | return @enumFromInt(self.global_id_base + @as(u32, @intCast(index))); | ||
| 333 | } | ||
| 334 | }; | ||
| 335 | |||
| 336 | arena: Allocator, | ||
| 337 | section: Section, | ||
| 338 | /// The ID bound of the new module. | ||
| 339 | id_bound: u32, | ||
| 340 | /// The first ID of the new entry points. Entry points are allocated from | ||
| 341 | /// here according to their index in `info.entry_points`. | ||
| 342 | entry_point_new_id_base: u32, | ||
| 343 | /// A set of all function types in the new program. SPIR-V mandates that these are unique, | ||
| 344 | /// and until a general type deduplication pass is programmed, we just handle it here via this. | ||
| 345 | function_types: std.ArrayHashMapUnmanaged(FunctionType, ResultId, FunctionType.Context, true) = .{}, | ||
| 346 | /// Maps functions to new information required for creating the module | ||
| 347 | function_new_info: std.AutoArrayHashMapUnmanaged(ResultId, FunctionNewInfo) = .{}, | ||
| 348 | |||
| 349 | fn init(arena: Allocator, binary: BinaryModule, info: ModuleInfo) !ModuleBuilder { | ||
| 350 | var section = Section{}; | ||
| 351 | |||
| 352 | try section.instructions.appendSlice(arena, &.{ | ||
| 353 | spec.magic_number, | ||
| 354 | @bitCast(binary.version), | ||
| 355 | spec.zig_generator_id, | ||
| 356 | 0, // Filled in in finalize() | ||
| 357 | 0, // Schema (reserved) | ||
| 358 | }); | ||
| 359 | |||
| 360 | var self = ModuleBuilder{ | ||
| 361 | .arena = arena, | ||
| 362 | .section = section, | ||
| 363 | .id_bound = binary.id_bound, | ||
| 364 | .entry_point_new_id_base = undefined, | ||
| 365 | }; | ||
| 366 | self.entry_point_new_id_base = @intFromEnum(self.allocIds(@intCast(info.entry_points.count()))); | ||
| 367 | return self; | ||
| 368 | } | ||
| 369 | |||
| 370 | fn allocId(self: *ModuleBuilder) ResultId { | ||
| 371 | return self.allocIds(1); | ||
| 372 | } | ||
| 373 | |||
| 374 | fn allocIds(self: *ModuleBuilder, n: u32) ResultId { | ||
| 375 | defer self.id_bound += n; | ||
| 376 | return @enumFromInt(self.id_bound); | ||
| 377 | } | ||
| 378 | |||
| 379 | fn finalize(self: *ModuleBuilder, a: Allocator) ![]Word { | ||
| 380 | self.section.instructions.items[3] = self.id_bound; | ||
| 381 | return try a.dupe(Word, self.section.instructions.items); | ||
| 382 | } | ||
| 383 | |||
| 384 | /// Process everything from `binary` up to the first function and emit it into the builder. | ||
| 385 | fn processPreamble(self: *ModuleBuilder, binary: BinaryModule, info: ModuleInfo) !void { | ||
| 386 | var it = binary.iterateInstructions(); | ||
| 387 | while (it.next()) |inst| { | ||
| 388 | switch (inst.opcode) { | ||
| 389 | // TODO: We should remove this instruction using something that eliminates unreferenced instructions. | ||
| 390 | // For now, this is the only place where the .zig instruction set is being referenced, so its safe | ||
| 391 | // to remove it here. | ||
| 392 | .OpExtInstImport => { | ||
| 393 | const set_id: ResultId = @enumFromInt(inst.operands[0]); | ||
| 394 | const set = binary.ext_inst_map.get(set_id).?; | ||
| 395 | if (set == .zig) { | ||
| 396 | continue; | ||
| 397 | } | ||
| 398 | }, | ||
| 399 | .OpExtInst => { | ||
| 400 | const set_id: ResultId = @enumFromInt(inst.operands[2]); | ||
| 401 | const set_inst = inst.operands[3]; | ||
| 402 | const set = binary.ext_inst_map.get(set_id).?; | ||
| 403 | if (set == .zig and set_inst == 0) { | ||
| 404 | continue; | ||
| 405 | } | ||
| 406 | }, | ||
| 407 | .OpEntryPoint => { | ||
| 408 | const original_id: ResultId = @enumFromInt(inst.operands[1]); | ||
| 409 | const new_id_index = info.entry_points.getIndex(original_id).?; | ||
| 410 | const new_id: ResultId = @enumFromInt(self.entry_point_new_id_base + new_id_index); | ||
| 411 | try self.section.emitRaw(self.arena, .OpEntryPoint, inst.operands.len); | ||
| 412 | self.section.writeWord(inst.operands[0]); | ||
| 413 | self.section.writeOperand(ResultId, new_id); | ||
| 414 | self.section.writeWords(inst.operands[2..]); | ||
| 415 | continue; | ||
| 416 | }, | ||
| 417 | .OpTypeFunction => { | ||
| 418 | // Re-emitted in `emitFunctionTypes()`. We can do this because | ||
| 419 | // OpTypeFunction's may not currently be used anywhere that is not | ||
| 420 | // directly with an OpFunction. For now we igore Intels function | ||
| 421 | // pointers extension, that is not a problem with a generalized | ||
| 422 | // pass anyway. | ||
| 423 | continue; | ||
| 424 | }, | ||
| 425 | .OpFunction => break, | ||
| 426 | else => {}, | ||
| 427 | } | ||
| 428 | |||
| 429 | try self.section.emitRawInstruction(self.arena, inst.opcode, inst.operands); | ||
| 430 | } | ||
| 431 | } | ||
| 432 | |||
| 433 | /// Derive new information required for further emitting this module, | ||
| 434 | fn deriveNewFnInfo(self: *ModuleBuilder, info: ModuleInfo) !void { | ||
| 435 | for (info.functions.keys(), info.functions.values()) |func, fn_info| { | ||
| 436 | const invocation_global_count = fn_info.invocation_globals.count(); | ||
| 437 | const new_param_types = try self.arena.alloc(ResultId, fn_info.param_types.len + invocation_global_count); | ||
| 438 | for (fn_info.invocation_globals.keys(), 0..) |global, i| { | ||
| 439 | new_param_types[i] = info.invocation_globals.get(global).?.ty; | ||
| 440 | } | ||
| 441 | @memcpy(new_param_types[invocation_global_count..], fn_info.param_types); | ||
| 442 | |||
| 443 | const new_type = try self.internFunctionType(fn_info.return_type, new_param_types); | ||
| 444 | try self.function_new_info.put(self.arena, func, .{ | ||
| 445 | .new_function_type = new_type, | ||
| 446 | .global_id_base = @intFromEnum(self.allocIds(@intCast(invocation_global_count))), | ||
| 447 | }); | ||
| 448 | } | ||
| 449 | } | ||
| 450 | |||
| 451 | /// Emit the new function types, which include the parameters for the invocation globals. | ||
| 452 | /// Currently, this function re-emits ALL function types to ensure that there are | ||
| 453 | /// no duplicates in the final program. | ||
| 454 | /// TODO: The above should be resolved by a generalized deduplication pass, and then | ||
| 455 | /// we only need to emit the new function pointers type here. | ||
| 456 | fn emitFunctionTypes(self: *ModuleBuilder, info: ModuleInfo) !void { | ||
| 457 | // TODO: Handle decorators. Function types usually don't have those | ||
| 458 | // though, but stuff like OpName could be a possibility. | ||
| 459 | |||
| 460 | // Entry points retain their old function type, so make sure to emit | ||
| 461 | // those in the `function_types` set. | ||
| 462 | for (info.entry_points.keys()) |func| { | ||
| 463 | const fn_info = info.functions.get(func).?; | ||
| 464 | _ = try self.internFunctionType(fn_info.return_type, fn_info.param_types); | ||
| 465 | } | ||
| 466 | |||
| 467 | for (self.function_types.keys(), self.function_types.values()) |fn_type, result_id| { | ||
| 468 | try self.section.emit(self.arena, .OpTypeFunction, .{ | ||
| 469 | .id_result = result_id, | ||
| 470 | .return_type = fn_type.return_type, | ||
| 471 | .id_ref_2 = fn_type.param_types, | ||
| 472 | }); | ||
| 473 | } | ||
| 474 | } | ||
| 475 | |||
| 476 | fn internFunctionType(self: *ModuleBuilder, return_type: ResultId, param_types: []const ResultId) !ResultId { | ||
| 477 | const entry = try self.function_types.getOrPut(self.arena, .{ | ||
| 478 | .return_type = return_type, | ||
| 479 | .param_types = param_types, | ||
| 480 | }); | ||
| 481 | |||
| 482 | if (!entry.found_existing) { | ||
| 483 | const new_id = self.allocId(); | ||
| 484 | entry.value_ptr.* = new_id; | ||
| 485 | } | ||
| 486 | |||
| 487 | return entry.value_ptr.*; | ||
| 488 | } | ||
| 489 | |||
| 490 | /// Rewrite the modules' functions and emit them with the new parameter types. | ||
| 491 | fn rewriteFunctions( | ||
| 492 | self: *ModuleBuilder, | ||
| 493 | parser: *BinaryModule.Parser, | ||
| 494 | binary: BinaryModule, | ||
| 495 | info: ModuleInfo, | ||
| 496 | ) !void { | ||
| 497 | var result_id_offsets = std.ArrayList(u16).init(self.arena); | ||
| 498 | var operands = std.ArrayList(u32).init(self.arena); | ||
| 499 | |||
| 500 | var maybe_current_function: ?ResultId = null; | ||
| 501 | var it = binary.iterateInstructionsFrom(binary.sections.functions); | ||
| 502 | while (it.next()) |inst| { | ||
| 503 | result_id_offsets.items.len = 0; | ||
| 504 | try parser.parseInstructionResultIds(binary, inst, &result_id_offsets); | ||
| 505 | |||
| 506 | operands.items.len = 0; | ||
| 507 | try operands.appendSlice(inst.operands); | ||
| 508 | |||
| 509 | // Replace the result-ids with the global's new result-id if required. | ||
| 510 | for (result_id_offsets.items) |off| { | ||
| 511 | const result_id: ResultId = @enumFromInt(operands.items[off]); | ||
| 512 | if (info.invocation_globals.contains(result_id)) { | ||
| 513 | const func = maybe_current_function.?; | ||
| 514 | const new_info = self.function_new_info.get(func).?; | ||
| 515 | const fn_info = info.functions.get(func).?; | ||
| 516 | const index = fn_info.invocation_globals.getIndex(result_id).?; | ||
| 517 | operands.items[off] = @intFromEnum(new_info.invocationGlobalId(index)); | ||
| 518 | } | ||
| 519 | } | ||
| 520 | |||
| 521 | switch (inst.opcode) { | ||
| 522 | .OpFunction => { | ||
| 523 | // Re-declare the function with the new parameters. | ||
| 524 | const func: ResultId = @enumFromInt(operands.items[1]); | ||
| 525 | const fn_info = info.functions.get(func).?; | ||
| 526 | const new_info = self.function_new_info.get(func).?; | ||
| 527 | |||
| 528 | try self.section.emitRaw(self.arena, .OpFunction, 4); | ||
| 529 | self.section.writeOperand(ResultId, fn_info.return_type); | ||
| 530 | self.section.writeOperand(ResultId, func); | ||
| 531 | self.section.writeWord(operands.items[2]); | ||
| 532 | self.section.writeOperand(ResultId, new_info.new_function_type); | ||
| 533 | |||
| 534 | // Emit the OpFunctionParameters for the invocation globals. The functions | ||
| 535 | // actual parameters are emitted unchanged from their original form, so | ||
| 536 | // we don't need to handle those here. | ||
| 537 | |||
| 538 | for (fn_info.invocation_globals.keys(), 0..) |global, index| { | ||
| 539 | const ty = info.invocation_globals.get(global).?.ty; | ||
| 540 | const id = new_info.invocationGlobalId(index); | ||
| 541 | try self.section.emit(self.arena, .OpFunctionParameter, .{ | ||
| 542 | .id_result_type = ty, | ||
| 543 | .id_result = id, | ||
| 544 | }); | ||
| 545 | } | ||
| 546 | |||
| 547 | maybe_current_function = func; | ||
| 548 | }, | ||
| 549 | .OpFunctionCall => { | ||
| 550 | // Add the required invocation globals to the function's new parameter list. | ||
| 551 | const caller = maybe_current_function.?; | ||
| 552 | const callee: ResultId = @enumFromInt(operands.items[2]); | ||
| 553 | const caller_info = info.functions.get(caller).?; | ||
| 554 | const callee_info = info.functions.get(callee).?; | ||
| 555 | const caller_new_info = self.function_new_info.get(caller).?; | ||
| 556 | const total_params = callee_info.invocation_globals.count() + callee_info.param_types.len; | ||
| 557 | |||
| 558 | try self.section.emitRaw(self.arena, .OpFunctionCall, 3 + total_params); | ||
| 559 | self.section.writeWord(operands.items[0]); // Copy result type-id | ||
| 560 | self.section.writeWord(operands.items[1]); // Copy result-id | ||
| 561 | self.section.writeOperand(ResultId, callee); | ||
| 562 | |||
| 563 | // Add the new arguments | ||
| 564 | for (callee_info.invocation_globals.keys()) |global| { | ||
| 565 | const caller_global_index = caller_info.invocation_globals.getIndex(global).?; | ||
| 566 | const id = caller_new_info.invocationGlobalId(caller_global_index); | ||
| 567 | self.section.writeOperand(ResultId, id); | ||
| 568 | } | ||
| 569 | |||
| 570 | // Add the original arguments | ||
| 571 | self.section.writeWords(operands.items[3..]); | ||
| 572 | }, | ||
| 573 | else => { | ||
| 574 | try self.section.emitRawInstruction(self.arena, inst.opcode, operands.items); | ||
| 575 | }, | ||
| 576 | } | ||
| 577 | } | ||
| 578 | } | ||
| 579 | |||
| 580 | fn emitNewEntryPoints(self: *ModuleBuilder, info: ModuleInfo) !void { | ||
| 581 | var all_function_invocation_globals = std.AutoArrayHashMap(ResultId, void).init(self.arena); | ||
| 582 | |||
| 583 | for (info.entry_points.keys(), 0..) |func, entry_point_index| { | ||
| 584 | const fn_info = info.functions.get(func).?; | ||
| 585 | const ep_id: ResultId = @enumFromInt(self.entry_point_new_id_base + @as(u32, @intCast(entry_point_index))); | ||
| 586 | const fn_type = self.function_types.get(.{ | ||
| 587 | .return_type = fn_info.return_type, | ||
| 588 | .param_types = fn_info.param_types, | ||
| 589 | }).?; | ||
| 590 | |||
| 591 | try self.section.emit(self.arena, .OpFunction, .{ | ||
| 592 | .id_result_type = fn_info.return_type, | ||
| 593 | .id_result = ep_id, | ||
| 594 | .function_control = .{}, // TODO: Copy the attributes from the original function maybe? | ||
| 595 | .function_type = fn_type, | ||
| 596 | }); | ||
| 597 | |||
| 598 | // Emit OpFunctionParameter instructions for the original kernel's parameters. | ||
| 599 | const params_id_base: u32 = @intFromEnum(self.allocIds(@intCast(fn_info.param_types.len))); | ||
| 600 | for (fn_info.param_types, 0..) |param_type, i| { | ||
| 601 | const id: ResultId = @enumFromInt(params_id_base + @as(u32, @intCast(i))); | ||
| 602 | try self.section.emit(self.arena, .OpFunctionParameter, .{ | ||
| 603 | .id_result_type = param_type, | ||
| 604 | .id_result = id, | ||
| 605 | }); | ||
| 606 | } | ||
| 607 | |||
| 608 | try self.section.emit(self.arena, .OpLabel, .{ | ||
| 609 | .id_result = self.allocId(), | ||
| 610 | }); | ||
| 611 | |||
| 612 | // Besides the IDs of the main kernel, we also need the | ||
| 613 | // dependencies of the globals. | ||
| 614 | // Just quickly construct that set here. | ||
| 615 | all_function_invocation_globals.clearRetainingCapacity(); | ||
| 616 | for (fn_info.invocation_globals.keys()) |global| { | ||
| 617 | try all_function_invocation_globals.put(global, {}); | ||
| 618 | const global_info = info.invocation_globals.get(global).?; | ||
| 619 | for (global_info.dependencies.keys()) |dependency| { | ||
| 620 | try all_function_invocation_globals.put(dependency, {}); | ||
| 621 | } | ||
| 622 | } | ||
| 623 | |||
| 624 | // Declare the IDs of the invocation globals. | ||
| 625 | const global_id_base: u32 = @intFromEnum(self.allocIds(@intCast(all_function_invocation_globals.count()))); | ||
| 626 | for (all_function_invocation_globals.keys(), 0..) |global, i| { | ||
| 627 | const global_info = info.invocation_globals.get(global).?; | ||
| 628 | |||
| 629 | const id: ResultId = @enumFromInt(global_id_base + @as(u32, @intCast(i))); | ||
| 630 | try self.section.emit(self.arena, .OpVariable, .{ | ||
| 631 | .id_result_type = global_info.ty, | ||
| 632 | .id_result = id, | ||
| 633 | .storage_class = .Function, | ||
| 634 | .initializer = null, | ||
| 635 | }); | ||
| 636 | } | ||
| 637 | |||
| 638 | // Call initializers for invocation globals that need it | ||
| 639 | for (all_function_invocation_globals.keys()) |global| { | ||
| 640 | const global_info = info.invocation_globals.get(global).?; | ||
| 641 | if (global_info.initializer == .none) continue; | ||
| 642 | |||
| 643 | const initializer_info = info.functions.get(global_info.initializer).?; | ||
| 644 | assert(initializer_info.param_types.len == 0); | ||
| 645 | |||
| 646 | try self.callWithGlobalsAndLinearParams( | ||
| 647 | all_function_invocation_globals, | ||
| 648 | global_info.initializer, | ||
| 649 | initializer_info, | ||
| 650 | global_id_base, | ||
| 651 | undefined, | ||
| 652 | ); | ||
| 653 | } | ||
| 654 | |||
| 655 | // Call the main kernel entry | ||
| 656 | try self.callWithGlobalsAndLinearParams( | ||
| 657 | all_function_invocation_globals, | ||
| 658 | func, | ||
| 659 | fn_info, | ||
| 660 | global_id_base, | ||
| 661 | params_id_base, | ||
| 662 | ); | ||
| 663 | |||
| 664 | try self.section.emit(self.arena, .OpReturn, {}); | ||
| 665 | try self.section.emit(self.arena, .OpFunctionEnd, {}); | ||
| 666 | } | ||
| 667 | } | ||
| 668 | |||
| 669 | fn callWithGlobalsAndLinearParams( | ||
| 670 | self: *ModuleBuilder, | ||
| 671 | all_globals: std.AutoArrayHashMap(ResultId, void), | ||
| 672 | func: ResultId, | ||
| 673 | callee_info: ModuleInfo.Fn, | ||
| 674 | global_id_base: u32, | ||
| 675 | params_id_base: u32, | ||
| 676 | ) !void { | ||
| 677 | const total_arguments = callee_info.invocation_globals.count() + callee_info.param_types.len; | ||
| 678 | try self.section.emitRaw(self.arena, .OpFunctionCall, 3 + total_arguments); | ||
| 679 | self.section.writeOperand(ResultId, callee_info.return_type); | ||
| 680 | self.section.writeOperand(ResultId, self.allocId()); | ||
| 681 | self.section.writeOperand(ResultId, func); | ||
| 682 | |||
| 683 | // Add the invocation globals | ||
| 684 | for (callee_info.invocation_globals.keys()) |global| { | ||
| 685 | const index = all_globals.getIndex(global).?; | ||
| 686 | const id: ResultId = @enumFromInt(global_id_base + @as(u32, @intCast(index))); | ||
| 687 | self.section.writeOperand(ResultId, id); | ||
| 688 | } | ||
| 689 | |||
| 690 | // Add the arguments | ||
| 691 | for (0..callee_info.param_types.len) |index| { | ||
| 692 | const id: ResultId = @enumFromInt(params_id_base + @as(u32, @intCast(index))); | ||
| 693 | self.section.writeOperand(ResultId, id); | ||
| 694 | } | ||
| 695 | } | ||
| 696 | }; | ||
| 697 | |||
| 698 | pub fn run(parser: *BinaryModule.Parser, binary: BinaryModule) ![]Word { | ||
| 699 | var arena = std.heap.ArenaAllocator.init(parser.a); | ||
| 700 | defer arena.deinit(); | ||
| 701 | const a = arena.allocator(); | ||
| 702 | |||
| 703 | var info = try ModuleInfo.parse(a, parser, binary); | ||
| 704 | try info.resolve(a); | ||
| 705 | |||
| 706 | var builder = try ModuleBuilder.init(a, binary, info); | ||
| 707 | try builder.deriveNewFnInfo(info); | ||
| 708 | try builder.processPreamble(binary, info); | ||
| 709 | try builder.emitFunctionTypes(info); | ||
| 710 | try builder.rewriteFunctions(parser, binary, info); | ||
| 711 | try builder.emitNewEntryPoints(info); | ||
| 712 | |||
| 713 | return builder.finalize(parser.a); | ||
| 714 | } | ||
test/behavior/basic.zig+1| ... | @@ -757,6 +757,7 @@ test "extern variable with non-pointer opaque type" { | ... | @@ -757,6 +757,7 @@ test "extern variable with non-pointer opaque type" { |
| 757 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 757 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 758 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | 758 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 759 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest; | 759 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest; |
| 760 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO | ||
| 760 | 761 | ||
| 761 | @export(var_to_export, .{ .name = "opaque_extern_var" }); | 762 | @export(var_to_export, .{ .name = "opaque_extern_var" }); |
| 762 | try expect(@as(*align(1) u32, @ptrCast(&opaque_extern_var)).* == 42); | 763 | try expect(@as(*align(1) u32, @ptrCast(&opaque_extern_var)).* == 42); |
tools/gen_spirv_spec.zig+38-3| ... | @@ -42,6 +42,26 @@ const StringPairContext = struct { | ... | @@ -42,6 +42,26 @@ const StringPairContext = struct { |
| 42 | 42 | ||
| 43 | const OperandKindMap = std.ArrayHashMap(StringPair, OperandKind, StringPairContext, true); | 43 | const OperandKindMap = std.ArrayHashMap(StringPair, OperandKind, StringPairContext, true); |
| 44 | 44 | ||
| 45 | /// Khronos made it so that these names are not defined explicitly, so | ||
| 46 | /// we need to hardcode it (like they did). | ||
| 47 | /// See https://github.com/KhronosGroup/SPIRV-Registry/ | ||
| 48 | const set_names = std.ComptimeStringMap([]const u8, .{ | ||
| 49 | .{ "opencl.std.100", "OpenCL.std" }, | ||
| 50 | .{ "glsl.std.450", "GLSL.std.450" }, | ||
| 51 | .{ "opencl.debuginfo.100", "OpenCL.DebugInfo.100" }, | ||
| 52 | .{ "spv-amd-shader-ballot", "SPV_AMD_shader_ballot" }, | ||
| 53 | .{ "nonsemantic.shader.debuginfo.100", "NonSemantic.Shader.DebugInfo.100" }, | ||
| 54 | .{ "nonsemantic.vkspreflection", "NonSemantic.VkspReflection" }, | ||
| 55 | .{ "nonsemantic.clspvreflection", "NonSemantic.ClspvReflection.6" }, // This version needs to be handled manually | ||
| 56 | .{ "spv-amd-gcn-shader", "SPV_AMD_gcn_shader" }, | ||
| 57 | .{ "spv-amd-shader-trinary-minmax", "SPV_AMD_shader_trinary_minmax" }, | ||
| 58 | .{ "debuginfo", "DebugInfo" }, | ||
| 59 | .{ "nonsemantic.debugprintf", "NonSemantic.DebugPrintf" }, | ||
| 60 | .{ "spv-amd-shader-explicit-vertex-parameter", "SPV_AMD_shader_explicit_vertex_parameter" }, | ||
| 61 | .{ "nonsemantic.debugbreak", "NonSemantic.DebugBreak" }, | ||
| 62 | .{ "zig", "zig" }, | ||
| 63 | }); | ||
| 64 | |||
| 45 | pub fn main() !void { | 65 | pub fn main() !void { |
| 46 | var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); | 66 | var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); |
| 47 | defer arena.deinit(); | 67 | defer arena.deinit(); |
| ... | @@ -88,7 +108,7 @@ fn readExtRegistry(exts: *std.ArrayList(Extension), a: Allocator, dir: std.fs.Di | ... | @@ -88,7 +108,7 @@ fn readExtRegistry(exts: *std.ArrayList(Extension), a: Allocator, dir: std.fs.Di |
| 88 | 108 | ||
| 89 | std.sort.block(Instruction, spec.instructions, CmpInst{}, CmpInst.lt); | 109 | std.sort.block(Instruction, spec.instructions, CmpInst{}, CmpInst.lt); |
| 90 | 110 | ||
| 91 | try exts.append(.{ .name = try a.dupe(u8, name), .spec = spec }); | 111 | try exts.append(.{ .name = set_names.get(name).?, .spec = spec }); |
| 92 | } | 112 | } |
| 93 | 113 | ||
| 94 | fn readRegistry(comptime RegistryType: type, a: Allocator, dir: std.fs.Dir, path: []const u8) !RegistryType { | 114 | fn readRegistry(comptime RegistryType: type, a: Allocator, dir: std.fs.Dir, path: []const u8) !RegistryType { |
| ... | @@ -150,6 +170,8 @@ fn render(writer: anytype, a: Allocator, registry: CoreRegistry, extensions: []c | ... | @@ -150,6 +170,8 @@ fn render(writer: anytype, a: Allocator, registry: CoreRegistry, extensions: []c |
| 150 | try writer.writeAll( | 170 | try writer.writeAll( |
| 151 | \\//! This file is auto-generated by tools/gen_spirv_spec.zig. | 171 | \\//! This file is auto-generated by tools/gen_spirv_spec.zig. |
| 152 | \\ | 172 | \\ |
| 173 | \\const std = @import("std"); | ||
| 174 | \\ | ||
| 153 | \\pub const Version = packed struct(Word) { | 175 | \\pub const Version = packed struct(Word) { |
| 154 | \\ padding: u8 = 0, | 176 | \\ padding: u8 = 0, |
| 155 | \\ minor: u8, | 177 | \\ minor: u8, |
| ... | @@ -163,8 +185,20 @@ fn render(writer: anytype, a: Allocator, registry: CoreRegistry, extensions: []c | ... | @@ -163,8 +185,20 @@ fn render(writer: anytype, a: Allocator, registry: CoreRegistry, extensions: []c |
| 163 | \\ | 185 | \\ |
| 164 | \\pub const Word = u32; | 186 | \\pub const Word = u32; |
| 165 | \\pub const IdResult = enum(Word) { | 187 | \\pub const IdResult = enum(Word) { |
| 166 | \\ none, | 188 | \\ none, |
| 167 | \\ _, | 189 | \\ _, |
| 190 | \\ | ||
| 191 | \\ pub fn format( | ||
| 192 | \\ self: IdResult, | ||
| 193 | \\ comptime _: []const u8, | ||
| 194 | \\ _: std.fmt.FormatOptions, | ||
| 195 | \\ writer: anytype, | ||
| 196 | \\ ) @TypeOf(writer).Error!void { | ||
| 197 | \\ switch (self) { | ||
| 198 | \\ .none => try writer.writeAll("(none)"), | ||
| 199 | \\ else => try writer.print("%{}", .{@intFromEnum(self)}), | ||
| 200 | \\ } | ||
| 201 | \\ } | ||
| 168 | \\}; | 202 | \\}; |
| 169 | \\pub const IdResultType = IdResult; | 203 | \\pub const IdResultType = IdResult; |
| 170 | \\pub const IdRef = IdResult; | 204 | \\pub const IdRef = IdResult; |
| ... | @@ -220,6 +254,7 @@ fn render(writer: anytype, a: Allocator, registry: CoreRegistry, extensions: []c | ... | @@ -220,6 +254,7 @@ fn render(writer: anytype, a: Allocator, registry: CoreRegistry, extensions: []c |
| 220 | \\ operands: []const Operand, | 254 | \\ operands: []const Operand, |
| 221 | \\}; | 255 | \\}; |
| 222 | \\ | 256 | \\ |
| 257 | \\pub const zig_generator_id: Word = 41; | ||
| 223 | \\ | 258 | \\ |
| 224 | ); | 259 | ); |
| 225 | 260 |