| author | |
| committer | |
| log | 5e002910df398278f743a04fe40cf34320482cd1 |
| tree | f7770516b3bf0e2605df1aeb329c83bdd976cb87 |
| parent | c475f1fcd547a93d9e75770900b2fa0c45b43de3 |
| parent | 0ea79c85b2b22266a0b25edf04c392add8387d5b |
Reviewed-on: https://codeberg.org/ziglang/zig/pulls/30570
Reviewed-by: Andrew Kelley <andrew@ziglang.org>7 files changed, 73 insertions(+), 32 deletions(-)
lib/std/builtin.zig+11| ... | @@ -1101,6 +1101,17 @@ pub const ExternOptions = struct { | ... | @@ -1101,6 +1101,17 @@ pub const ExternOptions = struct { |
| 1101 | is_thread_local: bool = false, | 1101 | is_thread_local: bool = false, |
| 1102 | is_dll_import: bool = false, | 1102 | is_dll_import: bool = false, |
| 1103 | relocation: Relocation = .any, | 1103 | relocation: Relocation = .any, |
| 1104 | decoration: ?Decoration = null, | ||
| 1105 | |||
| 1106 | pub const Decoration = union(enum) { | ||
| 1107 | location: u32, | ||
| 1108 | descriptor: Descriptor, | ||
| 1109 | |||
| 1110 | pub const Descriptor = struct { | ||
| 1111 | binding: u32, | ||
| 1112 | set: u32, | ||
| 1113 | }; | ||
| 1114 | }; | ||
| 1104 | 1115 | ||
| 1105 | pub const Relocation = enum(u1) { | 1116 | pub const Relocation = enum(u1) { |
| 1106 | /// Any type of relocation is allowed. | 1117 | /// Any type of relocation is allowed. |
lib/std/gpu.zig-24| ... | @@ -20,30 +20,6 @@ pub extern const global_invocation_id: @Vector(3, u32) addrspace(.input); | ... | @@ -20,30 +20,6 @@ pub extern const global_invocation_id: @Vector(3, u32) addrspace(.input); |
| 20 | pub extern const vertex_index: u32 addrspace(.input); | 20 | pub extern const vertex_index: u32 addrspace(.input); |
| 21 | pub extern const instance_index: u32 addrspace(.input); | 21 | pub extern const instance_index: u32 addrspace(.input); |
| 22 | 22 | ||
| 23 | /// Forms the main linkage for `input` and `output` address spaces. | ||
| 24 | /// `ptr` must be a reference to variable or struct field. | ||
| 25 | pub fn location(comptime ptr: anytype, comptime loc: u32) void { | ||
| 26 | asm volatile ( | ||
| 27 | \\OpDecorate %ptr Location $loc | ||
| 28 | : | ||
| 29 | : [ptr] "" (ptr), | ||
| 30 | [loc] "c" (loc), | ||
| 31 | ); | ||
| 32 | } | ||
| 33 | |||
| 34 | /// Forms the main linkage for `input` and `output` address spaces. | ||
| 35 | /// `ptr` must be a reference to variable or struct field. | ||
| 36 | pub fn binding(comptime ptr: anytype, comptime set: u32, comptime bind: u32) void { | ||
| 37 | asm volatile ( | ||
| 38 | \\OpDecorate %ptr DescriptorSet $set | ||
| 39 | \\OpDecorate %ptr Binding $bind | ||
| 40 | : | ||
| 41 | : [ptr] "" (ptr), | ||
| 42 | [set] "c" (set), | ||
| 43 | [bind] "c" (bind), | ||
| 44 | ); | ||
| 45 | } | ||
| 46 | |||
| 47 | pub const ExecutionMode = union(Tag) { | 23 | pub const ExecutionMode = union(Tag) { |
| 48 | /// Sets origin of the framebuffer to the upper-left corner | 24 | /// Sets origin of the framebuffer to the upper-left corner |
| 49 | origin_upper_left, | 25 | origin_upper_left, |
src/InternPool.zig+24-1| ... | @@ -2316,6 +2316,7 @@ pub const Key = union(enum) { | ... | @@ -2316,6 +2316,7 @@ pub const Key = union(enum) { |
| 2316 | is_threadlocal: bool, | 2316 | is_threadlocal: bool, |
| 2317 | is_dll_import: bool, | 2317 | is_dll_import: bool, |
| 2318 | relocation: std.builtin.ExternOptions.Relocation, | 2318 | relocation: std.builtin.ExternOptions.Relocation, |
| 2319 | decoration: ?std.builtin.ExternOptions.Decoration, | ||
| 2319 | is_const: bool, | 2320 | is_const: bool, |
| 2320 | alignment: Alignment, | 2321 | alignment: Alignment, |
| 2321 | @"addrspace": std.builtin.AddressSpace, | 2322 | @"addrspace": std.builtin.AddressSpace, |
| ... | @@ -6075,6 +6076,8 @@ pub const Tag = enum(u8) { | ... | @@ -6075,6 +6076,8 @@ pub const Tag = enum(u8) { |
| 6075 | flags: Flags, | 6076 | flags: Flags, |
| 6076 | owner_nav: Nav.Index, | 6077 | owner_nav: Nav.Index, |
| 6077 | zir_index: TrackedInst.Index, | 6078 | zir_index: TrackedInst.Index, |
| 6079 | location_or_descriptor_set: u32, | ||
| 6080 | descriptor_binding: u32, | ||
| 6078 | 6081 | ||
| 6079 | pub const Flags = packed struct(u32) { | 6082 | pub const Flags = packed struct(u32) { |
| 6080 | linkage: std.builtin.GlobalLinkage, | 6083 | linkage: std.builtin.GlobalLinkage, |
| ... | @@ -6083,10 +6086,22 @@ pub const Tag = enum(u8) { | ... | @@ -6083,10 +6086,22 @@ pub const Tag = enum(u8) { |
| 6083 | is_dll_import: bool, | 6086 | is_dll_import: bool, |
| 6084 | relocation: std.builtin.ExternOptions.Relocation, | 6087 | relocation: std.builtin.ExternOptions.Relocation, |
| 6085 | source: Source, | 6088 | source: Source, |
| 6086 | _: u24 = 0, | 6089 | decoration_type: DecorationType, |
| 6090 | _: u22 = 0, | ||
| 6087 | 6091 | ||
| 6088 | pub const Source = enum(u1) { builtin, syntax }; | 6092 | pub const Source = enum(u1) { builtin, syntax }; |
| 6093 | pub const DecorationType = enum(u2) { none, location, descriptor }; | ||
| 6089 | }; | 6094 | }; |
| 6095 | |||
| 6096 | pub fn decoration(self: Extern) ?std.builtin.ExternOptions.Decoration { | ||
| 6097 | return switch (self.flags.decoration_type) { | ||
| 6098 | .none => null, | ||
| 6099 | .location => std.builtin.ExternOptions.Decoration{ | ||
| 6100 | .location = self.location_or_descriptor_set, | ||
| 6101 | }, | ||
| 6102 | .descriptor => std.builtin.ExternOptions.Decoration{ .descriptor = .{ .set = self.location_or_descriptor_set, .binding = self.descriptor_binding } }, | ||
| 6103 | }; | ||
| 6104 | } | ||
| 6090 | }; | 6105 | }; |
| 6091 | 6106 | ||
| 6092 | /// Trailing: | 6107 | /// Trailing: |
| ... | @@ -7444,6 +7459,7 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key { | ... | @@ -7444,6 +7459,7 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key { |
| 7444 | .is_threadlocal = extra.flags.is_threadlocal, | 7459 | .is_threadlocal = extra.flags.is_threadlocal, |
| 7445 | .is_dll_import = extra.flags.is_dll_import, | 7460 | .is_dll_import = extra.flags.is_dll_import, |
| 7446 | .relocation = extra.flags.relocation, | 7461 | .relocation = extra.flags.relocation, |
| 7462 | .decoration = extra.decoration(), | ||
| 7447 | .is_const = nav.status.fully_resolved.is_const, | 7463 | .is_const = nav.status.fully_resolved.is_const, |
| 7448 | .alignment = nav.status.fully_resolved.alignment, | 7464 | .alignment = nav.status.fully_resolved.alignment, |
| 7449 | .@"addrspace" = nav.status.fully_resolved.@"addrspace", | 7465 | .@"addrspace" = nav.status.fully_resolved.@"addrspace", |
| ... | @@ -9346,15 +9362,22 @@ pub fn getExtern( | ... | @@ -9346,15 +9362,22 @@ pub fn getExtern( |
| 9346 | .@"linksection" = .none, | 9362 | .@"linksection" = .none, |
| 9347 | .@"addrspace" = key.@"addrspace", | 9363 | .@"addrspace" = key.@"addrspace", |
| 9348 | }) catch unreachable; // capacity asserted above | 9364 | }) catch unreachable; // capacity asserted above |
| 9365 | const decoration_type, const location_or_descriptor_set, const descriptor_binding = if (key.decoration) |decoration| switch (decoration) { | ||
| 9366 | .location => |location| .{ Tag.Extern.Flags.DecorationType.location, location, undefined }, | ||
| 9367 | .descriptor => |descriptor| .{ Tag.Extern.Flags.DecorationType.descriptor, descriptor.binding, descriptor.set }, | ||
| 9368 | } else .{ Tag.Extern.Flags.DecorationType.none, undefined, undefined }; | ||
| 9349 | const extra_index = addExtraAssumeCapacity(extra, Tag.Extern{ | 9369 | const extra_index = addExtraAssumeCapacity(extra, Tag.Extern{ |
| 9350 | .ty = key.ty, | 9370 | .ty = key.ty, |
| 9351 | .lib_name = key.lib_name, | 9371 | .lib_name = key.lib_name, |
| 9372 | .location_or_descriptor_set = location_or_descriptor_set, | ||
| 9373 | .descriptor_binding = descriptor_binding, | ||
| 9352 | .flags = .{ | 9374 | .flags = .{ |
| 9353 | .linkage = key.linkage, | 9375 | .linkage = key.linkage, |
| 9354 | .visibility = key.visibility, | 9376 | .visibility = key.visibility, |
| 9355 | .is_threadlocal = key.is_threadlocal, | 9377 | .is_threadlocal = key.is_threadlocal, |
| 9356 | .is_dll_import = key.is_dll_import, | 9378 | .is_dll_import = key.is_dll_import, |
| 9357 | .relocation = key.relocation, | 9379 | .relocation = key.relocation, |
| 9380 | .decoration_type = decoration_type, | ||
| 9358 | .source = key.source, | 9381 | .source = key.source, |
| 9359 | }, | 9382 | }, |
| 9360 | .zir_index = key.zir_index, | 9383 | .zir_index = key.zir_index, |
src/Sema.zig+8| ... | @@ -25916,6 +25916,7 @@ fn resolveExternOptions( | ... | @@ -25916,6 +25916,7 @@ fn resolveExternOptions( |
| 25916 | is_thread_local: bool, | 25916 | is_thread_local: bool, |
| 25917 | is_dll_import: bool, | 25917 | is_dll_import: bool, |
| 25918 | relocation: std.builtin.ExternOptions.Relocation, | 25918 | relocation: std.builtin.ExternOptions.Relocation, |
| 25919 | decoration: ?std.builtin.ExternOptions.Decoration, | ||
| 25919 | } { | 25920 | } { |
| 25920 | const pt = sema.pt; | 25921 | const pt = sema.pt; |
| 25921 | const zcu = pt.zcu; | 25922 | const zcu = pt.zcu; |
| ... | @@ -25935,6 +25936,7 @@ fn resolveExternOptions( | ... | @@ -25935,6 +25936,7 @@ fn resolveExternOptions( |
| 25935 | const thread_local_src = block.src(.{ .init_field_thread_local = src.offset.node_offset_builtin_call_arg.builtin_call_node }); | 25936 | const thread_local_src = block.src(.{ .init_field_thread_local = src.offset.node_offset_builtin_call_arg.builtin_call_node }); |
| 25936 | const dll_import_src = block.src(.{ .init_field_dll_import = src.offset.node_offset_builtin_call_arg.builtin_call_node }); | 25937 | const dll_import_src = block.src(.{ .init_field_dll_import = src.offset.node_offset_builtin_call_arg.builtin_call_node }); |
| 25937 | const relocation_src = block.src(.{ .init_field_relocation = src.offset.node_offset_builtin_call_arg.builtin_call_node }); | 25938 | const relocation_src = block.src(.{ .init_field_relocation = src.offset.node_offset_builtin_call_arg.builtin_call_node }); |
| 25939 | const decoration_src = block.src(.{ .init_field_decoration = src.offset.node_offset_builtin_call_arg.builtin_call_node }); | ||
| 25938 | 25940 | ||
| 25939 | const name_ref = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, io, pt.tid, "name", .no_embedded_nulls), name_src); | 25941 | const name_ref = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, io, pt.tid, "name", .no_embedded_nulls), name_src); |
| 25940 | const name = try sema.toConstString(block, name_src, name_ref, .{ .simple = .extern_options }); | 25942 | const name = try sema.toConstString(block, name_src, name_ref, .{ .simple = .extern_options }); |
| ... | @@ -25969,6 +25971,10 @@ fn resolveExternOptions( | ... | @@ -25969,6 +25971,10 @@ fn resolveExternOptions( |
| 25969 | const relocation_val = try sema.resolveConstDefinedValue(block, relocation_src, relocation_ref, .{ .simple = .extern_options }); | 25971 | const relocation_val = try sema.resolveConstDefinedValue(block, relocation_src, relocation_ref, .{ .simple = .extern_options }); |
| 25970 | const relocation = try sema.interpretBuiltinType(block, relocation_src, relocation_val, std.builtin.ExternOptions.Relocation); | 25972 | const relocation = try sema.interpretBuiltinType(block, relocation_src, relocation_val, std.builtin.ExternOptions.Relocation); |
| 25971 | 25973 | ||
| 25974 | const decoration_ref = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, pt.tid, "decoration", .no_embedded_nulls), decoration_src); | ||
| 25975 | const decoration_val = try sema.resolveConstDefinedValue(block, decoration_src, decoration_ref, .{ .simple = .extern_options }); | ||
| 25976 | const decoration = try sema.interpretBuiltinType(block, decoration_src, decoration_val, ?std.builtin.ExternOptions.Decoration); | ||
| 25977 | |||
| 25972 | if (name.len == 0) { | 25978 | if (name.len == 0) { |
| 25973 | return sema.fail(block, name_src, "extern symbol name cannot be empty", .{}); | 25979 | return sema.fail(block, name_src, "extern symbol name cannot be empty", .{}); |
| 25974 | } | 25980 | } |
| ... | @@ -25985,6 +25991,7 @@ fn resolveExternOptions( | ... | @@ -25985,6 +25991,7 @@ fn resolveExternOptions( |
| 25985 | .is_thread_local = is_thread_local_val.toBool(), | 25991 | .is_thread_local = is_thread_local_val.toBool(), |
| 25986 | .is_dll_import = is_dll_import_val.toBool(), | 25992 | .is_dll_import = is_dll_import_val.toBool(), |
| 25987 | .relocation = relocation, | 25993 | .relocation = relocation, |
| 25994 | .decoration = decoration, | ||
| 25988 | }; | 25995 | }; |
| 25989 | } | 25996 | } |
| 25990 | 25997 | ||
| ... | @@ -26044,6 +26051,7 @@ fn zirBuiltinExtern( | ... | @@ -26044,6 +26051,7 @@ fn zirBuiltinExtern( |
| 26044 | .is_threadlocal = options.is_thread_local, | 26051 | .is_threadlocal = options.is_thread_local, |
| 26045 | .is_dll_import = options.is_dll_import, | 26052 | .is_dll_import = options.is_dll_import, |
| 26046 | .relocation = options.relocation, | 26053 | .relocation = options.relocation, |
| 26054 | .decoration = options.decoration, | ||
| 26047 | .is_const = ptr_info.flags.is_const, | 26055 | .is_const = ptr_info.flags.is_const, |
| 26048 | .alignment = ptr_info.flags.alignment, | 26056 | .alignment = ptr_info.flags.alignment, |
| 26049 | .@"addrspace" = ptr_info.flags.address_space, | 26057 | .@"addrspace" = ptr_info.flags.address_space, |
src/Zcu.zig+3| ... | @@ -2113,6 +2113,7 @@ pub const SrcLoc = struct { | ... | @@ -2113,6 +2113,7 @@ pub const SrcLoc = struct { |
| 2113 | .init_field_thread_local, | 2113 | .init_field_thread_local, |
| 2114 | .init_field_dll_import, | 2114 | .init_field_dll_import, |
| 2115 | .init_field_relocation, | 2115 | .init_field_relocation, |
| 2116 | .init_field_decoration, | ||
| 2116 | => |builtin_call_node| { | 2117 | => |builtin_call_node| { |
| 2117 | const wanted = switch (src_loc.lazy) { | 2118 | const wanted = switch (src_loc.lazy) { |
| 2118 | .init_field_name => "name", | 2119 | .init_field_name => "name", |
| ... | @@ -2126,6 +2127,7 @@ pub const SrcLoc = struct { | ... | @@ -2126,6 +2127,7 @@ pub const SrcLoc = struct { |
| 2126 | .init_field_thread_local => "thread_local", | 2127 | .init_field_thread_local => "thread_local", |
| 2127 | .init_field_dll_import => "dll_import", | 2128 | .init_field_dll_import => "dll_import", |
| 2128 | .init_field_relocation => "relocation", | 2129 | .init_field_relocation => "relocation", |
| 2130 | .init_field_decoration => "decoration", | ||
| 2129 | else => unreachable, | 2131 | else => unreachable, |
| 2130 | }; | 2132 | }; |
| 2131 | const tree = try src_loc.file_scope.getTree(zcu); | 2133 | const tree = try src_loc.file_scope.getTree(zcu); |
| ... | @@ -2606,6 +2608,7 @@ pub const LazySrcLoc = struct { | ... | @@ -2606,6 +2608,7 @@ pub const LazySrcLoc = struct { |
| 2606 | init_field_thread_local: Ast.Node.Offset, | 2608 | init_field_thread_local: Ast.Node.Offset, |
| 2607 | init_field_dll_import: Ast.Node.Offset, | 2609 | init_field_dll_import: Ast.Node.Offset, |
| 2608 | init_field_relocation: Ast.Node.Offset, | 2610 | init_field_relocation: Ast.Node.Offset, |
| 2611 | init_field_decoration: Ast.Node.Offset, | ||
| 2609 | /// The source location points to the value of an item in a specific | 2612 | /// The source location points to the value of an item in a specific |
| 2610 | /// case of a `switch`. | 2613 | /// case of a `switch`. |
| 2611 | switch_case_item: SwitchItem, | 2614 | switch_case_item: SwitchItem, |
src/Zcu/PerThread.zig+2| ... | @@ -1269,6 +1269,7 @@ fn analyzeNavVal(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileErr | ... | @@ -1269,6 +1269,7 @@ fn analyzeNavVal(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileErr |
| 1269 | .visibility = .default, | 1269 | .visibility = .default, |
| 1270 | .is_dll_import = false, | 1270 | .is_dll_import = false, |
| 1271 | .relocation = .any, | 1271 | .relocation = .any, |
| 1272 | .decoration = null, | ||
| 1272 | .is_const = is_const, | 1273 | .is_const = is_const, |
| 1273 | .alignment = modifiers.alignment, | 1274 | .alignment = modifiers.alignment, |
| 1274 | .@"addrspace" = modifiers.@"addrspace", | 1275 | .@"addrspace" = modifiers.@"addrspace", |
| ... | @@ -3490,6 +3491,7 @@ pub fn getCoerced(pt: Zcu.PerThread, val: Value, new_ty: Type) Allocator.Error!V | ... | @@ -3490,6 +3491,7 @@ pub fn getCoerced(pt: Zcu.PerThread, val: Value, new_ty: Type) Allocator.Error!V |
| 3490 | .visibility = e.visibility, | 3491 | .visibility = e.visibility, |
| 3491 | .is_dll_import = e.is_dll_import, | 3492 | .is_dll_import = e.is_dll_import, |
| 3492 | .relocation = e.relocation, | 3493 | .relocation = e.relocation, |
| 3494 | .decoration = e.decoration, | ||
| 3493 | .alignment = e.alignment, | 3495 | .alignment = e.alignment, |
| 3494 | .@"addrspace" = e.@"addrspace", | 3496 | .@"addrspace" = e.@"addrspace", |
| 3495 | .zir_index = e.zir_index, | 3497 | .zir_index = e.zir_index, |
src/codegen/spirv/CodeGen.zig+25-7| ... | @@ -254,7 +254,7 @@ pub fn genNav(cg: *CodeGen, do_codegen: bool) Error!void { | ... | @@ -254,7 +254,7 @@ pub fn genNav(cg: *CodeGen, do_codegen: bool) Error!void { |
| 254 | try cg.module.debugName(func_result_id, nav.fqn.toSlice(ip)); | 254 | try cg.module.debugName(func_result_id, nav.fqn.toSlice(ip)); |
| 255 | }, | 255 | }, |
| 256 | .global => { | 256 | .global => { |
| 257 | assert(ip.indexToKey(val.toIntern()) == .@"extern"); | 257 | const key = ip.indexToKey(val.toIntern()).@"extern"; |
| 258 | 258 | ||
| 259 | const storage_class = cg.module.storageClass(nav.getAddrspace()); | 259 | const storage_class = cg.module.storageClass(nav.getAddrspace()); |
| 260 | assert(storage_class != .generic); // These should be instance globals | 260 | assert(storage_class != .generic); // These should be instance globals |
| ... | @@ -277,14 +277,32 @@ pub fn genNav(cg: *CodeGen, do_codegen: bool) Error!void { | ... | @@ -277,14 +277,32 @@ pub fn genNav(cg: *CodeGen, do_codegen: bool) Error!void { |
| 277 | } | 277 | } |
| 278 | } | 278 | } |
| 279 | 279 | ||
| 280 | switch (ip.indexToKey(ty.toIntern())) { | 280 | try cg.module.decorate(ptr_ty_id, .{ |
| 281 | .func_type, .opaque_type => {}, | 281 | .array_stride = .{ .array_stride = @intCast(ty.abiSize(zcu)) }, |
| 282 | else => { | 282 | }); |
| 283 | try cg.module.decorate(ptr_ty_id, .{ | 283 | |
| 284 | .array_stride = .{ .array_stride = @intCast(ty.abiSize(zcu)) }, | 284 | if (key.decoration) |decoration| switch (decoration) { |
| 285 | .location => |location| { | ||
| 286 | if (storage_class != .output and storage_class != .input and storage_class != .uniform_constant) { | ||
| 287 | return cg.fail("storage class must be one of (output, input, uniform_constant) but is {s}", .{@tagName(storage_class)}); | ||
| 288 | } | ||
| 289 | try cg.module.decorate(result_id, .{ | ||
| 290 | .location = .{ .location = location }, | ||
| 285 | }); | 291 | }); |
| 286 | }, | 292 | }, |
| 287 | } | 293 | .descriptor => |descriptor| { |
| 294 | if (storage_class != .storage_buffer and storage_class != .uniform and storage_class != .uniform_constant) { | ||
| 295 | return cg.fail("storage class must be one of (storage_buffer, uniform, uniform_constant) but is {s}", .{@tagName(storage_class)}); | ||
| 296 | } | ||
| 297 | try cg.module.decorate(result_id, .{ | ||
| 298 | .binding = .{ .binding_point = descriptor.binding }, | ||
| 299 | }); | ||
| 300 | |||
| 301 | try cg.module.decorate(result_id, .{ | ||
| 302 | .descriptor_set = .{ .descriptor_set = descriptor.set }, | ||
| 303 | }); | ||
| 304 | }, | ||
| 305 | }; | ||
| 288 | }, | 306 | }, |
| 289 | else => {}, | 307 | else => {}, |
| 290 | } | 308 | } |