| ... | @@ -40,7 +40,6 @@ pub fn legalizeFeatures(_: *const std.Target) *const Air.Legalize.Features { | ... | @@ -40,7 +40,6 @@ pub fn legalizeFeatures(_: *const std.Target) *const Air.Legalize.Features { |
| 40 | } | 40 | } |
| 41 | | 41 | |
| 42 | pub const zig_call_abi_ver = 3; | 42 | pub const zig_call_abi_ver = 3; |
| 43 | pub const big_int_bits = 32; | | |
| 44 | | 43 | |
| 45 | const ControlFlow = union(enum) { | 44 | const ControlFlow = union(enum) { |
| 46 | const Structured = struct { | 45 | const Structured = struct { |
| ... | @@ -183,6 +182,7 @@ pub fn genNav(cg: *CodeGen, do_codegen: bool) Error!void { | ... | @@ -183,6 +182,7 @@ pub fn genNav(cg: *CodeGen, do_codegen: bool) Error!void { |
| 183 | const gpa = cg.module.gpa; | 182 | const gpa = cg.module.gpa; |
| 184 | const zcu = cg.module.zcu; | 183 | const zcu = cg.module.zcu; |
| 185 | const ip = &zcu.intern_pool; | 184 | const ip = &zcu.intern_pool; |
| | 185 | const target = zcu.getTarget(); |
| 186 | | 186 | |
| 187 | const nav = ip.getNav(cg.owner_nav); | 187 | const nav = ip.getNav(cg.owner_nav); |
| 188 | const val = zcu.navValue(cg.owner_nav); | 188 | const val = zcu.navValue(cg.owner_nav); |
| ... | @@ -251,19 +251,19 @@ pub fn genNav(cg: *CodeGen, do_codegen: bool) Error!void { | ... | @@ -251,19 +251,19 @@ pub fn genNav(cg: *CodeGen, do_codegen: bool) Error!void { |
| 251 | // Append the actual code into the functions section. | 251 | // Append the actual code into the functions section. |
| 252 | try cg.module.sections.functions.append(cg.module.gpa, cg.prologue); | 252 | try cg.module.sections.functions.append(cg.module.gpa, cg.prologue); |
| 253 | try cg.module.sections.functions.append(cg.module.gpa, cg.body); | 253 | try cg.module.sections.functions.append(cg.module.gpa, cg.body); |
| 254 | try cg.module.declareDeclDeps(spv_decl_index, cg.decl_deps.keys()); | | |
| 255 | | | |
| 256 | try cg.module.debugName(func_result_id, nav.fqn.toSlice(ip)); | | |
| 257 | | 254 | |
| 258 | // Temporarily generate a test kernel declaration if this is a test function. | 255 | // Temporarily generate a test kernel declaration if this is a test function. |
| 259 | if (is_test) { | 256 | if (is_test) { |
| 260 | try cg.generateTestEntryPoint(nav.fqn.toSlice(ip), spv_decl_index, func_result_id); | 257 | try cg.generateTestEntryPoint(nav.fqn.toSlice(ip), spv_decl_index, func_result_id); |
| 261 | } | 258 | } |
| | 259 | |
| | 260 | try cg.module.declareDeclDeps(spv_decl_index, cg.decl_deps.keys()); |
| | 261 | try cg.module.debugName(func_result_id, nav.fqn.toSlice(ip)); |
| 262 | }, | 262 | }, |
| 263 | .global => { | 263 | .global => { |
| 264 | const maybe_init_val: ?Value = switch (ip.indexToKey(val.toIntern())) { | 264 | const maybe_init_val: ?Value = switch (ip.indexToKey(val.toIntern())) { |
| 265 | .func => unreachable, | 265 | .func => unreachable, |
| 266 | .variable => |variable| Value.fromInterned(variable.init), | 266 | .variable => |variable| .fromInterned(variable.init), |
| 267 | .@"extern" => null, | 267 | .@"extern" => null, |
| 268 | else => val, | 268 | else => val, |
| 269 | }; | 269 | }; |
| ... | @@ -272,7 +272,8 @@ pub fn genNav(cg: *CodeGen, do_codegen: bool) Error!void { | ... | @@ -272,7 +272,8 @@ pub fn genNav(cg: *CodeGen, do_codegen: bool) Error!void { |
| 272 | const storage_class = cg.module.storageClass(nav.getAddrspace()); | 272 | const storage_class = cg.module.storageClass(nav.getAddrspace()); |
| 273 | assert(storage_class != .generic); // These should be instance globals | 273 | assert(storage_class != .generic); // These should be instance globals |
| 274 | | 274 | |
| 275 | const ptr_ty_id = try cg.ptrType(ty, storage_class, .indirect); | 275 | const ty_id = try cg.resolveType(ty, .indirect); |
| | 276 | const ptr_ty_id = try cg.module.ptrType(ty_id, storage_class); |
| 276 | | 277 | |
| 277 | try cg.module.sections.globals.emit(cg.module.gpa, .OpVariable, .{ | 278 | try cg.module.sections.globals.emit(cg.module.gpa, .OpVariable, .{ |
| 278 | .id_result_type = ptr_ty_id, | 279 | .id_result_type = ptr_ty_id, |
| ... | @@ -280,6 +281,27 @@ pub fn genNav(cg: *CodeGen, do_codegen: bool) Error!void { | ... | @@ -280,6 +281,27 @@ pub fn genNav(cg: *CodeGen, do_codegen: bool) Error!void { |
| 280 | .storage_class = storage_class, | 281 | .storage_class = storage_class, |
| 281 | }); | 282 | }); |
| 282 | | 283 | |
| | 284 | switch (target.os.tag) { |
| | 285 | .vulkan, .opengl => { |
| | 286 | if (ty.zigTypeTag(zcu) == .@"struct") { |
| | 287 | switch (storage_class) { |
| | 288 | .uniform, .push_constant => try cg.module.decorate(ty_id, .block), |
| | 289 | else => {}, |
| | 290 | } |
| | 291 | } |
| | 292 | |
| | 293 | switch (ip.indexToKey(ty.toIntern())) { |
| | 294 | .func_type, .opaque_type => {}, |
| | 295 | else => { |
| | 296 | try cg.module.decorate(ptr_ty_id, .{ |
| | 297 | .array_stride = .{ .array_stride = @intCast(ty.abiSize(zcu)) }, |
| | 298 | }); |
| | 299 | }, |
| | 300 | } |
| | 301 | }, |
| | 302 | else => {}, |
| | 303 | } |
| | 304 | |
| 283 | if (std.meta.stringToEnum(spec.BuiltIn, nav.fqn.toSlice(ip))) |builtin| { | 305 | if (std.meta.stringToEnum(spec.BuiltIn, nav.fqn.toSlice(ip))) |builtin| { |
| 284 | try cg.module.decorate(result_id, .{ .built_in = .{ .built_in = builtin } }); | 306 | try cg.module.decorate(result_id, .{ .built_in = .{ .built_in = builtin } }); |
| 285 | } | 307 | } |
| ... | @@ -290,18 +312,20 @@ pub fn genNav(cg: *CodeGen, do_codegen: bool) Error!void { | ... | @@ -290,18 +312,20 @@ pub fn genNav(cg: *CodeGen, do_codegen: bool) Error!void { |
| 290 | .invocation_global => { | 312 | .invocation_global => { |
| 291 | const maybe_init_val: ?Value = switch (ip.indexToKey(val.toIntern())) { | 313 | const maybe_init_val: ?Value = switch (ip.indexToKey(val.toIntern())) { |
| 292 | .func => unreachable, | 314 | .func => unreachable, |
| 293 | .variable => |variable| Value.fromInterned(variable.init), | 315 | .variable => |variable| .fromInterned(variable.init), |
| 294 | .@"extern" => null, | 316 | .@"extern" => null, |
| 295 | else => val, | 317 | else => val, |
| 296 | }; | 318 | }; |
| 297 | | 319 | |
| 298 | try cg.module.declareDeclDeps(spv_decl_index, &.{}); | 320 | try cg.module.declareDeclDeps(spv_decl_index, &.{}); |
| 299 | | 321 | |
| 300 | const ptr_ty_id = try cg.ptrType(ty, .function, .indirect); | 322 | const ty_id = try cg.resolveType(ty, .indirect); |
| | 323 | const ptr_ty_id = try cg.module.ptrType(ty_id, .function); |
| 301 | | 324 | |
| 302 | if (maybe_init_val) |init_val| { | 325 | if (maybe_init_val) |init_val| { |
| 303 | // TODO: Combine with resolveAnonDecl? | 326 | // TODO: Combine with resolveAnonDecl? |
| 304 | const initializer_proto_ty_id = try cg.functionType(.void, &.{}); | 327 | const void_ty_id = try cg.resolveType(.void, .direct); |
| | 328 | const initializer_proto_ty_id = try cg.module.functionType(void_ty_id, &.{}); |
| 305 | | 329 | |
| 306 | const initializer_id = cg.module.allocId(); | 330 | const initializer_id = cg.module.allocId(); |
| 307 | try cg.prologue.emit(cg.module.gpa, .OpFunction, .{ | 331 | try cg.prologue.emit(cg.module.gpa, .OpFunction, .{ |
| ... | @@ -406,7 +430,8 @@ fn resolveUav(cg: *CodeGen, val: InternPool.Index) !Id { | ... | @@ -406,7 +430,8 @@ fn resolveUav(cg: *CodeGen, val: InternPool.Index) !Id { |
| 406 | | 430 | |
| 407 | const zcu = cg.module.zcu; | 431 | const zcu = cg.module.zcu; |
| 408 | const ty: Type = .fromInterned(zcu.intern_pool.typeOf(val)); | 432 | const ty: Type = .fromInterned(zcu.intern_pool.typeOf(val)); |
| 409 | const decl_ptr_ty_id = try cg.ptrType(ty, cg.module.storageClass(.generic), .indirect); | 433 | const ty_id = try cg.resolveType(ty, .indirect); |
| | 434 | const decl_ptr_ty_id = try cg.module.ptrType(ty_id, cg.module.storageClass(.generic)); |
| 410 | | 435 | |
| 411 | const spv_decl_index = blk: { | 436 | const spv_decl_index = blk: { |
| 412 | const entry = try cg.module.uav_link.getOrPut(cg.module.gpa, .{ val, .function }); | 437 | const entry = try cg.module.uav_link.getOrPut(cg.module.gpa, .{ val, .function }); |
| ... | @@ -454,7 +479,8 @@ fn resolveUav(cg: *CodeGen, val: InternPool.Index) !Id { | ... | @@ -454,7 +479,8 @@ fn resolveUav(cg: *CodeGen, val: InternPool.Index) !Id { |
| 454 | cg.decl_deps.deinit(gpa); | 479 | cg.decl_deps.deinit(gpa); |
| 455 | } | 480 | } |
| 456 | | 481 | |
| 457 | const initializer_proto_ty_id = try cg.functionType(.void, &.{}); | 482 | const void_ty_id = try cg.resolveType(.void, .direct); |
| | 483 | const initializer_proto_ty_id = try cg.module.functionType(void_ty_id, &.{}); |
| 458 | | 484 | |
| 459 | const initializer_id = cg.module.allocId(); | 485 | const initializer_id = cg.module.allocId(); |
| 460 | try cg.prologue.emit(cg.module.gpa, .OpFunction, .{ | 486 | try cg.prologue.emit(cg.module.gpa, .OpFunction, .{ |
| ... | @@ -469,7 +495,7 @@ fn resolveUav(cg: *CodeGen, val: InternPool.Index) !Id { | ... | @@ -469,7 +495,7 @@ fn resolveUav(cg: *CodeGen, val: InternPool.Index) !Id { |
| 469 | }); | 495 | }); |
| 470 | cg.block_label = root_block_id; | 496 | cg.block_label = root_block_id; |
| 471 | | 497 | |
| 472 | const val_id = try cg.constant(ty, Value.fromInterned(val), .indirect); | 498 | const val_id = try cg.constant(ty, .fromInterned(val), .indirect); |
| 473 | try cg.body.emit(cg.module.gpa, .OpStore, .{ | 499 | try cg.body.emit(cg.module.gpa, .OpStore, .{ |
| 474 | .pointer = result_id, | 500 | .pointer = result_id, |
| 475 | .object = val_id, | 501 | .object = val_id, |
| ... | @@ -484,7 +510,7 @@ fn resolveUav(cg: *CodeGen, val: InternPool.Index) !Id { | ... | @@ -484,7 +510,7 @@ fn resolveUav(cg: *CodeGen, val: InternPool.Index) !Id { |
| 484 | | 510 | |
| 485 | try cg.module.debugNameFmt(initializer_id, "initializer of __anon_{d}", .{@intFromEnum(val)}); | 511 | try cg.module.debugNameFmt(initializer_id, "initializer of __anon_{d}", .{@intFromEnum(val)}); |
| 486 | | 512 | |
| 487 | const fn_decl_ptr_ty_id = try cg.ptrType(ty, .function, .indirect); | 513 | const fn_decl_ptr_ty_id = try cg.module.ptrType(ty_id, .function); |
| 488 | try cg.module.sections.globals.emit(cg.module.gpa, .OpExtInst, .{ | 514 | try cg.module.sections.globals.emit(cg.module.gpa, .OpExtInst, .{ |
| 489 | .id_result_type = fn_decl_ptr_ty_id, | 515 | .id_result_type = fn_decl_ptr_ty_id, |
| 490 | .id_result = result_id, | 516 | .id_result = result_id, |
| ... | @@ -533,44 +559,6 @@ fn beginSpvBlock(cg: *CodeGen, label: Id) !void { | ... | @@ -533,44 +559,6 @@ fn beginSpvBlock(cg: *CodeGen, label: Id) !void { |
| 533 | cg.block_label = label; | 559 | cg.block_label = label; |
| 534 | } | 560 | } |
| 535 | | 561 | |
| 536 | /// SPIR-V requires enabling specific integer sizes through capabilities, and so if they are not enabled, we need | | |
| 537 | /// to emulate them in other instructions/types. This function returns, given an integer bit width (signed or unsigned, sign | | |
| 538 | /// included), the width of the underlying type which represents it, given the enabled features for the current target. | | |
| 539 | /// If the result is `null`, the largest type the target platform supports natively is not able to perform computations using | | |
| 540 | /// that size. In this case, multiple elements of the largest type should be used. | | |
| 541 | /// The backing type will be chosen as the smallest supported integer larger or equal to it in number of bits. | | |
| 542 | /// The result is valid to be used with OpTypeInt. | | |
| 543 | /// TODO: Should the result of this function be cached? | | |
| 544 | fn backingIntBits(cg: *CodeGen, bits: u16) struct { u16, bool } { | | |
| 545 | const target = cg.module.zcu.getTarget(); | | |
| 546 | | | |
| 547 | // The backend will never be asked to compiler a 0-bit integer, so we won't have to handle those in this function. | | |
| 548 | assert(bits != 0); | | |
| 549 | | | |
| 550 | if (target.cpu.has(.spirv, .arbitrary_precision_integers) and bits <= 32) { | | |
| 551 | return .{ bits, false }; | | |
| 552 | } | | |
| 553 | | | |
| 554 | // We require Int8 and Int16 capabilities and benefit Int64 when available. | | |
| 555 | // 32-bit integers are always supported (see spec, 2.16.1, Data rules). | | |
| 556 | const ints = [_]struct { bits: u16, enabled: bool }{ | | |
| 557 | .{ .bits = 8, .enabled = true }, | | |
| 558 | .{ .bits = 16, .enabled = true }, | | |
| 559 | .{ .bits = 32, .enabled = true }, | | |
| 560 | .{ | | |
| 561 | .bits = 64, | | |
| 562 | .enabled = target.cpu.has(.spirv, .int64) or target.cpu.arch == .spirv64, | | |
| 563 | }, | | |
| 564 | }; | | |
| 565 | | | |
| 566 | for (ints) |int| { | | |
| 567 | if (bits <= int.bits and int.enabled) return .{ int.bits, false }; | | |
| 568 | } | | |
| 569 | | | |
| 570 | // Big int | | |
| 571 | return .{ std.mem.alignForward(u16, bits, big_int_bits), true }; | | |
| 572 | } | | |
| 573 | | | |
| 574 | /// Return the amount of bits in the largest supported integer type. This is either 32 (always supported), or 64 (if | 562 | /// Return the amount of bits in the largest supported integer type. This is either 32 (always supported), or 64 (if |
| 575 | /// the Int64 capability is enabled). | 563 | /// the Int64 capability is enabled). |
| 576 | /// Note: The extension SPV_INTEL_arbitrary_precision_integers allows any integer size (at least up to 32 bits). | 564 | /// Note: The extension SPV_INTEL_arbitrary_precision_integers allows any integer size (at least up to 32 bits). |
| ... | @@ -632,7 +620,7 @@ fn arithmeticTypeInfo(cg: *CodeGen, ty: Type) ArithmeticTypeInfo { | ... | @@ -632,7 +620,7 @@ fn arithmeticTypeInfo(cg: *CodeGen, ty: Type) ArithmeticTypeInfo { |
| 632 | return switch (scalar_ty.zigTypeTag(zcu)) { | 620 | return switch (scalar_ty.zigTypeTag(zcu)) { |
| 633 | .bool => .{ | 621 | .bool => .{ |
| 634 | .bits = 1, // Doesn't matter for this class. | 622 | .bits = 1, // Doesn't matter for this class. |
| 635 | .backing_bits = cg.backingIntBits(1).@"0", | 623 | .backing_bits = cg.module.backingIntBits(1).@"0", |
| 636 | .vector_len = vector_len, | 624 | .vector_len = vector_len, |
| 637 | .signedness = .unsigned, // Technically, but doesn't matter for this class. | 625 | .signedness = .unsigned, // Technically, but doesn't matter for this class. |
| 638 | .class = .bool, | 626 | .class = .bool, |
| ... | @@ -647,7 +635,7 @@ fn arithmeticTypeInfo(cg: *CodeGen, ty: Type) ArithmeticTypeInfo { | ... | @@ -647,7 +635,7 @@ fn arithmeticTypeInfo(cg: *CodeGen, ty: Type) ArithmeticTypeInfo { |
| 647 | .int => blk: { | 635 | .int => blk: { |
| 648 | const int_info = scalar_ty.intInfo(zcu); | 636 | const int_info = scalar_ty.intInfo(zcu); |
| 649 | // TODO: Maybe it's useful to also return this value. | 637 | // TODO: Maybe it's useful to also return this value. |
| 650 | const backing_bits, const big_int = cg.backingIntBits(int_info.bits); | 638 | const backing_bits, const big_int = cg.module.backingIntBits(int_info.bits); |
| 651 | break :blk .{ | 639 | break :blk .{ |
| 652 | .bits = int_info.bits, | 640 | .bits = int_info.bits, |
| 653 | .backing_bits = backing_bits, | 641 | .backing_bits = backing_bits, |
| ... | @@ -711,7 +699,7 @@ fn constInt(cg: *CodeGen, ty: Type, value: anytype) !Id { | ... | @@ -711,7 +699,7 @@ fn constInt(cg: *CodeGen, ty: Type, value: anytype) !Id { |
| 711 | const scalar_ty = ty.scalarType(zcu); | 699 | const scalar_ty = ty.scalarType(zcu); |
| 712 | const int_info = scalar_ty.intInfo(zcu); | 700 | const int_info = scalar_ty.intInfo(zcu); |
| 713 | // Use backing bits so that negatives are sign extended | 701 | // Use backing bits so that negatives are sign extended |
| 714 | const backing_bits, const big_int = cg.backingIntBits(int_info.bits); | 702 | const backing_bits, const big_int = cg.module.backingIntBits(int_info.bits); |
| 715 | assert(backing_bits != 0); // u0 is comptime | 703 | assert(backing_bits != 0); // u0 is comptime |
| 716 | | 704 | |
| 717 | const result_ty_id = try cg.resolveType(scalar_ty, .indirect); | 705 | const result_ty_id = try cg.resolveType(scalar_ty, .indirect); |
| ... | @@ -922,8 +910,8 @@ fn constant(cg: *CodeGen, ty: Type, val: Value, repr: Repr) Error!Id { | ... | @@ -922,8 +910,8 @@ fn constant(cg: *CodeGen, ty: Type, val: Value, repr: Repr) Error!Id { |
| 922 | }, | 910 | }, |
| 923 | .ptr => return cg.constantPtr(val), | 911 | .ptr => return cg.constantPtr(val), |
| 924 | .slice => |slice| { | 912 | .slice => |slice| { |
| 925 | const ptr_id = try cg.constantPtr(Value.fromInterned(slice.ptr)); | 913 | const ptr_id = try cg.constantPtr(.fromInterned(slice.ptr)); |
| 926 | const len_id = try cg.constant(.usize, Value.fromInterned(slice.len), .indirect); | 914 | const len_id = try cg.constant(.usize, .fromInterned(slice.len), .indirect); |
| 927 | const comp_ty_id = try cg.resolveType(ty, .direct); | 915 | const comp_ty_id = try cg.resolveType(ty, .direct); |
| 928 | return try cg.constructComposite(comp_ty_id, &.{ ptr_id, len_id }); | 916 | return try cg.constructComposite(comp_ty_id, &.{ ptr_id, len_id }); |
| 929 | }, | 917 | }, |
| ... | @@ -977,11 +965,11 @@ fn constant(cg: *CodeGen, ty: Type, val: Value, repr: Repr) Error!Id { | ... | @@ -977,11 +965,11 @@ fn constant(cg: *CodeGen, ty: Type, val: Value, repr: Repr) Error!Id { |
| 977 | }, | 965 | }, |
| 978 | .elems => |elems| { | 966 | .elems => |elems| { |
| 979 | for (constituents, elems) |*constituent, elem| { | 967 | for (constituents, elems) |*constituent, elem| { |
| 980 | constituent.* = try cg.constant(elem_ty, Value.fromInterned(elem), child_repr); | 968 | constituent.* = try cg.constant(elem_ty, .fromInterned(elem), child_repr); |
| 981 | } | 969 | } |
| 982 | }, | 970 | }, |
| 983 | .repeated_elem => |elem| { | 971 | .repeated_elem => |elem| { |
| 984 | @memset(constituents, try cg.constant(elem_ty, Value.fromInterned(elem), child_repr)); | 972 | @memset(constituents, try cg.constant(elem_ty, .fromInterned(elem), child_repr)); |
| 985 | }, | 973 | }, |
| 986 | } | 974 | } |
| 987 | | 975 | |
| ... | @@ -995,7 +983,7 @@ fn constant(cg: *CodeGen, ty: Type, val: Value, repr: Repr) Error!Id { | ... | @@ -995,7 +983,7 @@ fn constant(cg: *CodeGen, ty: Type, val: Value, repr: Repr) Error!Id { |
| 995 | // TODO: composite int | 983 | // TODO: composite int |
| 996 | // TODO: endianness | 984 | // TODO: endianness |
| 997 | const bits: u16 = @intCast(ty.bitSize(zcu)); | 985 | const bits: u16 = @intCast(ty.bitSize(zcu)); |
| 998 | const bytes = std.mem.alignForward(u16, cg.backingIntBits(bits).@"0", 8) / 8; | 986 | const bytes = std.mem.alignForward(u16, cg.module.backingIntBits(bits).@"0", 8) / 8; |
| 999 | var limbs: [8]u8 = undefined; | 987 | var limbs: [8]u8 = undefined; |
| 1000 | @memset(&limbs, 0); | 988 | @memset(&limbs, 0); |
| 1001 | val.writeToPackedMemory(ty, pt, limbs[0..bytes], 0) catch unreachable; | 989 | val.writeToPackedMemory(ty, pt, limbs[0..bytes], 0) catch unreachable; |
| ... | @@ -1035,13 +1023,13 @@ fn constant(cg: *CodeGen, ty: Type, val: Value, repr: Repr) Error!Id { | ... | @@ -1035,13 +1023,13 @@ fn constant(cg: *CodeGen, ty: Type, val: Value, repr: Repr) Error!Id { |
| 1035 | if (un.tag == .none) { | 1023 | if (un.tag == .none) { |
| 1036 | assert(ty.containerLayout(zcu) == .@"packed"); // TODO | 1024 | assert(ty.containerLayout(zcu) == .@"packed"); // TODO |
| 1037 | const int_ty = try pt.intType(.unsigned, @intCast(ty.bitSize(zcu))); | 1025 | const int_ty = try pt.intType(.unsigned, @intCast(ty.bitSize(zcu))); |
| 1038 | return try cg.constant(int_ty, Value.fromInterned(un.val), .direct); | 1026 | return try cg.constInt(int_ty, Value.toUnsignedInt(.fromInterned(un.val), zcu)); |
| 1039 | } | 1027 | } |
| 1040 | const active_field = ty.unionTagFieldIndex(Value.fromInterned(un.tag), zcu).?; | 1028 | const active_field = ty.unionTagFieldIndex(.fromInterned(un.tag), zcu).?; |
| 1041 | const union_obj = zcu.typeToUnion(ty).?; | 1029 | const union_obj = zcu.typeToUnion(ty).?; |
| 1042 | const field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[active_field]); | 1030 | const field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[active_field]); |
| 1043 | const payload = if (field_ty.hasRuntimeBitsIgnoreComptime(zcu)) | 1031 | const payload = if (field_ty.hasRuntimeBitsIgnoreComptime(zcu)) |
| 1044 | try cg.constant(field_ty, Value.fromInterned(un.val), .direct) | 1032 | try cg.constant(field_ty, .fromInterned(un.val), .direct) |
| 1045 | else | 1033 | else |
| 1046 | null; | 1034 | null; |
| 1047 | return try cg.unionInit(ty, active_field, payload); | 1035 | return try cg.unionInit(ty, active_field, payload); |
| ... | @@ -1084,10 +1072,11 @@ fn derivePtr(cg: *CodeGen, derivation: Value.PointerDeriveStep) !Id { | ... | @@ -1084,10 +1072,11 @@ fn derivePtr(cg: *CodeGen, derivation: Value.PointerDeriveStep) !Id { |
| 1084 | // that is not implemented by Mesa yet. Therefore, just generate it | 1072 | // that is not implemented by Mesa yet. Therefore, just generate it |
| 1085 | // as a runtime operation. | 1073 | // as a runtime operation. |
| 1086 | const result_ptr_id = cg.module.allocId(); | 1074 | const result_ptr_id = cg.module.allocId(); |
| | 1075 | const value_id = try cg.constInt(.usize, int.addr); |
| 1087 | try cg.body.emit(cg.module.gpa, .OpConvertUToPtr, .{ | 1076 | try cg.body.emit(cg.module.gpa, .OpConvertUToPtr, .{ |
| 1088 | .id_result_type = result_ty_id, | 1077 | .id_result_type = result_ty_id, |
| 1089 | .id_result = result_ptr_id, | 1078 | .id_result = result_ptr_id, |
| 1090 | .integer_value = try cg.constant(.usize, try pt.intValue(.usize, int.addr), .direct), | 1079 | .integer_value = value_id, |
| 1091 | }); | 1080 | }); |
| 1092 | return result_ptr_id; | 1081 | return result_ptr_id; |
| 1093 | }, | 1082 | }, |
| ... | @@ -1174,7 +1163,8 @@ fn constantUavRef( | ... | @@ -1174,7 +1163,8 @@ fn constantUavRef( |
| 1174 | | 1163 | |
| 1175 | // Uav refs are always generic. | 1164 | // Uav refs are always generic. |
| 1176 | assert(ty.ptrAddressSpace(zcu) == .generic); | 1165 | assert(ty.ptrAddressSpace(zcu) == .generic); |
| 1177 | const decl_ptr_ty_id = try cg.ptrType(uav_ty, .generic, .indirect); | 1166 | const uav_ty_id = try cg.resolveType(uav_ty, .indirect); |
| | 1167 | const decl_ptr_ty_id = try cg.module.ptrType(uav_ty_id, .generic); |
| 1178 | const ptr_id = try cg.resolveUav(uav.val); | 1168 | const ptr_id = try cg.resolveUav(uav.val); |
| 1179 | | 1169 | |
| 1180 | if (decl_ptr_ty_id != ty_id) { | 1170 | if (decl_ptr_ty_id != ty_id) { |
| ... | @@ -1228,7 +1218,8 @@ fn constantNavRef(cg: *CodeGen, ty: Type, nav_index: InternPool.Nav.Index) !Id { | ... | @@ -1228,7 +1218,8 @@ fn constantNavRef(cg: *CodeGen, ty: Type, nav_index: InternPool.Nav.Index) !Id { |
| 1228 | const storage_class = cg.module.storageClass(nav.getAddrspace()); | 1218 | const storage_class = cg.module.storageClass(nav.getAddrspace()); |
| 1229 | try cg.addFunctionDep(spv_decl_index, storage_class); | 1219 | try cg.addFunctionDep(spv_decl_index, storage_class); |
| 1230 | | 1220 | |
| 1231 | const decl_ptr_ty_id = try cg.ptrType(nav_ty, storage_class, .indirect); | 1221 | const nav_ty_id = try cg.resolveType(nav_ty, .indirect); |
| | 1222 | const decl_ptr_ty_id = try cg.module.ptrType(nav_ty_id, storage_class); |
| 1232 | | 1223 | |
| 1233 | const ptr_id = switch (storage_class) { | 1224 | const ptr_id = switch (storage_class) { |
| 1234 | .generic => try cg.castToGeneric(decl_ptr_ty_id, decl_id), | 1225 | .generic => try cg.castToGeneric(decl_ptr_ty_id, decl_id), |
| ... | @@ -1260,104 +1251,6 @@ fn resolveTypeName(cg: *CodeGen, ty: Type) ![]const u8 { | ... | @@ -1260,104 +1251,6 @@ fn resolveTypeName(cg: *CodeGen, ty: Type) ![]const u8 { |
| 1260 | return try aw.toOwnedSlice(); | 1251 | return try aw.toOwnedSlice(); |
| 1261 | } | 1252 | } |
| 1262 | | 1253 | |
| 1263 | /// Create an integer type suitable for storing at least 'bits' bits. | | |
| 1264 | /// The integer type that is returned by this function is the type that is used to perform | | |
| 1265 | /// actual operations (as well as store) a Zig type of a particular number of bits. To create | | |
| 1266 | /// a type with an exact size, use Module.intType. | | |
| 1267 | fn intType(cg: *CodeGen, signedness: std.builtin.Signedness, bits: u16) !Id { | | |
| 1268 | const target = cg.module.zcu.getTarget(); | | |
| 1269 | | | |
| 1270 | const backing_bits, const big_int = cg.backingIntBits(bits); | | |
| 1271 | if (big_int) { | | |
| 1272 | if (backing_bits > 64) { | | |
| 1273 | return cg.fail("composite integers larger than 64bit aren't supported", .{}); | | |
| 1274 | } | | |
| 1275 | const int_ty = try cg.resolveType(.u32, .direct); | | |
| 1276 | return cg.arrayType(backing_bits / big_int_bits, int_ty); | | |
| 1277 | } | | |
| 1278 | | | |
| 1279 | return switch (target.os.tag) { | | |
| 1280 | // Kernel only supports unsigned ints. | | |
| 1281 | .opencl, .amdhsa => return cg.module.intType(.unsigned, backing_bits), | | |
| 1282 | else => cg.module.intType(signedness, backing_bits), | | |
| 1283 | }; | | |
| 1284 | } | | |
| 1285 | | | |
| 1286 | fn arrayType(cg: *CodeGen, len: u32, child_ty: Id) !Id { | | |
| 1287 | const len_id = try cg.constInt(.u32, len); | | |
| 1288 | return cg.module.arrayType(len_id, child_ty); | | |
| 1289 | } | | |
| 1290 | | | |
| 1291 | fn ptrType(cg: *CodeGen, child_ty: Type, storage_class: StorageClass, child_repr: Repr) !Id { | | |
| 1292 | const gpa = cg.module.gpa; | | |
| 1293 | const zcu = cg.module.zcu; | | |
| 1294 | const ip = &zcu.intern_pool; | | |
| 1295 | const target = cg.module.zcu.getTarget(); | | |
| 1296 | | | |
| 1297 | const child_ty_id = try cg.resolveType(child_ty, child_repr); | | |
| 1298 | const key = .{ child_ty_id, storage_class }; | | |
| 1299 | const entry = try cg.module.ptr_types.getOrPut(gpa, key); | | |
| 1300 | if (entry.found_existing) { | | |
| 1301 | const fwd_id = entry.value_ptr.ty_id; | | |
| 1302 | if (!entry.value_ptr.fwd_emitted) { | | |
| 1303 | try cg.module.sections.globals.emit(cg.module.gpa, .OpTypeForwardPointer, .{ | | |
| 1304 | .pointer_type = fwd_id, | | |
| 1305 | .storage_class = storage_class, | | |
| 1306 | }); | | |
| 1307 | entry.value_ptr.fwd_emitted = true; | | |
| 1308 | } | | |
| 1309 | return fwd_id; | | |
| 1310 | } | | |
| 1311 | | | |
| 1312 | const result_id = cg.module.allocId(); | | |
| 1313 | entry.value_ptr.* = .{ | | |
| 1314 | .ty_id = result_id, | | |
| 1315 | .fwd_emitted = false, | | |
| 1316 | }; | | |
| 1317 | | | |
| 1318 | switch (target.os.tag) { | | |
| 1319 | .vulkan, .opengl => { | | |
| 1320 | if (child_ty.zigTypeTag(zcu) == .@"struct") { | | |
| 1321 | switch (storage_class) { | | |
| 1322 | .uniform, .push_constant => try cg.module.decorate(child_ty_id, .block), | | |
| 1323 | else => {}, | | |
| 1324 | } | | |
| 1325 | } | | |
| 1326 | | | |
| 1327 | switch (ip.indexToKey(child_ty.toIntern())) { | | |
| 1328 | .func_type, .opaque_type => {}, | | |
| 1329 | else => { | | |
| 1330 | try cg.module.decorate(result_id, .{ .array_stride = .{ .array_stride = @intCast(child_ty.abiSize(zcu)) } }); | | |
| 1331 | }, | | |
| 1332 | } | | |
| 1333 | }, | | |
| 1334 | else => {}, | | |
| 1335 | } | | |
| 1336 | | | |
| 1337 | try cg.module.sections.globals.emit(cg.module.gpa, .OpTypePointer, .{ | | |
| 1338 | .id_result = result_id, | | |
| 1339 | .storage_class = storage_class, | | |
| 1340 | .type = child_ty_id, | | |
| 1341 | }); | | |
| 1342 | | | |
| 1343 | cg.module.ptr_types.getPtr(key).?.fwd_emitted = true; | | |
| 1344 | | | |
| 1345 | return result_id; | | |
| 1346 | } | | |
| 1347 | | | |
| 1348 | fn functionType(cg: *CodeGen, return_ty: Type, param_types: []const Type) !Id { | | |
| 1349 | const gpa = cg.module.gpa; | | |
| 1350 | const return_ty_id = try cg.resolveFnReturnType(return_ty); | | |
| 1351 | const param_ids = try gpa.alloc(Id, param_types.len); | | |
| 1352 | defer gpa.free(param_ids); | | |
| 1353 | | | |
| 1354 | for (param_types, param_ids) |param_ty, *param_id| { | | |
| 1355 | param_id.* = try cg.resolveType(param_ty, .direct); | | |
| 1356 | } | | |
| 1357 | | | |
| 1358 | return cg.module.functionType(return_ty_id, param_ids); | | |
| 1359 | } | | |
| 1360 | | | |
| 1361 | /// Generate a union type. Union types are always generated with the | 1254 | /// Generate a union type. Union types are always generated with the |
| 1362 | /// most aligned field active. If the tag alignment is greater | 1255 | /// most aligned field active. If the tag alignment is greater |
| 1363 | /// than that of the payload, a regular union (non-packed, with both tag and | 1256 | /// than that of the payload, a regular union (non-packed, with both tag and |
| ... | @@ -1383,7 +1276,7 @@ fn resolveUnionType(cg: *CodeGen, ty: Type) !Id { | ... | @@ -1383,7 +1276,7 @@ fn resolveUnionType(cg: *CodeGen, ty: Type) !Id { |
| 1383 | const union_obj = zcu.typeToUnion(ty).?; | 1276 | const union_obj = zcu.typeToUnion(ty).?; |
| 1384 | | 1277 | |
| 1385 | if (union_obj.flagsUnordered(ip).layout == .@"packed") { | 1278 | if (union_obj.flagsUnordered(ip).layout == .@"packed") { |
| 1386 | return try cg.intType(.unsigned, @intCast(ty.bitSize(zcu))); | 1279 | return try cg.module.intType(.unsigned, @intCast(ty.bitSize(zcu))); |
| 1387 | } | 1280 | } |
| 1388 | | 1281 | |
| 1389 | const layout = cg.unionLayout(ty); | 1282 | const layout = cg.unionLayout(ty); |
| ... | @@ -1410,13 +1303,15 @@ fn resolveUnionType(cg: *CodeGen, ty: Type) !Id { | ... | @@ -1410,13 +1303,15 @@ fn resolveUnionType(cg: *CodeGen, ty: Type) !Id { |
| 1410 | } | 1303 | } |
| 1411 | | 1304 | |
| 1412 | if (layout.payload_padding_size != 0) { | 1305 | if (layout.payload_padding_size != 0) { |
| 1413 | const payload_padding_ty_id = try cg.arrayType(@intCast(layout.payload_padding_size), u8_ty_id); | 1306 | const len_id = try cg.constInt(.u32, layout.payload_padding_size); |
| | 1307 | const payload_padding_ty_id = try cg.module.arrayType(len_id, u8_ty_id); |
| 1414 | member_types[layout.payload_padding_index] = payload_padding_ty_id; | 1308 | member_types[layout.payload_padding_index] = payload_padding_ty_id; |
| 1415 | member_names[layout.payload_padding_index] = "(payload padding)"; | 1309 | member_names[layout.payload_padding_index] = "(payload padding)"; |
| 1416 | } | 1310 | } |
| 1417 | | 1311 | |
| 1418 | if (layout.padding_size != 0) { | 1312 | if (layout.padding_size != 0) { |
| 1419 | const padding_ty_id = try cg.arrayType(@intCast(layout.padding_size), u8_ty_id); | 1313 | const len_id = try cg.constInt(.u32, layout.padding_size); |
| | 1314 | const padding_ty_id = try cg.module.arrayType(len_id, u8_ty_id); |
| 1420 | member_types[layout.padding_index] = padding_ty_id; | 1315 | member_types[layout.padding_index] = padding_ty_id; |
| 1421 | member_names[layout.padding_index] = "(padding)"; | 1316 | member_names[layout.padding_index] = "(padding)"; |
| 1422 | } | 1317 | } |
| ... | @@ -1479,7 +1374,7 @@ fn resolveType(cg: *CodeGen, ty: Type, repr: Repr) Error!Id { | ... | @@ -1479,7 +1374,7 @@ fn resolveType(cg: *CodeGen, ty: Type, repr: Repr) Error!Id { |
| 1479 | assert(repr == .indirect); | 1374 | assert(repr == .indirect); |
| 1480 | return try cg.module.opaqueType("u0"); | 1375 | return try cg.module.opaqueType("u0"); |
| 1481 | } | 1376 | } |
| 1482 | return try cg.intType(int_info.signedness, int_info.bits); | 1377 | return try cg.module.intType(int_info.signedness, int_info.bits); |
| 1483 | }, | 1378 | }, |
| 1484 | .@"enum" => return try cg.resolveType(ty.intTagType(zcu), repr), | 1379 | .@"enum" => return try cg.resolveType(ty.intTagType(zcu), repr), |
| 1485 | .float => { | 1380 | .float => { |
| ... | @@ -1519,9 +1414,11 @@ fn resolveType(cg: *CodeGen, ty: Type, repr: Repr) Error!Id { | ... | @@ -1519,9 +1414,11 @@ fn resolveType(cg: *CodeGen, ty: Type, repr: Repr) Error!Id { |
| 1519 | // In this case, we have an array of a non-zero sized type. In this case, | 1414 | // In this case, we have an array of a non-zero sized type. In this case, |
| 1520 | // generate an array of 1 element instead, so that ptr_elem_ptr instructions | 1415 | // generate an array of 1 element instead, so that ptr_elem_ptr instructions |
| 1521 | // can be lowered to ptrAccessChain instead of manually performing the math. | 1416 | // can be lowered to ptrAccessChain instead of manually performing the math. |
| 1522 | return try cg.arrayType(1, elem_ty_id); | 1417 | const len_id = try cg.constInt(.u32, 1); |
| | 1418 | return try cg.module.arrayType(len_id, elem_ty_id); |
| 1523 | } else { | 1419 | } else { |
| 1524 | const result_id = try cg.arrayType(total_len, elem_ty_id); | 1420 | const total_len_id = try cg.constInt(.u32, total_len); |
| | 1421 | const result_id = try cg.module.arrayType(total_len_id, elem_ty_id); |
| 1525 | switch (target.os.tag) { | 1422 | switch (target.os.tag) { |
| 1526 | .vulkan, .opengl => { | 1423 | .vulkan, .opengl => { |
| 1527 | try cg.module.decorate(result_id, .{ | 1424 | try cg.module.decorate(result_id, .{ |
| ... | @@ -1540,7 +1437,8 @@ fn resolveType(cg: *CodeGen, ty: Type, repr: Repr) Error!Id { | ... | @@ -1540,7 +1437,8 @@ fn resolveType(cg: *CodeGen, ty: Type, repr: Repr) Error!Id { |
| 1540 | const elem_ty_id = try cg.resolveType(elem_ty, repr); | 1437 | const elem_ty_id = try cg.resolveType(elem_ty, repr); |
| 1541 | const len = ty.vectorLen(zcu); | 1438 | const len = ty.vectorLen(zcu); |
| 1542 | if (cg.isSpvVector(ty)) return try cg.module.vectorType(len, elem_ty_id); | 1439 | if (cg.isSpvVector(ty)) return try cg.module.vectorType(len, elem_ty_id); |
| 1543 | return try cg.arrayType(len, elem_ty_id); | 1440 | const len_id = try cg.constInt(.u32, len); |
| | 1441 | return try cg.module.arrayType(len_id, elem_ty_id); |
| 1544 | }, | 1442 | }, |
| 1545 | .@"fn" => switch (repr) { | 1443 | .@"fn" => switch (repr) { |
| 1546 | .direct => { | 1444 | .direct => { |
| ... | @@ -1582,8 +1480,9 @@ fn resolveType(cg: *CodeGen, ty: Type, repr: Repr) Error!Id { | ... | @@ -1582,8 +1480,9 @@ fn resolveType(cg: *CodeGen, ty: Type, repr: Repr) Error!Id { |
| 1582 | const ptr_info = ty.ptrInfo(zcu); | 1480 | const ptr_info = ty.ptrInfo(zcu); |
| 1583 | | 1481 | |
| 1584 | const child_ty: Type = .fromInterned(ptr_info.child); | 1482 | const child_ty: Type = .fromInterned(ptr_info.child); |
| | 1483 | const child_ty_id = try cg.resolveType(child_ty, .indirect); |
| 1585 | const storage_class = cg.module.storageClass(ptr_info.flags.address_space); | 1484 | const storage_class = cg.module.storageClass(ptr_info.flags.address_space); |
| 1586 | const ptr_ty_id = try cg.ptrType(child_ty, storage_class, .indirect); | 1485 | const ptr_ty_id = try cg.module.ptrType(child_ty_id, storage_class); |
| 1587 | | 1486 | |
| 1588 | if (ptr_info.flags.size != .slice) { | 1487 | if (ptr_info.flags.size != .slice) { |
| 1589 | return ptr_ty_id; | 1488 | return ptr_ty_id; |
| ... | @@ -2142,7 +2041,7 @@ fn buildConvert(cg: *CodeGen, dst_ty: Type, src: Temporary) !Temporary { | ... | @@ -2142,7 +2041,7 @@ fn buildConvert(cg: *CodeGen, dst_ty: Type, src: Temporary) !Temporary { |
| 2142 | | 2041 | |
| 2143 | for (0..ops) |i| { | 2042 | for (0..ops) |i| { |
| 2144 | try cg.body.emitRaw(cg.module.gpa, opcode, 3); | 2043 | try cg.body.emitRaw(cg.module.gpa, opcode, 3); |
| 2145 | cg.body.writeOperand(spec.Id, op_result_ty_id); | 2044 | cg.body.writeOperand(Id, op_result_ty_id); |
| 2146 | cg.body.writeOperand(Id, results.at(i)); | 2045 | cg.body.writeOperand(Id, results.at(i)); |
| 2147 | cg.body.writeOperand(Id, op_src.at(i)); | 2046 | cg.body.writeOperand(Id, op_src.at(i)); |
| 2148 | } | 2047 | } |
| ... | @@ -2277,7 +2176,7 @@ fn buildCmp(cg: *CodeGen, pred: CmpPredicate, lhs: Temporary, rhs: Temporary) !T | ... | @@ -2277,7 +2176,7 @@ fn buildCmp(cg: *CodeGen, pred: CmpPredicate, lhs: Temporary, rhs: Temporary) !T |
| 2277 | | 2176 | |
| 2278 | for (0..ops) |i| { | 2177 | for (0..ops) |i| { |
| 2279 | try cg.body.emitRaw(cg.module.gpa, opcode, 4); | 2178 | try cg.body.emitRaw(cg.module.gpa, opcode, 4); |
| 2280 | cg.body.writeOperand(spec.Id, op_result_ty_id); | 2179 | cg.body.writeOperand(Id, op_result_ty_id); |
| 2281 | cg.body.writeOperand(Id, results.at(i)); | 2180 | cg.body.writeOperand(Id, results.at(i)); |
| 2282 | cg.body.writeOperand(Id, op_lhs.at(i)); | 2181 | cg.body.writeOperand(Id, op_lhs.at(i)); |
| 2283 | cg.body.writeOperand(Id, op_rhs.at(i)); | 2182 | cg.body.writeOperand(Id, op_rhs.at(i)); |
| ... | @@ -2331,7 +2230,7 @@ fn buildUnary(cg: *CodeGen, op: UnaryOp, operand: Temporary) !Temporary { | ... | @@ -2331,7 +2230,7 @@ fn buildUnary(cg: *CodeGen, op: UnaryOp, operand: Temporary) !Temporary { |
| 2331 | }) |opcode| { | 2230 | }) |opcode| { |
| 2332 | for (0..ops) |i| { | 2231 | for (0..ops) |i| { |
| 2333 | try cg.body.emitRaw(cg.module.gpa, opcode, 3); | 2232 | try cg.body.emitRaw(cg.module.gpa, opcode, 3); |
| 2334 | cg.body.writeOperand(spec.Id, op_result_ty_id); | 2233 | cg.body.writeOperand(Id, op_result_ty_id); |
| 2335 | cg.body.writeOperand(Id, results.at(i)); | 2234 | cg.body.writeOperand(Id, results.at(i)); |
| 2336 | cg.body.writeOperand(Id, op_operand.at(i)); | 2235 | cg.body.writeOperand(Id, op_operand.at(i)); |
| 2337 | } | 2236 | } |
| ... | @@ -2472,7 +2371,7 @@ fn buildBinary(cg: *CodeGen, op: BinaryOp, lhs: Temporary, rhs: Temporary) !Temp | ... | @@ -2472,7 +2371,7 @@ fn buildBinary(cg: *CodeGen, op: BinaryOp, lhs: Temporary, rhs: Temporary) !Temp |
| 2472 | }) |opcode| { | 2371 | }) |opcode| { |
| 2473 | for (0..ops) |i| { | 2372 | for (0..ops) |i| { |
| 2474 | try cg.body.emitRaw(cg.module.gpa, opcode, 4); | 2373 | try cg.body.emitRaw(cg.module.gpa, opcode, 4); |
| 2475 | cg.body.writeOperand(spec.Id, op_result_ty_id); | 2374 | cg.body.writeOperand(Id, op_result_ty_id); |
| 2476 | cg.body.writeOperand(Id, results.at(i)); | 2375 | cg.body.writeOperand(Id, results.at(i)); |
| 2477 | cg.body.writeOperand(Id, op_lhs.at(i)); | 2376 | cg.body.writeOperand(Id, op_lhs.at(i)); |
| 2478 | cg.body.writeOperand(Id, op_rhs.at(i)); | 2377 | cg.body.writeOperand(Id, op_rhs.at(i)); |
| ... | @@ -2591,7 +2490,7 @@ fn buildWideMul( | ... | @@ -2591,7 +2490,7 @@ fn buildWideMul( |
| 2591 | const op_result = cg.module.allocId(); | 2490 | const op_result = cg.module.allocId(); |
| 2592 | | 2491 | |
| 2593 | try cg.body.emitRaw(cg.module.gpa, opcode, 4); | 2492 | try cg.body.emitRaw(cg.module.gpa, opcode, 4); |
| 2594 | cg.body.writeOperand(spec.Id, op_result_ty_id); | 2493 | cg.body.writeOperand(Id, op_result_ty_id); |
| 2595 | cg.body.writeOperand(Id, op_result); | 2494 | cg.body.writeOperand(Id, op_result); |
| 2596 | cg.body.writeOperand(Id, lhs_op.at(i)); | 2495 | cg.body.writeOperand(Id, lhs_op.at(i)); |
| 2597 | cg.body.writeOperand(Id, rhs_op.at(i)); | 2496 | cg.body.writeOperand(Id, rhs_op.at(i)); |
| ... | @@ -2664,30 +2563,27 @@ fn generateTestEntryPoint( | ... | @@ -2664,30 +2563,27 @@ fn generateTestEntryPoint( |
| 2664 | | 2563 | |
| 2665 | const kernel_id = cg.module.declPtr(spv_decl_index).result_id; | 2564 | const kernel_id = cg.module.declPtr(spv_decl_index).result_id; |
| 2666 | | 2565 | |
| 2667 | var decl_deps = std.ArrayList(Module.Decl.Index).init(gpa); | | |
| 2668 | defer decl_deps.deinit(); | | |
| 2669 | try decl_deps.append(spv_decl_index); | | |
| 2670 | | | |
| 2671 | const section = &cg.module.sections.functions; | 2566 | const section = &cg.module.sections.functions; |
| 2672 | | 2567 | |
| 2673 | const p_error_id = cg.module.allocId(); | 2568 | const p_error_id = cg.module.allocId(); |
| 2674 | switch (target.os.tag) { | 2569 | switch (target.os.tag) { |
| 2675 | .opencl, .amdhsa => { | 2570 | .opencl, .amdhsa => { |
| 2676 | const kernel_proto_ty_id = try cg.functionType(.void, &.{ptr_anyerror_ty}); | 2571 | const void_ty_id = try cg.resolveType(.void, .direct); |
| | 2572 | const kernel_proto_ty_id = try cg.module.functionType(void_ty_id, &.{ptr_anyerror_ty_id}); |
| 2677 | | 2573 | |
| 2678 | try section.emit(cg.module.gpa, .OpFunction, .{ | 2574 | try section.emit(gpa, .OpFunction, .{ |
| 2679 | .id_result_type = try cg.resolveType(.void, .direct), | 2575 | .id_result_type = try cg.resolveType(.void, .direct), |
| 2680 | .id_result = kernel_id, | 2576 | .id_result = kernel_id, |
| 2681 | .function_control = .{}, | 2577 | .function_control = .{}, |
| 2682 | .function_type = kernel_proto_ty_id, | 2578 | .function_type = kernel_proto_ty_id, |
| 2683 | }); | 2579 | }); |
| 2684 | | 2580 | |
| 2685 | try section.emit(cg.module.gpa, .OpFunctionParameter, .{ | 2581 | try section.emit(gpa, .OpFunctionParameter, .{ |
| 2686 | .id_result_type = ptr_anyerror_ty_id, | 2582 | .id_result_type = ptr_anyerror_ty_id, |
| 2687 | .id_result = p_error_id, | 2583 | .id_result = p_error_id, |
| 2688 | }); | 2584 | }); |
| 2689 | | 2585 | |
| 2690 | try section.emit(cg.module.gpa, .OpLabel, .{ | 2586 | try section.emit(gpa, .OpLabel, .{ |
| 2691 | .id_result = cg.module.allocId(), | 2587 | .id_result = cg.module.allocId(), |
| 2692 | }); | 2588 | }); |
| 2693 | }, | 2589 | }, |
| ... | @@ -2706,14 +2602,14 @@ fn generateTestEntryPoint( | ... | @@ -2706,14 +2602,14 @@ fn generateTestEntryPoint( |
| 2706 | try cg.module.decorateMember(buffer_struct_ty_id, 0, .{ .offset = .{ .byte_offset = 0 } }); | 2602 | try cg.module.decorateMember(buffer_struct_ty_id, 0, .{ .offset = .{ .byte_offset = 0 } }); |
| 2707 | | 2603 | |
| 2708 | const ptr_buffer_struct_ty_id = cg.module.allocId(); | 2604 | const ptr_buffer_struct_ty_id = cg.module.allocId(); |
| 2709 | try cg.module.sections.globals.emit(cg.module.gpa, .OpTypePointer, .{ | 2605 | try cg.module.sections.globals.emit(gpa, .OpTypePointer, .{ |
| 2710 | .id_result = ptr_buffer_struct_ty_id, | 2606 | .id_result = ptr_buffer_struct_ty_id, |
| 2711 | .storage_class = cg.module.storageClass(.global), | 2607 | .storage_class = cg.module.storageClass(.global), |
| 2712 | .type = buffer_struct_ty_id, | 2608 | .type = buffer_struct_ty_id, |
| 2713 | }); | 2609 | }); |
| 2714 | | 2610 | |
| 2715 | const buffer_struct_id = cg.module.declPtr(spv_err_decl_index).result_id; | 2611 | const buffer_struct_id = cg.module.declPtr(spv_err_decl_index).result_id; |
| 2716 | try cg.module.sections.globals.emit(cg.module.gpa, .OpVariable, .{ | 2612 | try cg.module.sections.globals.emit(gpa, .OpVariable, .{ |
| 2717 | .id_result_type = ptr_buffer_struct_ty_id, | 2613 | .id_result_type = ptr_buffer_struct_ty_id, |
| 2718 | .id_result = buffer_struct_id, | 2614 | .id_result = buffer_struct_id, |
| 2719 | .storage_class = cg.module.storageClass(.global), | 2615 | .storage_class = cg.module.storageClass(.global), |
| ... | @@ -2724,7 +2620,7 @@ fn generateTestEntryPoint( | ... | @@ -2724,7 +2620,7 @@ fn generateTestEntryPoint( |
| 2724 | cg.module.error_buffer = spv_err_decl_index; | 2620 | cg.module.error_buffer = spv_err_decl_index; |
| 2725 | } | 2621 | } |
| 2726 | | 2622 | |
| 2727 | try cg.module.sections.execution_modes.emit(cg.module.gpa, .OpExecutionMode, .{ | 2623 | try cg.module.sections.execution_modes.emit(gpa, .OpExecutionMode, .{ |
| 2728 | .entry_point = kernel_id, | 2624 | .entry_point = kernel_id, |
| 2729 | .mode = .{ .local_size = .{ | 2625 | .mode = .{ .local_size = .{ |
| 2730 | .x_size = 1, | 2626 | .x_size = 1, |
| ... | @@ -2733,23 +2629,24 @@ fn generateTestEntryPoint( | ... | @@ -2733,23 +2629,24 @@ fn generateTestEntryPoint( |
| 2733 | } }, | 2629 | } }, |
| 2734 | }); | 2630 | }); |
| 2735 | | 2631 | |
| 2736 | const kernel_proto_ty_id = try cg.functionType(.void, &.{}); | 2632 | const void_ty_id = try cg.resolveType(.void, .direct); |
| 2737 | try section.emit(cg.module.gpa, .OpFunction, .{ | 2633 | const kernel_proto_ty_id = try cg.module.functionType(void_ty_id, &.{}); |
| | 2634 | try section.emit(gpa, .OpFunction, .{ |
| 2738 | .id_result_type = try cg.resolveType(.void, .direct), | 2635 | .id_result_type = try cg.resolveType(.void, .direct), |
| 2739 | .id_result = kernel_id, | 2636 | .id_result = kernel_id, |
| 2740 | .function_control = .{}, | 2637 | .function_control = .{}, |
| 2741 | .function_type = kernel_proto_ty_id, | 2638 | .function_type = kernel_proto_ty_id, |
| 2742 | }); | 2639 | }); |
| 2743 | try section.emit(cg.module.gpa, .OpLabel, .{ | 2640 | try section.emit(gpa, .OpLabel, .{ |
| 2744 | .id_result = cg.module.allocId(), | 2641 | .id_result = cg.module.allocId(), |
| 2745 | }); | 2642 | }); |
| 2746 | | 2643 | |
| 2747 | const spv_err_decl_index = cg.module.error_buffer.?; | 2644 | const spv_err_decl_index = cg.module.error_buffer.?; |
| 2748 | const buffer_id = cg.module.declPtr(spv_err_decl_index).result_id; | 2645 | const buffer_id = cg.module.declPtr(spv_err_decl_index).result_id; |
| 2749 | try decl_deps.append(spv_err_decl_index); | 2646 | try cg.decl_deps.put(gpa, spv_err_decl_index, {}); |
| 2750 | | 2647 | |
| 2751 | const zero_id = try cg.constInt(.u32, 0); | 2648 | const zero_id = try cg.constInt(.u32, 0); |
| 2752 | try section.emit(cg.module.gpa, .OpInBoundsAccessChain, .{ | 2649 | try section.emit(gpa, .OpInBoundsAccessChain, .{ |
| 2753 | .id_result_type = ptr_anyerror_ty_id, | 2650 | .id_result_type = ptr_anyerror_ty_id, |
| 2754 | .id_result = p_error_id, | 2651 | .id_result = p_error_id, |
| 2755 | .base = buffer_id, | 2652 | .base = buffer_id, |
| ... | @@ -2760,25 +2657,25 @@ fn generateTestEntryPoint( | ... | @@ -2760,25 +2657,25 @@ fn generateTestEntryPoint( |
| 2760 | } | 2657 | } |
| 2761 | | 2658 | |
| 2762 | const error_id = cg.module.allocId(); | 2659 | const error_id = cg.module.allocId(); |
| 2763 | try section.emit(cg.module.gpa, .OpFunctionCall, .{ | 2660 | try section.emit(gpa, .OpFunctionCall, .{ |
| 2764 | .id_result_type = anyerror_ty_id, | 2661 | .id_result_type = anyerror_ty_id, |
| 2765 | .id_result = error_id, | 2662 | .id_result = error_id, |
| 2766 | .function = test_id, | 2663 | .function = test_id, |
| 2767 | }); | 2664 | }); |
| 2768 | // Note: Convert to direct not required. | 2665 | // Note: Convert to direct not required. |
| 2769 | try section.emit(cg.module.gpa, .OpStore, .{ | 2666 | try section.emit(gpa, .OpStore, .{ |
| 2770 | .pointer = p_error_id, | 2667 | .pointer = p_error_id, |
| 2771 | .object = error_id, | 2668 | .object = error_id, |
| 2772 | .memory_access = .{ | 2669 | .memory_access = .{ |
| 2773 | .aligned = .{ .literal_integer = @intCast(Type.abiAlignment(.anyerror, zcu).toByteUnits().?) }, | 2670 | .aligned = .{ .literal_integer = @intCast(Type.abiAlignment(.anyerror, zcu).toByteUnits().?) }, |
| 2774 | }, | 2671 | }, |
| 2775 | }); | 2672 | }); |
| 2776 | try section.emit(cg.module.gpa, .OpReturn, {}); | 2673 | try section.emit(gpa, .OpReturn, {}); |
| 2777 | try section.emit(cg.module.gpa, .OpFunctionEnd, {}); | 2674 | try section.emit(gpa, .OpFunctionEnd, {}); |
| 2778 | | 2675 | |
| 2779 | // Just generate a quick other name because the intel runtime crashes when the entry- | 2676 | // Just generate a quick other name because the intel runtime crashes when the entry- |
| 2780 | // point name is the same as a different OpName. | 2677 | // point name is the same as a different OpName. |
| 2781 | const test_name = try std.fmt.allocPrint(gpa, "test {s}", .{name}); | 2678 | const test_name = try std.fmt.allocPrint(cg.module.arena, "test {s}", .{name}); |
| 2782 | | 2679 | |
| 2783 | const execution_mode: spec.ExecutionModel = switch (target.os.tag) { | 2680 | const execution_mode: spec.ExecutionModel = switch (target.os.tag) { |
| 2784 | .vulkan, .opengl => .gl_compute, | 2681 | .vulkan, .opengl => .gl_compute, |
| ... | @@ -2786,7 +2683,6 @@ fn generateTestEntryPoint( | ... | @@ -2786,7 +2683,6 @@ fn generateTestEntryPoint( |
| 2786 | else => unreachable, | 2683 | else => unreachable, |
| 2787 | }; | 2684 | }; |
| 2788 | | 2685 | |
| 2789 | try cg.module.declareDeclDeps(spv_decl_index, decl_deps.items); | | |
| 2790 | try cg.module.declareEntryPoint(spv_decl_index, test_name, execution_mode, null); | 2686 | try cg.module.declareEntryPoint(spv_decl_index, test_name, execution_mode, null); |
| 2791 | } | 2687 | } |
| 2792 | | 2688 | |
| ... | @@ -3760,10 +3656,10 @@ fn airReduce(cg: *CodeGen, inst: Air.Inst.Index) !?Id { | ... | @@ -3760,10 +3656,10 @@ fn airReduce(cg: *CodeGen, inst: Air.Inst.Index) !?Id { |
| 3760 | result_id = cg.module.allocId(); | 3656 | result_id = cg.module.allocId(); |
| 3761 | | 3657 | |
| 3762 | try cg.body.emitRaw(cg.module.gpa, opcode, 4); | 3658 | try cg.body.emitRaw(cg.module.gpa, opcode, 4); |
| 3763 | cg.body.writeOperand(spec.Id, scalar_ty_id); | 3659 | cg.body.writeOperand(Id, scalar_ty_id); |
| 3764 | cg.body.writeOperand(spec.Id, result_id); | 3660 | cg.body.writeOperand(Id, result_id); |
| 3765 | cg.body.writeOperand(spec.Id, lhs); | 3661 | cg.body.writeOperand(Id, lhs); |
| 3766 | cg.body.writeOperand(spec.Id, rhs); | 3662 | cg.body.writeOperand(Id, rhs); |
| 3767 | } | 3663 | } |
| 3768 | | 3664 | |
| 3769 | return result_id; | 3665 | return result_id; |
| ... | @@ -4189,7 +4085,7 @@ fn bitCast( | ... | @@ -4189,7 +4085,7 @@ fn bitCast( |
| 4189 | break :blk result_id; | 4085 | break :blk result_id; |
| 4190 | } | 4086 | } |
| 4191 | | 4087 | |
| 4192 | const dst_ptr_ty_id = try cg.ptrType(dst_ty, .function, .indirect); | 4088 | const dst_ptr_ty_id = try cg.module.ptrType(dst_ty_id, .function); |
| 4193 | | 4089 | |
| 4194 | const tmp_id = try cg.alloc(src_ty, .{ .storage_class = .function }); | 4090 | const tmp_id = try cg.alloc(src_ty, .{ .storage_class = .function }); |
| 4195 | try cg.store(src_ty, tmp_id, src_id, .{}); | 4091 | try cg.store(src_ty, tmp_id, src_id, .{}); |
| ... | @@ -4594,7 +4490,8 @@ fn ptrElemPtr(cg: *CodeGen, ptr_ty: Type, ptr_id: Id, index_id: Id) !Id { | ... | @@ -4594,7 +4490,8 @@ fn ptrElemPtr(cg: *CodeGen, ptr_ty: Type, ptr_id: Id, index_id: Id) !Id { |
| 4594 | const zcu = cg.module.zcu; | 4490 | const zcu = cg.module.zcu; |
| 4595 | // Construct new pointer type for the resulting pointer | 4491 | // Construct new pointer type for the resulting pointer |
| 4596 | const elem_ty = ptr_ty.elemType2(zcu); // use elemType() so that we get T for *[N]T. | 4492 | const elem_ty = ptr_ty.elemType2(zcu); // use elemType() so that we get T for *[N]T. |
| 4597 | const elem_ptr_ty_id = try cg.ptrType(elem_ty, cg.module.storageClass(ptr_ty.ptrAddressSpace(zcu)), .indirect); | 4493 | const elem_ty_id = try cg.resolveType(elem_ty, .indirect); |
| | 4494 | const elem_ptr_ty_id = try cg.module.ptrType(elem_ty_id, cg.module.storageClass(ptr_ty.ptrAddressSpace(zcu))); |
| 4598 | if (ptr_ty.isSinglePointer(zcu)) { | 4495 | if (ptr_ty.isSinglePointer(zcu)) { |
| 4599 | // Pointer-to-array. In this case, the resulting pointer is not of the same type | 4496 | // Pointer-to-array. In this case, the resulting pointer is not of the same type |
| 4600 | // as the ptr_ty (we want a *T, not a *[N]T), and hence we need to use accessChain. | 4497 | // as the ptr_ty (we want a *T, not a *[N]T), and hence we need to use accessChain. |
| ... | @@ -4637,8 +4534,10 @@ fn airArrayElemVal(cg: *CodeGen, inst: Air.Inst.Index) !?Id { | ... | @@ -4637,8 +4534,10 @@ fn airArrayElemVal(cg: *CodeGen, inst: Air.Inst.Index) !?Id { |
| 4637 | const is_vector = array_ty.isVector(zcu); | 4534 | const is_vector = array_ty.isVector(zcu); |
| 4638 | | 4535 | |
| 4639 | const elem_repr: Repr = if (is_vector) .direct else .indirect; | 4536 | const elem_repr: Repr = if (is_vector) .direct else .indirect; |
| 4640 | const ptr_array_ty_id = try cg.ptrType(array_ty, .function, .direct); | 4537 | const array_ty_id = try cg.resolveType(array_ty, .direct); |
| 4641 | const ptr_elem_ty_id = try cg.ptrType(elem_ty, .function, elem_repr); | 4538 | const elem_ty_id = try cg.resolveType(elem_ty, elem_repr); |
| | 4539 | const ptr_array_ty_id = try cg.module.ptrType(array_ty_id, .function); |
| | 4540 | const ptr_elem_ty_id = try cg.module.ptrType(elem_ty_id, .function); |
| 4642 | | 4541 | |
| 4643 | const tmp_id = cg.module.allocId(); | 4542 | const tmp_id = cg.module.allocId(); |
| 4644 | try cg.prologue.emit(cg.module.gpa, .OpVariable, .{ | 4543 | try cg.prologue.emit(cg.module.gpa, .OpVariable, .{ |
| ... | @@ -4692,8 +4591,9 @@ fn airVectorStoreElem(cg: *CodeGen, inst: Air.Inst.Index) !void { | ... | @@ -4692,8 +4591,9 @@ fn airVectorStoreElem(cg: *CodeGen, inst: Air.Inst.Index) !void { |
| 4692 | const vector_ty = vector_ptr_ty.childType(zcu); | 4591 | const vector_ty = vector_ptr_ty.childType(zcu); |
| 4693 | const scalar_ty = vector_ty.scalarType(zcu); | 4592 | const scalar_ty = vector_ty.scalarType(zcu); |
| 4694 | | 4593 | |
| | 4594 | const scalar_ty_id = try cg.resolveType(scalar_ty, .indirect); |
| 4695 | const storage_class = cg.module.storageClass(vector_ptr_ty.ptrAddressSpace(zcu)); | 4595 | const storage_class = cg.module.storageClass(vector_ptr_ty.ptrAddressSpace(zcu)); |
| 4696 | const scalar_ptr_ty_id = try cg.ptrType(scalar_ty, storage_class, .indirect); | 4596 | const scalar_ptr_ty_id = try cg.module.ptrType(scalar_ty_id, storage_class); |
| 4697 | | 4597 | |
| 4698 | const vector_ptr = try cg.resolve(data.vector_ptr); | 4598 | const vector_ptr = try cg.resolve(data.vector_ptr); |
| 4699 | const index = try cg.resolve(extra.lhs); | 4599 | const index = try cg.resolve(extra.lhs); |
| ... | @@ -4715,7 +4615,8 @@ fn airSetUnionTag(cg: *CodeGen, inst: Air.Inst.Index) !void { | ... | @@ -4715,7 +4615,8 @@ fn airSetUnionTag(cg: *CodeGen, inst: Air.Inst.Index) !void { |
| 4715 | if (layout.tag_size == 0) return; | 4615 | if (layout.tag_size == 0) return; |
| 4716 | | 4616 | |
| 4717 | const tag_ty = un_ty.unionTagTypeSafety(zcu).?; | 4617 | const tag_ty = un_ty.unionTagTypeSafety(zcu).?; |
| 4718 | const tag_ptr_ty_id = try cg.ptrType(tag_ty, cg.module.storageClass(un_ptr_ty.ptrAddressSpace(zcu)), .indirect); | 4618 | const tag_ty_id = try cg.resolveType(tag_ty, .indirect); |
| | 4619 | const tag_ptr_ty_id = try cg.module.ptrType(tag_ty_id, cg.module.storageClass(un_ptr_ty.ptrAddressSpace(zcu))); |
| 4719 | | 4620 | |
| 4720 | const union_ptr_id = try cg.resolve(bin_op.lhs); | 4621 | const union_ptr_id = try cg.resolve(bin_op.lhs); |
| 4721 | const new_tag_id = try cg.resolve(bin_op.rhs); | 4622 | const new_tag_id = try cg.resolve(bin_op.rhs); |
| ... | @@ -4802,17 +4703,20 @@ fn unionInit( | ... | @@ -4802,17 +4703,20 @@ fn unionInit( |
| 4802 | const tmp_id = try cg.alloc(ty, .{ .storage_class = .function }); | 4703 | const tmp_id = try cg.alloc(ty, .{ .storage_class = .function }); |
| 4803 | | 4704 | |
| 4804 | if (layout.tag_size != 0) { | 4705 | if (layout.tag_size != 0) { |
| 4805 | const tag_ptr_ty_id = try cg.ptrType(tag_ty, .function, .indirect); | 4706 | const tag_ty_id = try cg.resolveType(tag_ty, .indirect); |
| | 4707 | const tag_ptr_ty_id = try cg.module.ptrType(tag_ty_id, .function); |
| 4806 | const ptr_id = try cg.accessChain(tag_ptr_ty_id, tmp_id, &.{@as(u32, @intCast(layout.tag_index))}); | 4708 | const ptr_id = try cg.accessChain(tag_ptr_ty_id, tmp_id, &.{@as(u32, @intCast(layout.tag_index))}); |
| 4807 | const tag_id = try cg.constInt(tag_ty, tag_int); | 4709 | const tag_id = try cg.constInt(tag_ty, tag_int); |
| 4808 | try cg.store(tag_ty, ptr_id, tag_id, .{}); | 4710 | try cg.store(tag_ty, ptr_id, tag_id, .{}); |
| 4809 | } | 4711 | } |
| 4810 | | 4712 | |
| 4811 | if (payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { | 4713 | if (payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { |
| 4812 | const pl_ptr_ty_id = try cg.ptrType(layout.payload_ty, .function, .indirect); | 4714 | const layout_payload_ty_id = try cg.resolveType(layout.payload_ty, .indirect); |
| | 4715 | const pl_ptr_ty_id = try cg.module.ptrType(layout_payload_ty_id, .function); |
| 4813 | const pl_ptr_id = try cg.accessChain(pl_ptr_ty_id, tmp_id, &.{layout.payload_index}); | 4716 | const pl_ptr_id = try cg.accessChain(pl_ptr_ty_id, tmp_id, &.{layout.payload_index}); |
| 4814 | const active_pl_ptr_id = if (!layout.payload_ty.eql(payload_ty, zcu)) blk: { | 4717 | const active_pl_ptr_id = if (!layout.payload_ty.eql(payload_ty, zcu)) blk: { |
| 4815 | const active_pl_ptr_ty_id = try cg.ptrType(payload_ty, .function, .indirect); | 4718 | const payload_ty_id = try cg.resolveType(payload_ty, .indirect); |
| | 4719 | const active_pl_ptr_ty_id = try cg.module.ptrType(payload_ty_id, .function); |
| 4816 | const active_pl_ptr_id = cg.module.allocId(); | 4720 | const active_pl_ptr_id = cg.module.allocId(); |
| 4817 | try cg.body.emit(cg.module.gpa, .OpBitcast, .{ | 4721 | try cg.body.emit(cg.module.gpa, .OpBitcast, .{ |
| 4818 | .id_result_type = active_pl_ptr_ty_id, | 4722 | .id_result_type = active_pl_ptr_ty_id, |
| ... | @@ -4876,7 +4780,7 @@ fn airStructFieldVal(cg: *CodeGen, inst: Air.Inst.Index) !?Id { | ... | @@ -4876,7 +4780,7 @@ fn airStructFieldVal(cg: *CodeGen, inst: Air.Inst.Index) !?Id { |
| 4876 | const mask_id = try cg.constInt(object_ty, (@as(u64, 1) << @as(u6, @intCast(field_bit_size))) - 1); | 4780 | const mask_id = try cg.constInt(object_ty, (@as(u64, 1) << @as(u6, @intCast(field_bit_size))) - 1); |
| 4877 | const masked = try cg.buildBinary(.bit_and, shift, .{ .ty = object_ty, .value = .{ .singleton = mask_id } }); | 4781 | const masked = try cg.buildBinary(.bit_and, shift, .{ .ty = object_ty, .value = .{ .singleton = mask_id } }); |
| 4878 | const result_id = blk: { | 4782 | const result_id = blk: { |
| 4879 | if (cg.backingIntBits(field_bit_size).@"0" == cg.backingIntBits(@intCast(object_ty.bitSize(zcu))).@"0") | 4783 | if (cg.module.backingIntBits(field_bit_size).@"0" == cg.module.backingIntBits(@intCast(object_ty.bitSize(zcu))).@"0") |
| 4880 | break :blk try cg.bitCast(field_int_ty, object_ty, try masked.materialize(cg)); | 4784 | break :blk try cg.bitCast(field_int_ty, object_ty, try masked.materialize(cg)); |
| 4881 | const trunc = try cg.buildConvert(field_int_ty, masked); | 4785 | const trunc = try cg.buildConvert(field_int_ty, masked); |
| 4882 | break :blk try trunc.materialize(cg); | 4786 | break :blk try trunc.materialize(cg); |
| ... | @@ -4900,7 +4804,7 @@ fn airStructFieldVal(cg: *CodeGen, inst: Air.Inst.Index) !?Id { | ... | @@ -4900,7 +4804,7 @@ fn airStructFieldVal(cg: *CodeGen, inst: Air.Inst.Index) !?Id { |
| 4900 | .{ .ty = backing_int_ty, .value = .{ .singleton = mask_id } }, | 4804 | .{ .ty = backing_int_ty, .value = .{ .singleton = mask_id } }, |
| 4901 | ); | 4805 | ); |
| 4902 | const result_id = blk: { | 4806 | const result_id = blk: { |
| 4903 | if (cg.backingIntBits(field_bit_size).@"0" == cg.backingIntBits(@intCast(backing_int_ty.bitSize(zcu))).@"0") | 4807 | if (cg.module.backingIntBits(field_bit_size).@"0" == cg.module.backingIntBits(@intCast(backing_int_ty.bitSize(zcu))).@"0") |
| 4904 | break :blk try cg.bitCast(int_ty, backing_int_ty, try masked.materialize(cg)); | 4808 | break :blk try cg.bitCast(int_ty, backing_int_ty, try masked.materialize(cg)); |
| 4905 | const trunc = try cg.buildConvert(int_ty, masked); | 4809 | const trunc = try cg.buildConvert(int_ty, masked); |
| 4906 | break :blk try trunc.materialize(cg); | 4810 | break :blk try trunc.materialize(cg); |
| ... | @@ -4917,10 +4821,12 @@ fn airStructFieldVal(cg: *CodeGen, inst: Air.Inst.Index) !?Id { | ... | @@ -4917,10 +4821,12 @@ fn airStructFieldVal(cg: *CodeGen, inst: Air.Inst.Index) !?Id { |
| 4917 | const tmp_id = try cg.alloc(object_ty, .{ .storage_class = .function }); | 4821 | const tmp_id = try cg.alloc(object_ty, .{ .storage_class = .function }); |
| 4918 | try cg.store(object_ty, tmp_id, object_id, .{}); | 4822 | try cg.store(object_ty, tmp_id, object_id, .{}); |
| 4919 | | 4823 | |
| 4920 | const pl_ptr_ty_id = try cg.ptrType(layout.payload_ty, .function, .indirect); | 4824 | const layout_payload_ty_id = try cg.resolveType(layout.payload_ty, .indirect); |
| | 4825 | const pl_ptr_ty_id = try cg.module.ptrType(layout_payload_ty_id, .function); |
| 4921 | const pl_ptr_id = try cg.accessChain(pl_ptr_ty_id, tmp_id, &.{layout.payload_index}); | 4826 | const pl_ptr_id = try cg.accessChain(pl_ptr_ty_id, tmp_id, &.{layout.payload_index}); |
| 4922 | | 4827 | |
| 4923 | const active_pl_ptr_ty_id = try cg.ptrType(field_ty, .function, .indirect); | 4828 | const field_ty_id = try cg.resolveType(field_ty, .indirect); |
| | 4829 | const active_pl_ptr_ty_id = try cg.module.ptrType(field_ty_id, .function); |
| 4924 | const active_pl_ptr_id = cg.module.allocId(); | 4830 | const active_pl_ptr_id = cg.module.allocId(); |
| 4925 | try cg.body.emit(cg.module.gpa, .OpBitcast, .{ | 4831 | try cg.body.emit(cg.module.gpa, .OpBitcast, .{ |
| 4926 | .id_result_type = active_pl_ptr_ty_id, | 4832 | .id_result_type = active_pl_ptr_ty_id, |
| ... | @@ -4997,7 +4903,8 @@ fn structFieldPtr( | ... | @@ -4997,7 +4903,8 @@ fn structFieldPtr( |
| 4997 | } | 4903 | } |
| 4998 | | 4904 | |
| 4999 | const storage_class = cg.module.storageClass(object_ptr_ty.ptrAddressSpace(zcu)); | 4905 | const storage_class = cg.module.storageClass(object_ptr_ty.ptrAddressSpace(zcu)); |
| 5000 | const pl_ptr_ty_id = try cg.ptrType(layout.payload_ty, storage_class, .indirect); | 4906 | const layout_payload_ty_id = try cg.resolveType(layout.payload_ty, .indirect); |
| | 4907 | const pl_ptr_ty_id = try cg.module.ptrType(layout_payload_ty_id, storage_class); |
| 5001 | const pl_ptr_id = blk: { | 4908 | const pl_ptr_id = blk: { |
| 5002 | if (object_ty.containerLayout(zcu) == .@"packed") break :blk object_ptr; | 4909 | if (object_ty.containerLayout(zcu) == .@"packed") break :blk object_ptr; |
| 5003 | break :blk try cg.accessChain(pl_ptr_ty_id, object_ptr, &.{layout.payload_index}); | 4910 | break :blk try cg.accessChain(pl_ptr_ty_id, object_ptr, &.{layout.payload_index}); |
| ... | @@ -5041,7 +4948,8 @@ fn alloc( | ... | @@ -5041,7 +4948,8 @@ fn alloc( |
| 5041 | options: AllocOptions, | 4948 | options: AllocOptions, |
| 5042 | ) !Id { | 4949 | ) !Id { |
| 5043 | const target = cg.module.zcu.getTarget(); | 4950 | const target = cg.module.zcu.getTarget(); |
| 5044 | const ptr_fn_ty_id = try cg.ptrType(ty, .function, .indirect); | 4951 | const ty_id = try cg.resolveType(ty, .indirect); |
| | 4952 | const ptr_fn_ty_id = try cg.module.ptrType(ty_id, .function); |
| 5045 | | 4953 | |
| 5046 | // SPIR-V requires that OpVariable declarations for locals go into the first block, so we are just going to | 4954 | // SPIR-V requires that OpVariable declarations for locals go into the first block, so we are just going to |
| 5047 | // directly generate them into func.prologue instead of the body. | 4955 | // directly generate them into func.prologue instead of the body. |
| ... | @@ -5060,7 +4968,7 @@ fn alloc( | ... | @@ -5060,7 +4968,7 @@ fn alloc( |
| 5060 | | 4968 | |
| 5061 | switch (options.storage_class) { | 4969 | switch (options.storage_class) { |
| 5062 | .generic => { | 4970 | .generic => { |
| 5063 | const ptr_gn_ty_id = try cg.ptrType(ty, .generic, .indirect); | 4971 | const ptr_gn_ty_id = try cg.module.ptrType(ty_id, .generic); |
| 5064 | // Convert to a generic pointer | 4972 | // Convert to a generic pointer |
| 5065 | return cg.castToGeneric(ptr_gn_ty_id, var_id); | 4973 | return cg.castToGeneric(ptr_gn_ty_id, var_id); |
| 5066 | }, | 4974 | }, |
| ... | @@ -5093,8 +5001,8 @@ fn structuredNextBlock(cg: *CodeGen, incoming: []const ControlFlow.Structured.Bl | ... | @@ -5093,8 +5001,8 @@ fn structuredNextBlock(cg: *CodeGen, incoming: []const ControlFlow.Structured.Bl |
| 5093 | const result_id = cg.module.allocId(); | 5001 | const result_id = cg.module.allocId(); |
| 5094 | const block_id_ty_id = try cg.resolveType(.u32, .direct); | 5002 | const block_id_ty_id = try cg.resolveType(.u32, .direct); |
| 5095 | try cg.body.emitRaw(cg.module.gpa, .OpPhi, @intCast(2 + incoming.len * 2)); // result type + result + variable/parent... | 5003 | try cg.body.emitRaw(cg.module.gpa, .OpPhi, @intCast(2 + incoming.len * 2)); // result type + result + variable/parent... |
| 5096 | cg.body.writeOperand(spec.Id, block_id_ty_id); | 5004 | cg.body.writeOperand(Id, block_id_ty_id); |
| 5097 | cg.body.writeOperand(spec.Id, result_id); | 5005 | cg.body.writeOperand(Id, result_id); |
| 5098 | | 5006 | |
| 5099 | for (incoming) |incoming_block| { | 5007 | for (incoming) |incoming_block| { |
| 5100 | cg.body.writeOperand(spec.PairIdRefIdRef, .{ incoming_block.next_block, incoming_block.src_label }); | 5008 | cg.body.writeOperand(spec.PairIdRefIdRef, .{ incoming_block.next_block, incoming_block.src_label }); |
| ... | @@ -5285,8 +5193,8 @@ fn lowerBlock(cg: *CodeGen, inst: Air.Inst.Index, body: []const Air.Inst.Index) | ... | @@ -5285,8 +5193,8 @@ fn lowerBlock(cg: *CodeGen, inst: Air.Inst.Index, body: []const Air.Inst.Index) |
| 5285 | // result type + result + variable/parent... | 5193 | // result type + result + variable/parent... |
| 5286 | 2 + @as(u16, @intCast(block.incoming_blocks.items.len * 2)), | 5194 | 2 + @as(u16, @intCast(block.incoming_blocks.items.len * 2)), |
| 5287 | ); | 5195 | ); |
| 5288 | cg.body.writeOperand(spec.Id, result_type_id); | 5196 | cg.body.writeOperand(Id, result_type_id); |
| 5289 | cg.body.writeOperand(spec.Id, result_id); | 5197 | cg.body.writeOperand(Id, result_id); |
| 5290 | | 5198 | |
| 5291 | for (block.incoming_blocks.items) |incoming| { | 5199 | for (block.incoming_blocks.items) |incoming| { |
| 5292 | cg.body.writeOperand( | 5200 | cg.body.writeOperand( |
| ... | @@ -5793,7 +5701,8 @@ fn airIsNull(cg: *CodeGen, inst: Air.Inst.Index, is_pointer: bool, pred: enum { | ... | @@ -5793,7 +5701,8 @@ fn airIsNull(cg: *CodeGen, inst: Air.Inst.Index, is_pointer: bool, pred: enum { |
| 5793 | if (is_pointer) { | 5701 | if (is_pointer) { |
| 5794 | if (payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { | 5702 | if (payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { |
| 5795 | const storage_class = cg.module.storageClass(operand_ty.ptrAddressSpace(zcu)); | 5703 | const storage_class = cg.module.storageClass(operand_ty.ptrAddressSpace(zcu)); |
| 5796 | const bool_ptr_ty_id = try cg.ptrType(.bool, storage_class, .indirect); | 5704 | const bool_indirect_ty_id = try cg.resolveType(.bool, .indirect); |
| | 5705 | const bool_ptr_ty_id = try cg.module.ptrType(bool_indirect_ty_id, storage_class); |
| 5797 | const tag_ptr_id = try cg.accessChain(bool_ptr_ty_id, operand_id, &.{1}); | 5706 | const tag_ptr_id = try cg.accessChain(bool_ptr_ty_id, operand_id, &.{1}); |
| 5798 | break :blk try cg.load(.bool, tag_ptr_id, .{}); | 5707 | break :blk try cg.load(.bool, tag_ptr_id, .{}); |
| 5799 | } | 5708 | } |
| ... | @@ -5939,14 +5848,14 @@ fn airSwitchBr(cg: *CodeGen, inst: Air.Inst.Index) !void { | ... | @@ -5939,14 +5848,14 @@ fn airSwitchBr(cg: *CodeGen, inst: Air.Inst.Index) !void { |
| 5939 | .bool, .error_set => 1, | 5848 | .bool, .error_set => 1, |
| 5940 | .int => blk: { | 5849 | .int => blk: { |
| 5941 | const bits = cond_ty.intInfo(zcu).bits; | 5850 | const bits = cond_ty.intInfo(zcu).bits; |
| 5942 | const backing_bits, const big_int = cg.backingIntBits(bits); | 5851 | const backing_bits, const big_int = cg.module.backingIntBits(bits); |
| 5943 | if (big_int) return cg.todo("implement composite int switch", .{}); | 5852 | if (big_int) return cg.todo("implement composite int switch", .{}); |
| 5944 | break :blk if (backing_bits <= 32) 1 else 2; | 5853 | break :blk if (backing_bits <= 32) 1 else 2; |
| 5945 | }, | 5854 | }, |
| 5946 | .@"enum" => blk: { | 5855 | .@"enum" => blk: { |
| 5947 | const int_ty = cond_ty.intTagType(zcu); | 5856 | const int_ty = cond_ty.intTagType(zcu); |
| 5948 | const int_info = int_ty.intInfo(zcu); | 5857 | const int_info = int_ty.intInfo(zcu); |
| 5949 | const backing_bits, const big_int = cg.backingIntBits(int_info.bits); | 5858 | const backing_bits, const big_int = cg.module.backingIntBits(int_info.bits); |
| 5950 | if (big_int) return cg.todo("implement composite int switch", .{}); | 5859 | if (big_int) return cg.todo("implement composite int switch", .{}); |
| 5951 | break :blk if (backing_bits <= 32) 1 else 2; | 5860 | break :blk if (backing_bits <= 32) 1 else 2; |
| 5952 | }, | 5861 | }, |
| ... | @@ -6298,7 +6207,7 @@ fn airCall(cg: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModifie | ... | @@ -6298,7 +6207,7 @@ fn airCall(cg: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModifie |
| 6298 | const callee_id = try cg.resolve(pl_op.operand); | 6207 | const callee_id = try cg.resolve(pl_op.operand); |
| 6299 | | 6208 | |
| 6300 | comptime assert(zig_call_abi_ver == 3); | 6209 | comptime assert(zig_call_abi_ver == 3); |
| 6301 | const params = try gpa.alloc(spec.Id, args.len); | 6210 | const params = try gpa.alloc(Id, args.len); |
| 6302 | defer gpa.free(params); | 6211 | defer gpa.free(params); |
| 6303 | var n_params: usize = 0; | 6212 | var n_params: usize = 0; |
| 6304 | for (args) |arg| { | 6213 | for (args) |arg| { |
| ... | @@ -6327,50 +6236,49 @@ fn airCall(cg: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModifie | ... | @@ -6327,50 +6236,49 @@ fn airCall(cg: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModifie |
| 6327 | return result_id; | 6236 | return result_id; |
| 6328 | } | 6237 | } |
| 6329 | | 6238 | |
| 6330 | fn builtin3D(cg: *CodeGen, result_ty: Type, builtin: spec.BuiltIn, dimension: u32, out_of_range_value: anytype) !Id { | 6239 | fn builtin3D( |
| 6331 | if (dimension >= 3) { | 6240 | cg: *CodeGen, |
| 6332 | return try cg.constInt(result_ty, out_of_range_value); | 6241 | result_ty: Type, |
| 6333 | } | 6242 | builtin: spec.BuiltIn, |
| 6334 | const vec_ty = try cg.pt.vectorType(.{ | 6243 | dimension: u32, |
| 6335 | .len = 3, | 6244 | out_of_range_value: anytype, |
| 6336 | .child = result_ty.toIntern(), | 6245 | ) !Id { |
| 6337 | }); | 6246 | if (dimension >= 3) return try cg.constInt(result_ty, out_of_range_value); |
| 6338 | const ptr_ty_id = try cg.ptrType(vec_ty, .input, .indirect); | 6247 | const u32_ty_id = try cg.module.intType(.unsigned, 32); |
| 6339 | const spv_decl_index = try cg.module.builtin(ptr_ty_id, builtin); | 6248 | const vec_ty_id = try cg.module.vectorType(3, u32_ty_id); |
| | 6249 | const ptr_ty_id = try cg.module.ptrType(vec_ty_id, .input); |
| | 6250 | const spv_decl_index = try cg.module.builtin(ptr_ty_id, builtin, .input); |
| 6340 | try cg.decl_deps.put(cg.module.gpa, spv_decl_index, {}); | 6251 | try cg.decl_deps.put(cg.module.gpa, spv_decl_index, {}); |
| 6341 | const ptr = cg.module.declPtr(spv_decl_index).result_id; | 6252 | const ptr_id = cg.module.declPtr(spv_decl_index).result_id; |
| 6342 | const vec = try cg.load(vec_ty, ptr, .{}); | 6253 | const vec_id = cg.module.allocId(); |
| 6343 | return try cg.extractVectorComponent(result_ty, vec, dimension); | 6254 | try cg.body.emit(cg.module.gpa, .OpLoad, .{ |
| | 6255 | .id_result_type = vec_ty_id, |
| | 6256 | .id_result = vec_id, |
| | 6257 | .pointer = ptr_id, |
| | 6258 | }); |
| | 6259 | return try cg.extractVectorComponent(result_ty, vec_id, dimension); |
| 6344 | } | 6260 | } |
| 6345 | | 6261 | |
| 6346 | fn airWorkItemId(cg: *CodeGen, inst: Air.Inst.Index) !?Id { | 6262 | fn airWorkItemId(cg: *CodeGen, inst: Air.Inst.Index) !?Id { |
| 6347 | if (cg.liveness.isUnused(inst)) return null; | 6263 | if (cg.liveness.isUnused(inst)) return null; |
| 6348 | const pl_op = cg.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; | 6264 | const pl_op = cg.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; |
| 6349 | const dimension = pl_op.payload; | 6265 | const dimension = pl_op.payload; |
| 6350 | const result_id = try cg.builtin3D(.u32, .local_invocation_id, dimension, 0); | 6266 | return try cg.builtin3D(.u32, .local_invocation_id, dimension, 0); |
| 6351 | const tmp: Temporary = .init(.u32, result_id); | | |
| 6352 | const result = try cg.buildConvert(.u32, tmp); | | |
| 6353 | return try result.materialize(cg); | | |
| 6354 | } | 6267 | } |
| 6355 | | 6268 | |
| | 6269 | // TODO: this must be an OpConstant/OpSpec but even then the driver crashes. |
| 6356 | fn airWorkGroupSize(cg: *CodeGen, inst: Air.Inst.Index) !?Id { | 6270 | fn airWorkGroupSize(cg: *CodeGen, inst: Air.Inst.Index) !?Id { |
| 6357 | if (cg.liveness.isUnused(inst)) return null; | 6271 | if (cg.liveness.isUnused(inst)) return null; |
| 6358 | const pl_op = cg.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; | 6272 | const pl_op = cg.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; |
| 6359 | const dimension = pl_op.payload; | 6273 | const dimension = pl_op.payload; |
| 6360 | const result_id = try cg.builtin3D(.u32, .workgroup_size, dimension, 0); | 6274 | return try cg.builtin3D(.u32, .workgroup_id, dimension, 0); |
| 6361 | const tmp: Temporary = .init(.u32, result_id); | | |
| 6362 | const result = try cg.buildConvert(.u32, tmp); | | |
| 6363 | return try result.materialize(cg); | | |
| 6364 | } | 6275 | } |
| 6365 | | 6276 | |
| 6366 | fn airWorkGroupId(cg: *CodeGen, inst: Air.Inst.Index) !?Id { | 6277 | fn airWorkGroupId(cg: *CodeGen, inst: Air.Inst.Index) !?Id { |
| 6367 | if (cg.liveness.isUnused(inst)) return null; | 6278 | if (cg.liveness.isUnused(inst)) return null; |
| 6368 | const pl_op = cg.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; | 6279 | const pl_op = cg.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; |
| 6369 | const dimension = pl_op.payload; | 6280 | const dimension = pl_op.payload; |
| 6370 | const result_id = try cg.builtin3D(.u32, .workgroup_id, dimension, 0); | 6281 | return try cg.builtin3D(.u32, .workgroup_id, dimension, 0); |
| 6371 | const tmp: Temporary = .init(.u32, result_id); | | |
| 6372 | const result = try cg.buildConvert(.u32, tmp); | | |
| 6373 | return try result.materialize(cg); | | |
| 6374 | } | 6282 | } |
| 6375 | | 6283 | |
| 6376 | fn typeOf(cg: *CodeGen, inst: Air.Inst.Ref) Type { | 6284 | fn typeOf(cg: *CodeGen, inst: Air.Inst.Ref) Type { |