| author | |
| committer | |
| log | a6ed3e6d29b0e2cedfc20048b014cff4e0ae4eaa |
| tree | 11b933e936d64f00a7a820a21afe2633b34d5941 |
| parent | aff71c6132fd17c6fa455a6e7b9f53567e3e55b2 |
| parent | e5ba70bb5c176ba553a5458f89004b44da2b93d6 |
| signature |
Rework `@fieldParentPtr` to use RLS105 files changed, 7223 insertions(+), 5165 deletions(-)
CMakeLists.txt+1-1| ... | @@ -564,7 +564,7 @@ set(ZIG_STAGE2_SOURCES | ... | @@ -564,7 +564,7 @@ set(ZIG_STAGE2_SOURCES |
| 564 | "${CMAKE_SOURCE_DIR}/src/clang_options_data.zig" | 564 | "${CMAKE_SOURCE_DIR}/src/clang_options_data.zig" |
| 565 | "${CMAKE_SOURCE_DIR}/src/codegen.zig" | 565 | "${CMAKE_SOURCE_DIR}/src/codegen.zig" |
| 566 | "${CMAKE_SOURCE_DIR}/src/codegen/c.zig" | 566 | "${CMAKE_SOURCE_DIR}/src/codegen/c.zig" |
| 567 | "${CMAKE_SOURCE_DIR}/src/codegen/c/type.zig" | 567 | "${CMAKE_SOURCE_DIR}/src/codegen/c/Type.zig" |
| 568 | "${CMAKE_SOURCE_DIR}/src/codegen/llvm.zig" | 568 | "${CMAKE_SOURCE_DIR}/src/codegen/llvm.zig" |
| 569 | "${CMAKE_SOURCE_DIR}/src/codegen/llvm/bindings.zig" | 569 | "${CMAKE_SOURCE_DIR}/src/codegen/llvm/bindings.zig" |
| 570 | "${CMAKE_SOURCE_DIR}/src/glibc.zig" | 570 | "${CMAKE_SOURCE_DIR}/src/glibc.zig" |
build.zig+1-3| ... | @@ -16,9 +16,7 @@ pub fn build(b: *std.Build) !void { | ... | @@ -16,9 +16,7 @@ pub fn build(b: *std.Build) !void { |
| 16 | const only_c = b.option(bool, "only-c", "Translate the Zig compiler to C code, with only the C backend enabled") orelse false; | 16 | const only_c = b.option(bool, "only-c", "Translate the Zig compiler to C code, with only the C backend enabled") orelse false; |
| 17 | const target = t: { | 17 | const target = t: { |
| 18 | var default_target: std.zig.CrossTarget = .{}; | 18 | var default_target: std.zig.CrossTarget = .{}; |
| 19 | if (only_c) { | 19 | default_target.ofmt = b.option(std.Target.ObjectFormat, "ofmt", "Object format to target") orelse if (only_c) .c else null; |
| 20 | default_target.ofmt = .c; | ||
| 21 | } | ||
| 22 | break :t b.standardTargetOptions(.{ .default_target = default_target }); | 20 | break :t b.standardTargetOptions(.{ .default_target = default_target }); |
| 23 | }; | 21 | }; |
| 24 | 22 |
doc/langref.html.in+2-3| ... | @@ -3107,7 +3107,7 @@ test "struct namespaced variable" { | ... | @@ -3107,7 +3107,7 @@ test "struct namespaced variable" { |
| 3107 | // struct field order is determined by the compiler for optimal performance. | 3107 | // struct field order is determined by the compiler for optimal performance. |
| 3108 | // however, you can still calculate a struct base pointer given a field pointer: | 3108 | // however, you can still calculate a struct base pointer given a field pointer: |
| 3109 | fn setYBasedOnX(x: *f32, y: f32) void { | 3109 | fn setYBasedOnX(x: *f32, y: f32) void { |
| 3110 | const point = @fieldParentPtr(Point, "x", x); | 3110 | const point: *Point = @fieldParentPtr("x", x); |
| 3111 | point.y = y; | 3111 | point.y = y; |
| 3112 | } | 3112 | } |
| 3113 | test "field parent pointer" { | 3113 | test "field parent pointer" { |
| ... | @@ -8757,8 +8757,7 @@ test "decl access by string" { | ... | @@ -8757,8 +8757,7 @@ test "decl access by string" { |
| 8757 | {#header_close#} | 8757 | {#header_close#} |
| 8758 | 8758 | ||
| 8759 | {#header_open|@fieldParentPtr#} | 8759 | {#header_open|@fieldParentPtr#} |
| 8760 | <pre>{#syntax#}@fieldParentPtr(comptime ParentType: type, comptime field_name: []const u8, | 8760 | <pre>{#syntax#}@fieldParentPtr(comptime field_name: []const u8, field_ptr: *T) anytype{#endsyntax#}</pre> |
| 8761 | field_ptr: *T) *ParentType{#endsyntax#}</pre> | ||
| 8762 | <p> | 8761 | <p> |
| 8763 | Given a pointer to a field, returns the base pointer of a struct. | 8762 | Given a pointer to a field, returns the base pointer of a struct. |
| 8764 | </p> | 8763 | </p> |
lib/compiler/aro/aro/pragmas/gcc.zig+6-6| ... | @@ -37,18 +37,18 @@ const Directive = enum { | ... | @@ -37,18 +37,18 @@ const Directive = enum { |
| 37 | }; | 37 | }; |
| 38 | 38 | ||
| 39 | fn beforePreprocess(pragma: *Pragma, comp: *Compilation) void { | 39 | fn beforePreprocess(pragma: *Pragma, comp: *Compilation) void { |
| 40 | var self = @fieldParentPtr(GCC, "pragma", pragma); | 40 | var self: *GCC = @fieldParentPtr("pragma", pragma); |
| 41 | self.original_options = comp.diagnostics.options; | 41 | self.original_options = comp.diagnostics.options; |
| 42 | } | 42 | } |
| 43 | 43 | ||
| 44 | fn beforeParse(pragma: *Pragma, comp: *Compilation) void { | 44 | fn beforeParse(pragma: *Pragma, comp: *Compilation) void { |
| 45 | var self = @fieldParentPtr(GCC, "pragma", pragma); | 45 | var self: *GCC = @fieldParentPtr("pragma", pragma); |
| 46 | comp.diagnostics.options = self.original_options; | 46 | comp.diagnostics.options = self.original_options; |
| 47 | self.options_stack.items.len = 0; | 47 | self.options_stack.items.len = 0; |
| 48 | } | 48 | } |
| 49 | 49 | ||
| 50 | fn afterParse(pragma: *Pragma, comp: *Compilation) void { | 50 | fn afterParse(pragma: *Pragma, comp: *Compilation) void { |
| 51 | var self = @fieldParentPtr(GCC, "pragma", pragma); | 51 | var self: *GCC = @fieldParentPtr("pragma", pragma); |
| 52 | comp.diagnostics.options = self.original_options; | 52 | comp.diagnostics.options = self.original_options; |
| 53 | self.options_stack.items.len = 0; | 53 | self.options_stack.items.len = 0; |
| 54 | } | 54 | } |
| ... | @@ -60,7 +60,7 @@ pub fn init(allocator: mem.Allocator) !*Pragma { | ... | @@ -60,7 +60,7 @@ pub fn init(allocator: mem.Allocator) !*Pragma { |
| 60 | } | 60 | } |
| 61 | 61 | ||
| 62 | fn deinit(pragma: *Pragma, comp: *Compilation) void { | 62 | fn deinit(pragma: *Pragma, comp: *Compilation) void { |
| 63 | var self = @fieldParentPtr(GCC, "pragma", pragma); | 63 | var self: *GCC = @fieldParentPtr("pragma", pragma); |
| 64 | self.options_stack.deinit(comp.gpa); | 64 | self.options_stack.deinit(comp.gpa); |
| 65 | comp.gpa.destroy(self); | 65 | comp.gpa.destroy(self); |
| 66 | } | 66 | } |
| ... | @@ -108,7 +108,7 @@ fn diagnosticHandler(self: *GCC, pp: *Preprocessor, start_idx: TokenIndex) Pragm | ... | @@ -108,7 +108,7 @@ fn diagnosticHandler(self: *GCC, pp: *Preprocessor, start_idx: TokenIndex) Pragm |
| 108 | } | 108 | } |
| 109 | 109 | ||
| 110 | fn preprocessorHandler(pragma: *Pragma, pp: *Preprocessor, start_idx: TokenIndex) Pragma.Error!void { | 110 | fn preprocessorHandler(pragma: *Pragma, pp: *Preprocessor, start_idx: TokenIndex) Pragma.Error!void { |
| 111 | var self = @fieldParentPtr(GCC, "pragma", pragma); | 111 | var self: *GCC = @fieldParentPtr("pragma", pragma); |
| 112 | const directive_tok = pp.tokens.get(start_idx + 1); | 112 | const directive_tok = pp.tokens.get(start_idx + 1); |
| 113 | if (directive_tok.id == .nl) return; | 113 | if (directive_tok.id == .nl) return; |
| 114 | 114 | ||
| ... | @@ -174,7 +174,7 @@ fn preprocessorHandler(pragma: *Pragma, pp: *Preprocessor, start_idx: TokenIndex | ... | @@ -174,7 +174,7 @@ fn preprocessorHandler(pragma: *Pragma, pp: *Preprocessor, start_idx: TokenIndex |
| 174 | } | 174 | } |
| 175 | 175 | ||
| 176 | fn parserHandler(pragma: *Pragma, p: *Parser, start_idx: TokenIndex) Compilation.Error!void { | 176 | fn parserHandler(pragma: *Pragma, p: *Parser, start_idx: TokenIndex) Compilation.Error!void { |
| 177 | var self = @fieldParentPtr(GCC, "pragma", pragma); | 177 | var self: *GCC = @fieldParentPtr("pragma", pragma); |
| 178 | const directive_tok = p.pp.tokens.get(start_idx + 1); | 178 | const directive_tok = p.pp.tokens.get(start_idx + 1); |
| 179 | if (directive_tok.id == .nl) return; | 179 | if (directive_tok.id == .nl) return; |
| 180 | const name = p.pp.expandedSlice(directive_tok); | 180 | const name = p.pp.expandedSlice(directive_tok); |
lib/compiler/aro/aro/pragmas/message.zig+1-1| ... | @@ -22,7 +22,7 @@ pub fn init(allocator: mem.Allocator) !*Pragma { | ... | @@ -22,7 +22,7 @@ pub fn init(allocator: mem.Allocator) !*Pragma { |
| 22 | } | 22 | } |
| 23 | 23 | ||
| 24 | fn deinit(pragma: *Pragma, comp: *Compilation) void { | 24 | fn deinit(pragma: *Pragma, comp: *Compilation) void { |
| 25 | const self = @fieldParentPtr(Message, "pragma", pragma); | 25 | const self: *Message = @fieldParentPtr("pragma", pragma); |
| 26 | comp.gpa.destroy(self); | 26 | comp.gpa.destroy(self); |
| 27 | } | 27 | } |
| 28 | 28 |
lib/compiler/aro/aro/pragmas/once.zig+3-3| ... | @@ -27,18 +27,18 @@ pub fn init(allocator: mem.Allocator) !*Pragma { | ... | @@ -27,18 +27,18 @@ pub fn init(allocator: mem.Allocator) !*Pragma { |
| 27 | } | 27 | } |
| 28 | 28 | ||
| 29 | fn afterParse(pragma: *Pragma, _: *Compilation) void { | 29 | fn afterParse(pragma: *Pragma, _: *Compilation) void { |
| 30 | var self = @fieldParentPtr(Once, "pragma", pragma); | 30 | var self: *Once = @fieldParentPtr("pragma", pragma); |
| 31 | self.pragma_once.clearRetainingCapacity(); | 31 | self.pragma_once.clearRetainingCapacity(); |
| 32 | } | 32 | } |
| 33 | 33 | ||
| 34 | fn deinit(pragma: *Pragma, comp: *Compilation) void { | 34 | fn deinit(pragma: *Pragma, comp: *Compilation) void { |
| 35 | var self = @fieldParentPtr(Once, "pragma", pragma); | 35 | var self: *Once = @fieldParentPtr("pragma", pragma); |
| 36 | self.pragma_once.deinit(); | 36 | self.pragma_once.deinit(); |
| 37 | comp.gpa.destroy(self); | 37 | comp.gpa.destroy(self); |
| 38 | } | 38 | } |
| 39 | 39 | ||
| 40 | fn preprocessorHandler(pragma: *Pragma, pp: *Preprocessor, start_idx: TokenIndex) Pragma.Error!void { | 40 | fn preprocessorHandler(pragma: *Pragma, pp: *Preprocessor, start_idx: TokenIndex) Pragma.Error!void { |
| 41 | var self = @fieldParentPtr(Once, "pragma", pragma); | 41 | var self: *Once = @fieldParentPtr("pragma", pragma); |
| 42 | const name_tok = pp.tokens.get(start_idx); | 42 | const name_tok = pp.tokens.get(start_idx); |
| 43 | const next = pp.tokens.get(start_idx + 1); | 43 | const next = pp.tokens.get(start_idx + 1); |
| 44 | if (next.id != .nl) { | 44 | if (next.id != .nl) { |
lib/compiler/aro/aro/pragmas/pack.zig+2-2| ... | @@ -24,13 +24,13 @@ pub fn init(allocator: mem.Allocator) !*Pragma { | ... | @@ -24,13 +24,13 @@ pub fn init(allocator: mem.Allocator) !*Pragma { |
| 24 | } | 24 | } |
| 25 | 25 | ||
| 26 | fn deinit(pragma: *Pragma, comp: *Compilation) void { | 26 | fn deinit(pragma: *Pragma, comp: *Compilation) void { |
| 27 | var self = @fieldParentPtr(Pack, "pragma", pragma); | 27 | var self: *Pack = @fieldParentPtr("pragma", pragma); |
| 28 | self.stack.deinit(comp.gpa); | 28 | self.stack.deinit(comp.gpa); |
| 29 | comp.gpa.destroy(self); | 29 | comp.gpa.destroy(self); |
| 30 | } | 30 | } |
| 31 | 31 | ||
| 32 | fn parserHandler(pragma: *Pragma, p: *Parser, start_idx: TokenIndex) Compilation.Error!void { | 32 | fn parserHandler(pragma: *Pragma, p: *Parser, start_idx: TokenIndex) Compilation.Error!void { |
| 33 | var pack = @fieldParentPtr(Pack, "pragma", pragma); | 33 | var pack: *Pack = @fieldParentPtr("pragma", pragma); |
| 34 | var idx = start_idx + 1; | 34 | var idx = start_idx + 1; |
| 35 | const l_paren = p.pp.tokens.get(idx); | 35 | const l_paren = p.pp.tokens.get(idx); |
| 36 | if (l_paren.id != .l_paren) { | 36 | if (l_paren.id != .l_paren) { |
lib/compiler/aro/backend/Object.zig+5-5| ... | @@ -16,7 +16,7 @@ pub fn create(gpa: Allocator, target: std.Target) !*Object { | ... | @@ -16,7 +16,7 @@ pub fn create(gpa: Allocator, target: std.Target) !*Object { |
| 16 | 16 | ||
| 17 | pub fn deinit(obj: *Object) void { | 17 | pub fn deinit(obj: *Object) void { |
| 18 | switch (obj.format) { | 18 | switch (obj.format) { |
| 19 | .elf => @fieldParentPtr(Elf, "obj", obj).deinit(), | 19 | .elf => @as(*Elf, @fieldParentPtr("obj", obj)).deinit(), |
| 20 | else => unreachable, | 20 | else => unreachable, |
| 21 | } | 21 | } |
| 22 | } | 22 | } |
| ... | @@ -32,7 +32,7 @@ pub const Section = union(enum) { | ... | @@ -32,7 +32,7 @@ pub const Section = union(enum) { |
| 32 | 32 | ||
| 33 | pub fn getSection(obj: *Object, section: Section) !*std.ArrayList(u8) { | 33 | pub fn getSection(obj: *Object, section: Section) !*std.ArrayList(u8) { |
| 34 | switch (obj.format) { | 34 | switch (obj.format) { |
| 35 | .elf => return @fieldParentPtr(Elf, "obj", obj).getSection(section), | 35 | .elf => return @as(*Elf, @fieldParentPtr("obj", obj)).getSection(section), |
| 36 | else => unreachable, | 36 | else => unreachable, |
| 37 | } | 37 | } |
| 38 | } | 38 | } |
| ... | @@ -53,21 +53,21 @@ pub fn declareSymbol( | ... | @@ -53,21 +53,21 @@ pub fn declareSymbol( |
| 53 | size: u64, | 53 | size: u64, |
| 54 | ) ![]const u8 { | 54 | ) ![]const u8 { |
| 55 | switch (obj.format) { | 55 | switch (obj.format) { |
| 56 | .elf => return @fieldParentPtr(Elf, "obj", obj).declareSymbol(section, name, linkage, @"type", offset, size), | 56 | .elf => return @as(*Elf, @fieldParentPtr("obj", obj)).declareSymbol(section, name, linkage, @"type", offset, size), |
| 57 | else => unreachable, | 57 | else => unreachable, |
| 58 | } | 58 | } |
| 59 | } | 59 | } |
| 60 | 60 | ||
| 61 | pub fn addRelocation(obj: *Object, name: []const u8, section: Section, address: u64, addend: i64) !void { | 61 | pub fn addRelocation(obj: *Object, name: []const u8, section: Section, address: u64, addend: i64) !void { |
| 62 | switch (obj.format) { | 62 | switch (obj.format) { |
| 63 | .elf => return @fieldParentPtr(Elf, "obj", obj).addRelocation(name, section, address, addend), | 63 | .elf => return @as(*Elf, @fieldParentPtr("obj", obj)).addRelocation(name, section, address, addend), |
| 64 | else => unreachable, | 64 | else => unreachable, |
| 65 | } | 65 | } |
| 66 | } | 66 | } |
| 67 | 67 | ||
| 68 | pub fn finish(obj: *Object, file: std.fs.File) !void { | 68 | pub fn finish(obj: *Object, file: std.fs.File) !void { |
| 69 | switch (obj.format) { | 69 | switch (obj.format) { |
| 70 | .elf => return @fieldParentPtr(Elf, "obj", obj).finish(file), | 70 | .elf => return @as(*Elf, @fieldParentPtr("obj", obj)).finish(file), |
| 71 | else => unreachable, | 71 | else => unreachable, |
| 72 | } | 72 | } |
| 73 | } | 73 | } |
lib/compiler/aro_translate_c.zig+10-10| ... | @@ -1098,13 +1098,13 @@ pub fn ScopeExtra(comptime ScopeExtraContext: type, comptime ScopeExtraType: typ | ... | @@ -1098,13 +1098,13 @@ pub fn ScopeExtra(comptime ScopeExtraContext: type, comptime ScopeExtraType: typ |
| 1098 | } | 1098 | } |
| 1099 | }; | 1099 | }; |
| 1100 | 1100 | ||
| 1101 | pub fn findBlockScope(inner: *ScopeExtraScope, c: *ScopeExtraContext) !*ScopeExtraScope.Block { | 1101 | pub fn findBlockScope(inner: *ScopeExtraScope, c: *ScopeExtraContext) !*Block { |
| 1102 | var scope = inner; | 1102 | var scope = inner; |
| 1103 | while (true) { | 1103 | while (true) { |
| 1104 | switch (scope.id) { | 1104 | switch (scope.id) { |
| 1105 | .root => unreachable, | 1105 | .root => unreachable, |
| 1106 | .block => return @fieldParentPtr(Block, "base", scope), | 1106 | .block => return @fieldParentPtr("base", scope), |
| 1107 | .condition => return @fieldParentPtr(Condition, "base", scope).getBlockScope(c), | 1107 | .condition => return @as(*Condition, @fieldParentPtr("base", scope)).getBlockScope(c), |
| 1108 | else => scope = scope.parent.?, | 1108 | else => scope = scope.parent.?, |
| 1109 | } | 1109 | } |
| 1110 | } | 1110 | } |
| ... | @@ -1116,7 +1116,7 @@ pub fn ScopeExtra(comptime ScopeExtraContext: type, comptime ScopeExtraType: typ | ... | @@ -1116,7 +1116,7 @@ pub fn ScopeExtra(comptime ScopeExtraContext: type, comptime ScopeExtraType: typ |
| 1116 | switch (scope.id) { | 1116 | switch (scope.id) { |
| 1117 | .root => unreachable, | 1117 | .root => unreachable, |
| 1118 | .block => { | 1118 | .block => { |
| 1119 | const block = @fieldParentPtr(Block, "base", scope); | 1119 | const block: *Block = @fieldParentPtr("base", scope); |
| 1120 | if (block.return_type) |ty| return ty; | 1120 | if (block.return_type) |ty| return ty; |
| 1121 | scope = scope.parent.?; | 1121 | scope = scope.parent.?; |
| 1122 | }, | 1122 | }, |
| ... | @@ -1128,15 +1128,15 @@ pub fn ScopeExtra(comptime ScopeExtraContext: type, comptime ScopeExtraType: typ | ... | @@ -1128,15 +1128,15 @@ pub fn ScopeExtra(comptime ScopeExtraContext: type, comptime ScopeExtraType: typ |
| 1128 | pub fn getAlias(scope: *ScopeExtraScope, name: []const u8) []const u8 { | 1128 | pub fn getAlias(scope: *ScopeExtraScope, name: []const u8) []const u8 { |
| 1129 | return switch (scope.id) { | 1129 | return switch (scope.id) { |
| 1130 | .root => return name, | 1130 | .root => return name, |
| 1131 | .block => @fieldParentPtr(Block, "base", scope).getAlias(name), | 1131 | .block => @as(*Block, @fieldParentPtr("base", scope)).getAlias(name), |
| 1132 | .loop, .do_loop, .condition => scope.parent.?.getAlias(name), | 1132 | .loop, .do_loop, .condition => scope.parent.?.getAlias(name), |
| 1133 | }; | 1133 | }; |
| 1134 | } | 1134 | } |
| 1135 | 1135 | ||
| 1136 | pub fn contains(scope: *ScopeExtraScope, name: []const u8) bool { | 1136 | pub fn contains(scope: *ScopeExtraScope, name: []const u8) bool { |
| 1137 | return switch (scope.id) { | 1137 | return switch (scope.id) { |
| 1138 | .root => @fieldParentPtr(Root, "base", scope).contains(name), | 1138 | .root => @as(*Root, @fieldParentPtr("base", scope)).contains(name), |
| 1139 | .block => @fieldParentPtr(Block, "base", scope).contains(name), | 1139 | .block => @as(*Block, @fieldParentPtr("base", scope)).contains(name), |
| 1140 | .loop, .do_loop, .condition => scope.parent.?.contains(name), | 1140 | .loop, .do_loop, .condition => scope.parent.?.contains(name), |
| 1141 | }; | 1141 | }; |
| 1142 | } | 1142 | } |
| ... | @@ -1158,11 +1158,11 @@ pub fn ScopeExtra(comptime ScopeExtraContext: type, comptime ScopeExtraType: typ | ... | @@ -1158,11 +1158,11 @@ pub fn ScopeExtra(comptime ScopeExtraContext: type, comptime ScopeExtraType: typ |
| 1158 | while (true) { | 1158 | while (true) { |
| 1159 | switch (scope.id) { | 1159 | switch (scope.id) { |
| 1160 | .root => { | 1160 | .root => { |
| 1161 | const root = @fieldParentPtr(Root, "base", scope); | 1161 | const root: *Root = @fieldParentPtr("base", scope); |
| 1162 | return root.nodes.append(node); | 1162 | return root.nodes.append(node); |
| 1163 | }, | 1163 | }, |
| 1164 | .block => { | 1164 | .block => { |
| 1165 | const block = @fieldParentPtr(Block, "base", scope); | 1165 | const block: *Block = @fieldParentPtr("base", scope); |
| 1166 | return block.statements.append(node); | 1166 | return block.statements.append(node); |
| 1167 | }, | 1167 | }, |
| 1168 | else => scope = scope.parent.?, | 1168 | else => scope = scope.parent.?, |
| ... | @@ -1184,7 +1184,7 @@ pub fn ScopeExtra(comptime ScopeExtraContext: type, comptime ScopeExtraType: typ | ... | @@ -1184,7 +1184,7 @@ pub fn ScopeExtra(comptime ScopeExtraContext: type, comptime ScopeExtraType: typ |
| 1184 | switch (scope.id) { | 1184 | switch (scope.id) { |
| 1185 | .root => return, | 1185 | .root => return, |
| 1186 | .block => { | 1186 | .block => { |
| 1187 | const block = @fieldParentPtr(Block, "base", scope); | 1187 | const block: *Block = @fieldParentPtr("base", scope); |
| 1188 | if (block.variable_discards.get(name)) |discard| { | 1188 | if (block.variable_discards.get(name)) |discard| { |
| 1189 | discard.data.should_skip = true; | 1189 | discard.data.should_skip = true; |
| 1190 | return; | 1190 | return; |
lib/compiler/aro_translate_c/ast.zig+8-8| ... | @@ -409,7 +409,7 @@ pub const Node = extern union { | ... | @@ -409,7 +409,7 @@ pub const Node = extern union { |
| 409 | return null; | 409 | return null; |
| 410 | 410 | ||
| 411 | if (self.ptr_otherwise.tag == t) | 411 | if (self.ptr_otherwise.tag == t) |
| 412 | return @fieldParentPtr(t.Type(), "base", self.ptr_otherwise); | 412 | return @alignCast(@fieldParentPtr("base", self.ptr_otherwise)); |
| 413 | 413 | ||
| 414 | return null; | 414 | return null; |
| 415 | } | 415 | } |
| ... | @@ -1220,7 +1220,7 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex { | ... | @@ -1220,7 +1220,7 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex { |
| 1220 | }); | 1220 | }); |
| 1221 | }, | 1221 | }, |
| 1222 | .pub_var_simple, .var_simple => { | 1222 | .pub_var_simple, .var_simple => { |
| 1223 | const payload = @fieldParentPtr(Payload.SimpleVarDecl, "base", node.ptr_otherwise).data; | 1223 | const payload = @as(*Payload.SimpleVarDecl, @alignCast(@fieldParentPtr("base", node.ptr_otherwise))).data; |
| 1224 | if (node.tag() == .pub_var_simple) _ = try c.addToken(.keyword_pub, "pub"); | 1224 | if (node.tag() == .pub_var_simple) _ = try c.addToken(.keyword_pub, "pub"); |
| 1225 | const const_tok = try c.addToken(.keyword_const, "const"); | 1225 | const const_tok = try c.addToken(.keyword_const, "const"); |
| 1226 | _ = try c.addIdentifier(payload.name); | 1226 | _ = try c.addIdentifier(payload.name); |
| ... | @@ -1293,7 +1293,7 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex { | ... | @@ -1293,7 +1293,7 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex { |
| 1293 | }, | 1293 | }, |
| 1294 | .var_decl => return renderVar(c, node), | 1294 | .var_decl => return renderVar(c, node), |
| 1295 | .arg_redecl, .alias => { | 1295 | .arg_redecl, .alias => { |
| 1296 | const payload = @fieldParentPtr(Payload.ArgRedecl, "base", node.ptr_otherwise).data; | 1296 | const payload = @as(*Payload.ArgRedecl, @alignCast(@fieldParentPtr("base", node.ptr_otherwise))).data; |
| 1297 | if (node.tag() == .alias) _ = try c.addToken(.keyword_pub, "pub"); | 1297 | if (node.tag() == .alias) _ = try c.addToken(.keyword_pub, "pub"); |
| 1298 | const mut_tok = if (node.tag() == .alias) | 1298 | const mut_tok = if (node.tag() == .alias) |
| 1299 | try c.addToken(.keyword_const, "const") | 1299 | try c.addToken(.keyword_const, "const") |
| ... | @@ -1492,7 +1492,7 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex { | ... | @@ -1492,7 +1492,7 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex { |
| 1492 | }); | 1492 | }); |
| 1493 | }, | 1493 | }, |
| 1494 | .c_pointer, .single_pointer => { | 1494 | .c_pointer, .single_pointer => { |
| 1495 | const payload = @fieldParentPtr(Payload.Pointer, "base", node.ptr_otherwise).data; | 1495 | const payload = @as(*Payload.Pointer, @alignCast(@fieldParentPtr("base", node.ptr_otherwise))).data; |
| 1496 | 1496 | ||
| 1497 | const asterisk = if (node.tag() == .single_pointer) | 1497 | const asterisk = if (node.tag() == .single_pointer) |
| 1498 | try c.addToken(.asterisk, "*") | 1498 | try c.addToken(.asterisk, "*") |
| ... | @@ -2085,7 +2085,7 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex { | ... | @@ -2085,7 +2085,7 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex { |
| 2085 | } | 2085 | } |
| 2086 | 2086 | ||
| 2087 | fn renderRecord(c: *Context, node: Node) !NodeIndex { | 2087 | fn renderRecord(c: *Context, node: Node) !NodeIndex { |
| 2088 | const payload = @fieldParentPtr(Payload.Record, "base", node.ptr_otherwise).data; | 2088 | const payload = @as(*Payload.Record, @alignCast(@fieldParentPtr("base", node.ptr_otherwise))).data; |
| 2089 | if (payload.layout == .@"packed") | 2089 | if (payload.layout == .@"packed") |
| 2090 | _ = try c.addToken(.keyword_packed, "packed") | 2090 | _ = try c.addToken(.keyword_packed, "packed") |
| 2091 | else if (payload.layout == .@"extern") | 2091 | else if (payload.layout == .@"extern") |
| ... | @@ -2487,7 +2487,7 @@ fn renderNodeGrouped(c: *Context, node: Node) !NodeIndex { | ... | @@ -2487,7 +2487,7 @@ fn renderNodeGrouped(c: *Context, node: Node) !NodeIndex { |
| 2487 | } | 2487 | } |
| 2488 | 2488 | ||
| 2489 | fn renderPrefixOp(c: *Context, node: Node, tag: std.zig.Ast.Node.Tag, tok_tag: TokenTag, bytes: []const u8) !NodeIndex { | 2489 | fn renderPrefixOp(c: *Context, node: Node, tag: std.zig.Ast.Node.Tag, tok_tag: TokenTag, bytes: []const u8) !NodeIndex { |
| 2490 | const payload = @fieldParentPtr(Payload.UnOp, "base", node.ptr_otherwise).data; | 2490 | const payload = @as(*Payload.UnOp, @alignCast(@fieldParentPtr("base", node.ptr_otherwise))).data; |
| 2491 | return c.addNode(.{ | 2491 | return c.addNode(.{ |
| 2492 | .tag = tag, | 2492 | .tag = tag, |
| 2493 | .main_token = try c.addToken(tok_tag, bytes), | 2493 | .main_token = try c.addToken(tok_tag, bytes), |
| ... | @@ -2499,7 +2499,7 @@ fn renderPrefixOp(c: *Context, node: Node, tag: std.zig.Ast.Node.Tag, tok_tag: T | ... | @@ -2499,7 +2499,7 @@ fn renderPrefixOp(c: *Context, node: Node, tag: std.zig.Ast.Node.Tag, tok_tag: T |
| 2499 | } | 2499 | } |
| 2500 | 2500 | ||
| 2501 | fn renderBinOpGrouped(c: *Context, node: Node, tag: std.zig.Ast.Node.Tag, tok_tag: TokenTag, bytes: []const u8) !NodeIndex { | 2501 | fn renderBinOpGrouped(c: *Context, node: Node, tag: std.zig.Ast.Node.Tag, tok_tag: TokenTag, bytes: []const u8) !NodeIndex { |
| 2502 | const payload = @fieldParentPtr(Payload.BinOp, "base", node.ptr_otherwise).data; | 2502 | const payload = @as(*Payload.BinOp, @alignCast(@fieldParentPtr("base", node.ptr_otherwise))).data; |
| 2503 | const lhs = try renderNodeGrouped(c, payload.lhs); | 2503 | const lhs = try renderNodeGrouped(c, payload.lhs); |
| 2504 | return c.addNode(.{ | 2504 | return c.addNode(.{ |
| 2505 | .tag = tag, | 2505 | .tag = tag, |
| ... | @@ -2512,7 +2512,7 @@ fn renderBinOpGrouped(c: *Context, node: Node, tag: std.zig.Ast.Node.Tag, tok_ta | ... | @@ -2512,7 +2512,7 @@ fn renderBinOpGrouped(c: *Context, node: Node, tag: std.zig.Ast.Node.Tag, tok_ta |
| 2512 | } | 2512 | } |
| 2513 | 2513 | ||
| 2514 | fn renderBinOp(c: *Context, node: Node, tag: std.zig.Ast.Node.Tag, tok_tag: TokenTag, bytes: []const u8) !NodeIndex { | 2514 | fn renderBinOp(c: *Context, node: Node, tag: std.zig.Ast.Node.Tag, tok_tag: TokenTag, bytes: []const u8) !NodeIndex { |
| 2515 | const payload = @fieldParentPtr(Payload.BinOp, "base", node.ptr_otherwise).data; | 2515 | const payload = @as(*Payload.BinOp, @alignCast(@fieldParentPtr("base", node.ptr_otherwise))).data; |
| 2516 | const lhs = try renderNode(c, payload.lhs); | 2516 | const lhs = try renderNode(c, payload.lhs); |
| 2517 | return c.addNode(.{ | 2517 | return c.addNode(.{ |
| 2518 | .tag = tag, | 2518 | .tag = tag, |
lib/compiler/resinator/ast.zig+85-88| ... | @@ -19,7 +19,7 @@ pub const Tree = struct { | ... | @@ -19,7 +19,7 @@ pub const Tree = struct { |
| 19 | } | 19 | } |
| 20 | 20 | ||
| 21 | pub fn root(self: *Tree) *Node.Root { | 21 | pub fn root(self: *Tree) *Node.Root { |
| 22 | return @fieldParentPtr(Node.Root, "base", self.node); | 22 | return @alignCast(@fieldParentPtr("base", self.node)); |
| 23 | } | 23 | } |
| 24 | 24 | ||
| 25 | pub fn dump(self: *Tree, writer: anytype) @TypeOf(writer).Error!void { | 25 | pub fn dump(self: *Tree, writer: anytype) @TypeOf(writer).Error!void { |
| ... | @@ -174,7 +174,7 @@ pub const Node = struct { | ... | @@ -174,7 +174,7 @@ pub const Node = struct { |
| 174 | 174 | ||
| 175 | pub fn cast(base: *Node, comptime id: Id) ?*id.Type() { | 175 | pub fn cast(base: *Node, comptime id: Id) ?*id.Type() { |
| 176 | if (base.id == id) { | 176 | if (base.id == id) { |
| 177 | return @fieldParentPtr(id.Type(), "base", base); | 177 | return @alignCast(@fieldParentPtr("base", base)); |
| 178 | } | 178 | } |
| 179 | return null; | 179 | return null; |
| 180 | } | 180 | } |
| ... | @@ -461,7 +461,7 @@ pub const Node = struct { | ... | @@ -461,7 +461,7 @@ pub const Node = struct { |
| 461 | pub fn isNumberExpression(node: *const Node) bool { | 461 | pub fn isNumberExpression(node: *const Node) bool { |
| 462 | switch (node.id) { | 462 | switch (node.id) { |
| 463 | .literal => { | 463 | .literal => { |
| 464 | const literal = @fieldParentPtr(Node.Literal, "base", node); | 464 | const literal: *const Node.Literal = @alignCast(@fieldParentPtr("base", node)); |
| 465 | return switch (literal.token.id) { | 465 | return switch (literal.token.id) { |
| 466 | .number => true, | 466 | .number => true, |
| 467 | else => false, | 467 | else => false, |
| ... | @@ -475,7 +475,7 @@ pub const Node = struct { | ... | @@ -475,7 +475,7 @@ pub const Node = struct { |
| 475 | pub fn isStringLiteral(node: *const Node) bool { | 475 | pub fn isStringLiteral(node: *const Node) bool { |
| 476 | switch (node.id) { | 476 | switch (node.id) { |
| 477 | .literal => { | 477 | .literal => { |
| 478 | const literal = @fieldParentPtr(Node.Literal, "base", node); | 478 | const literal: *const Node.Literal = @alignCast(@fieldParentPtr("base", node)); |
| 479 | return switch (literal.token.id) { | 479 | return switch (literal.token.id) { |
| 480 | .quoted_ascii_string, .quoted_wide_string => true, | 480 | .quoted_ascii_string, .quoted_wide_string => true, |
| 481 | else => false, | 481 | else => false, |
| ... | @@ -489,105 +489,103 @@ pub const Node = struct { | ... | @@ -489,105 +489,103 @@ pub const Node = struct { |
| 489 | switch (node.id) { | 489 | switch (node.id) { |
| 490 | .root => unreachable, | 490 | .root => unreachable, |
| 491 | .resource_external => { | 491 | .resource_external => { |
| 492 | const casted = @fieldParentPtr(Node.ResourceExternal, "base", node); | 492 | const casted: *const Node.ResourceExternal = @alignCast(@fieldParentPtr("base", node)); |
| 493 | return casted.id; | 493 | return casted.id; |
| 494 | }, | 494 | }, |
| 495 | .resource_raw_data => { | 495 | .resource_raw_data => { |
| 496 | const casted = @fieldParentPtr(Node.ResourceRawData, "base", node); | 496 | const casted: *const Node.ResourceRawData = @alignCast(@fieldParentPtr("base", node)); |
| 497 | return casted.id; | 497 | return casted.id; |
| 498 | }, | 498 | }, |
| 499 | .literal => { | 499 | .literal => { |
| 500 | const casted = @fieldParentPtr(Node.Literal, "base", node); | 500 | const casted: *const Node.Literal = @alignCast(@fieldParentPtr("base", node)); |
| 501 | return casted.token; | 501 | return casted.token; |
| 502 | }, | 502 | }, |
| 503 | .binary_expression => { | 503 | .binary_expression => { |
| 504 | const casted = @fieldParentPtr(Node.BinaryExpression, "base", node); | 504 | const casted: *const Node.BinaryExpression = @alignCast(@fieldParentPtr("base", node)); |
| 505 | return casted.left.getFirstToken(); | 505 | return casted.left.getFirstToken(); |
| 506 | }, | 506 | }, |
| 507 | .grouped_expression => { | 507 | .grouped_expression => { |
| 508 | const casted = @fieldParentPtr(Node.GroupedExpression, "base", node); | 508 | const casted: *const Node.GroupedExpression = @alignCast(@fieldParentPtr("base", node)); |
| 509 | return casted.open_token; | 509 | return casted.open_token; |
| 510 | }, | 510 | }, |
| 511 | .not_expression => { | 511 | .not_expression => { |
| 512 | const casted = @fieldParentPtr(Node.NotExpression, "base", node); | 512 | const casted: *const Node.NotExpression = @alignCast(@fieldParentPtr("base", node)); |
| 513 | return casted.not_token; | 513 | return casted.not_token; |
| 514 | }, | 514 | }, |
| 515 | .accelerators => { | 515 | .accelerators => { |
| 516 | const casted = @fieldParentPtr(Node.Accelerators, "base", node); | 516 | const casted: *const Node.Accelerators = @alignCast(@fieldParentPtr("base", node)); |
| 517 | return casted.id; | 517 | return casted.id; |
| 518 | }, | 518 | }, |
| 519 | .accelerator => { | 519 | .accelerator => { |
| 520 | const casted = @fieldParentPtr(Node.Accelerator, "base", node); | 520 | const casted: *const Node.Accelerator = @alignCast(@fieldParentPtr("base", node)); |
| 521 | return casted.event.getFirstToken(); | 521 | return casted.event.getFirstToken(); |
| 522 | }, | 522 | }, |
| 523 | .dialog => { | 523 | .dialog => { |
| 524 | const casted = @fieldParentPtr(Node.Dialog, "base", node); | 524 | const casted: *const Node.Dialog = @alignCast(@fieldParentPtr("base", node)); |
| 525 | return casted.id; | 525 | return casted.id; |
| 526 | }, | 526 | }, |
| 527 | .control_statement => { | 527 | .control_statement => { |
| 528 | const casted = @fieldParentPtr(Node.ControlStatement, "base", node); | 528 | const casted: *const Node.ControlStatement = @alignCast(@fieldParentPtr("base", node)); |
| 529 | return casted.type; | 529 | return casted.type; |
| 530 | }, | 530 | }, |
| 531 | .toolbar => { | 531 | .toolbar => { |
| 532 | const casted = @fieldParentPtr(Node.Toolbar, "base", node); | 532 | const casted: *const Node.Toolbar = @alignCast(@fieldParentPtr("base", node)); |
| 533 | return casted.id; | 533 | return casted.id; |
| 534 | }, | 534 | }, |
| 535 | .menu => { | 535 | .menu => { |
| 536 | const casted = @fieldParentPtr(Node.Menu, "base", node); | 536 | const casted: *const Node.Menu = @alignCast(@fieldParentPtr("base", node)); |
| 537 | return casted.id; | 537 | return casted.id; |
| 538 | }, | 538 | }, |
| 539 | inline .menu_item, .menu_item_separator, .menu_item_ex => |menu_item_type| { | 539 | inline .menu_item, .menu_item_separator, .menu_item_ex => |menu_item_type| { |
| 540 | const node_type = menu_item_type.Type(); | 540 | const casted: *const menu_item_type.Type() = @alignCast(@fieldParentPtr("base", node)); |
| 541 | const casted = @fieldParentPtr(node_type, "base", node); | ||
| 542 | return casted.menuitem; | 541 | return casted.menuitem; |
| 543 | }, | 542 | }, |
| 544 | inline .popup, .popup_ex => |popup_type| { | 543 | inline .popup, .popup_ex => |popup_type| { |
| 545 | const node_type = popup_type.Type(); | 544 | const casted: *const popup_type.Type() = @alignCast(@fieldParentPtr("base", node)); |
| 546 | const casted = @fieldParentPtr(node_type, "base", node); | ||
| 547 | return casted.popup; | 545 | return casted.popup; |
| 548 | }, | 546 | }, |
| 549 | .version_info => { | 547 | .version_info => { |
| 550 | const casted = @fieldParentPtr(Node.VersionInfo, "base", node); | 548 | const casted: *const Node.VersionInfo = @alignCast(@fieldParentPtr("base", node)); |
| 551 | return casted.id; | 549 | return casted.id; |
| 552 | }, | 550 | }, |
| 553 | .version_statement => { | 551 | .version_statement => { |
| 554 | const casted = @fieldParentPtr(Node.VersionStatement, "base", node); | 552 | const casted: *const Node.VersionStatement = @alignCast(@fieldParentPtr("base", node)); |
| 555 | return casted.type; | 553 | return casted.type; |
| 556 | }, | 554 | }, |
| 557 | .block => { | 555 | .block => { |
| 558 | const casted = @fieldParentPtr(Node.Block, "base", node); | 556 | const casted: *const Node.Block = @alignCast(@fieldParentPtr("base", node)); |
| 559 | return casted.identifier; | 557 | return casted.identifier; |
| 560 | }, | 558 | }, |
| 561 | .block_value => { | 559 | .block_value => { |
| 562 | const casted = @fieldParentPtr(Node.BlockValue, "base", node); | 560 | const casted: *const Node.BlockValue = @alignCast(@fieldParentPtr("base", node)); |
| 563 | return casted.identifier; | 561 | return casted.identifier; |
| 564 | }, | 562 | }, |
| 565 | .block_value_value => { | 563 | .block_value_value => { |
| 566 | const casted = @fieldParentPtr(Node.BlockValueValue, "base", node); | 564 | const casted: *const Node.BlockValueValue = @alignCast(@fieldParentPtr("base", node)); |
| 567 | return casted.expression.getFirstToken(); | 565 | return casted.expression.getFirstToken(); |
| 568 | }, | 566 | }, |
| 569 | .string_table => { | 567 | .string_table => { |
| 570 | const casted = @fieldParentPtr(Node.StringTable, "base", node); | 568 | const casted: *const Node.StringTable = @alignCast(@fieldParentPtr("base", node)); |
| 571 | return casted.type; | 569 | return casted.type; |
| 572 | }, | 570 | }, |
| 573 | .string_table_string => { | 571 | .string_table_string => { |
| 574 | const casted = @fieldParentPtr(Node.StringTableString, "base", node); | 572 | const casted: *const Node.StringTableString = @alignCast(@fieldParentPtr("base", node)); |
| 575 | return casted.id.getFirstToken(); | 573 | return casted.id.getFirstToken(); |
| 576 | }, | 574 | }, |
| 577 | .language_statement => { | 575 | .language_statement => { |
| 578 | const casted = @fieldParentPtr(Node.LanguageStatement, "base", node); | 576 | const casted: *const Node.LanguageStatement = @alignCast(@fieldParentPtr("base", node)); |
| 579 | return casted.language_token; | 577 | return casted.language_token; |
| 580 | }, | 578 | }, |
| 581 | .font_statement => { | 579 | .font_statement => { |
| 582 | const casted = @fieldParentPtr(Node.FontStatement, "base", node); | 580 | const casted: *const Node.FontStatement = @alignCast(@fieldParentPtr("base", node)); |
| 583 | return casted.identifier; | 581 | return casted.identifier; |
| 584 | }, | 582 | }, |
| 585 | .simple_statement => { | 583 | .simple_statement => { |
| 586 | const casted = @fieldParentPtr(Node.SimpleStatement, "base", node); | 584 | const casted: *const Node.SimpleStatement = @alignCast(@fieldParentPtr("base", node)); |
| 587 | return casted.identifier; | 585 | return casted.identifier; |
| 588 | }, | 586 | }, |
| 589 | .invalid => { | 587 | .invalid => { |
| 590 | const casted = @fieldParentPtr(Node.Invalid, "base", node); | 588 | const casted: *const Node.Invalid = @alignCast(@fieldParentPtr("base", node)); |
| 591 | return casted.context[0]; | 589 | return casted.context[0]; |
| 592 | }, | 590 | }, |
| 593 | } | 591 | } |
| ... | @@ -597,44 +595,44 @@ pub const Node = struct { | ... | @@ -597,44 +595,44 @@ pub const Node = struct { |
| 597 | switch (node.id) { | 595 | switch (node.id) { |
| 598 | .root => unreachable, | 596 | .root => unreachable, |
| 599 | .resource_external => { | 597 | .resource_external => { |
| 600 | const casted = @fieldParentPtr(Node.ResourceExternal, "base", node); | 598 | const casted: *const Node.ResourceExternal = @alignCast(@fieldParentPtr("base", node)); |
| 601 | return casted.filename.getLastToken(); | 599 | return casted.filename.getLastToken(); |
| 602 | }, | 600 | }, |
| 603 | .resource_raw_data => { | 601 | .resource_raw_data => { |
| 604 | const casted = @fieldParentPtr(Node.ResourceRawData, "base", node); | 602 | const casted: *const Node.ResourceRawData = @alignCast(@fieldParentPtr("base", node)); |
| 605 | return casted.end_token; | 603 | return casted.end_token; |
| 606 | }, | 604 | }, |
| 607 | .literal => { | 605 | .literal => { |
| 608 | const casted = @fieldParentPtr(Node.Literal, "base", node); | 606 | const casted: *const Node.Literal = @alignCast(@fieldParentPtr("base", node)); |
| 609 | return casted.token; | 607 | return casted.token; |
| 610 | }, | 608 | }, |
| 611 | .binary_expression => { | 609 | .binary_expression => { |
| 612 | const casted = @fieldParentPtr(Node.BinaryExpression, "base", node); | 610 | const casted: *const Node.BinaryExpression = @alignCast(@fieldParentPtr("base", node)); |
| 613 | return casted.right.getLastToken(); | 611 | return casted.right.getLastToken(); |
| 614 | }, | 612 | }, |
| 615 | .grouped_expression => { | 613 | .grouped_expression => { |
| 616 | const casted = @fieldParentPtr(Node.GroupedExpression, "base", node); | 614 | const casted: *const Node.GroupedExpression = @alignCast(@fieldParentPtr("base", node)); |
| 617 | return casted.close_token; | 615 | return casted.close_token; |
| 618 | }, | 616 | }, |
| 619 | .not_expression => { | 617 | .not_expression => { |
| 620 | const casted = @fieldParentPtr(Node.NotExpression, "base", node); | 618 | const casted: *const Node.NotExpression = @alignCast(@fieldParentPtr("base", node)); |
| 621 | return casted.number_token; | 619 | return casted.number_token; |
| 622 | }, | 620 | }, |
| 623 | .accelerators => { | 621 | .accelerators => { |
| 624 | const casted = @fieldParentPtr(Node.Accelerators, "base", node); | 622 | const casted: *const Node.Accelerators = @alignCast(@fieldParentPtr("base", node)); |
| 625 | return casted.end_token; | 623 | return casted.end_token; |
| 626 | }, | 624 | }, |
| 627 | .accelerator => { | 625 | .accelerator => { |
| 628 | const casted = @fieldParentPtr(Node.Accelerator, "base", node); | 626 | const casted: *const Node.Accelerator = @alignCast(@fieldParentPtr("base", node)); |
| 629 | if (casted.type_and_options.len > 0) return casted.type_and_options[casted.type_and_options.len - 1]; | 627 | if (casted.type_and_options.len > 0) return casted.type_and_options[casted.type_and_options.len - 1]; |
| 630 | return casted.idvalue.getLastToken(); | 628 | return casted.idvalue.getLastToken(); |
| 631 | }, | 629 | }, |
| 632 | .dialog => { | 630 | .dialog => { |
| 633 | const casted = @fieldParentPtr(Node.Dialog, "base", node); | 631 | const casted: *const Node.Dialog = @alignCast(@fieldParentPtr("base", node)); |
| 634 | return casted.end_token; | 632 | return casted.end_token; |
| 635 | }, | 633 | }, |
| 636 | .control_statement => { | 634 | .control_statement => { |
| 637 | const casted = @fieldParentPtr(Node.ControlStatement, "base", node); | 635 | const casted: *const Node.ControlStatement = @alignCast(@fieldParentPtr("base", node)); |
| 638 | if (casted.extra_data_end) |token| return token; | 636 | if (casted.extra_data_end) |token| return token; |
| 639 | if (casted.help_id) |help_id_node| return help_id_node.getLastToken(); | 637 | if (casted.help_id) |help_id_node| return help_id_node.getLastToken(); |
| 640 | if (casted.exstyle) |exstyle_node| return exstyle_node.getLastToken(); | 638 | if (casted.exstyle) |exstyle_node| return exstyle_node.getLastToken(); |
| ... | @@ -647,80 +645,79 @@ pub const Node = struct { | ... | @@ -647,80 +645,79 @@ pub const Node = struct { |
| 647 | return casted.height.getLastToken(); | 645 | return casted.height.getLastToken(); |
| 648 | }, | 646 | }, |
| 649 | .toolbar => { | 647 | .toolbar => { |
| 650 | const casted = @fieldParentPtr(Node.Toolbar, "base", node); | 648 | const casted: *const Node.Toolbar = @alignCast(@fieldParentPtr("base", node)); |
| 651 | return casted.end_token; | 649 | return casted.end_token; |
| 652 | }, | 650 | }, |
| 653 | .menu => { | 651 | .menu => { |
| 654 | const casted = @fieldParentPtr(Node.Menu, "base", node); | 652 | const casted: *const Node.Menu = @alignCast(@fieldParentPtr("base", node)); |
| 655 | return casted.end_token; | 653 | return casted.end_token; |
| 656 | }, | 654 | }, |
| 657 | .menu_item => { | 655 | .menu_item => { |
| 658 | const casted = @fieldParentPtr(Node.MenuItem, "base", node); | 656 | const casted: *const Node.MenuItem = @alignCast(@fieldParentPtr("base", node)); |
| 659 | if (casted.option_list.len > 0) return casted.option_list[casted.option_list.len - 1]; | 657 | if (casted.option_list.len > 0) return casted.option_list[casted.option_list.len - 1]; |
| 660 | return casted.result.getLastToken(); | 658 | return casted.result.getLastToken(); |
| 661 | }, | 659 | }, |
| 662 | .menu_item_separator => { | 660 | .menu_item_separator => { |
| 663 | const casted = @fieldParentPtr(Node.MenuItemSeparator, "base", node); | 661 | const casted: *const Node.MenuItemSeparator = @alignCast(@fieldParentPtr("base", node)); |
| 664 | return casted.separator; | 662 | return casted.separator; |
| 665 | }, | 663 | }, |
| 666 | .menu_item_ex => { | 664 | .menu_item_ex => { |
| 667 | const casted = @fieldParentPtr(Node.MenuItemEx, "base", node); | 665 | const casted: *const Node.MenuItemEx = @alignCast(@fieldParentPtr("base", node)); |
| 668 | if (casted.state) |state_node| return state_node.getLastToken(); | 666 | if (casted.state) |state_node| return state_node.getLastToken(); |
| 669 | if (casted.type) |type_node| return type_node.getLastToken(); | 667 | if (casted.type) |type_node| return type_node.getLastToken(); |
| 670 | if (casted.id) |id_node| return id_node.getLastToken(); | 668 | if (casted.id) |id_node| return id_node.getLastToken(); |
| 671 | return casted.text; | 669 | return casted.text; |
| 672 | }, | 670 | }, |
| 673 | inline .popup, .popup_ex => |popup_type| { | 671 | inline .popup, .popup_ex => |popup_type| { |
| 674 | const node_type = popup_type.Type(); | 672 | const casted: *const popup_type.Type() = @alignCast(@fieldParentPtr("base", node)); |
| 675 | const casted = @fieldParentPtr(node_type, "base", node); | ||
| 676 | return casted.end_token; | 673 | return casted.end_token; |
| 677 | }, | 674 | }, |
| 678 | .version_info => { | 675 | .version_info => { |
| 679 | const casted = @fieldParentPtr(Node.VersionInfo, "base", node); | 676 | const casted: *const Node.VersionInfo = @alignCast(@fieldParentPtr("base", node)); |
| 680 | return casted.end_token; | 677 | return casted.end_token; |
| 681 | }, | 678 | }, |
| 682 | .version_statement => { | 679 | .version_statement => { |
| 683 | const casted = @fieldParentPtr(Node.VersionStatement, "base", node); | 680 | const casted: *const Node.VersionStatement = @alignCast(@fieldParentPtr("base", node)); |
| 684 | return casted.parts[casted.parts.len - 1].getLastToken(); | 681 | return casted.parts[casted.parts.len - 1].getLastToken(); |
| 685 | }, | 682 | }, |
| 686 | .block => { | 683 | .block => { |
| 687 | const casted = @fieldParentPtr(Node.Block, "base", node); | 684 | const casted: *const Node.Block = @alignCast(@fieldParentPtr("base", node)); |
| 688 | return casted.end_token; | 685 | return casted.end_token; |
| 689 | }, | 686 | }, |
| 690 | .block_value => { | 687 | .block_value => { |
| 691 | const casted = @fieldParentPtr(Node.BlockValue, "base", node); | 688 | const casted: *const Node.BlockValue = @alignCast(@fieldParentPtr("base", node)); |
| 692 | if (casted.values.len > 0) return casted.values[casted.values.len - 1].getLastToken(); | 689 | if (casted.values.len > 0) return casted.values[casted.values.len - 1].getLastToken(); |
| 693 | return casted.key; | 690 | return casted.key; |
| 694 | }, | 691 | }, |
| 695 | .block_value_value => { | 692 | .block_value_value => { |
| 696 | const casted = @fieldParentPtr(Node.BlockValueValue, "base", node); | 693 | const casted: *const Node.BlockValueValue = @alignCast(@fieldParentPtr("base", node)); |
| 697 | return casted.expression.getLastToken(); | 694 | return casted.expression.getLastToken(); |
| 698 | }, | 695 | }, |
| 699 | .string_table => { | 696 | .string_table => { |
| 700 | const casted = @fieldParentPtr(Node.StringTable, "base", node); | 697 | const casted: *const Node.StringTable = @alignCast(@fieldParentPtr("base", node)); |
| 701 | return casted.end_token; | 698 | return casted.end_token; |
| 702 | }, | 699 | }, |
| 703 | .string_table_string => { | 700 | .string_table_string => { |
| 704 | const casted = @fieldParentPtr(Node.StringTableString, "base", node); | 701 | const casted: *const Node.StringTableString = @alignCast(@fieldParentPtr("base", node)); |
| 705 | return casted.string; | 702 | return casted.string; |
| 706 | }, | 703 | }, |
| 707 | .language_statement => { | 704 | .language_statement => { |
| 708 | const casted = @fieldParentPtr(Node.LanguageStatement, "base", node); | 705 | const casted: *const Node.LanguageStatement = @alignCast(@fieldParentPtr("base", node)); |
| 709 | return casted.sublanguage_id.getLastToken(); | 706 | return casted.sublanguage_id.getLastToken(); |
| 710 | }, | 707 | }, |
| 711 | .font_statement => { | 708 | .font_statement => { |
| 712 | const casted = @fieldParentPtr(Node.FontStatement, "base", node); | 709 | const casted: *const Node.FontStatement = @alignCast(@fieldParentPtr("base", node)); |
| 713 | if (casted.char_set) |char_set_node| return char_set_node.getLastToken(); | 710 | if (casted.char_set) |char_set_node| return char_set_node.getLastToken(); |
| 714 | if (casted.italic) |italic_node| return italic_node.getLastToken(); | 711 | if (casted.italic) |italic_node| return italic_node.getLastToken(); |
| 715 | if (casted.weight) |weight_node| return weight_node.getLastToken(); | 712 | if (casted.weight) |weight_node| return weight_node.getLastToken(); |
| 716 | return casted.typeface; | 713 | return casted.typeface; |
| 717 | }, | 714 | }, |
| 718 | .simple_statement => { | 715 | .simple_statement => { |
| 719 | const casted = @fieldParentPtr(Node.SimpleStatement, "base", node); | 716 | const casted: *const Node.SimpleStatement = @alignCast(@fieldParentPtr("base", node)); |
| 720 | return casted.value.getLastToken(); | 717 | return casted.value.getLastToken(); |
| 721 | }, | 718 | }, |
| 722 | .invalid => { | 719 | .invalid => { |
| 723 | const casted = @fieldParentPtr(Node.Invalid, "base", node); | 720 | const casted: *const Node.Invalid = @alignCast(@fieldParentPtr("base", node)); |
| 724 | return casted.context[casted.context.len - 1]; | 721 | return casted.context[casted.context.len - 1]; |
| 725 | }, | 722 | }, |
| 726 | } | 723 | } |
| ... | @@ -737,31 +734,31 @@ pub const Node = struct { | ... | @@ -737,31 +734,31 @@ pub const Node = struct { |
| 737 | switch (node.id) { | 734 | switch (node.id) { |
| 738 | .root => { | 735 | .root => { |
| 739 | try writer.writeAll("\n"); | 736 | try writer.writeAll("\n"); |
| 740 | const root = @fieldParentPtr(Node.Root, "base", node); | 737 | const root: *Node.Root = @alignCast(@fieldParentPtr("base", node)); |
| 741 | for (root.body) |body_node| { | 738 | for (root.body) |body_node| { |
| 742 | try body_node.dump(tree, writer, indent + 1); | 739 | try body_node.dump(tree, writer, indent + 1); |
| 743 | } | 740 | } |
| 744 | }, | 741 | }, |
| 745 | .resource_external => { | 742 | .resource_external => { |
| 746 | const resource = @fieldParentPtr(Node.ResourceExternal, "base", node); | 743 | const resource: *Node.ResourceExternal = @alignCast(@fieldParentPtr("base", node)); |
| 747 | try writer.print(" {s} {s} [{d} common_resource_attributes]\n", .{ resource.id.slice(tree.source), resource.type.slice(tree.source), resource.common_resource_attributes.len }); | 744 | try writer.print(" {s} {s} [{d} common_resource_attributes]\n", .{ resource.id.slice(tree.source), resource.type.slice(tree.source), resource.common_resource_attributes.len }); |
| 748 | try resource.filename.dump(tree, writer, indent + 1); | 745 | try resource.filename.dump(tree, writer, indent + 1); |
| 749 | }, | 746 | }, |
| 750 | .resource_raw_data => { | 747 | .resource_raw_data => { |
| 751 | const resource = @fieldParentPtr(Node.ResourceRawData, "base", node); | 748 | const resource: *Node.ResourceRawData = @alignCast(@fieldParentPtr("base", node)); |
| 752 | try writer.print(" {s} {s} [{d} common_resource_attributes] raw data: {}\n", .{ resource.id.slice(tree.source), resource.type.slice(tree.source), resource.common_resource_attributes.len, resource.raw_data.len }); | 749 | try writer.print(" {s} {s} [{d} common_resource_attributes] raw data: {}\n", .{ resource.id.slice(tree.source), resource.type.slice(tree.source), resource.common_resource_attributes.len, resource.raw_data.len }); |
| 753 | for (resource.raw_data) |data_expression| { | 750 | for (resource.raw_data) |data_expression| { |
| 754 | try data_expression.dump(tree, writer, indent + 1); | 751 | try data_expression.dump(tree, writer, indent + 1); |
| 755 | } | 752 | } |
| 756 | }, | 753 | }, |
| 757 | .literal => { | 754 | .literal => { |
| 758 | const literal = @fieldParentPtr(Node.Literal, "base", node); | 755 | const literal: *Node.Literal = @alignCast(@fieldParentPtr("base", node)); |
| 759 | try writer.writeAll(" "); | 756 | try writer.writeAll(" "); |
| 760 | try writer.writeAll(literal.token.slice(tree.source)); | 757 | try writer.writeAll(literal.token.slice(tree.source)); |
| 761 | try writer.writeAll("\n"); | 758 | try writer.writeAll("\n"); |
| 762 | }, | 759 | }, |
| 763 | .binary_expression => { | 760 | .binary_expression => { |
| 764 | const binary = @fieldParentPtr(Node.BinaryExpression, "base", node); | 761 | const binary: *Node.BinaryExpression = @alignCast(@fieldParentPtr("base", node)); |
| 765 | try writer.writeAll(" "); | 762 | try writer.writeAll(" "); |
| 766 | try writer.writeAll(binary.operator.slice(tree.source)); | 763 | try writer.writeAll(binary.operator.slice(tree.source)); |
| 767 | try writer.writeAll("\n"); | 764 | try writer.writeAll("\n"); |
| ... | @@ -769,7 +766,7 @@ pub const Node = struct { | ... | @@ -769,7 +766,7 @@ pub const Node = struct { |
| 769 | try binary.right.dump(tree, writer, indent + 1); | 766 | try binary.right.dump(tree, writer, indent + 1); |
| 770 | }, | 767 | }, |
| 771 | .grouped_expression => { | 768 | .grouped_expression => { |
| 772 | const grouped = @fieldParentPtr(Node.GroupedExpression, "base", node); | 769 | const grouped: *Node.GroupedExpression = @alignCast(@fieldParentPtr("base", node)); |
| 773 | try writer.writeAll("\n"); | 770 | try writer.writeAll("\n"); |
| 774 | try writer.writeByteNTimes(' ', indent); | 771 | try writer.writeByteNTimes(' ', indent); |
| 775 | try writer.writeAll(grouped.open_token.slice(tree.source)); | 772 | try writer.writeAll(grouped.open_token.slice(tree.source)); |
| ... | @@ -780,7 +777,7 @@ pub const Node = struct { | ... | @@ -780,7 +777,7 @@ pub const Node = struct { |
| 780 | try writer.writeAll("\n"); | 777 | try writer.writeAll("\n"); |
| 781 | }, | 778 | }, |
| 782 | .not_expression => { | 779 | .not_expression => { |
| 783 | const not = @fieldParentPtr(Node.NotExpression, "base", node); | 780 | const not: *Node.NotExpression = @alignCast(@fieldParentPtr("base", node)); |
| 784 | try writer.writeAll(" "); | 781 | try writer.writeAll(" "); |
| 785 | try writer.writeAll(not.not_token.slice(tree.source)); | 782 | try writer.writeAll(not.not_token.slice(tree.source)); |
| 786 | try writer.writeAll(" "); | 783 | try writer.writeAll(" "); |
| ... | @@ -788,7 +785,7 @@ pub const Node = struct { | ... | @@ -788,7 +785,7 @@ pub const Node = struct { |
| 788 | try writer.writeAll("\n"); | 785 | try writer.writeAll("\n"); |
| 789 | }, | 786 | }, |
| 790 | .accelerators => { | 787 | .accelerators => { |
| 791 | const accelerators = @fieldParentPtr(Node.Accelerators, "base", node); | 788 | const accelerators: *Node.Accelerators = @alignCast(@fieldParentPtr("base", node)); |
| 792 | try writer.print(" {s} {s} [{d} common_resource_attributes]\n", .{ accelerators.id.slice(tree.source), accelerators.type.slice(tree.source), accelerators.common_resource_attributes.len }); | 789 | try writer.print(" {s} {s} [{d} common_resource_attributes]\n", .{ accelerators.id.slice(tree.source), accelerators.type.slice(tree.source), accelerators.common_resource_attributes.len }); |
| 793 | for (accelerators.optional_statements) |statement| { | 790 | for (accelerators.optional_statements) |statement| { |
| 794 | try statement.dump(tree, writer, indent + 1); | 791 | try statement.dump(tree, writer, indent + 1); |
| ... | @@ -804,7 +801,7 @@ pub const Node = struct { | ... | @@ -804,7 +801,7 @@ pub const Node = struct { |
| 804 | try writer.writeAll("\n"); | 801 | try writer.writeAll("\n"); |
| 805 | }, | 802 | }, |
| 806 | .accelerator => { | 803 | .accelerator => { |
| 807 | const accelerator = @fieldParentPtr(Node.Accelerator, "base", node); | 804 | const accelerator: *Node.Accelerator = @alignCast(@fieldParentPtr("base", node)); |
| 808 | for (accelerator.type_and_options, 0..) |option, i| { | 805 | for (accelerator.type_and_options, 0..) |option, i| { |
| 809 | if (i != 0) try writer.writeAll(","); | 806 | if (i != 0) try writer.writeAll(","); |
| 810 | try writer.writeByte(' '); | 807 | try writer.writeByte(' '); |
| ... | @@ -815,7 +812,7 @@ pub const Node = struct { | ... | @@ -815,7 +812,7 @@ pub const Node = struct { |
| 815 | try accelerator.idvalue.dump(tree, writer, indent + 1); | 812 | try accelerator.idvalue.dump(tree, writer, indent + 1); |
| 816 | }, | 813 | }, |
| 817 | .dialog => { | 814 | .dialog => { |
| 818 | const dialog = @fieldParentPtr(Node.Dialog, "base", node); | 815 | const dialog: *Node.Dialog = @alignCast(@fieldParentPtr("base", node)); |
| 819 | try writer.print(" {s} {s} [{d} common_resource_attributes]\n", .{ dialog.id.slice(tree.source), dialog.type.slice(tree.source), dialog.common_resource_attributes.len }); | 816 | try writer.print(" {s} {s} [{d} common_resource_attributes]\n", .{ dialog.id.slice(tree.source), dialog.type.slice(tree.source), dialog.common_resource_attributes.len }); |
| 820 | inline for (.{ "x", "y", "width", "height" }) |arg| { | 817 | inline for (.{ "x", "y", "width", "height" }) |arg| { |
| 821 | try writer.writeByteNTimes(' ', indent + 1); | 818 | try writer.writeByteNTimes(' ', indent + 1); |
| ... | @@ -841,7 +838,7 @@ pub const Node = struct { | ... | @@ -841,7 +838,7 @@ pub const Node = struct { |
| 841 | try writer.writeAll("\n"); | 838 | try writer.writeAll("\n"); |
| 842 | }, | 839 | }, |
| 843 | .control_statement => { | 840 | .control_statement => { |
| 844 | const control = @fieldParentPtr(Node.ControlStatement, "base", node); | 841 | const control: *Node.ControlStatement = @alignCast(@fieldParentPtr("base", node)); |
| 845 | try writer.print(" {s}", .{control.type.slice(tree.source)}); | 842 | try writer.print(" {s}", .{control.type.slice(tree.source)}); |
| 846 | if (control.text) |text| { | 843 | if (control.text) |text| { |
| 847 | try writer.print(" text: {s}", .{text.slice(tree.source)}); | 844 | try writer.print(" text: {s}", .{text.slice(tree.source)}); |
| ... | @@ -877,7 +874,7 @@ pub const Node = struct { | ... | @@ -877,7 +874,7 @@ pub const Node = struct { |
| 877 | } | 874 | } |
| 878 | }, | 875 | }, |
| 879 | .toolbar => { | 876 | .toolbar => { |
| 880 | const toolbar = @fieldParentPtr(Node.Toolbar, "base", node); | 877 | const toolbar: *Node.Toolbar = @alignCast(@fieldParentPtr("base", node)); |
| 881 | try writer.print(" {s} {s} [{d} common_resource_attributes]\n", .{ toolbar.id.slice(tree.source), toolbar.type.slice(tree.source), toolbar.common_resource_attributes.len }); | 878 | try writer.print(" {s} {s} [{d} common_resource_attributes]\n", .{ toolbar.id.slice(tree.source), toolbar.type.slice(tree.source), toolbar.common_resource_attributes.len }); |
| 882 | inline for (.{ "button_width", "button_height" }) |arg| { | 879 | inline for (.{ "button_width", "button_height" }) |arg| { |
| 883 | try writer.writeByteNTimes(' ', indent + 1); | 880 | try writer.writeByteNTimes(' ', indent + 1); |
| ... | @@ -895,7 +892,7 @@ pub const Node = struct { | ... | @@ -895,7 +892,7 @@ pub const Node = struct { |
| 895 | try writer.writeAll("\n"); | 892 | try writer.writeAll("\n"); |
| 896 | }, | 893 | }, |
| 897 | .menu => { | 894 | .menu => { |
| 898 | const menu = @fieldParentPtr(Node.Menu, "base", node); | 895 | const menu: *Node.Menu = @alignCast(@fieldParentPtr("base", node)); |
| 899 | try writer.print(" {s} {s} [{d} common_resource_attributes]\n", .{ menu.id.slice(tree.source), menu.type.slice(tree.source), menu.common_resource_attributes.len }); | 896 | try writer.print(" {s} {s} [{d} common_resource_attributes]\n", .{ menu.id.slice(tree.source), menu.type.slice(tree.source), menu.common_resource_attributes.len }); |
| 900 | for (menu.optional_statements) |statement| { | 897 | for (menu.optional_statements) |statement| { |
| 901 | try statement.dump(tree, writer, indent + 1); | 898 | try statement.dump(tree, writer, indent + 1); |
| ... | @@ -916,16 +913,16 @@ pub const Node = struct { | ... | @@ -916,16 +913,16 @@ pub const Node = struct { |
| 916 | try writer.writeAll("\n"); | 913 | try writer.writeAll("\n"); |
| 917 | }, | 914 | }, |
| 918 | .menu_item => { | 915 | .menu_item => { |
| 919 | const menu_item = @fieldParentPtr(Node.MenuItem, "base", node); | 916 | const menu_item: *Node.MenuItem = @alignCast(@fieldParentPtr("base", node)); |
| 920 | try writer.print(" {s} {s} [{d} options]\n", .{ menu_item.menuitem.slice(tree.source), menu_item.text.slice(tree.source), menu_item.option_list.len }); | 917 | try writer.print(" {s} {s} [{d} options]\n", .{ menu_item.menuitem.slice(tree.source), menu_item.text.slice(tree.source), menu_item.option_list.len }); |
| 921 | try menu_item.result.dump(tree, writer, indent + 1); | 918 | try menu_item.result.dump(tree, writer, indent + 1); |
| 922 | }, | 919 | }, |
| 923 | .menu_item_separator => { | 920 | .menu_item_separator => { |
| 924 | const menu_item = @fieldParentPtr(Node.MenuItemSeparator, "base", node); | 921 | const menu_item: *Node.MenuItemSeparator = @alignCast(@fieldParentPtr("base", node)); |
| 925 | try writer.print(" {s} {s}\n", .{ menu_item.menuitem.slice(tree.source), menu_item.separator.slice(tree.source) }); | 922 | try writer.print(" {s} {s}\n", .{ menu_item.menuitem.slice(tree.source), menu_item.separator.slice(tree.source) }); |
| 926 | }, | 923 | }, |
| 927 | .menu_item_ex => { | 924 | .menu_item_ex => { |
| 928 | const menu_item = @fieldParentPtr(Node.MenuItemEx, "base", node); | 925 | const menu_item: *Node.MenuItemEx = @alignCast(@fieldParentPtr("base", node)); |
| 929 | try writer.print(" {s} {s}\n", .{ menu_item.menuitem.slice(tree.source), menu_item.text.slice(tree.source) }); | 926 | try writer.print(" {s} {s}\n", .{ menu_item.menuitem.slice(tree.source), menu_item.text.slice(tree.source) }); |
| 930 | inline for (.{ "id", "type", "state" }) |arg| { | 927 | inline for (.{ "id", "type", "state" }) |arg| { |
| 931 | if (@field(menu_item, arg)) |val_node| { | 928 | if (@field(menu_item, arg)) |val_node| { |
| ... | @@ -936,7 +933,7 @@ pub const Node = struct { | ... | @@ -936,7 +933,7 @@ pub const Node = struct { |
| 936 | } | 933 | } |
| 937 | }, | 934 | }, |
| 938 | .popup => { | 935 | .popup => { |
| 939 | const popup = @fieldParentPtr(Node.Popup, "base", node); | 936 | const popup: *Node.Popup = @alignCast(@fieldParentPtr("base", node)); |
| 940 | try writer.print(" {s} {s} [{d} options]\n", .{ popup.popup.slice(tree.source), popup.text.slice(tree.source), popup.option_list.len }); | 937 | try writer.print(" {s} {s} [{d} options]\n", .{ popup.popup.slice(tree.source), popup.text.slice(tree.source), popup.option_list.len }); |
| 941 | try writer.writeByteNTimes(' ', indent); | 938 | try writer.writeByteNTimes(' ', indent); |
| 942 | try writer.writeAll(popup.begin_token.slice(tree.source)); | 939 | try writer.writeAll(popup.begin_token.slice(tree.source)); |
| ... | @@ -949,7 +946,7 @@ pub const Node = struct { | ... | @@ -949,7 +946,7 @@ pub const Node = struct { |
| 949 | try writer.writeAll("\n"); | 946 | try writer.writeAll("\n"); |
| 950 | }, | 947 | }, |
| 951 | .popup_ex => { | 948 | .popup_ex => { |
| 952 | const popup = @fieldParentPtr(Node.PopupEx, "base", node); | 949 | const popup: *Node.PopupEx = @alignCast(@fieldParentPtr("base", node)); |
| 953 | try writer.print(" {s} {s}\n", .{ popup.popup.slice(tree.source), popup.text.slice(tree.source) }); | 950 | try writer.print(" {s} {s}\n", .{ popup.popup.slice(tree.source), popup.text.slice(tree.source) }); |
| 954 | inline for (.{ "id", "type", "state", "help_id" }) |arg| { | 951 | inline for (.{ "id", "type", "state", "help_id" }) |arg| { |
| 955 | if (@field(popup, arg)) |val_node| { | 952 | if (@field(popup, arg)) |val_node| { |
| ... | @@ -969,7 +966,7 @@ pub const Node = struct { | ... | @@ -969,7 +966,7 @@ pub const Node = struct { |
| 969 | try writer.writeAll("\n"); | 966 | try writer.writeAll("\n"); |
| 970 | }, | 967 | }, |
| 971 | .version_info => { | 968 | .version_info => { |
| 972 | const version_info = @fieldParentPtr(Node.VersionInfo, "base", node); | 969 | const version_info: *Node.VersionInfo = @alignCast(@fieldParentPtr("base", node)); |
| 973 | try writer.print(" {s} {s} [{d} common_resource_attributes]\n", .{ version_info.id.slice(tree.source), version_info.versioninfo.slice(tree.source), version_info.common_resource_attributes.len }); | 970 | try writer.print(" {s} {s} [{d} common_resource_attributes]\n", .{ version_info.id.slice(tree.source), version_info.versioninfo.slice(tree.source), version_info.common_resource_attributes.len }); |
| 974 | for (version_info.fixed_info) |fixed_info| { | 971 | for (version_info.fixed_info) |fixed_info| { |
| 975 | try fixed_info.dump(tree, writer, indent + 1); | 972 | try fixed_info.dump(tree, writer, indent + 1); |
| ... | @@ -985,14 +982,14 @@ pub const Node = struct { | ... | @@ -985,14 +982,14 @@ pub const Node = struct { |
| 985 | try writer.writeAll("\n"); | 982 | try writer.writeAll("\n"); |
| 986 | }, | 983 | }, |
| 987 | .version_statement => { | 984 | .version_statement => { |
| 988 | const version_statement = @fieldParentPtr(Node.VersionStatement, "base", node); | 985 | const version_statement: *Node.VersionStatement = @alignCast(@fieldParentPtr("base", node)); |
| 989 | try writer.print(" {s}\n", .{version_statement.type.slice(tree.source)}); | 986 | try writer.print(" {s}\n", .{version_statement.type.slice(tree.source)}); |
| 990 | for (version_statement.parts) |part| { | 987 | for (version_statement.parts) |part| { |
| 991 | try part.dump(tree, writer, indent + 1); | 988 | try part.dump(tree, writer, indent + 1); |
| 992 | } | 989 | } |
| 993 | }, | 990 | }, |
| 994 | .block => { | 991 | .block => { |
| 995 | const block = @fieldParentPtr(Node.Block, "base", node); | 992 | const block: *Node.Block = @alignCast(@fieldParentPtr("base", node)); |
| 996 | try writer.print(" {s} {s}\n", .{ block.identifier.slice(tree.source), block.key.slice(tree.source) }); | 993 | try writer.print(" {s} {s}\n", .{ block.identifier.slice(tree.source), block.key.slice(tree.source) }); |
| 997 | for (block.values) |value| { | 994 | for (block.values) |value| { |
| 998 | try value.dump(tree, writer, indent + 1); | 995 | try value.dump(tree, writer, indent + 1); |
| ... | @@ -1008,14 +1005,14 @@ pub const Node = struct { | ... | @@ -1008,14 +1005,14 @@ pub const Node = struct { |
| 1008 | try writer.writeAll("\n"); | 1005 | try writer.writeAll("\n"); |
| 1009 | }, | 1006 | }, |
| 1010 | .block_value => { | 1007 | .block_value => { |
| 1011 | const block_value = @fieldParentPtr(Node.BlockValue, "base", node); | 1008 | const block_value: *Node.BlockValue = @alignCast(@fieldParentPtr("base", node)); |
| 1012 | try writer.print(" {s} {s}\n", .{ block_value.identifier.slice(tree.source), block_value.key.slice(tree.source) }); | 1009 | try writer.print(" {s} {s}\n", .{ block_value.identifier.slice(tree.source), block_value.key.slice(tree.source) }); |
| 1013 | for (block_value.values) |value| { | 1010 | for (block_value.values) |value| { |
| 1014 | try value.dump(tree, writer, indent + 1); | 1011 | try value.dump(tree, writer, indent + 1); |
| 1015 | } | 1012 | } |
| 1016 | }, | 1013 | }, |
| 1017 | .block_value_value => { | 1014 | .block_value_value => { |
| 1018 | const block_value = @fieldParentPtr(Node.BlockValueValue, "base", node); | 1015 | const block_value: *Node.BlockValueValue = @alignCast(@fieldParentPtr("base", node)); |
| 1019 | if (block_value.trailing_comma) { | 1016 | if (block_value.trailing_comma) { |
| 1020 | try writer.writeAll(" ,"); | 1017 | try writer.writeAll(" ,"); |
| 1021 | } | 1018 | } |
| ... | @@ -1023,7 +1020,7 @@ pub const Node = struct { | ... | @@ -1023,7 +1020,7 @@ pub const Node = struct { |
| 1023 | try block_value.expression.dump(tree, writer, indent + 1); | 1020 | try block_value.expression.dump(tree, writer, indent + 1); |
| 1024 | }, | 1021 | }, |
| 1025 | .string_table => { | 1022 | .string_table => { |
| 1026 | const string_table = @fieldParentPtr(Node.StringTable, "base", node); | 1023 | const string_table: *Node.StringTable = @alignCast(@fieldParentPtr("base", node)); |
| 1027 | try writer.print(" {s} [{d} common_resource_attributes]\n", .{ string_table.type.slice(tree.source), string_table.common_resource_attributes.len }); | 1024 | try writer.print(" {s} [{d} common_resource_attributes]\n", .{ string_table.type.slice(tree.source), string_table.common_resource_attributes.len }); |
| 1028 | for (string_table.optional_statements) |statement| { | 1025 | for (string_table.optional_statements) |statement| { |
| 1029 | try statement.dump(tree, writer, indent + 1); | 1026 | try statement.dump(tree, writer, indent + 1); |
| ... | @@ -1040,19 +1037,19 @@ pub const Node = struct { | ... | @@ -1040,19 +1037,19 @@ pub const Node = struct { |
| 1040 | }, | 1037 | }, |
| 1041 | .string_table_string => { | 1038 | .string_table_string => { |
| 1042 | try writer.writeAll("\n"); | 1039 | try writer.writeAll("\n"); |
| 1043 | const string = @fieldParentPtr(Node.StringTableString, "base", node); | 1040 | const string: *Node.StringTableString = @alignCast(@fieldParentPtr("base", node)); |
| 1044 | try string.id.dump(tree, writer, indent + 1); | 1041 | try string.id.dump(tree, writer, indent + 1); |
| 1045 | try writer.writeByteNTimes(' ', indent + 1); | 1042 | try writer.writeByteNTimes(' ', indent + 1); |
| 1046 | try writer.print("{s}\n", .{string.string.slice(tree.source)}); | 1043 | try writer.print("{s}\n", .{string.string.slice(tree.source)}); |
| 1047 | }, | 1044 | }, |
| 1048 | .language_statement => { | 1045 | .language_statement => { |
| 1049 | const language = @fieldParentPtr(Node.LanguageStatement, "base", node); | 1046 | const language: *Node.LanguageStatement = @alignCast(@fieldParentPtr("base", node)); |
| 1050 | try writer.print(" {s}\n", .{language.language_token.slice(tree.source)}); | 1047 | try writer.print(" {s}\n", .{language.language_token.slice(tree.source)}); |
| 1051 | try language.primary_language_id.dump(tree, writer, indent + 1); | 1048 | try language.primary_language_id.dump(tree, writer, indent + 1); |
| 1052 | try language.sublanguage_id.dump(tree, writer, indent + 1); | 1049 | try language.sublanguage_id.dump(tree, writer, indent + 1); |
| 1053 | }, | 1050 | }, |
| 1054 | .font_statement => { | 1051 | .font_statement => { |
| 1055 | const font = @fieldParentPtr(Node.FontStatement, "base", node); | 1052 | const font: *Node.FontStatement = @alignCast(@fieldParentPtr("base", node)); |
| 1056 | try writer.print(" {s} typeface: {s}\n", .{ font.identifier.slice(tree.source), font.typeface.slice(tree.source) }); | 1053 | try writer.print(" {s} typeface: {s}\n", .{ font.identifier.slice(tree.source), font.typeface.slice(tree.source) }); |
| 1057 | try writer.writeByteNTimes(' ', indent + 1); | 1054 | try writer.writeByteNTimes(' ', indent + 1); |
| 1058 | try writer.writeAll("point_size:\n"); | 1055 | try writer.writeAll("point_size:\n"); |
| ... | @@ -1066,12 +1063,12 @@ pub const Node = struct { | ... | @@ -1066,12 +1063,12 @@ pub const Node = struct { |
| 1066 | } | 1063 | } |
| 1067 | }, | 1064 | }, |
| 1068 | .simple_statement => { | 1065 | .simple_statement => { |
| 1069 | const statement = @fieldParentPtr(Node.SimpleStatement, "base", node); | 1066 | const statement: *Node.SimpleStatement = @alignCast(@fieldParentPtr("base", node)); |
| 1070 | try writer.print(" {s}\n", .{statement.identifier.slice(tree.source)}); | 1067 | try writer.print(" {s}\n", .{statement.identifier.slice(tree.source)}); |
| 1071 | try statement.value.dump(tree, writer, indent + 1); | 1068 | try statement.value.dump(tree, writer, indent + 1); |
| 1072 | }, | 1069 | }, |
| 1073 | .invalid => { | 1070 | .invalid => { |
| 1074 | const invalid = @fieldParentPtr(Node.Invalid, "base", node); | 1071 | const invalid: *Node.Invalid = @alignCast(@fieldParentPtr("base", node)); |
| 1075 | try writer.print(" context.len: {}\n", .{invalid.context.len}); | 1072 | try writer.print(" context.len: {}\n", .{invalid.context.len}); |
| 1076 | for (invalid.context) |context_token| { | 1073 | for (invalid.context) |context_token| { |
| 1077 | try writer.writeByteNTimes(' ', indent + 1); | 1074 | try writer.writeByteNTimes(' ', indent + 1); |
lib/compiler/resinator/compile.zig+33-33| ... | @@ -229,34 +229,34 @@ pub const Compiler = struct { | ... | @@ -229,34 +229,34 @@ pub const Compiler = struct { |
| 229 | pub fn writeNode(self: *Compiler, node: *Node, writer: anytype) !void { | 229 | pub fn writeNode(self: *Compiler, node: *Node, writer: anytype) !void { |
| 230 | switch (node.id) { | 230 | switch (node.id) { |
| 231 | .root => unreachable, // writeRoot should be called directly instead | 231 | .root => unreachable, // writeRoot should be called directly instead |
| 232 | .resource_external => try self.writeResourceExternal(@fieldParentPtr(Node.ResourceExternal, "base", node), writer), | 232 | .resource_external => try self.writeResourceExternal(@alignCast(@fieldParentPtr("base", node)), writer), |
| 233 | .resource_raw_data => try self.writeResourceRawData(@fieldParentPtr(Node.ResourceRawData, "base", node), writer), | 233 | .resource_raw_data => try self.writeResourceRawData(@alignCast(@fieldParentPtr("base", node)), writer), |
| 234 | .literal => unreachable, // this is context dependent and should be handled by its parent | 234 | .literal => unreachable, // this is context dependent and should be handled by its parent |
| 235 | .binary_expression => unreachable, | 235 | .binary_expression => unreachable, |
| 236 | .grouped_expression => unreachable, | 236 | .grouped_expression => unreachable, |
| 237 | .not_expression => unreachable, | 237 | .not_expression => unreachable, |
| 238 | .invalid => {}, // no-op, currently only used for dangling literals at EOF | 238 | .invalid => {}, // no-op, currently only used for dangling literals at EOF |
| 239 | .accelerators => try self.writeAccelerators(@fieldParentPtr(Node.Accelerators, "base", node), writer), | 239 | .accelerators => try self.writeAccelerators(@alignCast(@fieldParentPtr("base", node)), writer), |
| 240 | .accelerator => unreachable, // handled by writeAccelerators | 240 | .accelerator => unreachable, // handled by writeAccelerators |
| 241 | .dialog => try self.writeDialog(@fieldParentPtr(Node.Dialog, "base", node), writer), | 241 | .dialog => try self.writeDialog(@alignCast(@fieldParentPtr("base", node)), writer), |
| 242 | .control_statement => unreachable, | 242 | .control_statement => unreachable, |
| 243 | .toolbar => try self.writeToolbar(@fieldParentPtr(Node.Toolbar, "base", node), writer), | 243 | .toolbar => try self.writeToolbar(@alignCast(@fieldParentPtr("base", node)), writer), |
| 244 | .menu => try self.writeMenu(@fieldParentPtr(Node.Menu, "base", node), writer), | 244 | .menu => try self.writeMenu(@alignCast(@fieldParentPtr("base", node)), writer), |
| 245 | .menu_item => unreachable, | 245 | .menu_item => unreachable, |
| 246 | .menu_item_separator => unreachable, | 246 | .menu_item_separator => unreachable, |
| 247 | .menu_item_ex => unreachable, | 247 | .menu_item_ex => unreachable, |
| 248 | .popup => unreachable, | 248 | .popup => unreachable, |
| 249 | .popup_ex => unreachable, | 249 | .popup_ex => unreachable, |
| 250 | .version_info => try self.writeVersionInfo(@fieldParentPtr(Node.VersionInfo, "base", node), writer), | 250 | .version_info => try self.writeVersionInfo(@alignCast(@fieldParentPtr("base", node)), writer), |
| 251 | .version_statement => unreachable, | 251 | .version_statement => unreachable, |
| 252 | .block => unreachable, | 252 | .block => unreachable, |
| 253 | .block_value => unreachable, | 253 | .block_value => unreachable, |
| 254 | .block_value_value => unreachable, | 254 | .block_value_value => unreachable, |
| 255 | .string_table => try self.writeStringTable(@fieldParentPtr(Node.StringTable, "base", node)), | 255 | .string_table => try self.writeStringTable(@alignCast(@fieldParentPtr("base", node))), |
| 256 | .string_table_string => unreachable, // handled by writeStringTable | 256 | .string_table_string => unreachable, // handled by writeStringTable |
| 257 | .language_statement => self.writeLanguageStatement(@fieldParentPtr(Node.LanguageStatement, "base", node)), | 257 | .language_statement => self.writeLanguageStatement(@alignCast(@fieldParentPtr("base", node))), |
| 258 | .font_statement => unreachable, | 258 | .font_statement => unreachable, |
| 259 | .simple_statement => self.writeTopLevelSimpleStatement(@fieldParentPtr(Node.SimpleStatement, "base", node)), | 259 | .simple_statement => self.writeTopLevelSimpleStatement(@alignCast(@fieldParentPtr("base", node))), |
| 260 | } | 260 | } |
| 261 | } | 261 | } |
| 262 | 262 | ||
| ... | @@ -1289,7 +1289,7 @@ pub const Compiler = struct { | ... | @@ -1289,7 +1289,7 @@ pub const Compiler = struct { |
| 1289 | return evaluateNumberExpression(node, self.source, self.input_code_pages).asWord(); | 1289 | return evaluateNumberExpression(node, self.source, self.input_code_pages).asWord(); |
| 1290 | } else { | 1290 | } else { |
| 1291 | std.debug.assert(node.isStringLiteral()); | 1291 | std.debug.assert(node.isStringLiteral()); |
| 1292 | const literal = @fieldParentPtr(Node.Literal, "base", node); | 1292 | const literal: *Node.Literal = @alignCast(@fieldParentPtr("base", node)); |
| 1293 | const bytes = SourceBytes{ | 1293 | const bytes = SourceBytes{ |
| 1294 | .slice = literal.token.slice(self.source), | 1294 | .slice = literal.token.slice(self.source), |
| 1295 | .code_page = self.input_code_pages.getForToken(literal.token), | 1295 | .code_page = self.input_code_pages.getForToken(literal.token), |
| ... | @@ -1342,7 +1342,7 @@ pub const Compiler = struct { | ... | @@ -1342,7 +1342,7 @@ pub const Compiler = struct { |
| 1342 | /// the writer within this function could return error.NoSpaceLeft | 1342 | /// the writer within this function could return error.NoSpaceLeft |
| 1343 | pub fn writeAcceleratorsData(self: *Compiler, node: *Node.Accelerators, data_writer: anytype) !void { | 1343 | pub fn writeAcceleratorsData(self: *Compiler, node: *Node.Accelerators, data_writer: anytype) !void { |
| 1344 | for (node.accelerators, 0..) |accel_node, i| { | 1344 | for (node.accelerators, 0..) |accel_node, i| { |
| 1345 | const accelerator = @fieldParentPtr(Node.Accelerator, "base", accel_node); | 1345 | const accelerator: *Node.Accelerator = @alignCast(@fieldParentPtr("base", accel_node)); |
| 1346 | var modifiers = res.AcceleratorModifiers{}; | 1346 | var modifiers = res.AcceleratorModifiers{}; |
| 1347 | for (accelerator.type_and_options) |type_or_option| { | 1347 | for (accelerator.type_and_options) |type_or_option| { |
| 1348 | const modifier = rc.AcceleratorTypeAndOptions.map.get(type_or_option.slice(self.source)).?; | 1348 | const modifier = rc.AcceleratorTypeAndOptions.map.get(type_or_option.slice(self.source)).?; |
| ... | @@ -1426,7 +1426,7 @@ pub const Compiler = struct { | ... | @@ -1426,7 +1426,7 @@ pub const Compiler = struct { |
| 1426 | for (node.optional_statements) |optional_statement| { | 1426 | for (node.optional_statements) |optional_statement| { |
| 1427 | switch (optional_statement.id) { | 1427 | switch (optional_statement.id) { |
| 1428 | .simple_statement => { | 1428 | .simple_statement => { |
| 1429 | const simple_statement = @fieldParentPtr(Node.SimpleStatement, "base", optional_statement); | 1429 | const simple_statement: *Node.SimpleStatement = @alignCast(@fieldParentPtr("base", optional_statement)); |
| 1430 | const statement_identifier = simple_statement.identifier; | 1430 | const statement_identifier = simple_statement.identifier; |
| 1431 | const statement_type = rc.OptionalStatements.dialog_map.get(statement_identifier.slice(self.source)) orelse continue; | 1431 | const statement_type = rc.OptionalStatements.dialog_map.get(statement_identifier.slice(self.source)) orelse continue; |
| 1432 | switch (statement_type) { | 1432 | switch (statement_type) { |
| ... | @@ -1440,7 +1440,7 @@ pub const Compiler = struct { | ... | @@ -1440,7 +1440,7 @@ pub const Compiler = struct { |
| 1440 | }, | 1440 | }, |
| 1441 | .caption => { | 1441 | .caption => { |
| 1442 | std.debug.assert(simple_statement.value.id == .literal); | 1442 | std.debug.assert(simple_statement.value.id == .literal); |
| 1443 | const literal_node = @fieldParentPtr(Node.Literal, "base", simple_statement.value); | 1443 | const literal_node: *Node.Literal = @alignCast(@fieldParentPtr("base", simple_statement.value)); |
| 1444 | optional_statement_values.caption = literal_node.token; | 1444 | optional_statement_values.caption = literal_node.token; |
| 1445 | }, | 1445 | }, |
| 1446 | .class => { | 1446 | .class => { |
| ... | @@ -1466,7 +1466,7 @@ pub const Compiler = struct { | ... | @@ -1466,7 +1466,7 @@ pub const Compiler = struct { |
| 1466 | optional_statement_values.class = NameOrOrdinal{ .ordinal = class_ordinal.asWord() }; | 1466 | optional_statement_values.class = NameOrOrdinal{ .ordinal = class_ordinal.asWord() }; |
| 1467 | } else { | 1467 | } else { |
| 1468 | std.debug.assert(simple_statement.value.isStringLiteral()); | 1468 | std.debug.assert(simple_statement.value.isStringLiteral()); |
| 1469 | const literal_node = @fieldParentPtr(Node.Literal, "base", simple_statement.value); | 1469 | const literal_node: *Node.Literal = @alignCast(@fieldParentPtr("base", simple_statement.value)); |
| 1470 | const parsed = try self.parseQuotedStringAsWideString(literal_node.token); | 1470 | const parsed = try self.parseQuotedStringAsWideString(literal_node.token); |
| 1471 | optional_statement_values.class = NameOrOrdinal{ .name = parsed }; | 1471 | optional_statement_values.class = NameOrOrdinal{ .name = parsed }; |
| 1472 | } | 1472 | } |
| ... | @@ -1492,7 +1492,7 @@ pub const Compiler = struct { | ... | @@ -1492,7 +1492,7 @@ pub const Compiler = struct { |
| 1492 | } | 1492 | } |
| 1493 | 1493 | ||
| 1494 | std.debug.assert(simple_statement.value.id == .literal); | 1494 | std.debug.assert(simple_statement.value.id == .literal); |
| 1495 | const literal_node = @fieldParentPtr(Node.Literal, "base", simple_statement.value); | 1495 | const literal_node: *Node.Literal = @alignCast(@fieldParentPtr("base", simple_statement.value)); |
| 1496 | 1496 | ||
| 1497 | const token_slice = literal_node.token.slice(self.source); | 1497 | const token_slice = literal_node.token.slice(self.source); |
| 1498 | const bytes = SourceBytes{ | 1498 | const bytes = SourceBytes{ |
| ... | @@ -1542,7 +1542,7 @@ pub const Compiler = struct { | ... | @@ -1542,7 +1542,7 @@ pub const Compiler = struct { |
| 1542 | } | 1542 | } |
| 1543 | }, | 1543 | }, |
| 1544 | .font_statement => { | 1544 | .font_statement => { |
| 1545 | const font = @fieldParentPtr(Node.FontStatement, "base", optional_statement); | 1545 | const font: *Node.FontStatement = @alignCast(@fieldParentPtr("base", optional_statement)); |
| 1546 | if (optional_statement_values.font != null) { | 1546 | if (optional_statement_values.font != null) { |
| 1547 | optional_statement_values.font.?.node = font; | 1547 | optional_statement_values.font.?.node = font; |
| 1548 | } else { | 1548 | } else { |
| ... | @@ -1581,7 +1581,7 @@ pub const Compiler = struct { | ... | @@ -1581,7 +1581,7 @@ pub const Compiler = struct { |
| 1581 | // Multiple CLASS parameters are specified and any of them are treated as a number, then | 1581 | // Multiple CLASS parameters are specified and any of them are treated as a number, then |
| 1582 | // the last CLASS is always treated as a number no matter what | 1582 | // the last CLASS is always treated as a number no matter what |
| 1583 | if (last_class_would_be_forced_ordinal and optional_statement_values.class.? == .name) { | 1583 | if (last_class_would_be_forced_ordinal and optional_statement_values.class.? == .name) { |
| 1584 | const literal_node = @fieldParentPtr(Node.Literal, "base", last_class.value); | 1584 | const literal_node: *Node.Literal = @alignCast(@fieldParentPtr("base", last_class.value)); |
| 1585 | const ordinal_value = res.ForcedOrdinal.fromUtf16Le(optional_statement_values.class.?.name); | 1585 | const ordinal_value = res.ForcedOrdinal.fromUtf16Le(optional_statement_values.class.?.name); |
| 1586 | 1586 | ||
| 1587 | try self.addErrorDetails(.{ | 1587 | try self.addErrorDetails(.{ |
| ... | @@ -1611,7 +1611,7 @@ pub const Compiler = struct { | ... | @@ -1611,7 +1611,7 @@ pub const Compiler = struct { |
| 1611 | // 2. Multiple MENU parameters are specified and any of them are treated as a number, then | 1611 | // 2. Multiple MENU parameters are specified and any of them are treated as a number, then |
| 1612 | // the last MENU is always treated as a number no matter what | 1612 | // the last MENU is always treated as a number no matter what |
| 1613 | if ((last_menu_would_be_forced_ordinal or last_menu_has_digit_as_first_char) and optional_statement_values.menu.? == .name) { | 1613 | if ((last_menu_would_be_forced_ordinal or last_menu_has_digit_as_first_char) and optional_statement_values.menu.? == .name) { |
| 1614 | const literal_node = @fieldParentPtr(Node.Literal, "base", last_menu.value); | 1614 | const literal_node: *Node.Literal = @alignCast(@fieldParentPtr("base", last_menu.value)); |
| 1615 | const token_slice = literal_node.token.slice(self.source); | 1615 | const token_slice = literal_node.token.slice(self.source); |
| 1616 | const bytes = SourceBytes{ | 1616 | const bytes = SourceBytes{ |
| 1617 | .slice = token_slice, | 1617 | .slice = token_slice, |
| ... | @@ -1658,7 +1658,7 @@ pub const Compiler = struct { | ... | @@ -1658,7 +1658,7 @@ pub const Compiler = struct { |
| 1658 | // between resinator and the Win32 RC compiler, we only emit a hint instead of | 1658 | // between resinator and the Win32 RC compiler, we only emit a hint instead of |
| 1659 | // a warning. | 1659 | // a warning. |
| 1660 | if (last_menu_did_uppercase) { | 1660 | if (last_menu_did_uppercase) { |
| 1661 | const literal_node = @fieldParentPtr(Node.Literal, "base", last_menu.value); | 1661 | const literal_node: *Node.Literal = @alignCast(@fieldParentPtr("base", last_menu.value)); |
| 1662 | try self.addErrorDetails(.{ | 1662 | try self.addErrorDetails(.{ |
| 1663 | .err = .dialog_menu_id_was_uppercased, | 1663 | .err = .dialog_menu_id_was_uppercased, |
| 1664 | .type = .hint, | 1664 | .type = .hint, |
| ... | @@ -1704,7 +1704,7 @@ pub const Compiler = struct { | ... | @@ -1704,7 +1704,7 @@ pub const Compiler = struct { |
| 1704 | defer controls_by_id.deinit(); | 1704 | defer controls_by_id.deinit(); |
| 1705 | 1705 | ||
| 1706 | for (node.controls) |control_node| { | 1706 | for (node.controls) |control_node| { |
| 1707 | const control = @fieldParentPtr(Node.ControlStatement, "base", control_node); | 1707 | const control: *Node.ControlStatement = @alignCast(@fieldParentPtr("base", control_node)); |
| 1708 | 1708 | ||
| 1709 | self.writeDialogControl( | 1709 | self.writeDialogControl( |
| 1710 | control, | 1710 | control, |
| ... | @@ -1940,7 +1940,7 @@ pub const Compiler = struct { | ... | @@ -1940,7 +1940,7 @@ pub const Compiler = struct { |
| 1940 | // And then write out the ordinal using a proper a NameOrOrdinal encoding. | 1940 | // And then write out the ordinal using a proper a NameOrOrdinal encoding. |
| 1941 | try ordinal.write(data_writer); | 1941 | try ordinal.write(data_writer); |
| 1942 | } else if (class_node.isStringLiteral()) { | 1942 | } else if (class_node.isStringLiteral()) { |
| 1943 | const literal_node = @fieldParentPtr(Node.Literal, "base", class_node); | 1943 | const literal_node: *Node.Literal = @alignCast(@fieldParentPtr("base", class_node)); |
| 1944 | const parsed = try self.parseQuotedStringAsWideString(literal_node.token); | 1944 | const parsed = try self.parseQuotedStringAsWideString(literal_node.token); |
| 1945 | defer self.allocator.free(parsed); | 1945 | defer self.allocator.free(parsed); |
| 1946 | if (rc.ControlClass.fromWideString(parsed)) |control_class| { | 1946 | if (rc.ControlClass.fromWideString(parsed)) |control_class| { |
| ... | @@ -1955,7 +1955,7 @@ pub const Compiler = struct { | ... | @@ -1955,7 +1955,7 @@ pub const Compiler = struct { |
| 1955 | try name.write(data_writer); | 1955 | try name.write(data_writer); |
| 1956 | } | 1956 | } |
| 1957 | } else { | 1957 | } else { |
| 1958 | const literal_node = @fieldParentPtr(Node.Literal, "base", class_node); | 1958 | const literal_node: *Node.Literal = @alignCast(@fieldParentPtr("base", class_node)); |
| 1959 | const literal_slice = literal_node.token.slice(self.source); | 1959 | const literal_slice = literal_node.token.slice(self.source); |
| 1960 | // This succeeding is guaranteed by the parser | 1960 | // This succeeding is guaranteed by the parser |
| 1961 | const control_class = rc.ControlClass.map.get(literal_slice) orelse unreachable; | 1961 | const control_class = rc.ControlClass.map.get(literal_slice) orelse unreachable; |
| ... | @@ -2178,7 +2178,7 @@ pub const Compiler = struct { | ... | @@ -2178,7 +2178,7 @@ pub const Compiler = struct { |
| 2178 | try writer.writeInt(u16, 0, .little); // null-terminated UTF-16 text | 2178 | try writer.writeInt(u16, 0, .little); // null-terminated UTF-16 text |
| 2179 | }, | 2179 | }, |
| 2180 | .menu_item => { | 2180 | .menu_item => { |
| 2181 | const menu_item = @fieldParentPtr(Node.MenuItem, "base", node); | 2181 | const menu_item: *Node.MenuItem = @alignCast(@fieldParentPtr("base", node)); |
| 2182 | var flags = res.MenuItemFlags{}; | 2182 | var flags = res.MenuItemFlags{}; |
| 2183 | for (menu_item.option_list) |option_token| { | 2183 | for (menu_item.option_list) |option_token| { |
| 2184 | // This failing would be a bug in the parser | 2184 | // This failing would be a bug in the parser |
| ... | @@ -2196,7 +2196,7 @@ pub const Compiler = struct { | ... | @@ -2196,7 +2196,7 @@ pub const Compiler = struct { |
| 2196 | try writer.writeAll(std.mem.sliceAsBytes(text[0 .. text.len + 1])); | 2196 | try writer.writeAll(std.mem.sliceAsBytes(text[0 .. text.len + 1])); |
| 2197 | }, | 2197 | }, |
| 2198 | .popup => { | 2198 | .popup => { |
| 2199 | const popup = @fieldParentPtr(Node.Popup, "base", node); | 2199 | const popup: *Node.Popup = @alignCast(@fieldParentPtr("base", node)); |
| 2200 | var flags = res.MenuItemFlags{ .value = res.MF.POPUP }; | 2200 | var flags = res.MenuItemFlags{ .value = res.MF.POPUP }; |
| 2201 | for (popup.option_list) |option_token| { | 2201 | for (popup.option_list) |option_token| { |
| 2202 | // This failing would be a bug in the parser | 2202 | // This failing would be a bug in the parser |
| ... | @@ -2216,7 +2216,7 @@ pub const Compiler = struct { | ... | @@ -2216,7 +2216,7 @@ pub const Compiler = struct { |
| 2216 | } | 2216 | } |
| 2217 | }, | 2217 | }, |
| 2218 | inline .menu_item_ex, .popup_ex => |node_type| { | 2218 | inline .menu_item_ex, .popup_ex => |node_type| { |
| 2219 | const menu_item = @fieldParentPtr(node_type.Type(), "base", node); | 2219 | const menu_item: *node_type.Type() = @alignCast(@fieldParentPtr("base", node)); |
| 2220 | 2220 | ||
| 2221 | if (menu_item.type) |flags| { | 2221 | if (menu_item.type) |flags| { |
| 2222 | const value = evaluateNumberExpression(flags, self.source, self.input_code_pages); | 2222 | const value = evaluateNumberExpression(flags, self.source, self.input_code_pages); |
| ... | @@ -2295,7 +2295,7 @@ pub const Compiler = struct { | ... | @@ -2295,7 +2295,7 @@ pub const Compiler = struct { |
| 2295 | for (node.fixed_info) |fixed_info| { | 2295 | for (node.fixed_info) |fixed_info| { |
| 2296 | switch (fixed_info.id) { | 2296 | switch (fixed_info.id) { |
| 2297 | .version_statement => { | 2297 | .version_statement => { |
| 2298 | const version_statement = @fieldParentPtr(Node.VersionStatement, "base", fixed_info); | 2298 | const version_statement: *Node.VersionStatement = @alignCast(@fieldParentPtr("base", fixed_info)); |
| 2299 | const version_type = rc.VersionInfo.map.get(version_statement.type.slice(self.source)).?; | 2299 | const version_type = rc.VersionInfo.map.get(version_statement.type.slice(self.source)).?; |
| 2300 | 2300 | ||
| 2301 | // Ensure that all parts are cleared for each version, to properly account for | 2301 | // Ensure that all parts are cleared for each version, to properly account for |
| ... | @@ -2345,7 +2345,7 @@ pub const Compiler = struct { | ... | @@ -2345,7 +2345,7 @@ pub const Compiler = struct { |
| 2345 | } | 2345 | } |
| 2346 | }, | 2346 | }, |
| 2347 | .simple_statement => { | 2347 | .simple_statement => { |
| 2348 | const statement = @fieldParentPtr(Node.SimpleStatement, "base", fixed_info); | 2348 | const statement: *Node.SimpleStatement = @alignCast(@fieldParentPtr("base", fixed_info)); |
| 2349 | const statement_type = rc.VersionInfo.map.get(statement.identifier.slice(self.source)).?; | 2349 | const statement_type = rc.VersionInfo.map.get(statement.identifier.slice(self.source)).?; |
| 2350 | const value = evaluateNumberExpression(statement.value, self.source, self.input_code_pages); | 2350 | const value = evaluateNumberExpression(statement.value, self.source, self.input_code_pages); |
| 2351 | switch (statement_type) { | 2351 | switch (statement_type) { |
| ... | @@ -2416,7 +2416,7 @@ pub const Compiler = struct { | ... | @@ -2416,7 +2416,7 @@ pub const Compiler = struct { |
| 2416 | 2416 | ||
| 2417 | switch (node.id) { | 2417 | switch (node.id) { |
| 2418 | inline .block, .block_value => |node_type| { | 2418 | inline .block, .block_value => |node_type| { |
| 2419 | const block_or_value = @fieldParentPtr(node_type.Type(), "base", node); | 2419 | const block_or_value: *node_type.Type() = @alignCast(@fieldParentPtr("base", node)); |
| 2420 | const parsed_key = try self.parseQuotedStringAsWideString(block_or_value.key); | 2420 | const parsed_key = try self.parseQuotedStringAsWideString(block_or_value.key); |
| 2421 | defer self.allocator.free(parsed_key); | 2421 | defer self.allocator.free(parsed_key); |
| 2422 | 2422 | ||
| ... | @@ -2506,7 +2506,7 @@ pub const Compiler = struct { | ... | @@ -2506,7 +2506,7 @@ pub const Compiler = struct { |
| 2506 | const language = getLanguageFromOptionalStatements(node.optional_statements, self.source, self.input_code_pages) orelse self.state.language; | 2506 | const language = getLanguageFromOptionalStatements(node.optional_statements, self.source, self.input_code_pages) orelse self.state.language; |
| 2507 | 2507 | ||
| 2508 | for (node.strings) |string_node| { | 2508 | for (node.strings) |string_node| { |
| 2509 | const string = @fieldParentPtr(Node.StringTableString, "base", string_node); | 2509 | const string: *Node.StringTableString = @alignCast(@fieldParentPtr("base", string_node)); |
| 2510 | const string_id_data = try self.evaluateDataExpression(string.id); | 2510 | const string_id_data = try self.evaluateDataExpression(string.id); |
| 2511 | const string_id = string_id_data.number.asWord(); | 2511 | const string_id = string_id_data.number.asWord(); |
| 2512 | 2512 | ||
| ... | @@ -2795,11 +2795,11 @@ pub const Compiler = struct { | ... | @@ -2795,11 +2795,11 @@ pub const Compiler = struct { |
| 2795 | fn applyToOptionalStatements(language: *res.Language, version: *u32, characteristics: *u32, statements: []*Node, source: []const u8, code_page_lookup: *const CodePageLookup) void { | 2795 | fn applyToOptionalStatements(language: *res.Language, version: *u32, characteristics: *u32, statements: []*Node, source: []const u8, code_page_lookup: *const CodePageLookup) void { |
| 2796 | for (statements) |node| switch (node.id) { | 2796 | for (statements) |node| switch (node.id) { |
| 2797 | .language_statement => { | 2797 | .language_statement => { |
| 2798 | const language_statement = @fieldParentPtr(Node.LanguageStatement, "base", node); | 2798 | const language_statement: *Node.LanguageStatement = @alignCast(@fieldParentPtr("base", node)); |
| 2799 | language.* = languageFromLanguageStatement(language_statement, source, code_page_lookup); | 2799 | language.* = languageFromLanguageStatement(language_statement, source, code_page_lookup); |
| 2800 | }, | 2800 | }, |
| 2801 | .simple_statement => { | 2801 | .simple_statement => { |
| 2802 | const simple_statement = @fieldParentPtr(Node.SimpleStatement, "base", node); | 2802 | const simple_statement: *Node.SimpleStatement = @alignCast(@fieldParentPtr("base", node)); |
| 2803 | const statement_type = rc.OptionalStatements.map.get(simple_statement.identifier.slice(source)) orelse continue; | 2803 | const statement_type = rc.OptionalStatements.map.get(simple_statement.identifier.slice(source)) orelse continue; |
| 2804 | const result = Compiler.evaluateNumberExpression(simple_statement.value, source, code_page_lookup); | 2804 | const result = Compiler.evaluateNumberExpression(simple_statement.value, source, code_page_lookup); |
| 2805 | switch (statement_type) { | 2805 | switch (statement_type) { |
| ... | @@ -2824,7 +2824,7 @@ pub const Compiler = struct { | ... | @@ -2824,7 +2824,7 @@ pub const Compiler = struct { |
| 2824 | pub fn getLanguageFromOptionalStatements(statements: []*Node, source: []const u8, code_page_lookup: *const CodePageLookup) ?res.Language { | 2824 | pub fn getLanguageFromOptionalStatements(statements: []*Node, source: []const u8, code_page_lookup: *const CodePageLookup) ?res.Language { |
| 2825 | for (statements) |node| switch (node.id) { | 2825 | for (statements) |node| switch (node.id) { |
| 2826 | .language_statement => { | 2826 | .language_statement => { |
| 2827 | const language_statement = @fieldParentPtr(Node.LanguageStatement, "base", node); | 2827 | const language_statement: *Node.LanguageStatement = @alignCast(@fieldParentPtr("base", node)); |
| 2828 | return languageFromLanguageStatement(language_statement, source, code_page_lookup); | 2828 | return languageFromLanguageStatement(language_statement, source, code_page_lookup); |
| 2829 | }, | 2829 | }, |
| 2830 | else => continue, | 2830 | else => continue, |
lib/compiler/resinator/parse.zig+1-1| ... | @@ -889,7 +889,7 @@ pub const Parser = struct { | ... | @@ -889,7 +889,7 @@ pub const Parser = struct { |
| 889 | if (control == .control) { | 889 | if (control == .control) { |
| 890 | class = try self.parseExpression(.{}); | 890 | class = try self.parseExpression(.{}); |
| 891 | if (class.?.id == .literal) { | 891 | if (class.?.id == .literal) { |
| 892 | const class_literal = @fieldParentPtr(Node.Literal, "base", class.?); | 892 | const class_literal: *Node.Literal = @alignCast(@fieldParentPtr("base", class.?)); |
| 893 | const is_invalid_control_class = class_literal.token.id == .literal and !rc.ControlClass.map.has(class_literal.token.slice(self.lexer.buffer)); | 893 | const is_invalid_control_class = class_literal.token.id == .literal and !rc.ControlClass.map.has(class_literal.token.slice(self.lexer.buffer)); |
| 894 | if (is_invalid_control_class) { | 894 | if (is_invalid_control_class) { |
| 895 | return self.addErrorDetailsAndFail(.{ | 895 | return self.addErrorDetailsAndFail(.{ |
lib/docs/wasm/Walk.zig+6-6| ... | @@ -48,7 +48,7 @@ pub const File = struct { | ... | @@ -48,7 +48,7 @@ pub const File = struct { |
| 48 | pub fn field_count(file: *const File, node: Ast.Node.Index) u32 { | 48 | pub fn field_count(file: *const File, node: Ast.Node.Index) u32 { |
| 49 | const scope = file.scopes.get(node) orelse return 0; | 49 | const scope = file.scopes.get(node) orelse return 0; |
| 50 | if (scope.tag != .namespace) return 0; | 50 | if (scope.tag != .namespace) return 0; |
| 51 | const namespace = @fieldParentPtr(Scope.Namespace, "base", scope); | 51 | const namespace: *Scope.Namespace = @alignCast(@fieldParentPtr("base", scope)); |
| 52 | return namespace.field_count; | 52 | return namespace.field_count; |
| 53 | } | 53 | } |
| 54 | 54 | ||
| ... | @@ -439,11 +439,11 @@ pub const Scope = struct { | ... | @@ -439,11 +439,11 @@ pub const Scope = struct { |
| 439 | while (true) switch (it.tag) { | 439 | while (true) switch (it.tag) { |
| 440 | .top => unreachable, | 440 | .top => unreachable, |
| 441 | .local => { | 441 | .local => { |
| 442 | const local = @fieldParentPtr(Local, "base", it); | 442 | const local: *Local = @alignCast(@fieldParentPtr("base", it)); |
| 443 | it = local.parent; | 443 | it = local.parent; |
| 444 | }, | 444 | }, |
| 445 | .namespace => { | 445 | .namespace => { |
| 446 | const namespace = @fieldParentPtr(Namespace, "base", it); | 446 | const namespace: *Namespace = @alignCast(@fieldParentPtr("base", it)); |
| 447 | return namespace.decl_index; | 447 | return namespace.decl_index; |
| 448 | }, | 448 | }, |
| 449 | }; | 449 | }; |
| ... | @@ -453,7 +453,7 @@ pub const Scope = struct { | ... | @@ -453,7 +453,7 @@ pub const Scope = struct { |
| 453 | switch (scope.tag) { | 453 | switch (scope.tag) { |
| 454 | .top, .local => return null, | 454 | .top, .local => return null, |
| 455 | .namespace => { | 455 | .namespace => { |
| 456 | const namespace = @fieldParentPtr(Namespace, "base", scope); | 456 | const namespace: *Namespace = @alignCast(@fieldParentPtr("base", scope)); |
| 457 | return namespace.names.get(name); | 457 | return namespace.names.get(name); |
| 458 | }, | 458 | }, |
| 459 | } | 459 | } |
| ... | @@ -465,7 +465,7 @@ pub const Scope = struct { | ... | @@ -465,7 +465,7 @@ pub const Scope = struct { |
| 465 | while (true) switch (it.tag) { | 465 | while (true) switch (it.tag) { |
| 466 | .top => break, | 466 | .top => break, |
| 467 | .local => { | 467 | .local => { |
| 468 | const local = @fieldParentPtr(Local, "base", it); | 468 | const local: *Local = @alignCast(@fieldParentPtr("base", it)); |
| 469 | const name_token = main_tokens[local.var_node] + 1; | 469 | const name_token = main_tokens[local.var_node] + 1; |
| 470 | const ident_name = ast.tokenSlice(name_token); | 470 | const ident_name = ast.tokenSlice(name_token); |
| 471 | if (std.mem.eql(u8, ident_name, name)) { | 471 | if (std.mem.eql(u8, ident_name, name)) { |
| ... | @@ -474,7 +474,7 @@ pub const Scope = struct { | ... | @@ -474,7 +474,7 @@ pub const Scope = struct { |
| 474 | it = local.parent; | 474 | it = local.parent; |
| 475 | }, | 475 | }, |
| 476 | .namespace => { | 476 | .namespace => { |
| 477 | const namespace = @fieldParentPtr(Namespace, "base", it); | 477 | const namespace: *Namespace = @alignCast(@fieldParentPtr("base", it)); |
| 478 | if (namespace.names.get(name)) |node| { | 478 | if (namespace.names.get(name)) |node| { |
| 479 | return node; | 479 | return node; |
| 480 | } | 480 | } |
lib/std/Build.zig+2-2| ... | @@ -1062,8 +1062,8 @@ pub fn getUninstallStep(self: *Build) *Step { | ... | @@ -1062,8 +1062,8 @@ pub fn getUninstallStep(self: *Build) *Step { |
| 1062 | 1062 | ||
| 1063 | fn makeUninstall(uninstall_step: *Step, prog_node: *std.Progress.Node) anyerror!void { | 1063 | fn makeUninstall(uninstall_step: *Step, prog_node: *std.Progress.Node) anyerror!void { |
| 1064 | _ = prog_node; | 1064 | _ = prog_node; |
| 1065 | const uninstall_tls = @fieldParentPtr(TopLevelStep, "step", uninstall_step); | 1065 | const uninstall_tls: *TopLevelStep = @fieldParentPtr("step", uninstall_step); |
| 1066 | const self = @fieldParentPtr(Build, "uninstall_tls", uninstall_tls); | 1066 | const self: *Build = @fieldParentPtr("uninstall_tls", uninstall_tls); |
| 1067 | 1067 | ||
| 1068 | for (self.installed_files.items) |installed_file| { | 1068 | for (self.installed_files.items) |installed_file| { |
| 1069 | const full_path = self.getInstallPath(installed_file.dir, installed_file.path); | 1069 | const full_path = self.getInstallPath(installed_file.dir, installed_file.path); |
lib/std/Build/Step.zig+1-1| ... | @@ -231,7 +231,7 @@ fn makeNoOp(step: *Step, prog_node: *std.Progress.Node) anyerror!void { | ... | @@ -231,7 +231,7 @@ fn makeNoOp(step: *Step, prog_node: *std.Progress.Node) anyerror!void { |
| 231 | 231 | ||
| 232 | pub fn cast(step: *Step, comptime T: type) ?*T { | 232 | pub fn cast(step: *Step, comptime T: type) ?*T { |
| 233 | if (step.id == T.base_id) { | 233 | if (step.id == T.base_id) { |
| 234 | return @fieldParentPtr(T, "step", step); | 234 | return @fieldParentPtr("step", step); |
| 235 | } | 235 | } |
| 236 | return null; | 236 | return null; |
| 237 | } | 237 | } |
lib/std/Build/Step/CheckFile.zig+1-1| ... | @@ -49,7 +49,7 @@ pub fn setName(self: *CheckFile, name: []const u8) void { | ... | @@ -49,7 +49,7 @@ pub fn setName(self: *CheckFile, name: []const u8) void { |
| 49 | fn make(step: *Step, prog_node: *std.Progress.Node) !void { | 49 | fn make(step: *Step, prog_node: *std.Progress.Node) !void { |
| 50 | _ = prog_node; | 50 | _ = prog_node; |
| 51 | const b = step.owner; | 51 | const b = step.owner; |
| 52 | const self = @fieldParentPtr(CheckFile, "step", step); | 52 | const self: *CheckFile = @fieldParentPtr("step", step); |
| 53 | 53 | ||
| 54 | const src_path = self.source.getPath(b); | 54 | const src_path = self.source.getPath(b); |
| 55 | const contents = fs.cwd().readFileAlloc(b.allocator, src_path, self.max_bytes) catch |err| { | 55 | const contents = fs.cwd().readFileAlloc(b.allocator, src_path, self.max_bytes) catch |err| { |
lib/std/Build/Step/CheckObject.zig+1-1| ... | @@ -530,7 +530,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { | ... | @@ -530,7 +530,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { |
| 530 | _ = prog_node; | 530 | _ = prog_node; |
| 531 | const b = step.owner; | 531 | const b = step.owner; |
| 532 | const gpa = b.allocator; | 532 | const gpa = b.allocator; |
| 533 | const self = @fieldParentPtr(CheckObject, "step", step); | 533 | const self: *CheckObject = @fieldParentPtr("step", step); |
| 534 | 534 | ||
| 535 | const src_path = self.source.getPath(b); | 535 | const src_path = self.source.getPath(b); |
| 536 | const contents = fs.cwd().readFileAllocOptions( | 536 | const contents = fs.cwd().readFileAllocOptions( |
lib/std/Build/Step/Compile.zig+1-1| ... | @@ -918,7 +918,7 @@ fn getGeneratedFilePath(self: *Compile, comptime tag_name: []const u8, asking_st | ... | @@ -918,7 +918,7 @@ fn getGeneratedFilePath(self: *Compile, comptime tag_name: []const u8, asking_st |
| 918 | fn make(step: *Step, prog_node: *std.Progress.Node) !void { | 918 | fn make(step: *Step, prog_node: *std.Progress.Node) !void { |
| 919 | const b = step.owner; | 919 | const b = step.owner; |
| 920 | const arena = b.allocator; | 920 | const arena = b.allocator; |
| 921 | const self = @fieldParentPtr(Compile, "step", step); | 921 | const self: *Compile = @fieldParentPtr("step", step); |
| 922 | 922 | ||
| 923 | var zig_args = ArrayList([]const u8).init(arena); | 923 | var zig_args = ArrayList([]const u8).init(arena); |
| 924 | defer zig_args.deinit(); | 924 | defer zig_args.deinit(); |
lib/std/Build/Step/ConfigHeader.zig+1-1| ... | @@ -167,7 +167,7 @@ fn putValue(self: *ConfigHeader, field_name: []const u8, comptime T: type, v: T) | ... | @@ -167,7 +167,7 @@ fn putValue(self: *ConfigHeader, field_name: []const u8, comptime T: type, v: T) |
| 167 | fn make(step: *Step, prog_node: *std.Progress.Node) !void { | 167 | fn make(step: *Step, prog_node: *std.Progress.Node) !void { |
| 168 | _ = prog_node; | 168 | _ = prog_node; |
| 169 | const b = step.owner; | 169 | const b = step.owner; |
| 170 | const self = @fieldParentPtr(ConfigHeader, "step", step); | 170 | const self: *ConfigHeader = @fieldParentPtr("step", step); |
| 171 | const gpa = b.allocator; | 171 | const gpa = b.allocator; |
| 172 | const arena = b.allocator; | 172 | const arena = b.allocator; |
| 173 | 173 |
lib/std/Build/Step/Fmt.zig+1-1| ... | @@ -47,7 +47,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { | ... | @@ -47,7 +47,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { |
| 47 | 47 | ||
| 48 | const b = step.owner; | 48 | const b = step.owner; |
| 49 | const arena = b.allocator; | 49 | const arena = b.allocator; |
| 50 | const self = @fieldParentPtr(Fmt, "step", step); | 50 | const self: *Fmt = @fieldParentPtr("step", step); |
| 51 | 51 | ||
| 52 | var argv: std.ArrayListUnmanaged([]const u8) = .{}; | 52 | var argv: std.ArrayListUnmanaged([]const u8) = .{}; |
| 53 | try argv.ensureUnusedCapacity(arena, 2 + 1 + self.paths.len + 2 * self.exclude_paths.len); | 53 | try argv.ensureUnusedCapacity(arena, 2 + 1 + self.paths.len + 2 * self.exclude_paths.len); |
lib/std/Build/Step/InstallArtifact.zig+1-1| ... | @@ -121,7 +121,7 @@ pub fn create(owner: *std.Build, artifact: *Step.Compile, options: Options) *Ins | ... | @@ -121,7 +121,7 @@ pub fn create(owner: *std.Build, artifact: *Step.Compile, options: Options) *Ins |
| 121 | 121 | ||
| 122 | fn make(step: *Step, prog_node: *std.Progress.Node) !void { | 122 | fn make(step: *Step, prog_node: *std.Progress.Node) !void { |
| 123 | _ = prog_node; | 123 | _ = prog_node; |
| 124 | const self = @fieldParentPtr(InstallArtifact, "step", step); | 124 | const self: *InstallArtifact = @fieldParentPtr("step", step); |
| 125 | const dest_builder = step.owner; | 125 | const dest_builder = step.owner; |
| 126 | const cwd = fs.cwd(); | 126 | const cwd = fs.cwd(); |
| 127 | 127 |
lib/std/Build/Step/InstallDir.zig+1-1| ... | @@ -63,7 +63,7 @@ pub fn create(owner: *std.Build, options: Options) *InstallDirStep { | ... | @@ -63,7 +63,7 @@ pub fn create(owner: *std.Build, options: Options) *InstallDirStep { |
| 63 | 63 | ||
| 64 | fn make(step: *Step, prog_node: *std.Progress.Node) !void { | 64 | fn make(step: *Step, prog_node: *std.Progress.Node) !void { |
| 65 | _ = prog_node; | 65 | _ = prog_node; |
| 66 | const self = @fieldParentPtr(InstallDirStep, "step", step); | 66 | const self: *InstallDirStep = @fieldParentPtr("step", step); |
| 67 | const dest_builder = self.dest_builder; | 67 | const dest_builder = self.dest_builder; |
| 68 | const arena = dest_builder.allocator; | 68 | const arena = dest_builder.allocator; |
| 69 | const dest_prefix = dest_builder.getInstallPath(self.options.install_dir, self.options.install_subdir); | 69 | const dest_prefix = dest_builder.getInstallPath(self.options.install_dir, self.options.install_subdir); |
lib/std/Build/Step/InstallFile.zig+1-1| ... | @@ -43,7 +43,7 @@ pub fn create( | ... | @@ -43,7 +43,7 @@ pub fn create( |
| 43 | fn make(step: *Step, prog_node: *std.Progress.Node) !void { | 43 | fn make(step: *Step, prog_node: *std.Progress.Node) !void { |
| 44 | _ = prog_node; | 44 | _ = prog_node; |
| 45 | const src_builder = step.owner; | 45 | const src_builder = step.owner; |
| 46 | const self = @fieldParentPtr(InstallFile, "step", step); | 46 | const self: *InstallFile = @fieldParentPtr("step", step); |
| 47 | const dest_builder = self.dest_builder; | 47 | const dest_builder = self.dest_builder; |
| 48 | const full_src_path = self.source.getPath2(src_builder, step); | 48 | const full_src_path = self.source.getPath2(src_builder, step); |
| 49 | const full_dest_path = dest_builder.getInstallPath(self.dir, self.dest_rel_path); | 49 | const full_dest_path = dest_builder.getInstallPath(self.dir, self.dest_rel_path); |
lib/std/Build/Step/ObjCopy.zig+1-1| ... | @@ -92,7 +92,7 @@ pub fn getOutputSeparatedDebug(self: *const ObjCopy) ?std.Build.LazyPath { | ... | @@ -92,7 +92,7 @@ pub fn getOutputSeparatedDebug(self: *const ObjCopy) ?std.Build.LazyPath { |
| 92 | 92 | ||
| 93 | fn make(step: *Step, prog_node: *std.Progress.Node) !void { | 93 | fn make(step: *Step, prog_node: *std.Progress.Node) !void { |
| 94 | const b = step.owner; | 94 | const b = step.owner; |
| 95 | const self = @fieldParentPtr(ObjCopy, "step", step); | 95 | const self: *ObjCopy = @fieldParentPtr("step", step); |
| 96 | 96 | ||
| 97 | var man = b.graph.cache.obtain(); | 97 | var man = b.graph.cache.obtain(); |
| 98 | defer man.deinit(); | 98 | defer man.deinit(); |
lib/std/Build/Step/Options.zig+1-1| ... | @@ -415,7 +415,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { | ... | @@ -415,7 +415,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { |
| 415 | _ = prog_node; | 415 | _ = prog_node; |
| 416 | 416 | ||
| 417 | const b = step.owner; | 417 | const b = step.owner; |
| 418 | const self = @fieldParentPtr(Options, "step", step); | 418 | const self: *Options = @fieldParentPtr("step", step); |
| 419 | 419 | ||
| 420 | for (self.args.items) |item| { | 420 | for (self.args.items) |item| { |
| 421 | self.addOption( | 421 | self.addOption( |
lib/std/Build/Step/RemoveDir.zig+1-1| ... | @@ -28,7 +28,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { | ... | @@ -28,7 +28,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { |
| 28 | _ = prog_node; | 28 | _ = prog_node; |
| 29 | 29 | ||
| 30 | const b = step.owner; | 30 | const b = step.owner; |
| 31 | const self = @fieldParentPtr(RemoveDir, "step", step); | 31 | const self: *RemoveDir = @fieldParentPtr("step", step); |
| 32 | 32 | ||
| 33 | b.build_root.handle.deleteTree(self.dir_path) catch |err| { | 33 | b.build_root.handle.deleteTree(self.dir_path) catch |err| { |
| 34 | if (b.build_root.path) |base| { | 34 | if (b.build_root.path) |base| { |
lib/std/Build/Step/Run.zig+1-1| ... | @@ -497,7 +497,7 @@ const IndexedOutput = struct { | ... | @@ -497,7 +497,7 @@ const IndexedOutput = struct { |
| 497 | fn make(step: *Step, prog_node: *std.Progress.Node) !void { | 497 | fn make(step: *Step, prog_node: *std.Progress.Node) !void { |
| 498 | const b = step.owner; | 498 | const b = step.owner; |
| 499 | const arena = b.allocator; | 499 | const arena = b.allocator; |
| 500 | const self = @fieldParentPtr(Run, "step", step); | 500 | const self: *Run = @fieldParentPtr("step", step); |
| 501 | const has_side_effects = self.hasSideEffects(); | 501 | const has_side_effects = self.hasSideEffects(); |
| 502 | 502 | ||
| 503 | var argv_list = ArrayList([]const u8).init(arena); | 503 | var argv_list = ArrayList([]const u8).init(arena); |
lib/std/Build/Step/TranslateC.zig+1-1| ... | @@ -118,7 +118,7 @@ pub fn defineCMacroRaw(self: *TranslateC, name_and_value: []const u8) void { | ... | @@ -118,7 +118,7 @@ pub fn defineCMacroRaw(self: *TranslateC, name_and_value: []const u8) void { |
| 118 | 118 | ||
| 119 | fn make(step: *Step, prog_node: *std.Progress.Node) !void { | 119 | fn make(step: *Step, prog_node: *std.Progress.Node) !void { |
| 120 | const b = step.owner; | 120 | const b = step.owner; |
| 121 | const self = @fieldParentPtr(TranslateC, "step", step); | 121 | const self: *TranslateC = @fieldParentPtr("step", step); |
| 122 | 122 | ||
| 123 | var argv_list = std.ArrayList([]const u8).init(b.allocator); | 123 | var argv_list = std.ArrayList([]const u8).init(b.allocator); |
| 124 | try argv_list.append(b.graph.zig_exe); | 124 | try argv_list.append(b.graph.zig_exe); |
lib/std/Build/Step/WriteFile.zig+1-1| ... | @@ -141,7 +141,7 @@ fn maybeUpdateName(wf: *WriteFile) void { | ... | @@ -141,7 +141,7 @@ fn maybeUpdateName(wf: *WriteFile) void { |
| 141 | fn make(step: *Step, prog_node: *std.Progress.Node) !void { | 141 | fn make(step: *Step, prog_node: *std.Progress.Node) !void { |
| 142 | _ = prog_node; | 142 | _ = prog_node; |
| 143 | const b = step.owner; | 143 | const b = step.owner; |
| 144 | const wf = @fieldParentPtr(WriteFile, "step", step); | 144 | const wf: *WriteFile = @fieldParentPtr("step", step); |
| 145 | 145 | ||
| 146 | // Writing to source files is kind of an extra capability of this | 146 | // Writing to source files is kind of an extra capability of this |
| 147 | // WriteFile - arguably it should be a different step. But anyway here | 147 | // WriteFile - arguably it should be a different step. But anyway here |
lib/std/Thread/Futex.zig+3-3| ... | @@ -644,7 +644,7 @@ const PosixImpl = struct { | ... | @@ -644,7 +644,7 @@ const PosixImpl = struct { |
| 644 | }; | 644 | }; |
| 645 | 645 | ||
| 646 | // There's a wait queue on the address; get the queue head and tail. | 646 | // There's a wait queue on the address; get the queue head and tail. |
| 647 | const head = @fieldParentPtr(Waiter, "node", entry_node); | 647 | const head: *Waiter = @fieldParentPtr("node", entry_node); |
| 648 | const tail = head.tail orelse unreachable; | 648 | const tail = head.tail orelse unreachable; |
| 649 | 649 | ||
| 650 | // Push the waiter to the tail by replacing it and linking to the previous tail. | 650 | // Push the waiter to the tail by replacing it and linking to the previous tail. |
| ... | @@ -656,7 +656,7 @@ const PosixImpl = struct { | ... | @@ -656,7 +656,7 @@ const PosixImpl = struct { |
| 656 | fn remove(treap: *Treap, address: usize, max_waiters: usize) WaitList { | 656 | fn remove(treap: *Treap, address: usize, max_waiters: usize) WaitList { |
| 657 | // Find the wait queue associated with this address and get the head/tail if any. | 657 | // Find the wait queue associated with this address and get the head/tail if any. |
| 658 | var entry = treap.getEntryFor(address); | 658 | var entry = treap.getEntryFor(address); |
| 659 | var queue_head = if (entry.node) |node| @fieldParentPtr(Waiter, "node", node) else null; | 659 | var queue_head: ?*Waiter = if (entry.node) |node| @fieldParentPtr("node", node) else null; |
| 660 | const queue_tail = if (queue_head) |head| head.tail else null; | 660 | const queue_tail = if (queue_head) |head| head.tail else null; |
| 661 | 661 | ||
| 662 | // Once we're done updating the head, fix it's tail pointer and update the treap's queue head as well. | 662 | // Once we're done updating the head, fix it's tail pointer and update the treap's queue head as well. |
| ... | @@ -699,7 +699,7 @@ const PosixImpl = struct { | ... | @@ -699,7 +699,7 @@ const PosixImpl = struct { |
| 699 | }; | 699 | }; |
| 700 | 700 | ||
| 701 | // The queue head and tail must exist if we're removing a queued waiter. | 701 | // The queue head and tail must exist if we're removing a queued waiter. |
| 702 | const head = @fieldParentPtr(Waiter, "node", entry.node orelse unreachable); | 702 | const head: *Waiter = @fieldParentPtr("node", entry.node orelse unreachable); |
| 703 | const tail = head.tail orelse unreachable; | 703 | const tail = head.tail orelse unreachable; |
| 704 | 704 | ||
| 705 | // A waiter with a previous link is never the head of the queue. | 705 | // A waiter with a previous link is never the head of the queue. |
lib/std/Thread/Pool.zig+2-2| ... | @@ -88,8 +88,8 @@ pub fn spawn(pool: *Pool, comptime func: anytype, args: anytype) !void { | ... | @@ -88,8 +88,8 @@ pub fn spawn(pool: *Pool, comptime func: anytype, args: anytype) !void { |
| 88 | run_node: RunQueue.Node = .{ .data = .{ .runFn = runFn } }, | 88 | run_node: RunQueue.Node = .{ .data = .{ .runFn = runFn } }, |
| 89 | 89 | ||
| 90 | fn runFn(runnable: *Runnable) void { | 90 | fn runFn(runnable: *Runnable) void { |
| 91 | const run_node = @fieldParentPtr(RunQueue.Node, "data", runnable); | 91 | const run_node: *RunQueue.Node = @fieldParentPtr("data", runnable); |
| 92 | const closure = @fieldParentPtr(@This(), "run_node", run_node); | 92 | const closure: *@This() = @fieldParentPtr("run_node", run_node); |
| 93 | @call(.auto, func, closure.arguments); | 93 | @call(.auto, func, closure.arguments); |
| 94 | 94 | ||
| 95 | // The thread pool's allocator is protected by the mutex. | 95 | // The thread pool's allocator is protected by the mutex. |
lib/std/c/darwin.zig+2-2| ... | @@ -1150,8 +1150,8 @@ pub const siginfo_t = extern struct { | ... | @@ -1150,8 +1150,8 @@ pub const siginfo_t = extern struct { |
| 1150 | 1150 | ||
| 1151 | /// Renamed from `sigaction` to `Sigaction` to avoid conflict with function name. | 1151 | /// Renamed from `sigaction` to `Sigaction` to avoid conflict with function name. |
| 1152 | pub const Sigaction = extern struct { | 1152 | pub const Sigaction = extern struct { |
| 1153 | pub const handler_fn = *align(1) const fn (c_int) callconv(.C) void; | 1153 | pub const handler_fn = *align(1) const fn (i32) callconv(.C) void; |
| 1154 | pub const sigaction_fn = *const fn (c_int, *const siginfo_t, ?*anyopaque) callconv(.C) void; | 1154 | pub const sigaction_fn = *const fn (i32, *const siginfo_t, ?*anyopaque) callconv(.C) void; |
| 1155 | 1155 | ||
| 1156 | handler: extern union { | 1156 | handler: extern union { |
| 1157 | handler: ?handler_fn, | 1157 | handler: ?handler_fn, |
lib/std/c/dragonfly.zig+3-3| ... | @@ -690,8 +690,8 @@ pub const empty_sigset = sigset_t{ .__bits = [_]c_uint{0} ** _SIG_WORDS }; | ... | @@ -690,8 +690,8 @@ pub const empty_sigset = sigset_t{ .__bits = [_]c_uint{0} ** _SIG_WORDS }; |
| 690 | pub const sig_atomic_t = c_int; | 690 | pub const sig_atomic_t = c_int; |
| 691 | 691 | ||
| 692 | pub const Sigaction = extern struct { | 692 | pub const Sigaction = extern struct { |
| 693 | pub const handler_fn = *align(1) const fn (c_int) callconv(.C) void; | 693 | pub const handler_fn = *align(1) const fn (i32) callconv(.C) void; |
| 694 | pub const sigaction_fn = *const fn (c_int, *const siginfo_t, ?*anyopaque) callconv(.C) void; | 694 | pub const sigaction_fn = *const fn (i32, *const siginfo_t, ?*anyopaque) callconv(.C) void; |
| 695 | 695 | ||
| 696 | /// signal handler | 696 | /// signal handler |
| 697 | handler: extern union { | 697 | handler: extern union { |
| ... | @@ -702,7 +702,7 @@ pub const Sigaction = extern struct { | ... | @@ -702,7 +702,7 @@ pub const Sigaction = extern struct { |
| 702 | mask: sigset_t, | 702 | mask: sigset_t, |
| 703 | }; | 703 | }; |
| 704 | 704 | ||
| 705 | pub const sig_t = *const fn (c_int) callconv(.C) void; | 705 | pub const sig_t = *const fn (i32) callconv(.C) void; |
| 706 | 706 | ||
| 707 | pub const SOCK = struct { | 707 | pub const SOCK = struct { |
| 708 | pub const STREAM = 1; | 708 | pub const STREAM = 1; |
lib/std/c/freebsd.zig+2-2| ... | @@ -1171,8 +1171,8 @@ const NSIG = 32; | ... | @@ -1171,8 +1171,8 @@ const NSIG = 32; |
| 1171 | 1171 | ||
| 1172 | /// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall. | 1172 | /// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall. |
| 1173 | pub const Sigaction = extern struct { | 1173 | pub const Sigaction = extern struct { |
| 1174 | pub const handler_fn = *align(1) const fn (c_int) callconv(.C) void; | 1174 | pub const handler_fn = *align(1) const fn (i32) callconv(.C) void; |
| 1175 | pub const sigaction_fn = *const fn (c_int, *const siginfo_t, ?*anyopaque) callconv(.C) void; | 1175 | pub const sigaction_fn = *const fn (i32, *const siginfo_t, ?*anyopaque) callconv(.C) void; |
| 1176 | 1176 | ||
| 1177 | /// signal handler | 1177 | /// signal handler |
| 1178 | handler: extern union { | 1178 | handler: extern union { |
lib/std/c/haiku.zig+1-1| ... | @@ -501,7 +501,7 @@ pub const siginfo_t = extern struct { | ... | @@ -501,7 +501,7 @@ pub const siginfo_t = extern struct { |
| 501 | /// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall. | 501 | /// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall. |
| 502 | pub const Sigaction = extern struct { | 502 | pub const Sigaction = extern struct { |
| 503 | pub const handler_fn = *align(1) const fn (i32) callconv(.C) void; | 503 | pub const handler_fn = *align(1) const fn (i32) callconv(.C) void; |
| 504 | pub const sigaction_fn = *const fn (c_int, *allowzero anyopaque, ?*anyopaque) callconv(.C) void; | 504 | pub const sigaction_fn = *const fn (i32, *const siginfo_t, ?*anyopaque) callconv(.C) void; |
| 505 | 505 | ||
| 506 | /// signal handler | 506 | /// signal handler |
| 507 | handler: extern union { | 507 | handler: extern union { |
lib/std/c/netbsd.zig+2-2| ... | @@ -864,8 +864,8 @@ pub const SIG = struct { | ... | @@ -864,8 +864,8 @@ pub const SIG = struct { |
| 864 | 864 | ||
| 865 | /// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall. | 865 | /// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall. |
| 866 | pub const Sigaction = extern struct { | 866 | pub const Sigaction = extern struct { |
| 867 | pub const handler_fn = *align(1) const fn (c_int) callconv(.C) void; | 867 | pub const handler_fn = *align(1) const fn (i32) callconv(.C) void; |
| 868 | pub const sigaction_fn = *const fn (c_int, *const siginfo_t, ?*anyopaque) callconv(.C) void; | 868 | pub const sigaction_fn = *const fn (i32, *const siginfo_t, ?*anyopaque) callconv(.C) void; |
| 869 | 869 | ||
| 870 | /// signal handler | 870 | /// signal handler |
| 871 | handler: extern union { | 871 | handler: extern union { |
lib/std/c/openbsd.zig+2-2| ... | @@ -842,8 +842,8 @@ pub const SIG = struct { | ... | @@ -842,8 +842,8 @@ pub const SIG = struct { |
| 842 | 842 | ||
| 843 | /// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall. | 843 | /// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall. |
| 844 | pub const Sigaction = extern struct { | 844 | pub const Sigaction = extern struct { |
| 845 | pub const handler_fn = *align(1) const fn (c_int) callconv(.C) void; | 845 | pub const handler_fn = *align(1) const fn (i32) callconv(.C) void; |
| 846 | pub const sigaction_fn = *const fn (c_int, *const siginfo_t, ?*anyopaque) callconv(.C) void; | 846 | pub const sigaction_fn = *const fn (i32, *const siginfo_t, ?*anyopaque) callconv(.C) void; |
| 847 | 847 | ||
| 848 | /// signal handler | 848 | /// signal handler |
| 849 | handler: extern union { | 849 | handler: extern union { |
lib/std/c/solaris.zig+2-2| ... | @@ -874,8 +874,8 @@ pub const SIG = struct { | ... | @@ -874,8 +874,8 @@ pub const SIG = struct { |
| 874 | 874 | ||
| 875 | /// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall. | 875 | /// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall. |
| 876 | pub const Sigaction = extern struct { | 876 | pub const Sigaction = extern struct { |
| 877 | pub const handler_fn = *align(1) const fn (c_int) callconv(.C) void; | 877 | pub const handler_fn = *align(1) const fn (i32) callconv(.C) void; |
| 878 | pub const sigaction_fn = *const fn (c_int, *const siginfo_t, ?*anyopaque) callconv(.C) void; | 878 | pub const sigaction_fn = *const fn (i32, *const siginfo_t, ?*anyopaque) callconv(.C) void; |
| 879 | 879 | ||
| 880 | /// signal options | 880 | /// signal options |
| 881 | flags: c_uint, | 881 | flags: c_uint, |
lib/std/debug.zig+1-1| ... | @@ -2570,7 +2570,7 @@ fn resetSegfaultHandler() void { | ... | @@ -2570,7 +2570,7 @@ fn resetSegfaultHandler() void { |
| 2570 | updateSegfaultHandler(&act) catch {}; | 2570 | updateSegfaultHandler(&act) catch {}; |
| 2571 | } | 2571 | } |
| 2572 | 2572 | ||
| 2573 | fn handleSegfaultPosix(sig: i32, info: *const posix.siginfo_t, ctx_ptr: ?*const anyopaque) callconv(.C) noreturn { | 2573 | fn handleSegfaultPosix(sig: i32, info: *const posix.siginfo_t, ctx_ptr: ?*anyopaque) callconv(.C) noreturn { |
| 2574 | // Reset to the default handler so that if a segfault happens in this handler it will crash | 2574 | // Reset to the default handler so that if a segfault happens in this handler it will crash |
| 2575 | // the process. Also when this handler returns, the original instruction will be repeated | 2575 | // the process. Also when this handler returns, the original instruction will be repeated |
| 2576 | // and the resulting segfault will crash the process rather than continually dump stack traces. | 2576 | // and the resulting segfault will crash the process rather than continually dump stack traces. |
lib/std/http/Client.zig+1-1| ... | @@ -108,7 +108,7 @@ pub const ConnectionPool = struct { | ... | @@ -108,7 +108,7 @@ pub const ConnectionPool = struct { |
| 108 | pool.mutex.lock(); | 108 | pool.mutex.lock(); |
| 109 | defer pool.mutex.unlock(); | 109 | defer pool.mutex.unlock(); |
| 110 | 110 | ||
| 111 | const node = @fieldParentPtr(Node, "data", connection); | 111 | const node: *Node = @fieldParentPtr("data", connection); |
| 112 | 112 | ||
| 113 | pool.used.remove(node); | 113 | pool.used.remove(node); |
| 114 | 114 |
lib/std/os/emscripten.zig+2-2| ... | @@ -695,8 +695,8 @@ pub const SIG = struct { | ... | @@ -695,8 +695,8 @@ pub const SIG = struct { |
| 695 | }; | 695 | }; |
| 696 | 696 | ||
| 697 | pub const Sigaction = extern struct { | 697 | pub const Sigaction = extern struct { |
| 698 | pub const handler_fn = *align(1) const fn (c_int) callconv(.C) void; | 698 | pub const handler_fn = *align(1) const fn (i32) callconv(.C) void; |
| 699 | pub const sigaction_fn = *const fn (c_int, *const siginfo_t, ?*anyopaque) callconv(.C) void; | 699 | pub const sigaction_fn = *const fn (i32, *const siginfo_t, ?*anyopaque) callconv(.C) void; |
| 700 | 700 | ||
| 701 | handler: extern union { | 701 | handler: extern union { |
| 702 | handler: ?handler_fn, | 702 | handler: ?handler_fn, |
lib/std/os/linux.zig+3-3| ... | @@ -4301,7 +4301,7 @@ pub const all_mask: sigset_t = [_]u32{0xffffffff} ** @typeInfo(sigset_t).Array.l | ... | @@ -4301,7 +4301,7 @@ pub const all_mask: sigset_t = [_]u32{0xffffffff} ** @typeInfo(sigset_t).Array.l |
| 4301 | pub const app_mask: sigset_t = [2]u32{ 0xfffffffc, 0x7fffffff } ++ [_]u32{0xffffffff} ** 30; | 4301 | pub const app_mask: sigset_t = [2]u32{ 0xfffffffc, 0x7fffffff } ++ [_]u32{0xffffffff} ** 30; |
| 4302 | 4302 | ||
| 4303 | const k_sigaction_funcs = struct { | 4303 | const k_sigaction_funcs = struct { |
| 4304 | const handler = ?*align(1) const fn (c_int) callconv(.C) void; | 4304 | const handler = ?*align(1) const fn (i32) callconv(.C) void; |
| 4305 | const restorer = *const fn () callconv(.C) void; | 4305 | const restorer = *const fn () callconv(.C) void; |
| 4306 | }; | 4306 | }; |
| 4307 | 4307 | ||
| ... | @@ -4328,8 +4328,8 @@ pub const k_sigaction = switch (native_arch) { | ... | @@ -4328,8 +4328,8 @@ pub const k_sigaction = switch (native_arch) { |
| 4328 | 4328 | ||
| 4329 | /// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall. | 4329 | /// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall. |
| 4330 | pub const Sigaction = extern struct { | 4330 | pub const Sigaction = extern struct { |
| 4331 | pub const handler_fn = *align(1) const fn (c_int) callconv(.C) void; | 4331 | pub const handler_fn = *align(1) const fn (i32) callconv(.C) void; |
| 4332 | pub const sigaction_fn = *const fn (c_int, *const siginfo_t, ?*anyopaque) callconv(.C) void; | 4332 | pub const sigaction_fn = *const fn (i32, *const siginfo_t, ?*anyopaque) callconv(.C) void; |
| 4333 | 4333 | ||
| 4334 | handler: extern union { | 4334 | handler: extern union { |
| 4335 | handler: ?handler_fn, | 4335 | handler: ?handler_fn, |
lib/std/os/plan9.zig+2-2| ... | @@ -186,8 +186,8 @@ pub const empty_sigset = 0; | ... | @@ -186,8 +186,8 @@ pub const empty_sigset = 0; |
| 186 | pub const siginfo_t = c_long; | 186 | pub const siginfo_t = c_long; |
| 187 | // TODO plan9 doesn't have sigaction_fn. Sigaction is not a union, but we incude it here to be compatible. | 187 | // TODO plan9 doesn't have sigaction_fn. Sigaction is not a union, but we incude it here to be compatible. |
| 188 | pub const Sigaction = extern struct { | 188 | pub const Sigaction = extern struct { |
| 189 | pub const handler_fn = *const fn (c_int) callconv(.C) void; | 189 | pub const handler_fn = *const fn (i32) callconv(.C) void; |
| 190 | pub const sigaction_fn = *const fn (c_int, *const siginfo_t, ?*anyopaque) callconv(.C) void; | 190 | pub const sigaction_fn = *const fn (i32, *const siginfo_t, ?*anyopaque) callconv(.C) void; |
| 191 | 191 | ||
| 192 | handler: extern union { | 192 | handler: extern union { |
| 193 | handler: ?handler_fn, | 193 | handler: ?handler_fn, |
lib/std/start.zig+1-1| ... | @@ -597,4 +597,4 @@ fn maybeIgnoreSigpipe() void { | ... | @@ -597,4 +597,4 @@ fn maybeIgnoreSigpipe() void { |
| 597 | } | 597 | } |
| 598 | } | 598 | } |
| 599 | 599 | ||
| 600 | fn noopSigHandler(_: c_int) callconv(.C) void {} | 600 | fn noopSigHandler(_: i32) callconv(.C) void {} |
lib/std/zig.zig+1| ... | @@ -1021,4 +1021,5 @@ test { | ... | @@ -1021,4 +1021,5 @@ test { |
| 1021 | _ = string_literal; | 1021 | _ = string_literal; |
| 1022 | _ = system; | 1022 | _ = system; |
| 1023 | _ = target; | 1023 | _ = target; |
| 1024 | _ = c_translation; | ||
| 1024 | } | 1025 | } |
lib/std/zig/AstGen.zig+65-36| ... | @@ -316,8 +316,7 @@ const ResultInfo = struct { | ... | @@ -316,8 +316,7 @@ const ResultInfo = struct { |
| 316 | }; | 316 | }; |
| 317 | 317 | ||
| 318 | /// Find the result type for a cast builtin given the result location. | 318 | /// Find the result type for a cast builtin given the result location. |
| 319 | /// If the location does not have a known result type, emits an error on | 319 | /// If the location does not have a known result type, returns `null`. |
| 320 | /// the given node. | ||
| 321 | fn resultType(rl: Loc, gz: *GenZir, node: Ast.Node.Index) !?Zir.Inst.Ref { | 320 | fn resultType(rl: Loc, gz: *GenZir, node: Ast.Node.Index) !?Zir.Inst.Ref { |
| 322 | return switch (rl) { | 321 | return switch (rl) { |
| 323 | .discard, .none, .ref, .inferred_ptr, .destructure => null, | 322 | .discard, .none, .ref, .inferred_ptr, .destructure => null, |
| ... | @@ -330,6 +329,9 @@ const ResultInfo = struct { | ... | @@ -330,6 +329,9 @@ const ResultInfo = struct { |
| 330 | }; | 329 | }; |
| 331 | } | 330 | } |
| 332 | 331 | ||
| 332 | /// Find the result type for a cast builtin given the result location. | ||
| 333 | /// If the location does not have a known result type, emits an error on | ||
| 334 | /// the given node. | ||
| 333 | fn resultTypeForCast(rl: Loc, gz: *GenZir, node: Ast.Node.Index, builtin_name: []const u8) !Zir.Inst.Ref { | 335 | fn resultTypeForCast(rl: Loc, gz: *GenZir, node: Ast.Node.Index, builtin_name: []const u8) !Zir.Inst.Ref { |
| 334 | const astgen = gz.astgen; | 336 | const astgen = gz.astgen; |
| 335 | if (try rl.resultType(gz, node)) |ty| return ty; | 337 | if (try rl.resultType(gz, node)) |ty| return ty; |
| ... | @@ -2786,7 +2788,6 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As | ... | @@ -2786,7 +2788,6 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As |
| 2786 | .atomic_load, | 2788 | .atomic_load, |
| 2787 | .atomic_rmw, | 2789 | .atomic_rmw, |
| 2788 | .mul_add, | 2790 | .mul_add, |
| 2789 | .field_parent_ptr, | ||
| 2790 | .max, | 2791 | .max, |
| 2791 | .min, | 2792 | .min, |
| 2792 | .c_import, | 2793 | .c_import, |
| ... | @@ -8853,6 +8854,7 @@ fn ptrCast( | ... | @@ -8853,6 +8854,7 @@ fn ptrCast( |
| 8853 | const node_datas = tree.nodes.items(.data); | 8854 | const node_datas = tree.nodes.items(.data); |
| 8854 | const node_tags = tree.nodes.items(.tag); | 8855 | const node_tags = tree.nodes.items(.tag); |
| 8855 | 8856 | ||
| 8857 | const FlagsInt = @typeInfo(Zir.Inst.FullPtrCastFlags).Struct.backing_integer.?; | ||
| 8856 | var flags: Zir.Inst.FullPtrCastFlags = .{}; | 8858 | var flags: Zir.Inst.FullPtrCastFlags = .{}; |
| 8857 | 8859 | ||
| 8858 | // Note that all pointer cast builtins have one parameter, so we only need | 8860 | // Note that all pointer cast builtins have one parameter, so we only need |
| ... | @@ -8870,36 +8872,62 @@ fn ptrCast( | ... | @@ -8870,36 +8872,62 @@ fn ptrCast( |
| 8870 | } | 8872 | } |
| 8871 | 8873 | ||
| 8872 | if (node_datas[node].lhs == 0) break; // 0 args | 8874 | if (node_datas[node].lhs == 0) break; // 0 args |
| 8873 | if (node_datas[node].rhs != 0) break; // 2 args | ||
| 8874 | 8875 | ||
| 8875 | const builtin_token = main_tokens[node]; | 8876 | const builtin_token = main_tokens[node]; |
| 8876 | const builtin_name = tree.tokenSlice(builtin_token); | 8877 | const builtin_name = tree.tokenSlice(builtin_token); |
| 8877 | const info = BuiltinFn.list.get(builtin_name) orelse break; | 8878 | const info = BuiltinFn.list.get(builtin_name) orelse break; |
| 8878 | if (info.param_count != 1) break; | 8879 | if (node_datas[node].rhs == 0) { |
| 8880 | // 1 arg | ||
| 8881 | if (info.param_count != 1) break; | ||
| 8882 | |||
| 8883 | switch (info.tag) { | ||
| 8884 | else => break, | ||
| 8885 | inline .ptr_cast, | ||
| 8886 | .align_cast, | ||
| 8887 | .addrspace_cast, | ||
| 8888 | .const_cast, | ||
| 8889 | .volatile_cast, | ||
| 8890 | => |tag| { | ||
| 8891 | if (@field(flags, @tagName(tag))) { | ||
| 8892 | return astgen.failNode(node, "redundant {s}", .{builtin_name}); | ||
| 8893 | } | ||
| 8894 | @field(flags, @tagName(tag)) = true; | ||
| 8895 | }, | ||
| 8896 | } | ||
| 8879 | 8897 | ||
| 8880 | switch (info.tag) { | 8898 | node = node_datas[node].lhs; |
| 8881 | else => break, | 8899 | } else { |
| 8882 | inline .ptr_cast, | 8900 | // 2 args |
| 8883 | .align_cast, | 8901 | if (info.param_count != 2) break; |
| 8884 | .addrspace_cast, | 8902 | |
| 8885 | .const_cast, | 8903 | switch (info.tag) { |
| 8886 | .volatile_cast, | 8904 | else => break, |
| 8887 | => |tag| { | 8905 | .field_parent_ptr => { |
| 8888 | if (@field(flags, @tagName(tag))) { | 8906 | if (flags.ptr_cast) break; |
| 8889 | return astgen.failNode(node, "redundant {s}", .{builtin_name}); | 8907 | |
| 8890 | } | 8908 | const flags_int: FlagsInt = @bitCast(flags); |
| 8891 | @field(flags, @tagName(tag)) = true; | 8909 | const cursor = maybeAdvanceSourceCursorToMainToken(gz, root_node); |
| 8892 | }, | 8910 | const parent_ptr_type = try ri.rl.resultTypeForCast(gz, root_node, "@alignCast"); |
| 8911 | const field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }, node_datas[node].lhs); | ||
| 8912 | const field_ptr = try expr(gz, scope, .{ .rl = .none }, node_datas[node].rhs); | ||
| 8913 | try emitDbgStmt(gz, cursor); | ||
| 8914 | const result = try gz.addExtendedPayloadSmall(.field_parent_ptr, flags_int, Zir.Inst.FieldParentPtr{ | ||
| 8915 | .src_node = gz.nodeIndexToRelative(node), | ||
| 8916 | .parent_ptr_type = parent_ptr_type, | ||
| 8917 | .field_name = field_name, | ||
| 8918 | .field_ptr = field_ptr, | ||
| 8919 | }); | ||
| 8920 | return rvalue(gz, ri, result, root_node); | ||
| 8921 | }, | ||
| 8922 | } | ||
| 8893 | } | 8923 | } |
| 8894 | |||
| 8895 | node = node_datas[node].lhs; | ||
| 8896 | } | 8924 | } |
| 8897 | 8925 | ||
| 8898 | const flags_i: u5 = @bitCast(flags); | 8926 | const flags_int: FlagsInt = @bitCast(flags); |
| 8899 | assert(flags_i != 0); | 8927 | assert(flags_int != 0); |
| 8900 | 8928 | ||
| 8901 | const ptr_only: Zir.Inst.FullPtrCastFlags = .{ .ptr_cast = true }; | 8929 | const ptr_only: Zir.Inst.FullPtrCastFlags = .{ .ptr_cast = true }; |
| 8902 | if (flags_i == @as(u5, @bitCast(ptr_only))) { | 8930 | if (flags_int == @as(FlagsInt, @bitCast(ptr_only))) { |
| 8903 | // Special case: simpler representation | 8931 | // Special case: simpler representation |
| 8904 | return typeCast(gz, scope, ri, root_node, node, .ptr_cast, "@ptrCast"); | 8932 | return typeCast(gz, scope, ri, root_node, node, .ptr_cast, "@ptrCast"); |
| 8905 | } | 8933 | } |
| ... | @@ -8908,12 +8936,12 @@ fn ptrCast( | ... | @@ -8908,12 +8936,12 @@ fn ptrCast( |
| 8908 | .const_cast = true, | 8936 | .const_cast = true, |
| 8909 | .volatile_cast = true, | 8937 | .volatile_cast = true, |
| 8910 | }; | 8938 | }; |
| 8911 | if ((flags_i & ~@as(u5, @bitCast(no_result_ty_flags))) == 0) { | 8939 | if ((flags_int & ~@as(FlagsInt, @bitCast(no_result_ty_flags))) == 0) { |
| 8912 | // Result type not needed | 8940 | // Result type not needed |
| 8913 | const cursor = maybeAdvanceSourceCursorToMainToken(gz, root_node); | 8941 | const cursor = maybeAdvanceSourceCursorToMainToken(gz, root_node); |
| 8914 | const operand = try expr(gz, scope, .{ .rl = .none }, node); | 8942 | const operand = try expr(gz, scope, .{ .rl = .none }, node); |
| 8915 | try emitDbgStmt(gz, cursor); | 8943 | try emitDbgStmt(gz, cursor); |
| 8916 | const result = try gz.addExtendedPayloadSmall(.ptr_cast_no_dest, flags_i, Zir.Inst.UnNode{ | 8944 | const result = try gz.addExtendedPayloadSmall(.ptr_cast_no_dest, flags_int, Zir.Inst.UnNode{ |
| 8917 | .node = gz.nodeIndexToRelative(root_node), | 8945 | .node = gz.nodeIndexToRelative(root_node), |
| 8918 | .operand = operand, | 8946 | .operand = operand, |
| 8919 | }); | 8947 | }); |
| ... | @@ -8926,7 +8954,7 @@ fn ptrCast( | ... | @@ -8926,7 +8954,7 @@ fn ptrCast( |
| 8926 | const result_type = try ri.rl.resultTypeForCast(gz, root_node, flags.needResultTypeBuiltinName()); | 8954 | const result_type = try ri.rl.resultTypeForCast(gz, root_node, flags.needResultTypeBuiltinName()); |
| 8927 | const operand = try expr(gz, scope, .{ .rl = .none }, node); | 8955 | const operand = try expr(gz, scope, .{ .rl = .none }, node); |
| 8928 | try emitDbgStmt(gz, cursor); | 8956 | try emitDbgStmt(gz, cursor); |
| 8929 | const result = try gz.addExtendedPayloadSmall(.ptr_cast_full, flags_i, Zir.Inst.BinNode{ | 8957 | const result = try gz.addExtendedPayloadSmall(.ptr_cast_full, flags_int, Zir.Inst.BinNode{ |
| 8930 | .node = gz.nodeIndexToRelative(root_node), | 8958 | .node = gz.nodeIndexToRelative(root_node), |
| 8931 | .lhs = result_type, | 8959 | .lhs = result_type, |
| 8932 | .rhs = operand, | 8960 | .rhs = operand, |
| ... | @@ -9379,7 +9407,7 @@ fn builtinCall( | ... | @@ -9379,7 +9407,7 @@ fn builtinCall( |
| 9379 | try emitDbgNode(gz, node); | 9407 | try emitDbgNode(gz, node); |
| 9380 | 9408 | ||
| 9381 | const result = try gz.addExtendedPayload(.error_cast, Zir.Inst.BinNode{ | 9409 | const result = try gz.addExtendedPayload(.error_cast, Zir.Inst.BinNode{ |
| 9382 | .lhs = try ri.rl.resultTypeForCast(gz, node, "@errorCast"), | 9410 | .lhs = try ri.rl.resultTypeForCast(gz, node, builtin_name), |
| 9383 | .rhs = try expr(gz, scope, .{ .rl = .none }, params[0]), | 9411 | .rhs = try expr(gz, scope, .{ .rl = .none }, params[0]), |
| 9384 | .node = gz.nodeIndexToRelative(node), | 9412 | .node = gz.nodeIndexToRelative(node), |
| 9385 | }); | 9413 | }); |
| ... | @@ -9452,7 +9480,7 @@ fn builtinCall( | ... | @@ -9452,7 +9480,7 @@ fn builtinCall( |
| 9452 | }, | 9480 | }, |
| 9453 | 9481 | ||
| 9454 | .splat => { | 9482 | .splat => { |
| 9455 | const result_type = try ri.rl.resultTypeForCast(gz, node, "@splat"); | 9483 | const result_type = try ri.rl.resultTypeForCast(gz, node, builtin_name); |
| 9456 | const elem_type = try gz.addUnNode(.vector_elem_type, result_type, node); | 9484 | const elem_type = try gz.addUnNode(.vector_elem_type, result_type, node); |
| 9457 | const scalar = try expr(gz, scope, .{ .rl = .{ .ty = elem_type } }, params[0]); | 9485 | const scalar = try expr(gz, scope, .{ .rl = .{ .ty = elem_type } }, params[0]); |
| 9458 | const result = try gz.addPlNode(.splat, node, Zir.Inst.Bin{ | 9486 | const result = try gz.addPlNode(.splat, node, Zir.Inst.Bin{ |
| ... | @@ -9537,12 +9565,13 @@ fn builtinCall( | ... | @@ -9537,12 +9565,13 @@ fn builtinCall( |
| 9537 | return rvalue(gz, ri, result, node); | 9565 | return rvalue(gz, ri, result, node); |
| 9538 | }, | 9566 | }, |
| 9539 | .field_parent_ptr => { | 9567 | .field_parent_ptr => { |
| 9540 | const parent_type = try typeExpr(gz, scope, params[0]); | 9568 | const parent_ptr_type = try ri.rl.resultTypeForCast(gz, node, builtin_name); |
| 9541 | const field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }, params[1]); | 9569 | const field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }, params[0]); |
| 9542 | const result = try gz.addPlNode(.field_parent_ptr, node, Zir.Inst.FieldParentPtr{ | 9570 | const result = try gz.addExtendedPayloadSmall(.field_parent_ptr, 0, Zir.Inst.FieldParentPtr{ |
| 9543 | .parent_type = parent_type, | 9571 | .src_node = gz.nodeIndexToRelative(node), |
| 9572 | .parent_ptr_type = parent_ptr_type, | ||
| 9544 | .field_name = field_name, | 9573 | .field_name = field_name, |
| 9545 | .field_ptr = try expr(gz, scope, .{ .rl = .none }, params[2]), | 9574 | .field_ptr = try expr(gz, scope, .{ .rl = .none }, params[1]), |
| 9546 | }); | 9575 | }); |
| 9547 | return rvalue(gz, ri, result, node); | 9576 | return rvalue(gz, ri, result, node); |
| 9548 | }, | 9577 | }, |
| ... | @@ -11686,20 +11715,20 @@ const Scope = struct { | ... | @@ -11686,20 +11715,20 @@ const Scope = struct { |
| 11686 | fn cast(base: *Scope, comptime T: type) ?*T { | 11715 | fn cast(base: *Scope, comptime T: type) ?*T { |
| 11687 | if (T == Defer) { | 11716 | if (T == Defer) { |
| 11688 | switch (base.tag) { | 11717 | switch (base.tag) { |
| 11689 | .defer_normal, .defer_error => return @fieldParentPtr(T, "base", base), | 11718 | .defer_normal, .defer_error => return @alignCast(@fieldParentPtr("base", base)), |
| 11690 | else => return null, | 11719 | else => return null, |
| 11691 | } | 11720 | } |
| 11692 | } | 11721 | } |
| 11693 | if (T == Namespace) { | 11722 | if (T == Namespace) { |
| 11694 | switch (base.tag) { | 11723 | switch (base.tag) { |
| 11695 | .namespace => return @fieldParentPtr(T, "base", base), | 11724 | .namespace => return @alignCast(@fieldParentPtr("base", base)), |
| 11696 | else => return null, | 11725 | else => return null, |
| 11697 | } | 11726 | } |
| 11698 | } | 11727 | } |
| 11699 | if (base.tag != T.base_tag) | 11728 | if (base.tag != T.base_tag) |
| 11700 | return null; | 11729 | return null; |
| 11701 | 11730 | ||
| 11702 | return @fieldParentPtr(T, "base", base); | 11731 | return @alignCast(@fieldParentPtr("base", base)); |
| 11703 | } | 11732 | } |
| 11704 | 11733 | ||
| 11705 | fn parent(base: *Scope) ?*Scope { | 11734 | fn parent(base: *Scope) ?*Scope { |
lib/std/zig/AstRlAnnotate.zig+1-1| ... | @@ -911,6 +911,7 @@ fn builtinCall(astrl: *AstRlAnnotate, block: ?*Block, ri: ResultInfo, node: Ast. | ... | @@ -911,6 +911,7 @@ fn builtinCall(astrl: *AstRlAnnotate, block: ?*Block, ri: ResultInfo, node: Ast. |
| 911 | .work_item_id, | 911 | .work_item_id, |
| 912 | .work_group_size, | 912 | .work_group_size, |
| 913 | .work_group_id, | 913 | .work_group_id, |
| 914 | .field_parent_ptr, | ||
| 914 | => { | 915 | => { |
| 915 | _ = try astrl.expr(args[0], block, ResultInfo.type_only); | 916 | _ = try astrl.expr(args[0], block, ResultInfo.type_only); |
| 916 | return false; | 917 | return false; |
| ... | @@ -976,7 +977,6 @@ fn builtinCall(astrl: *AstRlAnnotate, block: ?*Block, ri: ResultInfo, node: Ast. | ... | @@ -976,7 +977,6 @@ fn builtinCall(astrl: *AstRlAnnotate, block: ?*Block, ri: ResultInfo, node: Ast. |
| 976 | }, | 977 | }, |
| 977 | .bit_offset_of, | 978 | .bit_offset_of, |
| 978 | .offset_of, | 979 | .offset_of, |
| 979 | .field_parent_ptr, | ||
| 980 | .has_decl, | 980 | .has_decl, |
| 981 | .has_field, | 981 | .has_field, |
| 982 | .field, | 982 | .field, |
lib/std/zig/BuiltinFn.zig+1-1| ... | @@ -504,7 +504,7 @@ pub const list = list: { | ... | @@ -504,7 +504,7 @@ pub const list = list: { |
| 504 | "@fieldParentPtr", | 504 | "@fieldParentPtr", |
| 505 | .{ | 505 | .{ |
| 506 | .tag = .field_parent_ptr, | 506 | .tag = .field_parent_ptr, |
| 507 | .param_count = 3, | 507 | .param_count = 2, |
| 508 | }, | 508 | }, |
| 509 | }, | 509 | }, |
| 510 | .{ | 510 | .{ |
lib/std/zig/Zir.zig+12-7| ... | @@ -940,9 +940,6 @@ pub const Inst = struct { | ... | @@ -940,9 +940,6 @@ pub const Inst = struct { |
| 940 | /// The addend communicates the type of the builtin. | 940 | /// The addend communicates the type of the builtin. |
| 941 | /// The mulends need to be coerced to the same type. | 941 | /// The mulends need to be coerced to the same type. |
| 942 | mul_add, | 942 | mul_add, |
| 943 | /// Implements the `@fieldParentPtr` builtin. | ||
| 944 | /// Uses the `pl_node` union field with payload `FieldParentPtr`. | ||
| 945 | field_parent_ptr, | ||
| 946 | /// Implements the `@memcpy` builtin. | 943 | /// Implements the `@memcpy` builtin. |
| 947 | /// Uses the `pl_node` union field with payload `Bin`. | 944 | /// Uses the `pl_node` union field with payload `Bin`. |
| 948 | memcpy, | 945 | memcpy, |
| ... | @@ -1230,7 +1227,6 @@ pub const Inst = struct { | ... | @@ -1230,7 +1227,6 @@ pub const Inst = struct { |
| 1230 | .atomic_store, | 1227 | .atomic_store, |
| 1231 | .mul_add, | 1228 | .mul_add, |
| 1232 | .builtin_call, | 1229 | .builtin_call, |
| 1233 | .field_parent_ptr, | ||
| 1234 | .max, | 1230 | .max, |
| 1235 | .memcpy, | 1231 | .memcpy, |
| 1236 | .memset, | 1232 | .memset, |
| ... | @@ -1522,7 +1518,6 @@ pub const Inst = struct { | ... | @@ -1522,7 +1518,6 @@ pub const Inst = struct { |
| 1522 | .atomic_rmw, | 1518 | .atomic_rmw, |
| 1523 | .mul_add, | 1519 | .mul_add, |
| 1524 | .builtin_call, | 1520 | .builtin_call, |
| 1525 | .field_parent_ptr, | ||
| 1526 | .max, | 1521 | .max, |
| 1527 | .min, | 1522 | .min, |
| 1528 | .c_import, | 1523 | .c_import, |
| ... | @@ -1794,7 +1789,6 @@ pub const Inst = struct { | ... | @@ -1794,7 +1789,6 @@ pub const Inst = struct { |
| 1794 | .atomic_store = .pl_node, | 1789 | .atomic_store = .pl_node, |
| 1795 | .mul_add = .pl_node, | 1790 | .mul_add = .pl_node, |
| 1796 | .builtin_call = .pl_node, | 1791 | .builtin_call = .pl_node, |
| 1797 | .field_parent_ptr = .pl_node, | ||
| 1798 | .max = .pl_node, | 1792 | .max = .pl_node, |
| 1799 | .memcpy = .pl_node, | 1793 | .memcpy = .pl_node, |
| 1800 | .memset = .pl_node, | 1794 | .memset = .pl_node, |
| ... | @@ -2064,6 +2058,12 @@ pub const Inst = struct { | ... | @@ -2064,6 +2058,12 @@ pub const Inst = struct { |
| 2064 | /// with a specific value. For instance, this is used for the capture of an `errdefer`. | 2058 | /// with a specific value. For instance, this is used for the capture of an `errdefer`. |
| 2065 | /// This should never appear in a body. | 2059 | /// This should never appear in a body. |
| 2066 | value_placeholder, | 2060 | value_placeholder, |
| 2061 | /// Implements the `@fieldParentPtr` builtin. | ||
| 2062 | /// `operand` is payload index to `FieldParentPtr`. | ||
| 2063 | /// `small` contains `FullPtrCastFlags`. | ||
| 2064 | /// Guaranteed to not have the `ptr_cast` flag. | ||
| 2065 | /// Uses the `pl_node` union field with payload `FieldParentPtr`. | ||
| 2066 | field_parent_ptr, | ||
| 2067 | 2067 | ||
| 2068 | pub const InstData = struct { | 2068 | pub const InstData = struct { |
| 2069 | opcode: Extended, | 2069 | opcode: Extended, |
| ... | @@ -3363,9 +3363,14 @@ pub const Inst = struct { | ... | @@ -3363,9 +3363,14 @@ pub const Inst = struct { |
| 3363 | }; | 3363 | }; |
| 3364 | 3364 | ||
| 3365 | pub const FieldParentPtr = struct { | 3365 | pub const FieldParentPtr = struct { |
| 3366 | parent_type: Ref, | 3366 | src_node: i32, |
| 3367 | parent_ptr_type: Ref, | ||
| 3367 | field_name: Ref, | 3368 | field_name: Ref, |
| 3368 | field_ptr: Ref, | 3369 | field_ptr: Ref, |
| 3370 | |||
| 3371 | pub fn src(self: FieldParentPtr) LazySrcLoc { | ||
| 3372 | return LazySrcLoc.nodeOffset(self.src_node); | ||
| 3373 | } | ||
| 3369 | }; | 3374 | }; |
| 3370 | 3375 | ||
| 3371 | pub const Shuffle = struct { | 3376 | pub const Shuffle = struct { |
lib/std/zig/c_translation.zig+1-1| ... | @@ -414,7 +414,7 @@ pub const Macros = struct { | ... | @@ -414,7 +414,7 @@ pub const Macros = struct { |
| 414 | } | 414 | } |
| 415 | 415 | ||
| 416 | pub fn WL_CONTAINER_OF(ptr: anytype, sample: anytype, comptime member: []const u8) @TypeOf(sample) { | 416 | pub fn WL_CONTAINER_OF(ptr: anytype, sample: anytype, comptime member: []const u8) @TypeOf(sample) { |
| 417 | return @fieldParentPtr(@TypeOf(sample.*), member, ptr); | 417 | return @fieldParentPtr(member, ptr); |
| 418 | } | 418 | } |
| 419 | 419 | ||
| 420 | /// A 2-argument function-like macro defined as #define FOO(A, B) (A)(B) | 420 | /// A 2-argument function-like macro defined as #define FOO(A, B) (A)(B) |
lib/zig.h+13-14| ... | @@ -130,22 +130,18 @@ typedef char bool; | ... | @@ -130,22 +130,18 @@ typedef char bool; |
| 130 | #define zig_restrict | 130 | #define zig_restrict |
| 131 | #endif | 131 | #endif |
| 132 | 132 | ||
| 133 | #if __STDC_VERSION__ >= 201112L | 133 | #if zig_has_attribute(aligned) |
| 134 | #define zig_align(alignment) _Alignas(alignment) | 134 | #define zig_under_align(alignment) __attribute__((aligned(alignment))) |
| 135 | #elif zig_has_attribute(aligned) | ||
| 136 | #define zig_align(alignment) __attribute__((aligned(alignment))) | ||
| 137 | #elif _MSC_VER | 135 | #elif _MSC_VER |
| 138 | #define zig_align(alignment) __declspec(align(alignment)) | 136 | #define zig_under_align(alignment) __declspec(align(alignment)) |
| 139 | #else | 137 | #else |
| 140 | #define zig_align zig_align_unavailable | 138 | #define zig_under_align zig_align_unavailable |
| 141 | #endif | 139 | #endif |
| 142 | 140 | ||
| 143 | #if zig_has_attribute(aligned) | 141 | #if __STDC_VERSION__ >= 201112L |
| 144 | #define zig_under_align(alignment) __attribute__((aligned(alignment))) | 142 | #define zig_align(alignment) _Alignas(alignment) |
| 145 | #elif _MSC_VER | ||
| 146 | #define zig_under_align(alignment) zig_align(alignment) | ||
| 147 | #else | 143 | #else |
| 148 | #define zig_align zig_align_unavailable | 144 | #define zig_align(alignment) zig_under_align(alignment) |
| 149 | #endif | 145 | #endif |
| 150 | 146 | ||
| 151 | #if zig_has_attribute(aligned) | 147 | #if zig_has_attribute(aligned) |
| ... | @@ -165,11 +161,14 @@ typedef char bool; | ... | @@ -165,11 +161,14 @@ typedef char bool; |
| 165 | #endif | 161 | #endif |
| 166 | 162 | ||
| 167 | #if zig_has_attribute(section) | 163 | #if zig_has_attribute(section) |
| 168 | #define zig_linksection(name, def, ...) def __attribute__((section(name))) | 164 | #define zig_linksection(name) __attribute__((section(name))) |
| 165 | #define zig_linksection_fn zig_linksection | ||
| 169 | #elif _MSC_VER | 166 | #elif _MSC_VER |
| 170 | #define zig_linksection(name, def, ...) __pragma(section(name, __VA_ARGS__)) __declspec(allocate(name)) def | 167 | #define zig_linksection(name) __pragma(section(name, read, write)) __declspec(allocate(name)) |
| 168 | #define zig_linksection_fn(name) __pragma(section(name, read, execute)) __declspec(code_seg(name)) | ||
| 171 | #else | 169 | #else |
| 172 | #define zig_linksection(name, def, ...) zig_linksection_unavailable | 170 | #define zig_linksection(name) zig_linksection_unavailable |
| 171 | #define zig_linksection_fn zig_linksection | ||
| 173 | #endif | 172 | #endif |
| 174 | 173 | ||
| 175 | #if zig_has_builtin(unreachable) || defined(zig_gnuc) | 174 | #if zig_has_builtin(unreachable) || defined(zig_gnuc) |
src/Compilation.zig+9-7| ... | @@ -3451,19 +3451,24 @@ fn processOneJob(comp: *Compilation, job: Job, prog_node: *std.Progress.Node) !v | ... | @@ -3451,19 +3451,24 @@ fn processOneJob(comp: *Compilation, job: Job, prog_node: *std.Progress.Node) !v |
| 3451 | 3451 | ||
| 3452 | var dg: c_codegen.DeclGen = .{ | 3452 | var dg: c_codegen.DeclGen = .{ |
| 3453 | .gpa = gpa, | 3453 | .gpa = gpa, |
| 3454 | .module = module, | 3454 | .zcu = module, |
| 3455 | .mod = module.namespacePtr(decl.src_namespace).file_scope.mod, | ||
| 3455 | .error_msg = null, | 3456 | .error_msg = null, |
| 3456 | .pass = .{ .decl = decl_index }, | 3457 | .pass = .{ .decl = decl_index }, |
| 3457 | .is_naked_fn = false, | 3458 | .is_naked_fn = false, |
| 3458 | .fwd_decl = fwd_decl.toManaged(gpa), | 3459 | .fwd_decl = fwd_decl.toManaged(gpa), |
| 3459 | .ctypes = .{}, | 3460 | .ctype_pool = c_codegen.CType.Pool.empty, |
| 3461 | .scratch = .{}, | ||
| 3460 | .anon_decl_deps = .{}, | 3462 | .anon_decl_deps = .{}, |
| 3461 | .aligned_anon_decls = .{}, | 3463 | .aligned_anon_decls = .{}, |
| 3462 | }; | 3464 | }; |
| 3463 | defer { | 3465 | defer { |
| 3464 | dg.ctypes.deinit(gpa); | 3466 | fwd_decl.* = dg.fwd_decl.moveToUnmanaged(); |
| 3465 | dg.fwd_decl.deinit(); | 3467 | fwd_decl.shrinkAndFree(gpa, fwd_decl.items.len); |
| 3468 | dg.ctype_pool.deinit(gpa); | ||
| 3469 | dg.scratch.deinit(gpa); | ||
| 3466 | } | 3470 | } |
| 3471 | try dg.ctype_pool.init(gpa); | ||
| 3467 | 3472 | ||
| 3468 | c_codegen.genHeader(&dg) catch |err| switch (err) { | 3473 | c_codegen.genHeader(&dg) catch |err| switch (err) { |
| 3469 | error.AnalysisFail => { | 3474 | error.AnalysisFail => { |
| ... | @@ -3472,9 +3477,6 @@ fn processOneJob(comp: *Compilation, job: Job, prog_node: *std.Progress.Node) !v | ... | @@ -3472,9 +3477,6 @@ fn processOneJob(comp: *Compilation, job: Job, prog_node: *std.Progress.Node) !v |
| 3472 | }, | 3477 | }, |
| 3473 | else => |e| return e, | 3478 | else => |e| return e, |
| 3474 | }; | 3479 | }; |
| 3475 | |||
| 3476 | fwd_decl.* = dg.fwd_decl.moveToUnmanaged(); | ||
| 3477 | fwd_decl.shrinkAndFree(gpa, fwd_decl.items.len); | ||
| 3478 | }, | 3480 | }, |
| 3479 | } | 3481 | } |
| 3480 | }, | 3482 | }, |
src/InternPool.zig+35-35| ... | @@ -712,7 +712,7 @@ pub const Key = union(enum) { | ... | @@ -712,7 +712,7 @@ pub const Key = union(enum) { |
| 712 | pub fn fieldName( | 712 | pub fn fieldName( |
| 713 | self: AnonStructType, | 713 | self: AnonStructType, |
| 714 | ip: *const InternPool, | 714 | ip: *const InternPool, |
| 715 | index: u32, | 715 | index: usize, |
| 716 | ) OptionalNullTerminatedString { | 716 | ) OptionalNullTerminatedString { |
| 717 | if (self.names.len == 0) | 717 | if (self.names.len == 0) |
| 718 | return .none; | 718 | return .none; |
| ... | @@ -3879,20 +3879,13 @@ pub const Alignment = enum(u6) { | ... | @@ -3879,20 +3879,13 @@ pub const Alignment = enum(u6) { |
| 3879 | none = std.math.maxInt(u6), | 3879 | none = std.math.maxInt(u6), |
| 3880 | _, | 3880 | _, |
| 3881 | 3881 | ||
| 3882 | pub fn toByteUnitsOptional(a: Alignment) ?u64 { | 3882 | pub fn toByteUnits(a: Alignment) ?u64 { |
| 3883 | return switch (a) { | 3883 | return switch (a) { |
| 3884 | .none => null, | 3884 | .none => null, |
| 3885 | else => @as(u64, 1) << @intFromEnum(a), | 3885 | else => @as(u64, 1) << @intFromEnum(a), |
| 3886 | }; | 3886 | }; |
| 3887 | } | 3887 | } |
| 3888 | 3888 | ||
| 3889 | pub fn toByteUnits(a: Alignment, default: u64) u64 { | ||
| 3890 | return switch (a) { | ||
| 3891 | .none => default, | ||
| 3892 | else => @as(u64, 1) << @intFromEnum(a), | ||
| 3893 | }; | ||
| 3894 | } | ||
| 3895 | |||
| 3896 | pub fn fromByteUnits(n: u64) Alignment { | 3889 | pub fn fromByteUnits(n: u64) Alignment { |
| 3897 | if (n == 0) return .none; | 3890 | if (n == 0) return .none; |
| 3898 | assert(std.math.isPowerOfTwo(n)); | 3891 | assert(std.math.isPowerOfTwo(n)); |
| ... | @@ -5170,48 +5163,55 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index { | ... | @@ -5170,48 +5163,55 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index { |
| 5170 | .ptr => |ptr| { | 5163 | .ptr => |ptr| { |
| 5171 | const ptr_type = ip.indexToKey(ptr.ty).ptr_type; | 5164 | const ptr_type = ip.indexToKey(ptr.ty).ptr_type; |
| 5172 | assert(ptr_type.flags.size != .Slice); | 5165 | assert(ptr_type.flags.size != .Slice); |
| 5173 | switch (ptr.addr) { | 5166 | ip.items.appendAssumeCapacity(switch (ptr.addr) { |
| 5174 | .decl => |decl| ip.items.appendAssumeCapacity(.{ | 5167 | .decl => |decl| .{ |
| 5175 | .tag = .ptr_decl, | 5168 | .tag = .ptr_decl, |
| 5176 | .data = try ip.addExtra(gpa, PtrDecl{ | 5169 | .data = try ip.addExtra(gpa, PtrDecl{ |
| 5177 | .ty = ptr.ty, | 5170 | .ty = ptr.ty, |
| 5178 | .decl = decl, | 5171 | .decl = decl, |
| 5179 | }), | 5172 | }), |
| 5180 | }), | 5173 | }, |
| 5181 | .comptime_alloc => |alloc_index| ip.items.appendAssumeCapacity(.{ | 5174 | .comptime_alloc => |alloc_index| .{ |
| 5182 | .tag = .ptr_comptime_alloc, | 5175 | .tag = .ptr_comptime_alloc, |
| 5183 | .data = try ip.addExtra(gpa, PtrComptimeAlloc{ | 5176 | .data = try ip.addExtra(gpa, PtrComptimeAlloc{ |
| 5184 | .ty = ptr.ty, | 5177 | .ty = ptr.ty, |
| 5185 | .index = alloc_index, | 5178 | .index = alloc_index, |
| 5186 | }), | 5179 | }), |
| 5187 | }), | 5180 | }, |
| 5188 | .anon_decl => |anon_decl| ip.items.appendAssumeCapacity( | 5181 | .anon_decl => |anon_decl| if (ptrsHaveSameAlignment(ip, ptr.ty, ptr_type, anon_decl.orig_ty)) item: { |
| 5189 | if (ptrsHaveSameAlignment(ip, ptr.ty, ptr_type, anon_decl.orig_ty)) .{ | 5182 | if (ptr.ty != anon_decl.orig_ty) { |
| 5183 | _ = ip.map.pop(); | ||
| 5184 | var new_key = key; | ||
| 5185 | new_key.ptr.addr.anon_decl.orig_ty = ptr.ty; | ||
| 5186 | const new_gop = try ip.map.getOrPutAdapted(gpa, new_key, adapter); | ||
| 5187 | if (new_gop.found_existing) return @enumFromInt(new_gop.index); | ||
| 5188 | } | ||
| 5189 | break :item .{ | ||
| 5190 | .tag = .ptr_anon_decl, | 5190 | .tag = .ptr_anon_decl, |
| 5191 | .data = try ip.addExtra(gpa, PtrAnonDecl{ | 5191 | .data = try ip.addExtra(gpa, PtrAnonDecl{ |
| 5192 | .ty = ptr.ty, | 5192 | .ty = ptr.ty, |
| 5193 | .val = anon_decl.val, | 5193 | .val = anon_decl.val, |
| 5194 | }), | 5194 | }), |
| 5195 | } else .{ | 5195 | }; |
| 5196 | .tag = .ptr_anon_decl_aligned, | 5196 | } else .{ |
| 5197 | .data = try ip.addExtra(gpa, PtrAnonDeclAligned{ | 5197 | .tag = .ptr_anon_decl_aligned, |
| 5198 | .ty = ptr.ty, | 5198 | .data = try ip.addExtra(gpa, PtrAnonDeclAligned{ |
| 5199 | .val = anon_decl.val, | 5199 | .ty = ptr.ty, |
| 5200 | .orig_ty = anon_decl.orig_ty, | 5200 | .val = anon_decl.val, |
| 5201 | }), | 5201 | .orig_ty = anon_decl.orig_ty, |
| 5202 | }, | 5202 | }), |
| 5203 | ), | 5203 | }, |
| 5204 | .comptime_field => |field_val| { | 5204 | .comptime_field => |field_val| item: { |
| 5205 | assert(field_val != .none); | 5205 | assert(field_val != .none); |
| 5206 | ip.items.appendAssumeCapacity(.{ | 5206 | break :item .{ |
| 5207 | .tag = .ptr_comptime_field, | 5207 | .tag = .ptr_comptime_field, |
| 5208 | .data = try ip.addExtra(gpa, PtrComptimeField{ | 5208 | .data = try ip.addExtra(gpa, PtrComptimeField{ |
| 5209 | .ty = ptr.ty, | 5209 | .ty = ptr.ty, |
| 5210 | .field_val = field_val, | 5210 | .field_val = field_val, |
| 5211 | }), | 5211 | }), |
| 5212 | }); | 5212 | }; |
| 5213 | }, | 5213 | }, |
| 5214 | .int, .eu_payload, .opt_payload => |base| { | 5214 | .int, .eu_payload, .opt_payload => |base| item: { |
| 5215 | switch (ptr.addr) { | 5215 | switch (ptr.addr) { |
| 5216 | .int => assert(ip.typeOf(base) == .usize_type), | 5216 | .int => assert(ip.typeOf(base) == .usize_type), |
| 5217 | .eu_payload => assert(ip.indexToKey( | 5217 | .eu_payload => assert(ip.indexToKey( |
| ... | @@ -5222,7 +5222,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index { | ... | @@ -5222,7 +5222,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index { |
| 5222 | ) == .opt_type), | 5222 | ) == .opt_type), |
| 5223 | else => unreachable, | 5223 | else => unreachable, |
| 5224 | } | 5224 | } |
| 5225 | ip.items.appendAssumeCapacity(.{ | 5225 | break :item .{ |
| 5226 | .tag = switch (ptr.addr) { | 5226 | .tag = switch (ptr.addr) { |
| 5227 | .int => .ptr_int, | 5227 | .int => .ptr_int, |
| 5228 | .eu_payload => .ptr_eu_payload, | 5228 | .eu_payload => .ptr_eu_payload, |
| ... | @@ -5233,9 +5233,9 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index { | ... | @@ -5233,9 +5233,9 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index { |
| 5233 | .ty = ptr.ty, | 5233 | .ty = ptr.ty, |
| 5234 | .base = base, | 5234 | .base = base, |
| 5235 | }), | 5235 | }), |
| 5236 | }); | 5236 | }; |
| 5237 | }, | 5237 | }, |
| 5238 | .elem, .field => |base_index| { | 5238 | .elem, .field => |base_index| item: { |
| 5239 | const base_ptr_type = ip.indexToKey(ip.typeOf(base_index.base)).ptr_type; | 5239 | const base_ptr_type = ip.indexToKey(ip.typeOf(base_index.base)).ptr_type; |
| 5240 | switch (ptr.addr) { | 5240 | switch (ptr.addr) { |
| 5241 | .elem => assert(base_ptr_type.flags.size == .Many), | 5241 | .elem => assert(base_ptr_type.flags.size == .Many), |
| ... | @@ -5272,7 +5272,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index { | ... | @@ -5272,7 +5272,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index { |
| 5272 | } }); | 5272 | } }); |
| 5273 | assert(!(try ip.map.getOrPutAdapted(gpa, key, adapter)).found_existing); | 5273 | assert(!(try ip.map.getOrPutAdapted(gpa, key, adapter)).found_existing); |
| 5274 | try ip.items.ensureUnusedCapacity(gpa, 1); | 5274 | try ip.items.ensureUnusedCapacity(gpa, 1); |
| 5275 | ip.items.appendAssumeCapacity(.{ | 5275 | break :item .{ |
| 5276 | .tag = switch (ptr.addr) { | 5276 | .tag = switch (ptr.addr) { |
| 5277 | .elem => .ptr_elem, | 5277 | .elem => .ptr_elem, |
| 5278 | .field => .ptr_field, | 5278 | .field => .ptr_field, |
| ... | @@ -5283,9 +5283,9 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index { | ... | @@ -5283,9 +5283,9 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index { |
| 5283 | .base = base_index.base, | 5283 | .base = base_index.base, |
| 5284 | .index = index_index, | 5284 | .index = index_index, |
| 5285 | }), | 5285 | }), |
| 5286 | }); | 5286 | }; |
| 5287 | }, | 5287 | }, |
| 5288 | } | 5288 | }); |
| 5289 | }, | 5289 | }, |
| 5290 | 5290 | ||
| 5291 | .opt => |opt| { | 5291 | .opt => |opt| { |
src/Module.zig+3-3| ... | @@ -299,7 +299,7 @@ const ValueArena = struct { | ... | @@ -299,7 +299,7 @@ const ValueArena = struct { |
| 299 | /// and must live until the matching call to release(). | 299 | /// and must live until the matching call to release(). |
| 300 | pub fn acquire(self: *ValueArena, child_allocator: Allocator, out_arena_allocator: *std.heap.ArenaAllocator) Allocator { | 300 | pub fn acquire(self: *ValueArena, child_allocator: Allocator, out_arena_allocator: *std.heap.ArenaAllocator) Allocator { |
| 301 | if (self.state_acquired) |state_acquired| { | 301 | if (self.state_acquired) |state_acquired| { |
| 302 | return @fieldParentPtr(std.heap.ArenaAllocator, "state", state_acquired).allocator(); | 302 | return @as(*std.heap.ArenaAllocator, @fieldParentPtr("state", state_acquired)).allocator(); |
| 303 | } | 303 | } |
| 304 | 304 | ||
| 305 | out_arena_allocator.* = self.state.promote(child_allocator); | 305 | out_arena_allocator.* = self.state.promote(child_allocator); |
| ... | @@ -309,7 +309,7 @@ const ValueArena = struct { | ... | @@ -309,7 +309,7 @@ const ValueArena = struct { |
| 309 | 309 | ||
| 310 | /// Releases the allocator acquired by `acquire. `arena_allocator` must match the one passed to `acquire`. | 310 | /// Releases the allocator acquired by `acquire. `arena_allocator` must match the one passed to `acquire`. |
| 311 | pub fn release(self: *ValueArena, arena_allocator: *std.heap.ArenaAllocator) void { | 311 | pub fn release(self: *ValueArena, arena_allocator: *std.heap.ArenaAllocator) void { |
| 312 | if (@fieldParentPtr(std.heap.ArenaAllocator, "state", self.state_acquired.?) == arena_allocator) { | 312 | if (@as(*std.heap.ArenaAllocator, @fieldParentPtr("state", self.state_acquired.?)) == arena_allocator) { |
| 313 | self.state = self.state_acquired.?.*; | 313 | self.state = self.state_acquired.?.*; |
| 314 | self.state_acquired = null; | 314 | self.state_acquired = null; |
| 315 | } | 315 | } |
| ... | @@ -5846,7 +5846,7 @@ pub fn intBitsForValue(mod: *Module, val: Value, sign: bool) u16 { | ... | @@ -5846,7 +5846,7 @@ pub fn intBitsForValue(mod: *Module, val: Value, sign: bool) u16 { |
| 5846 | return @as(u16, @intCast(big.bitCountTwosComp())); | 5846 | return @as(u16, @intCast(big.bitCountTwosComp())); |
| 5847 | }, | 5847 | }, |
| 5848 | .lazy_align => |lazy_ty| { | 5848 | .lazy_align => |lazy_ty| { |
| 5849 | return Type.smallestUnsignedBits(Type.fromInterned(lazy_ty).abiAlignment(mod).toByteUnits(0)) + @intFromBool(sign); | 5849 | return Type.smallestUnsignedBits(Type.fromInterned(lazy_ty).abiAlignment(mod).toByteUnits() orelse 0) + @intFromBool(sign); |
| 5850 | }, | 5850 | }, |
| 5851 | .lazy_size => |lazy_ty| { | 5851 | .lazy_size => |lazy_ty| { |
| 5852 | return Type.smallestUnsignedBits(Type.fromInterned(lazy_ty).abiSize(mod)) + @intFromBool(sign); | 5852 | return Type.smallestUnsignedBits(Type.fromInterned(lazy_ty).abiSize(mod)) + @intFromBool(sign); |
src/Sema.zig+180-118| ... | @@ -1131,7 +1131,6 @@ fn analyzeBodyInner( | ... | @@ -1131,7 +1131,6 @@ fn analyzeBodyInner( |
| 1131 | .atomic_rmw => try sema.zirAtomicRmw(block, inst), | 1131 | .atomic_rmw => try sema.zirAtomicRmw(block, inst), |
| 1132 | .mul_add => try sema.zirMulAdd(block, inst), | 1132 | .mul_add => try sema.zirMulAdd(block, inst), |
| 1133 | .builtin_call => try sema.zirBuiltinCall(block, inst), | 1133 | .builtin_call => try sema.zirBuiltinCall(block, inst), |
| 1134 | .field_parent_ptr => try sema.zirFieldParentPtr(block, inst), | ||
| 1135 | .@"resume" => try sema.zirResume(block, inst), | 1134 | .@"resume" => try sema.zirResume(block, inst), |
| 1136 | .@"await" => try sema.zirAwait(block, inst), | 1135 | .@"await" => try sema.zirAwait(block, inst), |
| 1137 | .for_len => try sema.zirForLen(block, inst), | 1136 | .for_len => try sema.zirForLen(block, inst), |
| ... | @@ -1296,6 +1295,7 @@ fn analyzeBodyInner( | ... | @@ -1296,6 +1295,7 @@ fn analyzeBodyInner( |
| 1296 | continue; | 1295 | continue; |
| 1297 | }, | 1296 | }, |
| 1298 | .value_placeholder => unreachable, // never appears in a body | 1297 | .value_placeholder => unreachable, // never appears in a body |
| 1298 | .field_parent_ptr => try sema.zirFieldParentPtr(block, extended), | ||
| 1299 | }; | 1299 | }; |
| 1300 | }, | 1300 | }, |
| 1301 | 1301 | ||
| ... | @@ -6508,7 +6508,7 @@ fn zirSetAlignStack(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Inst | ... | @@ -6508,7 +6508,7 @@ fn zirSetAlignStack(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Inst |
| 6508 | const alignment = try sema.resolveAlign(block, operand_src, extra.operand); | 6508 | const alignment = try sema.resolveAlign(block, operand_src, extra.operand); |
| 6509 | if (alignment.order(Alignment.fromNonzeroByteUnits(256)).compare(.gt)) { | 6509 | if (alignment.order(Alignment.fromNonzeroByteUnits(256)).compare(.gt)) { |
| 6510 | return sema.fail(block, src, "attempt to @setAlignStack({d}); maximum is 256", .{ | 6510 | return sema.fail(block, src, "attempt to @setAlignStack({d}); maximum is 256", .{ |
| 6511 | alignment.toByteUnitsOptional().?, | 6511 | alignment.toByteUnits().?, |
| 6512 | }); | 6512 | }); |
| 6513 | } | 6513 | } |
| 6514 | 6514 | ||
| ... | @@ -17699,19 +17699,20 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -17699,19 +17699,20 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 17699 | .ty = new_decl_ty.toIntern(), | 17699 | .ty = new_decl_ty.toIntern(), |
| 17700 | .storage = .{ .elems = param_vals }, | 17700 | .storage = .{ .elems = param_vals }, |
| 17701 | } }); | 17701 | } }); |
| 17702 | const ptr_ty = (try sema.ptrType(.{ | 17702 | const slice_ty = (try sema.ptrType(.{ |
| 17703 | .child = param_info_ty.toIntern(), | 17703 | .child = param_info_ty.toIntern(), |
| 17704 | .flags = .{ | 17704 | .flags = .{ |
| 17705 | .size = .Slice, | 17705 | .size = .Slice, |
| 17706 | .is_const = true, | 17706 | .is_const = true, |
| 17707 | }, | 17707 | }, |
| 17708 | })).toIntern(); | 17708 | })).toIntern(); |
| 17709 | const manyptr_ty = Type.fromInterned(slice_ty).slicePtrFieldType(mod).toIntern(); | ||
| 17709 | break :v try mod.intern(.{ .slice = .{ | 17710 | break :v try mod.intern(.{ .slice = .{ |
| 17710 | .ty = ptr_ty, | 17711 | .ty = slice_ty, |
| 17711 | .ptr = try mod.intern(.{ .ptr = .{ | 17712 | .ptr = try mod.intern(.{ .ptr = .{ |
| 17712 | .ty = Type.fromInterned(ptr_ty).slicePtrFieldType(mod).toIntern(), | 17713 | .ty = manyptr_ty, |
| 17713 | .addr = .{ .anon_decl = .{ | 17714 | .addr = .{ .anon_decl = .{ |
| 17714 | .orig_ty = ptr_ty, | 17715 | .orig_ty = manyptr_ty, |
| 17715 | .val = new_decl_val, | 17716 | .val = new_decl_val, |
| 17716 | } }, | 17717 | } }, |
| 17717 | } }), | 17718 | } }), |
| ... | @@ -17804,7 +17805,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -17804,7 +17805,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 17804 | }, | 17805 | }, |
| 17805 | .Pointer => { | 17806 | .Pointer => { |
| 17806 | const info = ty.ptrInfo(mod); | 17807 | const info = ty.ptrInfo(mod); |
| 17807 | const alignment = if (info.flags.alignment.toByteUnitsOptional()) |alignment| | 17808 | const alignment = if (info.flags.alignment.toByteUnits()) |alignment| |
| 17808 | try mod.intValue(Type.comptime_int, alignment) | 17809 | try mod.intValue(Type.comptime_int, alignment) |
| 17809 | else | 17810 | else |
| 17810 | try Type.fromInterned(info.child).lazyAbiAlignment(mod); | 17811 | try Type.fromInterned(info.child).lazyAbiAlignment(mod); |
| ... | @@ -18031,12 +18032,13 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -18031,12 +18032,13 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 18031 | .ty = array_errors_ty.toIntern(), | 18032 | .ty = array_errors_ty.toIntern(), |
| 18032 | .storage = .{ .elems = vals }, | 18033 | .storage = .{ .elems = vals }, |
| 18033 | } }); | 18034 | } }); |
| 18035 | const manyptr_errors_ty = slice_errors_ty.slicePtrFieldType(mod).toIntern(); | ||
| 18034 | break :v try mod.intern(.{ .slice = .{ | 18036 | break :v try mod.intern(.{ .slice = .{ |
| 18035 | .ty = slice_errors_ty.toIntern(), | 18037 | .ty = slice_errors_ty.toIntern(), |
| 18036 | .ptr = try mod.intern(.{ .ptr = .{ | 18038 | .ptr = try mod.intern(.{ .ptr = .{ |
| 18037 | .ty = slice_errors_ty.slicePtrFieldType(mod).toIntern(), | 18039 | .ty = manyptr_errors_ty, |
| 18038 | .addr = .{ .anon_decl = .{ | 18040 | .addr = .{ .anon_decl = .{ |
| 18039 | .orig_ty = slice_errors_ty.toIntern(), | 18041 | .orig_ty = manyptr_errors_ty, |
| 18040 | .val = new_decl_val, | 18042 | .val = new_decl_val, |
| 18041 | } }, | 18043 | } }, |
| 18042 | } }), | 18044 | } }), |
| ... | @@ -18155,20 +18157,21 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -18155,20 +18157,21 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 18155 | .ty = fields_array_ty.toIntern(), | 18157 | .ty = fields_array_ty.toIntern(), |
| 18156 | .storage = .{ .elems = enum_field_vals }, | 18158 | .storage = .{ .elems = enum_field_vals }, |
| 18157 | } }); | 18159 | } }); |
| 18158 | const ptr_ty = (try sema.ptrType(.{ | 18160 | const slice_ty = (try sema.ptrType(.{ |
| 18159 | .child = enum_field_ty.toIntern(), | 18161 | .child = enum_field_ty.toIntern(), |
| 18160 | .flags = .{ | 18162 | .flags = .{ |
| 18161 | .size = .Slice, | 18163 | .size = .Slice, |
| 18162 | .is_const = true, | 18164 | .is_const = true, |
| 18163 | }, | 18165 | }, |
| 18164 | })).toIntern(); | 18166 | })).toIntern(); |
| 18167 | const manyptr_ty = Type.fromInterned(slice_ty).slicePtrFieldType(mod).toIntern(); | ||
| 18165 | break :v try mod.intern(.{ .slice = .{ | 18168 | break :v try mod.intern(.{ .slice = .{ |
| 18166 | .ty = ptr_ty, | 18169 | .ty = slice_ty, |
| 18167 | .ptr = try mod.intern(.{ .ptr = .{ | 18170 | .ptr = try mod.intern(.{ .ptr = .{ |
| 18168 | .ty = Type.fromInterned(ptr_ty).slicePtrFieldType(mod).toIntern(), | 18171 | .ty = manyptr_ty, |
| 18169 | .addr = .{ .anon_decl = .{ | 18172 | .addr = .{ .anon_decl = .{ |
| 18170 | .val = new_decl_val, | 18173 | .val = new_decl_val, |
| 18171 | .orig_ty = ptr_ty, | 18174 | .orig_ty = manyptr_ty, |
| 18172 | } }, | 18175 | } }, |
| 18173 | } }), | 18176 | } }), |
| 18174 | .len = (try mod.intValue(Type.usize, enum_field_vals.len)).toIntern(), | 18177 | .len = (try mod.intValue(Type.usize, enum_field_vals.len)).toIntern(), |
| ... | @@ -18279,7 +18282,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -18279,7 +18282,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 18279 | // type: type, | 18282 | // type: type, |
| 18280 | field_ty, | 18283 | field_ty, |
| 18281 | // alignment: comptime_int, | 18284 | // alignment: comptime_int, |
| 18282 | (try mod.intValue(Type.comptime_int, alignment.toByteUnits(0))).toIntern(), | 18285 | (try mod.intValue(Type.comptime_int, alignment.toByteUnits() orelse 0)).toIntern(), |
| 18283 | }; | 18286 | }; |
| 18284 | field_val.* = try mod.intern(.{ .aggregate = .{ | 18287 | field_val.* = try mod.intern(.{ .aggregate = .{ |
| 18285 | .ty = union_field_ty.toIntern(), | 18288 | .ty = union_field_ty.toIntern(), |
| ... | @@ -18296,19 +18299,20 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -18296,19 +18299,20 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 18296 | .ty = array_fields_ty.toIntern(), | 18299 | .ty = array_fields_ty.toIntern(), |
| 18297 | .storage = .{ .elems = union_field_vals }, | 18300 | .storage = .{ .elems = union_field_vals }, |
| 18298 | } }); | 18301 | } }); |
| 18299 | const ptr_ty = (try sema.ptrType(.{ | 18302 | const slice_ty = (try sema.ptrType(.{ |
| 18300 | .child = union_field_ty.toIntern(), | 18303 | .child = union_field_ty.toIntern(), |
| 18301 | .flags = .{ | 18304 | .flags = .{ |
| 18302 | .size = .Slice, | 18305 | .size = .Slice, |
| 18303 | .is_const = true, | 18306 | .is_const = true, |
| 18304 | }, | 18307 | }, |
| 18305 | })).toIntern(); | 18308 | })).toIntern(); |
| 18309 | const manyptr_ty = Type.fromInterned(slice_ty).slicePtrFieldType(mod).toIntern(); | ||
| 18306 | break :v try mod.intern(.{ .slice = .{ | 18310 | break :v try mod.intern(.{ .slice = .{ |
| 18307 | .ty = ptr_ty, | 18311 | .ty = slice_ty, |
| 18308 | .ptr = try mod.intern(.{ .ptr = .{ | 18312 | .ptr = try mod.intern(.{ .ptr = .{ |
| 18309 | .ty = Type.fromInterned(ptr_ty).slicePtrFieldType(mod).toIntern(), | 18313 | .ty = manyptr_ty, |
| 18310 | .addr = .{ .anon_decl = .{ | 18314 | .addr = .{ .anon_decl = .{ |
| 18311 | .orig_ty = ptr_ty, | 18315 | .orig_ty = manyptr_ty, |
| 18312 | .val = new_decl_val, | 18316 | .val = new_decl_val, |
| 18313 | } }, | 18317 | } }, |
| 18314 | } }), | 18318 | } }), |
| ... | @@ -18436,7 +18440,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -18436,7 +18440,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 18436 | // is_comptime: bool, | 18440 | // is_comptime: bool, |
| 18437 | Value.makeBool(is_comptime).toIntern(), | 18441 | Value.makeBool(is_comptime).toIntern(), |
| 18438 | // alignment: comptime_int, | 18442 | // alignment: comptime_int, |
| 18439 | (try mod.intValue(Type.comptime_int, Type.fromInterned(field_ty).abiAlignment(mod).toByteUnits(0))).toIntern(), | 18443 | (try mod.intValue(Type.comptime_int, Type.fromInterned(field_ty).abiAlignment(mod).toByteUnits() orelse 0)).toIntern(), |
| 18440 | }; | 18444 | }; |
| 18441 | struct_field_val.* = try mod.intern(.{ .aggregate = .{ | 18445 | struct_field_val.* = try mod.intern(.{ .aggregate = .{ |
| 18442 | .ty = struct_field_ty.toIntern(), | 18446 | .ty = struct_field_ty.toIntern(), |
| ... | @@ -18505,7 +18509,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -18505,7 +18509,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 18505 | // is_comptime: bool, | 18509 | // is_comptime: bool, |
| 18506 | Value.makeBool(field_is_comptime).toIntern(), | 18510 | Value.makeBool(field_is_comptime).toIntern(), |
| 18507 | // alignment: comptime_int, | 18511 | // alignment: comptime_int, |
| 18508 | (try mod.intValue(Type.comptime_int, alignment.toByteUnits(0))).toIntern(), | 18512 | (try mod.intValue(Type.comptime_int, alignment.toByteUnits() orelse 0)).toIntern(), |
| 18509 | }; | 18513 | }; |
| 18510 | field_val.* = try mod.intern(.{ .aggregate = .{ | 18514 | field_val.* = try mod.intern(.{ .aggregate = .{ |
| 18511 | .ty = struct_field_ty.toIntern(), | 18515 | .ty = struct_field_ty.toIntern(), |
| ... | @@ -18523,19 +18527,20 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -18523,19 +18527,20 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 18523 | .ty = array_fields_ty.toIntern(), | 18527 | .ty = array_fields_ty.toIntern(), |
| 18524 | .storage = .{ .elems = struct_field_vals }, | 18528 | .storage = .{ .elems = struct_field_vals }, |
| 18525 | } }); | 18529 | } }); |
| 18526 | const ptr_ty = (try sema.ptrType(.{ | 18530 | const slice_ty = (try sema.ptrType(.{ |
| 18527 | .child = struct_field_ty.toIntern(), | 18531 | .child = struct_field_ty.toIntern(), |
| 18528 | .flags = .{ | 18532 | .flags = .{ |
| 18529 | .size = .Slice, | 18533 | .size = .Slice, |
| 18530 | .is_const = true, | 18534 | .is_const = true, |
| 18531 | }, | 18535 | }, |
| 18532 | })).toIntern(); | 18536 | })).toIntern(); |
| 18537 | const manyptr_ty = Type.fromInterned(slice_ty).slicePtrFieldType(mod).toIntern(); | ||
| 18533 | break :v try mod.intern(.{ .slice = .{ | 18538 | break :v try mod.intern(.{ .slice = .{ |
| 18534 | .ty = ptr_ty, | 18539 | .ty = slice_ty, |
| 18535 | .ptr = try mod.intern(.{ .ptr = .{ | 18540 | .ptr = try mod.intern(.{ .ptr = .{ |
| 18536 | .ty = Type.fromInterned(ptr_ty).slicePtrFieldType(mod).toIntern(), | 18541 | .ty = manyptr_ty, |
| 18537 | .addr = .{ .anon_decl = .{ | 18542 | .addr = .{ .anon_decl = .{ |
| 18538 | .orig_ty = ptr_ty, | 18543 | .orig_ty = manyptr_ty, |
| 18539 | .val = new_decl_val, | 18544 | .val = new_decl_val, |
| 18540 | } }, | 18545 | } }, |
| 18541 | } }), | 18546 | } }), |
| ... | @@ -18661,19 +18666,20 @@ fn typeInfoDecls( | ... | @@ -18661,19 +18666,20 @@ fn typeInfoDecls( |
| 18661 | .ty = array_decl_ty.toIntern(), | 18666 | .ty = array_decl_ty.toIntern(), |
| 18662 | .storage = .{ .elems = decl_vals.items }, | 18667 | .storage = .{ .elems = decl_vals.items }, |
| 18663 | } }); | 18668 | } }); |
| 18664 | const ptr_ty = (try sema.ptrType(.{ | 18669 | const slice_ty = (try sema.ptrType(.{ |
| 18665 | .child = declaration_ty.toIntern(), | 18670 | .child = declaration_ty.toIntern(), |
| 18666 | .flags = .{ | 18671 | .flags = .{ |
| 18667 | .size = .Slice, | 18672 | .size = .Slice, |
| 18668 | .is_const = true, | 18673 | .is_const = true, |
| 18669 | }, | 18674 | }, |
| 18670 | })).toIntern(); | 18675 | })).toIntern(); |
| 18676 | const manyptr_ty = Type.fromInterned(slice_ty).slicePtrFieldType(mod).toIntern(); | ||
| 18671 | return try mod.intern(.{ .slice = .{ | 18677 | return try mod.intern(.{ .slice = .{ |
| 18672 | .ty = ptr_ty, | 18678 | .ty = slice_ty, |
| 18673 | .ptr = try mod.intern(.{ .ptr = .{ | 18679 | .ptr = try mod.intern(.{ .ptr = .{ |
| 18674 | .ty = Type.fromInterned(ptr_ty).slicePtrFieldType(mod).toIntern(), | 18680 | .ty = manyptr_ty, |
| 18675 | .addr = .{ .anon_decl = .{ | 18681 | .addr = .{ .anon_decl = .{ |
| 18676 | .orig_ty = ptr_ty, | 18682 | .orig_ty = manyptr_ty, |
| 18677 | .val = new_decl_val, | 18683 | .val = new_decl_val, |
| 18678 | } }, | 18684 | } }, |
| 18679 | } }), | 18685 | } }), |
| ... | @@ -19803,8 +19809,18 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air | ... | @@ -19803,8 +19809,18 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 19803 | break :blk @intCast(host_size); | 19809 | break :blk @intCast(host_size); |
| 19804 | } else 0; | 19810 | } else 0; |
| 19805 | 19811 | ||
| 19806 | if (host_size != 0 and bit_offset >= host_size * 8) { | 19812 | if (host_size != 0) { |
| 19807 | return sema.fail(block, bitoffset_src, "bit offset starts after end of host integer", .{}); | 19813 | if (bit_offset >= host_size * 8) { |
| 19814 | return sema.fail(block, bitoffset_src, "packed type '{}' at bit offset {} starts {} bits after the end of a {} byte host integer", .{ | ||
| 19815 | elem_ty.fmt(mod), bit_offset, bit_offset - host_size * 8, host_size, | ||
| 19816 | }); | ||
| 19817 | } | ||
| 19818 | const elem_bit_size = try elem_ty.bitSizeAdvanced(mod, sema); | ||
| 19819 | if (elem_bit_size > host_size * 8 - bit_offset) { | ||
| 19820 | return sema.fail(block, bitoffset_src, "packed type '{}' at bit offset {} ends {} bits after the end of a {} byte host integer", .{ | ||
| 19821 | elem_ty.fmt(mod), bit_offset, elem_bit_size - (host_size * 8 - bit_offset), host_size, | ||
| 19822 | }); | ||
| 19823 | } | ||
| 19808 | } | 19824 | } |
| 19809 | 19825 | ||
| 19810 | if (elem_ty.zigTypeTag(mod) == .Fn) { | 19826 | if (elem_ty.zigTypeTag(mod) == .Fn) { |
| ... | @@ -22552,7 +22568,7 @@ fn zirPtrFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! | ... | @@ -22552,7 +22568,7 @@ fn zirPtrFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! |
| 22552 | try sema.addSafetyCheck(block, src, is_non_zero, .cast_to_null); | 22568 | try sema.addSafetyCheck(block, src, is_non_zero, .cast_to_null); |
| 22553 | } | 22569 | } |
| 22554 | if (ptr_align.compare(.gt, .@"1")) { | 22570 | if (ptr_align.compare(.gt, .@"1")) { |
| 22555 | const align_bytes_minus_1 = ptr_align.toByteUnitsOptional().? - 1; | 22571 | const align_bytes_minus_1 = ptr_align.toByteUnits().? - 1; |
| 22556 | const align_minus_1 = Air.internedToRef((try mod.intValue(Type.usize, align_bytes_minus_1)).toIntern()); | 22572 | const align_minus_1 = Air.internedToRef((try mod.intValue(Type.usize, align_bytes_minus_1)).toIntern()); |
| 22557 | const remainder = try block.addBinOp(.bit_and, operand_coerced, align_minus_1); | 22573 | const remainder = try block.addBinOp(.bit_and, operand_coerced, align_minus_1); |
| 22558 | const is_aligned = try block.addBinOp(.cmp_eq, remainder, .zero_usize); | 22574 | const is_aligned = try block.addBinOp(.cmp_eq, remainder, .zero_usize); |
| ... | @@ -22572,7 +22588,7 @@ fn zirPtrFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! | ... | @@ -22572,7 +22588,7 @@ fn zirPtrFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! |
| 22572 | try sema.addSafetyCheck(block, src, is_non_zero, .cast_to_null); | 22588 | try sema.addSafetyCheck(block, src, is_non_zero, .cast_to_null); |
| 22573 | } | 22589 | } |
| 22574 | if (ptr_align.compare(.gt, .@"1")) { | 22590 | if (ptr_align.compare(.gt, .@"1")) { |
| 22575 | const align_bytes_minus_1 = ptr_align.toByteUnitsOptional().? - 1; | 22591 | const align_bytes_minus_1 = ptr_align.toByteUnits().? - 1; |
| 22576 | const align_minus_1 = Air.internedToRef((try mod.intValue(Type.usize, align_bytes_minus_1)).toIntern()); | 22592 | const align_minus_1 = Air.internedToRef((try mod.intValue(Type.usize, align_bytes_minus_1)).toIntern()); |
| 22577 | const remainder = try block.addBinOp(.bit_and, elem_coerced, align_minus_1); | 22593 | const remainder = try block.addBinOp(.bit_and, elem_coerced, align_minus_1); |
| 22578 | const is_aligned = try block.addBinOp(.cmp_eq, remainder, .zero_usize); | 22594 | const is_aligned = try block.addBinOp(.cmp_eq, remainder, .zero_usize); |
| ... | @@ -22741,10 +22757,8 @@ fn zirErrorCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData | ... | @@ -22741,10 +22757,8 @@ fn zirErrorCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData |
| 22741 | } | 22757 | } |
| 22742 | 22758 | ||
| 22743 | fn zirPtrCastFull(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref { | 22759 | fn zirPtrCastFull(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref { |
| 22744 | const flags: Zir.Inst.FullPtrCastFlags = @bitCast(@as( | 22760 | const FlagsInt = @typeInfo(Zir.Inst.FullPtrCastFlags).Struct.backing_integer.?; |
| 22745 | @typeInfo(Zir.Inst.FullPtrCastFlags).Struct.backing_integer.?, | 22761 | const flags: Zir.Inst.FullPtrCastFlags = @bitCast(@as(FlagsInt, @truncate(extended.small))); |
| 22746 | @truncate(extended.small), | ||
| 22747 | )); | ||
| 22748 | const extra = sema.code.extraData(Zir.Inst.BinNode, extended.operand).data; | 22762 | const extra = sema.code.extraData(Zir.Inst.BinNode, extended.operand).data; |
| 22749 | const src = LazySrcLoc.nodeOffset(extra.node); | 22763 | const src = LazySrcLoc.nodeOffset(extra.node); |
| 22750 | const operand_src: LazySrcLoc = .{ .node_offset_ptrcast_operand = extra.node }; | 22764 | const operand_src: LazySrcLoc = .{ .node_offset_ptrcast_operand = extra.node }; |
| ... | @@ -22757,6 +22771,7 @@ fn zirPtrCastFull(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDa | ... | @@ -22757,6 +22771,7 @@ fn zirPtrCastFull(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDa |
| 22757 | operand, | 22771 | operand, |
| 22758 | operand_src, | 22772 | operand_src, |
| 22759 | dest_ty, | 22773 | dest_ty, |
| 22774 | flags.needResultTypeBuiltinName(), | ||
| 22760 | ); | 22775 | ); |
| 22761 | } | 22776 | } |
| 22762 | 22777 | ||
| ... | @@ -22775,6 +22790,7 @@ fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air | ... | @@ -22775,6 +22790,7 @@ fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 22775 | operand, | 22790 | operand, |
| 22776 | operand_src, | 22791 | operand_src, |
| 22777 | dest_ty, | 22792 | dest_ty, |
| 22793 | "@ptrCast", | ||
| 22778 | ); | 22794 | ); |
| 22779 | } | 22795 | } |
| 22780 | 22796 | ||
| ... | @@ -22786,6 +22802,7 @@ fn ptrCastFull( | ... | @@ -22786,6 +22802,7 @@ fn ptrCastFull( |
| 22786 | operand: Air.Inst.Ref, | 22802 | operand: Air.Inst.Ref, |
| 22787 | operand_src: LazySrcLoc, | 22803 | operand_src: LazySrcLoc, |
| 22788 | dest_ty: Type, | 22804 | dest_ty: Type, |
| 22805 | operation: []const u8, | ||
| 22789 | ) CompileError!Air.Inst.Ref { | 22806 | ) CompileError!Air.Inst.Ref { |
| 22790 | const mod = sema.mod; | 22807 | const mod = sema.mod; |
| 22791 | const operand_ty = sema.typeOf(operand); | 22808 | const operand_ty = sema.typeOf(operand); |
| ... | @@ -22818,7 +22835,7 @@ fn ptrCastFull( | ... | @@ -22818,7 +22835,7 @@ fn ptrCastFull( |
| 22818 | }; | 22835 | }; |
| 22819 | const dest_elem_size = Type.fromInterned(dest_info.child).abiSize(mod); | 22836 | const dest_elem_size = Type.fromInterned(dest_info.child).abiSize(mod); |
| 22820 | if (src_elem_size != dest_elem_size) { | 22837 | if (src_elem_size != dest_elem_size) { |
| 22821 | return sema.fail(block, src, "TODO: implement @ptrCast between slices changing the length", .{}); | 22838 | return sema.fail(block, src, "TODO: implement {s} between slices changing the length", .{operation}); |
| 22822 | } | 22839 | } |
| 22823 | } | 22840 | } |
| 22824 | 22841 | ||
| ... | @@ -22967,13 +22984,13 @@ fn ptrCastFull( | ... | @@ -22967,13 +22984,13 @@ fn ptrCastFull( |
| 22967 | if (!flags.align_cast) { | 22984 | if (!flags.align_cast) { |
| 22968 | if (dest_align.compare(.gt, src_align)) { | 22985 | if (dest_align.compare(.gt, src_align)) { |
| 22969 | return sema.failWithOwnedErrorMsg(block, msg: { | 22986 | return sema.failWithOwnedErrorMsg(block, msg: { |
| 22970 | const msg = try sema.errMsg(block, src, "cast increases pointer alignment", .{}); | 22987 | const msg = try sema.errMsg(block, src, "{s} increases pointer alignment", .{operation}); |
| 22971 | errdefer msg.destroy(sema.gpa); | 22988 | errdefer msg.destroy(sema.gpa); |
| 22972 | try sema.errNote(block, operand_src, msg, "'{}' has alignment '{d}'", .{ | 22989 | try sema.errNote(block, operand_src, msg, "'{}' has alignment '{d}'", .{ |
| 22973 | operand_ty.fmt(mod), src_align.toByteUnits(0), | 22990 | operand_ty.fmt(mod), src_align.toByteUnits() orelse 0, |
| 22974 | }); | 22991 | }); |
| 22975 | try sema.errNote(block, src, msg, "'{}' has alignment '{d}'", .{ | 22992 | try sema.errNote(block, src, msg, "'{}' has alignment '{d}'", .{ |
| 22976 | dest_ty.fmt(mod), dest_align.toByteUnits(0), | 22993 | dest_ty.fmt(mod), dest_align.toByteUnits() orelse 0, |
| 22977 | }); | 22994 | }); |
| 22978 | try sema.errNote(block, src, msg, "use @alignCast to assert pointer alignment", .{}); | 22995 | try sema.errNote(block, src, msg, "use @alignCast to assert pointer alignment", .{}); |
| 22979 | break :msg msg; | 22996 | break :msg msg; |
| ... | @@ -22984,7 +23001,7 @@ fn ptrCastFull( | ... | @@ -22984,7 +23001,7 @@ fn ptrCastFull( |
| 22984 | if (!flags.addrspace_cast) { | 23001 | if (!flags.addrspace_cast) { |
| 22985 | if (src_info.flags.address_space != dest_info.flags.address_space) { | 23002 | if (src_info.flags.address_space != dest_info.flags.address_space) { |
| 22986 | return sema.failWithOwnedErrorMsg(block, msg: { | 23003 | return sema.failWithOwnedErrorMsg(block, msg: { |
| 22987 | const msg = try sema.errMsg(block, src, "cast changes pointer address space", .{}); | 23004 | const msg = try sema.errMsg(block, src, "{s} changes pointer address space", .{operation}); |
| 22988 | errdefer msg.destroy(sema.gpa); | 23005 | errdefer msg.destroy(sema.gpa); |
| 22989 | try sema.errNote(block, operand_src, msg, "'{}' has address space '{s}'", .{ | 23006 | try sema.errNote(block, operand_src, msg, "'{}' has address space '{s}'", .{ |
| 22990 | operand_ty.fmt(mod), @tagName(src_info.flags.address_space), | 23007 | operand_ty.fmt(mod), @tagName(src_info.flags.address_space), |
| ... | @@ -23014,7 +23031,7 @@ fn ptrCastFull( | ... | @@ -23014,7 +23031,7 @@ fn ptrCastFull( |
| 23014 | if (!flags.const_cast) { | 23031 | if (!flags.const_cast) { |
| 23015 | if (src_info.flags.is_const and !dest_info.flags.is_const) { | 23032 | if (src_info.flags.is_const and !dest_info.flags.is_const) { |
| 23016 | return sema.failWithOwnedErrorMsg(block, msg: { | 23033 | return sema.failWithOwnedErrorMsg(block, msg: { |
| 23017 | const msg = try sema.errMsg(block, src, "cast discards const qualifier", .{}); | 23034 | const msg = try sema.errMsg(block, src, "{s} discards const qualifier", .{operation}); |
| 23018 | errdefer msg.destroy(sema.gpa); | 23035 | errdefer msg.destroy(sema.gpa); |
| 23019 | try sema.errNote(block, src, msg, "use @constCast to discard const qualifier", .{}); | 23036 | try sema.errNote(block, src, msg, "use @constCast to discard const qualifier", .{}); |
| 23020 | break :msg msg; | 23037 | break :msg msg; |
| ... | @@ -23025,7 +23042,7 @@ fn ptrCastFull( | ... | @@ -23025,7 +23042,7 @@ fn ptrCastFull( |
| 23025 | if (!flags.volatile_cast) { | 23042 | if (!flags.volatile_cast) { |
| 23026 | if (src_info.flags.is_volatile and !dest_info.flags.is_volatile) { | 23043 | if (src_info.flags.is_volatile and !dest_info.flags.is_volatile) { |
| 23027 | return sema.failWithOwnedErrorMsg(block, msg: { | 23044 | return sema.failWithOwnedErrorMsg(block, msg: { |
| 23028 | const msg = try sema.errMsg(block, src, "cast discards volatile qualifier", .{}); | 23045 | const msg = try sema.errMsg(block, src, "{s} discards volatile qualifier", .{operation}); |
| 23029 | errdefer msg.destroy(sema.gpa); | 23046 | errdefer msg.destroy(sema.gpa); |
| 23030 | try sema.errNote(block, src, msg, "use @volatileCast to discard volatile qualifier", .{}); | 23047 | try sema.errNote(block, src, msg, "use @volatileCast to discard volatile qualifier", .{}); |
| 23031 | break :msg msg; | 23048 | break :msg msg; |
| ... | @@ -23067,7 +23084,7 @@ fn ptrCastFull( | ... | @@ -23067,7 +23084,7 @@ fn ptrCastFull( |
| 23067 | if (!dest_align.check(addr)) { | 23084 | if (!dest_align.check(addr)) { |
| 23068 | return sema.fail(block, operand_src, "pointer address 0x{X} is not aligned to {d} bytes", .{ | 23085 | return sema.fail(block, operand_src, "pointer address 0x{X} is not aligned to {d} bytes", .{ |
| 23069 | addr, | 23086 | addr, |
| 23070 | dest_align.toByteUnitsOptional().?, | 23087 | dest_align.toByteUnits().?, |
| 23071 | }); | 23088 | }); |
| 23072 | } | 23089 | } |
| 23073 | } | 23090 | } |
| ... | @@ -23110,7 +23127,7 @@ fn ptrCastFull( | ... | @@ -23110,7 +23127,7 @@ fn ptrCastFull( |
| 23110 | dest_align.compare(.gt, src_align) and | 23127 | dest_align.compare(.gt, src_align) and |
| 23111 | try sema.typeHasRuntimeBits(Type.fromInterned(dest_info.child))) | 23128 | try sema.typeHasRuntimeBits(Type.fromInterned(dest_info.child))) |
| 23112 | { | 23129 | { |
| 23113 | const align_bytes_minus_1 = dest_align.toByteUnitsOptional().? - 1; | 23130 | const align_bytes_minus_1 = dest_align.toByteUnits().? - 1; |
| 23114 | const align_minus_1 = Air.internedToRef((try mod.intValue(Type.usize, align_bytes_minus_1)).toIntern()); | 23131 | const align_minus_1 = Air.internedToRef((try mod.intValue(Type.usize, align_bytes_minus_1)).toIntern()); |
| 23115 | const ptr_int = try block.addUnOp(.int_from_ptr, ptr); | 23132 | const ptr_int = try block.addUnOp(.int_from_ptr, ptr); |
| 23116 | const remainder = try block.addBinOp(.bit_and, ptr_int, align_minus_1); | 23133 | const remainder = try block.addBinOp(.bit_and, ptr_int, align_minus_1); |
| ... | @@ -23171,10 +23188,8 @@ fn ptrCastFull( | ... | @@ -23171,10 +23188,8 @@ fn ptrCastFull( |
| 23171 | 23188 | ||
| 23172 | fn zirPtrCastNoDest(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref { | 23189 | fn zirPtrCastNoDest(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref { |
| 23173 | const mod = sema.mod; | 23190 | const mod = sema.mod; |
| 23174 | const flags: Zir.Inst.FullPtrCastFlags = @bitCast(@as( | 23191 | const FlagsInt = @typeInfo(Zir.Inst.FullPtrCastFlags).Struct.backing_integer.?; |
| 23175 | @typeInfo(Zir.Inst.FullPtrCastFlags).Struct.backing_integer.?, | 23192 | const flags: Zir.Inst.FullPtrCastFlags = @bitCast(@as(FlagsInt, @truncate(extended.small))); |
| 23176 | @truncate(extended.small), | ||
| 23177 | )); | ||
| 23178 | const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data; | 23193 | const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data; |
| 23179 | const src = LazySrcLoc.nodeOffset(extra.node); | 23194 | const src = LazySrcLoc.nodeOffset(extra.node); |
| 23180 | const operand_src: LazySrcLoc = .{ .node_offset_ptrcast_operand = extra.node }; | 23195 | const operand_src: LazySrcLoc = .{ .node_offset_ptrcast_operand = extra.node }; |
| ... | @@ -24843,107 +24858,151 @@ fn zirBuiltinCall(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError | ... | @@ -24843,107 +24858,151 @@ fn zirBuiltinCall(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 24843 | ); | 24858 | ); |
| 24844 | } | 24859 | } |
| 24845 | 24860 | ||
| 24846 | fn zirFieldParentPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 24861 | fn zirFieldParentPtr(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref { |
| 24847 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; | ||
| 24848 | const extra = sema.code.extraData(Zir.Inst.FieldParentPtr, inst_data.payload_index).data; | ||
| 24849 | const src = inst_data.src(); | ||
| 24850 | const ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; | ||
| 24851 | const name_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node }; | ||
| 24852 | const ptr_src: LazySrcLoc = .{ .node_offset_builtin_call_arg2 = inst_data.src_node }; | ||
| 24853 | |||
| 24854 | const parent_ty = try sema.resolveType(block, ty_src, extra.parent_type); | ||
| 24855 | const field_name = try sema.resolveConstStringIntern(block, name_src, extra.field_name, .{ | ||
| 24856 | .needed_comptime_reason = "field name must be comptime-known", | ||
| 24857 | }); | ||
| 24858 | const field_ptr = try sema.resolveInst(extra.field_ptr); | ||
| 24859 | const field_ptr_ty = sema.typeOf(field_ptr); | ||
| 24860 | const mod = sema.mod; | 24862 | const mod = sema.mod; |
| 24861 | const ip = &mod.intern_pool; | 24863 | const ip = &mod.intern_pool; |
| 24862 | 24864 | ||
| 24863 | if (parent_ty.zigTypeTag(mod) != .Struct and parent_ty.zigTypeTag(mod) != .Union) { | 24865 | const extra = sema.code.extraData(Zir.Inst.FieldParentPtr, extended.operand).data; |
| 24864 | return sema.fail(block, ty_src, "expected struct or union type, found '{}'", .{parent_ty.fmt(sema.mod)}); | 24866 | const FlagsInt = @typeInfo(Zir.Inst.FullPtrCastFlags).Struct.backing_integer.?; |
| 24867 | const flags: Zir.Inst.FullPtrCastFlags = @bitCast(@as(FlagsInt, @truncate(extended.small))); | ||
| 24868 | assert(!flags.ptr_cast); | ||
| 24869 | const inst_src = extra.src(); | ||
| 24870 | const field_name_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.src_node }; | ||
| 24871 | const field_ptr_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = extra.src_node }; | ||
| 24872 | |||
| 24873 | const parent_ptr_ty = try sema.resolveDestType(block, inst_src, extra.parent_ptr_type, .remove_eu, "@fieldParentPtr"); | ||
| 24874 | try sema.checkPtrType(block, inst_src, parent_ptr_ty, true); | ||
| 24875 | const parent_ptr_info = parent_ptr_ty.ptrInfo(mod); | ||
| 24876 | if (parent_ptr_info.flags.size != .One) { | ||
| 24877 | return sema.fail(block, inst_src, "expected single pointer type, found '{}'", .{parent_ptr_ty.fmt(sema.mod)}); | ||
| 24878 | } | ||
| 24879 | const parent_ty = Type.fromInterned(parent_ptr_info.child); | ||
| 24880 | switch (parent_ty.zigTypeTag(mod)) { | ||
| 24881 | .Struct, .Union => {}, | ||
| 24882 | else => return sema.fail(block, inst_src, "expected pointer to struct or union type, found '{}'", .{parent_ptr_ty.fmt(sema.mod)}), | ||
| 24865 | } | 24883 | } |
| 24866 | try sema.resolveTypeLayout(parent_ty); | 24884 | try sema.resolveTypeLayout(parent_ty); |
| 24867 | 24885 | ||
| 24886 | const field_name = try sema.resolveConstStringIntern(block, field_name_src, extra.field_name, .{ | ||
| 24887 | .needed_comptime_reason = "field name must be comptime-known", | ||
| 24888 | }); | ||
| 24868 | const field_index = switch (parent_ty.zigTypeTag(mod)) { | 24889 | const field_index = switch (parent_ty.zigTypeTag(mod)) { |
| 24869 | .Struct => blk: { | 24890 | .Struct => blk: { |
| 24870 | if (parent_ty.isTuple(mod)) { | 24891 | if (parent_ty.isTuple(mod)) { |
| 24871 | if (ip.stringEqlSlice(field_name, "len")) { | 24892 | if (ip.stringEqlSlice(field_name, "len")) { |
| 24872 | return sema.fail(block, src, "cannot get @fieldParentPtr of 'len' field of tuple", .{}); | 24893 | return sema.fail(block, inst_src, "cannot get @fieldParentPtr of 'len' field of tuple", .{}); |
| 24873 | } | 24894 | } |
| 24874 | break :blk try sema.tupleFieldIndex(block, parent_ty, field_name, name_src); | 24895 | break :blk try sema.tupleFieldIndex(block, parent_ty, field_name, field_name_src); |
| 24875 | } else { | 24896 | } else { |
| 24876 | break :blk try sema.structFieldIndex(block, parent_ty, field_name, name_src); | 24897 | break :blk try sema.structFieldIndex(block, parent_ty, field_name, field_name_src); |
| 24877 | } | 24898 | } |
| 24878 | }, | 24899 | }, |
| 24879 | .Union => try sema.unionFieldIndex(block, parent_ty, field_name, name_src), | 24900 | .Union => try sema.unionFieldIndex(block, parent_ty, field_name, field_name_src), |
| 24880 | else => unreachable, | 24901 | else => unreachable, |
| 24881 | }; | 24902 | }; |
| 24882 | |||
| 24883 | if (parent_ty.zigTypeTag(mod) == .Struct and parent_ty.structFieldIsComptime(field_index, mod)) { | 24903 | if (parent_ty.zigTypeTag(mod) == .Struct and parent_ty.structFieldIsComptime(field_index, mod)) { |
| 24884 | return sema.fail(block, src, "cannot get @fieldParentPtr of a comptime field", .{}); | 24904 | return sema.fail(block, field_name_src, "cannot get @fieldParentPtr of a comptime field", .{}); |
| 24885 | } | 24905 | } |
| 24886 | 24906 | ||
| 24887 | try sema.checkPtrOperand(block, ptr_src, field_ptr_ty); | 24907 | const field_ptr = try sema.resolveInst(extra.field_ptr); |
| 24888 | const field_ptr_ty_info = field_ptr_ty.ptrInfo(mod); | 24908 | const field_ptr_ty = sema.typeOf(field_ptr); |
| 24909 | try sema.checkPtrOperand(block, field_ptr_src, field_ptr_ty); | ||
| 24910 | const field_ptr_info = field_ptr_ty.ptrInfo(mod); | ||
| 24889 | 24911 | ||
| 24890 | var ptr_ty_data: InternPool.Key.PtrType = .{ | 24912 | var actual_parent_ptr_info: InternPool.Key.PtrType = .{ |
| 24891 | .child = parent_ty.structFieldType(field_index, mod).toIntern(), | 24913 | .child = parent_ty.toIntern(), |
| 24892 | .flags = .{ | 24914 | .flags = .{ |
| 24893 | .address_space = field_ptr_ty_info.flags.address_space, | 24915 | .alignment = try parent_ptr_ty.ptrAlignmentAdvanced(mod, sema), |
| 24894 | .is_const = field_ptr_ty_info.flags.is_const, | 24916 | .is_const = field_ptr_info.flags.is_const, |
| 24917 | .is_volatile = field_ptr_info.flags.is_volatile, | ||
| 24918 | .is_allowzero = field_ptr_info.flags.is_allowzero, | ||
| 24919 | .address_space = field_ptr_info.flags.address_space, | ||
| 24895 | }, | 24920 | }, |
| 24921 | .packed_offset = parent_ptr_info.packed_offset, | ||
| 24896 | }; | 24922 | }; |
| 24923 | const field_ty = parent_ty.structFieldType(field_index, mod); | ||
| 24924 | var actual_field_ptr_info: InternPool.Key.PtrType = .{ | ||
| 24925 | .child = field_ty.toIntern(), | ||
| 24926 | .flags = .{ | ||
| 24927 | .alignment = try field_ptr_ty.ptrAlignmentAdvanced(mod, sema), | ||
| 24928 | .is_const = field_ptr_info.flags.is_const, | ||
| 24929 | .is_volatile = field_ptr_info.flags.is_volatile, | ||
| 24930 | .is_allowzero = field_ptr_info.flags.is_allowzero, | ||
| 24931 | .address_space = field_ptr_info.flags.address_space, | ||
| 24932 | }, | ||
| 24933 | .packed_offset = field_ptr_info.packed_offset, | ||
| 24934 | }; | ||
| 24935 | switch (parent_ty.containerLayout(mod)) { | ||
| 24936 | .auto => { | ||
| 24937 | actual_parent_ptr_info.flags.alignment = actual_field_ptr_info.flags.alignment.minStrict( | ||
| 24938 | if (mod.typeToStruct(parent_ty)) |struct_obj| try sema.structFieldAlignment( | ||
| 24939 | struct_obj.fieldAlign(ip, field_index), | ||
| 24940 | field_ty, | ||
| 24941 | struct_obj.layout, | ||
| 24942 | ) else if (mod.typeToUnion(parent_ty)) |union_obj| | ||
| 24943 | try sema.unionFieldAlignment(union_obj, field_index) | ||
| 24944 | else | ||
| 24945 | actual_field_ptr_info.flags.alignment, | ||
| 24946 | ); | ||
| 24897 | 24947 | ||
| 24898 | if (parent_ty.containerLayout(mod) == .@"packed") { | 24948 | actual_parent_ptr_info.packed_offset = .{ .bit_offset = 0, .host_size = 0 }; |
| 24899 | return sema.fail(block, src, "TODO handle packed structs/unions with @fieldParentPtr", .{}); | 24949 | actual_field_ptr_info.packed_offset = .{ .bit_offset = 0, .host_size = 0 }; |
| 24900 | } else { | 24950 | }, |
| 24901 | ptr_ty_data.flags.alignment = blk: { | 24951 | .@"extern" => { |
| 24902 | if (mod.typeToStruct(parent_ty)) |struct_type| { | 24952 | const field_offset = parent_ty.structFieldOffset(field_index, mod); |
| 24903 | break :blk struct_type.fieldAlign(ip, field_index); | 24953 | actual_parent_ptr_info.flags.alignment = actual_field_ptr_info.flags.alignment.minStrict(if (field_offset > 0) |
| 24904 | } else if (mod.typeToUnion(parent_ty)) |union_obj| { | 24954 | Alignment.fromLog2Units(@ctz(field_offset)) |
| 24905 | break :blk union_obj.fieldAlign(ip, field_index); | 24955 | else |
| 24906 | } else { | 24956 | actual_field_ptr_info.flags.alignment); |
| 24907 | break :blk .none; | ||
| 24908 | } | ||
| 24909 | }; | ||
| 24910 | } | ||
| 24911 | |||
| 24912 | const actual_field_ptr_ty = try sema.ptrType(ptr_ty_data); | ||
| 24913 | const casted_field_ptr = try sema.coerce(block, actual_field_ptr_ty, field_ptr, ptr_src); | ||
| 24914 | 24957 | ||
| 24915 | ptr_ty_data.child = parent_ty.toIntern(); | 24958 | actual_parent_ptr_info.packed_offset = .{ .bit_offset = 0, .host_size = 0 }; |
| 24916 | const result_ptr = try sema.ptrType(ptr_ty_data); | 24959 | actual_field_ptr_info.packed_offset = .{ .bit_offset = 0, .host_size = 0 }; |
| 24960 | }, | ||
| 24961 | .@"packed" => { | ||
| 24962 | const byte_offset = std.math.divExact(u32, @abs(@as(i32, actual_parent_ptr_info.packed_offset.bit_offset) + | ||
| 24963 | (if (mod.typeToStruct(parent_ty)) |struct_obj| mod.structPackedFieldBitOffset(struct_obj, field_index) else 0) - | ||
| 24964 | actual_field_ptr_info.packed_offset.bit_offset), 8) catch | ||
| 24965 | return sema.fail(block, inst_src, "pointer bit-offset mismatch", .{}); | ||
| 24966 | actual_parent_ptr_info.flags.alignment = actual_field_ptr_info.flags.alignment.minStrict(if (byte_offset > 0) | ||
| 24967 | Alignment.fromLog2Units(@ctz(byte_offset)) | ||
| 24968 | else | ||
| 24969 | actual_field_ptr_info.flags.alignment); | ||
| 24970 | }, | ||
| 24971 | } | ||
| 24917 | 24972 | ||
| 24918 | if (try sema.resolveDefinedValue(block, src, casted_field_ptr)) |field_ptr_val| { | 24973 | const actual_field_ptr_ty = try sema.ptrType(actual_field_ptr_info); |
| 24974 | const casted_field_ptr = try sema.coerce(block, actual_field_ptr_ty, field_ptr, field_ptr_src); | ||
| 24975 | const actual_parent_ptr_ty = try sema.ptrType(actual_parent_ptr_info); | ||
| 24976 | const result = if (try sema.resolveDefinedValue(block, field_ptr_src, casted_field_ptr)) |field_ptr_val| result: { | ||
| 24919 | const field = switch (ip.indexToKey(field_ptr_val.toIntern())) { | 24977 | const field = switch (ip.indexToKey(field_ptr_val.toIntern())) { |
| 24920 | .ptr => |ptr| switch (ptr.addr) { | 24978 | .ptr => |ptr| switch (ptr.addr) { |
| 24921 | .field => |field| field, | 24979 | .field => |field| field, |
| 24922 | else => null, | 24980 | else => null, |
| 24923 | }, | 24981 | }, |
| 24924 | else => null, | 24982 | else => null, |
| 24925 | } orelse return sema.fail(block, ptr_src, "pointer value not based on parent struct", .{}); | 24983 | } orelse return sema.fail(block, field_ptr_src, "pointer value not based on parent struct", .{}); |
| 24926 | 24984 | ||
| 24927 | if (field.index != field_index) { | 24985 | if (field.index != field_index) { |
| 24928 | return sema.fail(block, src, "field '{}' has index '{d}' but pointer value is index '{d}' of struct '{}'", .{ | 24986 | return sema.fail(block, inst_src, "field '{}' has index '{d}' but pointer value is index '{d}' of struct '{}'", .{ |
| 24929 | field_name.fmt(ip), field_index, field.index, parent_ty.fmt(sema.mod), | 24987 | field_name.fmt(ip), field_index, field.index, parent_ty.fmt(sema.mod), |
| 24930 | }); | 24988 | }); |
| 24931 | } | 24989 | } |
| 24932 | return Air.internedToRef(field.base); | 24990 | break :result try sema.coerce(block, actual_parent_ptr_ty, Air.internedToRef(field.base), inst_src); |
| 24933 | } | 24991 | } else result: { |
| 24934 | 24992 | try sema.requireRuntimeBlock(block, inst_src, field_ptr_src); | |
| 24935 | try sema.requireRuntimeBlock(block, src, ptr_src); | 24993 | try sema.queueFullTypeResolution(parent_ty); |
| 24936 | try sema.queueFullTypeResolution(result_ptr); | 24994 | break :result try block.addInst(.{ |
| 24937 | return block.addInst(.{ | 24995 | .tag = .field_parent_ptr, |
| 24938 | .tag = .field_parent_ptr, | 24996 | .data = .{ .ty_pl = .{ |
| 24939 | .data = .{ .ty_pl = .{ | 24997 | .ty = Air.internedToRef(actual_parent_ptr_ty.toIntern()), |
| 24940 | .ty = Air.internedToRef(result_ptr.toIntern()), | 24998 | .payload = try block.sema.addExtra(Air.FieldParentPtr{ |
| 24941 | .payload = try block.sema.addExtra(Air.FieldParentPtr{ | 24999 | .field_ptr = casted_field_ptr, |
| 24942 | .field_ptr = casted_field_ptr, | 25000 | .field_index = @intCast(field_index), |
| 24943 | .field_index = @intCast(field_index), | 25001 | }), |
| 24944 | }), | 25002 | } }, |
| 24945 | } }, | 25003 | }); |
| 24946 | }); | 25004 | }; |
| 25005 | return sema.ptrCastFull(block, flags, inst_src, result, inst_src, parent_ptr_ty, "@fieldParentPtr"); | ||
| 24947 | } | 25006 | } |
| 24948 | 25007 | ||
| 24949 | fn zirMinMax( | 25008 | fn zirMinMax( |
| ... | @@ -27837,7 +27896,7 @@ fn structFieldPtrByIndex( | ... | @@ -27837,7 +27896,7 @@ fn structFieldPtrByIndex( |
| 27837 | const elem_size_bits = Type.fromInterned(ptr_ty_data.child).bitSize(mod); | 27896 | const elem_size_bits = Type.fromInterned(ptr_ty_data.child).bitSize(mod); |
| 27838 | if (elem_size_bytes * 8 == elem_size_bits) { | 27897 | if (elem_size_bytes * 8 == elem_size_bits) { |
| 27839 | const byte_offset = ptr_ty_data.packed_offset.bit_offset / 8; | 27898 | const byte_offset = ptr_ty_data.packed_offset.bit_offset / 8; |
| 27840 | const new_align: Alignment = @enumFromInt(@ctz(byte_offset | parent_align.toByteUnitsOptional().?)); | 27899 | const new_align: Alignment = @enumFromInt(@ctz(byte_offset | parent_align.toByteUnits().?)); |
| 27841 | assert(new_align != .none); | 27900 | assert(new_align != .none); |
| 27842 | ptr_ty_data.flags.alignment = new_align; | 27901 | ptr_ty_data.flags.alignment = new_align; |
| 27843 | ptr_ty_data.packed_offset = .{ .host_size = 0, .bit_offset = 0 }; | 27902 | ptr_ty_data.packed_offset = .{ .host_size = 0, .bit_offset = 0 }; |
| ... | @@ -29132,7 +29191,7 @@ fn coerceExtra( | ... | @@ -29132,7 +29191,7 @@ fn coerceExtra( |
| 29132 | .addr = .{ .int = if (dest_info.flags.alignment != .none) | 29191 | .addr = .{ .int = if (dest_info.flags.alignment != .none) |
| 29133 | (try mod.intValue( | 29192 | (try mod.intValue( |
| 29134 | Type.usize, | 29193 | Type.usize, |
| 29135 | dest_info.flags.alignment.toByteUnitsOptional().?, | 29194 | dest_info.flags.alignment.toByteUnits().?, |
| 29136 | )).toIntern() | 29195 | )).toIntern() |
| 29137 | else | 29196 | else |
| 29138 | try mod.intern_pool.getCoercedInts( | 29197 | try mod.intern_pool.getCoercedInts( |
| ... | @@ -29800,7 +29859,7 @@ const InMemoryCoercionResult = union(enum) { | ... | @@ -29800,7 +29859,7 @@ const InMemoryCoercionResult = union(enum) { |
| 29800 | }, | 29859 | }, |
| 29801 | .ptr_alignment => |pair| { | 29860 | .ptr_alignment => |pair| { |
| 29802 | try sema.errNote(block, src, msg, "pointer alignment '{d}' cannot cast into pointer alignment '{d}'", .{ | 29861 | try sema.errNote(block, src, msg, "pointer alignment '{d}' cannot cast into pointer alignment '{d}'", .{ |
| 29803 | pair.actual.toByteUnits(0), pair.wanted.toByteUnits(0), | 29862 | pair.actual.toByteUnits() orelse 0, pair.wanted.toByteUnits() orelse 0, |
| 29804 | }); | 29863 | }); |
| 29805 | break; | 29864 | break; |
| 29806 | }, | 29865 | }, |
| ... | @@ -36066,7 +36125,7 @@ fn resolveUnionLayout(sema: *Sema, ty: Type) CompileError!void { | ... | @@ -36066,7 +36125,7 @@ fn resolveUnionLayout(sema: *Sema, ty: Type) CompileError!void { |
| 36066 | // alignment is greater. | 36125 | // alignment is greater. |
| 36067 | var size: u64 = 0; | 36126 | var size: u64 = 0; |
| 36068 | var padding: u32 = 0; | 36127 | var padding: u32 = 0; |
| 36069 | if (tag_align.compare(.gte, max_align)) { | 36128 | if (tag_align.order(max_align).compare(.gte)) { |
| 36070 | // {Tag, Payload} | 36129 | // {Tag, Payload} |
| 36071 | size += tag_size; | 36130 | size += tag_size; |
| 36072 | size = max_align.forward(size); | 36131 | size = max_align.forward(size); |
| ... | @@ -36077,7 +36136,10 @@ fn resolveUnionLayout(sema: *Sema, ty: Type) CompileError!void { | ... | @@ -36077,7 +36136,10 @@ fn resolveUnionLayout(sema: *Sema, ty: Type) CompileError!void { |
| 36077 | } else { | 36136 | } else { |
| 36078 | // {Payload, Tag} | 36137 | // {Payload, Tag} |
| 36079 | size += max_size; | 36138 | size += max_size; |
| 36080 | size = tag_align.forward(size); | 36139 | size = switch (mod.getTarget().ofmt) { |
| 36140 | .c => max_align, | ||
| 36141 | else => tag_align, | ||
| 36142 | }.forward(size); | ||
| 36081 | size += tag_size; | 36143 | size += tag_size; |
| 36082 | const prev_size = size; | 36144 | const prev_size = size; |
| 36083 | size = max_align.forward(size); | 36145 | size = max_align.forward(size); |
src/Value.zig+8-8| ... | @@ -176,7 +176,7 @@ pub fn toBigIntAdvanced( | ... | @@ -176,7 +176,7 @@ pub fn toBigIntAdvanced( |
| 176 | if (opt_sema) |sema| try sema.resolveTypeLayout(Type.fromInterned(ty)); | 176 | if (opt_sema) |sema| try sema.resolveTypeLayout(Type.fromInterned(ty)); |
| 177 | const x = switch (int.storage) { | 177 | const x = switch (int.storage) { |
| 178 | else => unreachable, | 178 | else => unreachable, |
| 179 | .lazy_align => Type.fromInterned(ty).abiAlignment(mod).toByteUnits(0), | 179 | .lazy_align => Type.fromInterned(ty).abiAlignment(mod).toByteUnits() orelse 0, |
| 180 | .lazy_size => Type.fromInterned(ty).abiSize(mod), | 180 | .lazy_size => Type.fromInterned(ty).abiSize(mod), |
| 181 | }; | 181 | }; |
| 182 | return BigIntMutable.init(&space.limbs, x).toConst(); | 182 | return BigIntMutable.init(&space.limbs, x).toConst(); |
| ... | @@ -237,9 +237,9 @@ pub fn getUnsignedIntAdvanced(val: Value, mod: *Module, opt_sema: ?*Sema) !?u64 | ... | @@ -237,9 +237,9 @@ pub fn getUnsignedIntAdvanced(val: Value, mod: *Module, opt_sema: ?*Sema) !?u64 |
| 237 | .u64 => |x| x, | 237 | .u64 => |x| x, |
| 238 | .i64 => |x| std.math.cast(u64, x), | 238 | .i64 => |x| std.math.cast(u64, x), |
| 239 | .lazy_align => |ty| if (opt_sema) |sema| | 239 | .lazy_align => |ty| if (opt_sema) |sema| |
| 240 | (try Type.fromInterned(ty).abiAlignmentAdvanced(mod, .{ .sema = sema })).scalar.toByteUnits(0) | 240 | (try Type.fromInterned(ty).abiAlignmentAdvanced(mod, .{ .sema = sema })).scalar.toByteUnits() orelse 0 |
| 241 | else | 241 | else |
| 242 | Type.fromInterned(ty).abiAlignment(mod).toByteUnits(0), | 242 | Type.fromInterned(ty).abiAlignment(mod).toByteUnits() orelse 0, |
| 243 | .lazy_size => |ty| if (opt_sema) |sema| | 243 | .lazy_size => |ty| if (opt_sema) |sema| |
| 244 | (try Type.fromInterned(ty).abiSizeAdvanced(mod, .{ .sema = sema })).scalar | 244 | (try Type.fromInterned(ty).abiSizeAdvanced(mod, .{ .sema = sema })).scalar |
| 245 | else | 245 | else |
| ... | @@ -289,7 +289,7 @@ pub fn toSignedInt(val: Value, mod: *Module) i64 { | ... | @@ -289,7 +289,7 @@ pub fn toSignedInt(val: Value, mod: *Module) i64 { |
| 289 | .big_int => |big_int| big_int.to(i64) catch unreachable, | 289 | .big_int => |big_int| big_int.to(i64) catch unreachable, |
| 290 | .i64 => |x| x, | 290 | .i64 => |x| x, |
| 291 | .u64 => |x| @intCast(x), | 291 | .u64 => |x| @intCast(x), |
| 292 | .lazy_align => |ty| @intCast(Type.fromInterned(ty).abiAlignment(mod).toByteUnits(0)), | 292 | .lazy_align => |ty| @intCast(Type.fromInterned(ty).abiAlignment(mod).toByteUnits() orelse 0), |
| 293 | .lazy_size => |ty| @intCast(Type.fromInterned(ty).abiSize(mod)), | 293 | .lazy_size => |ty| @intCast(Type.fromInterned(ty).abiSize(mod)), |
| 294 | }, | 294 | }, |
| 295 | else => unreachable, | 295 | else => unreachable, |
| ... | @@ -497,7 +497,7 @@ pub fn writeToPackedMemory( | ... | @@ -497,7 +497,7 @@ pub fn writeToPackedMemory( |
| 497 | inline .u64, .i64 => |int| std.mem.writeVarPackedInt(buffer, bit_offset, bits, int, endian), | 497 | inline .u64, .i64 => |int| std.mem.writeVarPackedInt(buffer, bit_offset, bits, int, endian), |
| 498 | .big_int => |bigint| bigint.writePackedTwosComplement(buffer, bit_offset, bits, endian), | 498 | .big_int => |bigint| bigint.writePackedTwosComplement(buffer, bit_offset, bits, endian), |
| 499 | .lazy_align => |lazy_align| { | 499 | .lazy_align => |lazy_align| { |
| 500 | const num = Type.fromInterned(lazy_align).abiAlignment(mod).toByteUnits(0); | 500 | const num = Type.fromInterned(lazy_align).abiAlignment(mod).toByteUnits() orelse 0; |
| 501 | std.mem.writeVarPackedInt(buffer, bit_offset, bits, num, endian); | 501 | std.mem.writeVarPackedInt(buffer, bit_offset, bits, num, endian); |
| 502 | }, | 502 | }, |
| 503 | .lazy_size => |lazy_size| { | 503 | .lazy_size => |lazy_size| { |
| ... | @@ -890,7 +890,7 @@ pub fn toFloat(val: Value, comptime T: type, mod: *Module) T { | ... | @@ -890,7 +890,7 @@ pub fn toFloat(val: Value, comptime T: type, mod: *Module) T { |
| 890 | } | 890 | } |
| 891 | return @floatFromInt(x); | 891 | return @floatFromInt(x); |
| 892 | }, | 892 | }, |
| 893 | .lazy_align => |ty| @floatFromInt(Type.fromInterned(ty).abiAlignment(mod).toByteUnits(0)), | 893 | .lazy_align => |ty| @floatFromInt(Type.fromInterned(ty).abiAlignment(mod).toByteUnits() orelse 0), |
| 894 | .lazy_size => |ty| @floatFromInt(Type.fromInterned(ty).abiSize(mod)), | 894 | .lazy_size => |ty| @floatFromInt(Type.fromInterned(ty).abiSize(mod)), |
| 895 | }, | 895 | }, |
| 896 | .float => |float| switch (float.storage) { | 896 | .float => |float| switch (float.storage) { |
| ... | @@ -1529,9 +1529,9 @@ pub fn floatFromIntScalar(val: Value, float_ty: Type, mod: *Module, opt_sema: ?* | ... | @@ -1529,9 +1529,9 @@ pub fn floatFromIntScalar(val: Value, float_ty: Type, mod: *Module, opt_sema: ?* |
| 1529 | }, | 1529 | }, |
| 1530 | inline .u64, .i64 => |x| floatFromIntInner(x, float_ty, mod), | 1530 | inline .u64, .i64 => |x| floatFromIntInner(x, float_ty, mod), |
| 1531 | .lazy_align => |ty| if (opt_sema) |sema| { | 1531 | .lazy_align => |ty| if (opt_sema) |sema| { |
| 1532 | return floatFromIntInner((try Type.fromInterned(ty).abiAlignmentAdvanced(mod, .{ .sema = sema })).scalar.toByteUnits(0), float_ty, mod); | 1532 | return floatFromIntInner((try Type.fromInterned(ty).abiAlignmentAdvanced(mod, .{ .sema = sema })).scalar.toByteUnits() orelse 0, float_ty, mod); |
| 1533 | } else { | 1533 | } else { |
| 1534 | return floatFromIntInner(Type.fromInterned(ty).abiAlignment(mod).toByteUnits(0), float_ty, mod); | 1534 | return floatFromIntInner(Type.fromInterned(ty).abiAlignment(mod).toByteUnits() orelse 0, float_ty, mod); |
| 1535 | }, | 1535 | }, |
| 1536 | .lazy_size => |ty| if (opt_sema) |sema| { | 1536 | .lazy_size => |ty| if (opt_sema) |sema| { |
| 1537 | return floatFromIntInner((try Type.fromInterned(ty).abiSizeAdvanced(mod, .{ .sema = sema })).scalar, float_ty, mod); | 1537 | return floatFromIntInner((try Type.fromInterned(ty).abiSizeAdvanced(mod, .{ .sema = sema })).scalar, float_ty, mod); |
src/arch/wasm/CodeGen.zig+15-15| ... | @@ -1296,7 +1296,7 @@ fn genFunc(func: *CodeGen) InnerError!void { | ... | @@ -1296,7 +1296,7 @@ fn genFunc(func: *CodeGen) InnerError!void { |
| 1296 | // subtract it from the current stack pointer | 1296 | // subtract it from the current stack pointer |
| 1297 | try prologue.append(.{ .tag = .i32_sub, .data = .{ .tag = {} } }); | 1297 | try prologue.append(.{ .tag = .i32_sub, .data = .{ .tag = {} } }); |
| 1298 | // Get negative stack aligment | 1298 | // Get negative stack aligment |
| 1299 | try prologue.append(.{ .tag = .i32_const, .data = .{ .imm32 = @as(i32, @intCast(func.stack_alignment.toByteUnitsOptional().?)) * -1 } }); | 1299 | try prologue.append(.{ .tag = .i32_const, .data = .{ .imm32 = @as(i32, @intCast(func.stack_alignment.toByteUnits().?)) * -1 } }); |
| 1300 | // Bitwise-and the value to get the new stack pointer to ensure the pointers are aligned with the abi alignment | 1300 | // Bitwise-and the value to get the new stack pointer to ensure the pointers are aligned with the abi alignment |
| 1301 | try prologue.append(.{ .tag = .i32_and, .data = .{ .tag = {} } }); | 1301 | try prologue.append(.{ .tag = .i32_and, .data = .{ .tag = {} } }); |
| 1302 | // store the current stack pointer as the bottom, which will be used to calculate all stack pointer offsets | 1302 | // store the current stack pointer as the bottom, which will be used to calculate all stack pointer offsets |
| ... | @@ -2107,7 +2107,7 @@ fn airRet(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -2107,7 +2107,7 @@ fn airRet(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 2107 | }); | 2107 | }); |
| 2108 | try func.addMemArg(Mir.Inst.Tag.fromOpcode(opcode), .{ | 2108 | try func.addMemArg(Mir.Inst.Tag.fromOpcode(opcode), .{ |
| 2109 | .offset = operand.offset(), | 2109 | .offset = operand.offset(), |
| 2110 | .alignment = @intCast(scalar_type.abiAlignment(mod).toByteUnitsOptional().?), | 2110 | .alignment = @intCast(scalar_type.abiAlignment(mod).toByteUnits().?), |
| 2111 | }); | 2111 | }); |
| 2112 | }, | 2112 | }, |
| 2113 | else => try func.emitWValue(operand), | 2113 | else => try func.emitWValue(operand), |
| ... | @@ -2384,7 +2384,7 @@ fn store(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerE | ... | @@ -2384,7 +2384,7 @@ fn store(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerE |
| 2384 | try func.mir_extra.appendSlice(func.gpa, &[_]u32{ | 2384 | try func.mir_extra.appendSlice(func.gpa, &[_]u32{ |
| 2385 | std.wasm.simdOpcode(.v128_store), | 2385 | std.wasm.simdOpcode(.v128_store), |
| 2386 | offset + lhs.offset(), | 2386 | offset + lhs.offset(), |
| 2387 | @intCast(ty.abiAlignment(mod).toByteUnits(0)), | 2387 | @intCast(ty.abiAlignment(mod).toByteUnits() orelse 0), |
| 2388 | }); | 2388 | }); |
| 2389 | return func.addInst(.{ .tag = .simd_prefix, .data = .{ .payload = extra_index } }); | 2389 | return func.addInst(.{ .tag = .simd_prefix, .data = .{ .payload = extra_index } }); |
| 2390 | }, | 2390 | }, |
| ... | @@ -2440,7 +2440,7 @@ fn store(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerE | ... | @@ -2440,7 +2440,7 @@ fn store(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerE |
| 2440 | Mir.Inst.Tag.fromOpcode(opcode), | 2440 | Mir.Inst.Tag.fromOpcode(opcode), |
| 2441 | .{ | 2441 | .{ |
| 2442 | .offset = offset + lhs.offset(), | 2442 | .offset = offset + lhs.offset(), |
| 2443 | .alignment = @intCast(ty.abiAlignment(mod).toByteUnitsOptional().?), | 2443 | .alignment = @intCast(ty.abiAlignment(mod).toByteUnits().?), |
| 2444 | }, | 2444 | }, |
| 2445 | ); | 2445 | ); |
| 2446 | } | 2446 | } |
| ... | @@ -2500,7 +2500,7 @@ fn load(func: *CodeGen, operand: WValue, ty: Type, offset: u32) InnerError!WValu | ... | @@ -2500,7 +2500,7 @@ fn load(func: *CodeGen, operand: WValue, ty: Type, offset: u32) InnerError!WValu |
| 2500 | try func.mir_extra.appendSlice(func.gpa, &[_]u32{ | 2500 | try func.mir_extra.appendSlice(func.gpa, &[_]u32{ |
| 2501 | std.wasm.simdOpcode(.v128_load), | 2501 | std.wasm.simdOpcode(.v128_load), |
| 2502 | offset + operand.offset(), | 2502 | offset + operand.offset(), |
| 2503 | @intCast(ty.abiAlignment(mod).toByteUnitsOptional().?), | 2503 | @intCast(ty.abiAlignment(mod).toByteUnits().?), |
| 2504 | }); | 2504 | }); |
| 2505 | try func.addInst(.{ .tag = .simd_prefix, .data = .{ .payload = extra_index } }); | 2505 | try func.addInst(.{ .tag = .simd_prefix, .data = .{ .payload = extra_index } }); |
| 2506 | return WValue{ .stack = {} }; | 2506 | return WValue{ .stack = {} }; |
| ... | @@ -2518,7 +2518,7 @@ fn load(func: *CodeGen, operand: WValue, ty: Type, offset: u32) InnerError!WValu | ... | @@ -2518,7 +2518,7 @@ fn load(func: *CodeGen, operand: WValue, ty: Type, offset: u32) InnerError!WValu |
| 2518 | Mir.Inst.Tag.fromOpcode(opcode), | 2518 | Mir.Inst.Tag.fromOpcode(opcode), |
| 2519 | .{ | 2519 | .{ |
| 2520 | .offset = offset + operand.offset(), | 2520 | .offset = offset + operand.offset(), |
| 2521 | .alignment = @intCast(ty.abiAlignment(mod).toByteUnitsOptional().?), | 2521 | .alignment = @intCast(ty.abiAlignment(mod).toByteUnits().?), |
| 2522 | }, | 2522 | }, |
| 2523 | ); | 2523 | ); |
| 2524 | 2524 | ||
| ... | @@ -3456,7 +3456,7 @@ fn intStorageAsI32(storage: InternPool.Key.Int.Storage, mod: *Module) i32 { | ... | @@ -3456,7 +3456,7 @@ fn intStorageAsI32(storage: InternPool.Key.Int.Storage, mod: *Module) i32 { |
| 3456 | .i64 => |x| @as(i32, @intCast(x)), | 3456 | .i64 => |x| @as(i32, @intCast(x)), |
| 3457 | .u64 => |x| @as(i32, @bitCast(@as(u32, @intCast(x)))), | 3457 | .u64 => |x| @as(i32, @bitCast(@as(u32, @intCast(x)))), |
| 3458 | .big_int => unreachable, | 3458 | .big_int => unreachable, |
| 3459 | .lazy_align => |ty| @as(i32, @bitCast(@as(u32, @intCast(Type.fromInterned(ty).abiAlignment(mod).toByteUnits(0))))), | 3459 | .lazy_align => |ty| @as(i32, @bitCast(@as(u32, @intCast(Type.fromInterned(ty).abiAlignment(mod).toByteUnits() orelse 0)))), |
| 3460 | .lazy_size => |ty| @as(i32, @bitCast(@as(u32, @intCast(Type.fromInterned(ty).abiSize(mod))))), | 3460 | .lazy_size => |ty| @as(i32, @bitCast(@as(u32, @intCast(Type.fromInterned(ty).abiSize(mod))))), |
| 3461 | }; | 3461 | }; |
| 3462 | } | 3462 | } |
| ... | @@ -4204,7 +4204,7 @@ fn airIsErr(func: *CodeGen, inst: Air.Inst.Index, opcode: wasm.Opcode) InnerErro | ... | @@ -4204,7 +4204,7 @@ fn airIsErr(func: *CodeGen, inst: Air.Inst.Index, opcode: wasm.Opcode) InnerErro |
| 4204 | if (pl_ty.hasRuntimeBitsIgnoreComptime(mod)) { | 4204 | if (pl_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 4205 | try func.addMemArg(.i32_load16_u, .{ | 4205 | try func.addMemArg(.i32_load16_u, .{ |
| 4206 | .offset = operand.offset() + @as(u32, @intCast(errUnionErrorOffset(pl_ty, mod))), | 4206 | .offset = operand.offset() + @as(u32, @intCast(errUnionErrorOffset(pl_ty, mod))), |
| 4207 | .alignment = @intCast(Type.anyerror.abiAlignment(mod).toByteUnitsOptional().?), | 4207 | .alignment = @intCast(Type.anyerror.abiAlignment(mod).toByteUnits().?), |
| 4208 | }); | 4208 | }); |
| 4209 | } | 4209 | } |
| 4210 | 4210 | ||
| ... | @@ -5141,7 +5141,7 @@ fn airSplat(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -5141,7 +5141,7 @@ fn airSplat(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 5141 | try func.mir_extra.appendSlice(func.gpa, &[_]u32{ | 5141 | try func.mir_extra.appendSlice(func.gpa, &[_]u32{ |
| 5142 | opcode, | 5142 | opcode, |
| 5143 | operand.offset(), | 5143 | operand.offset(), |
| 5144 | @intCast(elem_ty.abiAlignment(mod).toByteUnitsOptional().?), | 5144 | @intCast(elem_ty.abiAlignment(mod).toByteUnits().?), |
| 5145 | }); | 5145 | }); |
| 5146 | try func.addInst(.{ .tag = .simd_prefix, .data = .{ .payload = extra_index } }); | 5146 | try func.addInst(.{ .tag = .simd_prefix, .data = .{ .payload = extra_index } }); |
| 5147 | try func.addLabel(.local_set, result.local.value); | 5147 | try func.addLabel(.local_set, result.local.value); |
| ... | @@ -6552,7 +6552,7 @@ fn lowerTry( | ... | @@ -6552,7 +6552,7 @@ fn lowerTry( |
| 6552 | const err_offset = @as(u32, @intCast(errUnionErrorOffset(pl_ty, mod))); | 6552 | const err_offset = @as(u32, @intCast(errUnionErrorOffset(pl_ty, mod))); |
| 6553 | try func.addMemArg(.i32_load16_u, .{ | 6553 | try func.addMemArg(.i32_load16_u, .{ |
| 6554 | .offset = err_union.offset() + err_offset, | 6554 | .offset = err_union.offset() + err_offset, |
| 6555 | .alignment = @intCast(Type.anyerror.abiAlignment(mod).toByteUnitsOptional().?), | 6555 | .alignment = @intCast(Type.anyerror.abiAlignment(mod).toByteUnits().?), |
| 6556 | }); | 6556 | }); |
| 6557 | } | 6557 | } |
| 6558 | try func.addTag(.i32_eqz); | 6558 | try func.addTag(.i32_eqz); |
| ... | @@ -7499,7 +7499,7 @@ fn airCmpxchg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -7499,7 +7499,7 @@ fn airCmpxchg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 7499 | else => |size| return func.fail("TODO: implement `@cmpxchg` for types with abi size '{d}'", .{size}), | 7499 | else => |size| return func.fail("TODO: implement `@cmpxchg` for types with abi size '{d}'", .{size}), |
| 7500 | }, .{ | 7500 | }, .{ |
| 7501 | .offset = ptr_operand.offset(), | 7501 | .offset = ptr_operand.offset(), |
| 7502 | .alignment = @intCast(ty.abiAlignment(mod).toByteUnitsOptional().?), | 7502 | .alignment = @intCast(ty.abiAlignment(mod).toByteUnits().?), |
| 7503 | }); | 7503 | }); |
| 7504 | try func.addLabel(.local_tee, val_local.local.value); | 7504 | try func.addLabel(.local_tee, val_local.local.value); |
| 7505 | _ = try func.cmp(.stack, expected_val, ty, .eq); | 7505 | _ = try func.cmp(.stack, expected_val, ty, .eq); |
| ... | @@ -7561,7 +7561,7 @@ fn airAtomicLoad(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -7561,7 +7561,7 @@ fn airAtomicLoad(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 7561 | try func.emitWValue(ptr); | 7561 | try func.emitWValue(ptr); |
| 7562 | try func.addAtomicMemArg(tag, .{ | 7562 | try func.addAtomicMemArg(tag, .{ |
| 7563 | .offset = ptr.offset(), | 7563 | .offset = ptr.offset(), |
| 7564 | .alignment = @intCast(ty.abiAlignment(mod).toByteUnitsOptional().?), | 7564 | .alignment = @intCast(ty.abiAlignment(mod).toByteUnits().?), |
| 7565 | }); | 7565 | }); |
| 7566 | } else { | 7566 | } else { |
| 7567 | _ = try func.load(ptr, ty, 0); | 7567 | _ = try func.load(ptr, ty, 0); |
| ... | @@ -7622,7 +7622,7 @@ fn airAtomicRmw(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -7622,7 +7622,7 @@ fn airAtomicRmw(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 7622 | }, | 7622 | }, |
| 7623 | .{ | 7623 | .{ |
| 7624 | .offset = ptr.offset(), | 7624 | .offset = ptr.offset(), |
| 7625 | .alignment = @intCast(ty.abiAlignment(mod).toByteUnitsOptional().?), | 7625 | .alignment = @intCast(ty.abiAlignment(mod).toByteUnits().?), |
| 7626 | }, | 7626 | }, |
| 7627 | ); | 7627 | ); |
| 7628 | const select_res = try func.allocLocal(ty); | 7628 | const select_res = try func.allocLocal(ty); |
| ... | @@ -7682,7 +7682,7 @@ fn airAtomicRmw(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -7682,7 +7682,7 @@ fn airAtomicRmw(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 7682 | }; | 7682 | }; |
| 7683 | try func.addAtomicMemArg(tag, .{ | 7683 | try func.addAtomicMemArg(tag, .{ |
| 7684 | .offset = ptr.offset(), | 7684 | .offset = ptr.offset(), |
| 7685 | .alignment = @intCast(ty.abiAlignment(mod).toByteUnitsOptional().?), | 7685 | .alignment = @intCast(ty.abiAlignment(mod).toByteUnits().?), |
| 7686 | }); | 7686 | }); |
| 7687 | const result = try WValue.toLocal(.stack, func, ty); | 7687 | const result = try WValue.toLocal(.stack, func, ty); |
| 7688 | return func.finishAir(inst, result, &.{ pl_op.operand, extra.operand }); | 7688 | return func.finishAir(inst, result, &.{ pl_op.operand, extra.operand }); |
| ... | @@ -7781,7 +7781,7 @@ fn airAtomicStore(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -7781,7 +7781,7 @@ fn airAtomicStore(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 7781 | try func.lowerToStack(operand); | 7781 | try func.lowerToStack(operand); |
| 7782 | try func.addAtomicMemArg(tag, .{ | 7782 | try func.addAtomicMemArg(tag, .{ |
| 7783 | .offset = ptr.offset(), | 7783 | .offset = ptr.offset(), |
| 7784 | .alignment = @intCast(ty.abiAlignment(mod).toByteUnitsOptional().?), | 7784 | .alignment = @intCast(ty.abiAlignment(mod).toByteUnits().?), |
| 7785 | }); | 7785 | }); |
| 7786 | } else { | 7786 | } else { |
| 7787 | try func.store(ptr, operand, ty, 0); | 7787 | try func.store(ptr, operand, ty, 0); |
src/arch/x86_64/CodeGen.zig+21-22| ... | @@ -7920,17 +7920,14 @@ fn fieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, index: u32 | ... | @@ -7920,17 +7920,14 @@ fn fieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, index: u32 |
| 7920 | const mod = self.bin_file.comp.module.?; | 7920 | const mod = self.bin_file.comp.module.?; |
| 7921 | const ptr_field_ty = self.typeOfIndex(inst); | 7921 | const ptr_field_ty = self.typeOfIndex(inst); |
| 7922 | const ptr_container_ty = self.typeOf(operand); | 7922 | const ptr_container_ty = self.typeOf(operand); |
| 7923 | const ptr_container_ty_info = ptr_container_ty.ptrInfo(mod); | ||
| 7924 | const container_ty = ptr_container_ty.childType(mod); | 7923 | const container_ty = ptr_container_ty.childType(mod); |
| 7925 | 7924 | ||
| 7926 | const field_offset: i32 = if (mod.typeToPackedStruct(container_ty)) |struct_obj| | 7925 | const field_off: i32 = switch (container_ty.containerLayout(mod)) { |
| 7927 | if (ptr_field_ty.ptrInfo(mod).packed_offset.host_size == 0) | 7926 | .auto, .@"extern" => @intCast(container_ty.structFieldOffset(index, mod)), |
| 7928 | @divExact(mod.structPackedFieldBitOffset(struct_obj, index) + | 7927 | .@"packed" => @divExact(@as(i32, ptr_container_ty.ptrInfo(mod).packed_offset.bit_offset) + |
| 7929 | ptr_container_ty_info.packed_offset.bit_offset, 8) | 7928 | (if (mod.typeToStruct(container_ty)) |struct_obj| mod.structPackedFieldBitOffset(struct_obj, index) else 0) - |
| 7930 | else | 7929 | ptr_field_ty.ptrInfo(mod).packed_offset.bit_offset, 8), |
| 7931 | 0 | 7930 | }; |
| 7932 | else | ||
| 7933 | @intCast(container_ty.structFieldOffset(index, mod)); | ||
| 7934 | 7931 | ||
| 7935 | const src_mcv = try self.resolveInst(operand); | 7932 | const src_mcv = try self.resolveInst(operand); |
| 7936 | const dst_mcv = if (switch (src_mcv) { | 7933 | const dst_mcv = if (switch (src_mcv) { |
| ... | @@ -7938,7 +7935,7 @@ fn fieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, index: u32 | ... | @@ -7938,7 +7935,7 @@ fn fieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, index: u32 |
| 7938 | .register, .register_offset => self.reuseOperand(inst, operand, 0, src_mcv), | 7935 | .register, .register_offset => self.reuseOperand(inst, operand, 0, src_mcv), |
| 7939 | else => false, | 7936 | else => false, |
| 7940 | }) src_mcv else try self.copyToRegisterWithInstTracking(inst, ptr_field_ty, src_mcv); | 7937 | }) src_mcv else try self.copyToRegisterWithInstTracking(inst, ptr_field_ty, src_mcv); |
| 7941 | return dst_mcv.offset(field_offset); | 7938 | return dst_mcv.offset(field_off); |
| 7942 | } | 7939 | } |
| 7943 | 7940 | ||
| 7944 | fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { | 7941 | fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { |
| ... | @@ -7958,11 +7955,8 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -7958,11 +7955,8 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { |
| 7958 | 7955 | ||
| 7959 | const src_mcv = try self.resolveInst(operand); | 7956 | const src_mcv = try self.resolveInst(operand); |
| 7960 | const field_off: u32 = switch (container_ty.containerLayout(mod)) { | 7957 | const field_off: u32 = switch (container_ty.containerLayout(mod)) { |
| 7961 | .auto, .@"extern" => @intCast(container_ty.structFieldOffset(index, mod) * 8), | 7958 | .auto, .@"extern" => @intCast(container_ty.structFieldOffset(extra.field_index, mod) * 8), |
| 7962 | .@"packed" => if (mod.typeToStruct(container_ty)) |struct_type| | 7959 | .@"packed" => if (mod.typeToStruct(container_ty)) |struct_obj| mod.structPackedFieldBitOffset(struct_obj, extra.field_index) else 0, |
| 7963 | mod.structPackedFieldBitOffset(struct_type, index) | ||
| 7964 | else | ||
| 7965 | 0, | ||
| 7966 | }; | 7960 | }; |
| 7967 | 7961 | ||
| 7968 | switch (src_mcv) { | 7962 | switch (src_mcv) { |
| ... | @@ -8239,7 +8233,12 @@ fn airFieldParentPtr(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -8239,7 +8233,12 @@ fn airFieldParentPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 8239 | 8233 | ||
| 8240 | const inst_ty = self.typeOfIndex(inst); | 8234 | const inst_ty = self.typeOfIndex(inst); |
| 8241 | const parent_ty = inst_ty.childType(mod); | 8235 | const parent_ty = inst_ty.childType(mod); |
| 8242 | const field_offset: i32 = @intCast(parent_ty.structFieldOffset(extra.field_index, mod)); | 8236 | const field_off: i32 = switch (parent_ty.containerLayout(mod)) { |
| 8237 | .auto, .@"extern" => @intCast(parent_ty.structFieldOffset(extra.field_index, mod)), | ||
| 8238 | .@"packed" => @divExact(@as(i32, inst_ty.ptrInfo(mod).packed_offset.bit_offset) + | ||
| 8239 | (if (mod.typeToStruct(parent_ty)) |struct_obj| mod.structPackedFieldBitOffset(struct_obj, extra.field_index) else 0) - | ||
| 8240 | self.typeOf(extra.field_ptr).ptrInfo(mod).packed_offset.bit_offset, 8), | ||
| 8241 | }; | ||
| 8243 | 8242 | ||
| 8244 | const src_mcv = try self.resolveInst(extra.field_ptr); | 8243 | const src_mcv = try self.resolveInst(extra.field_ptr); |
| 8245 | const dst_mcv = if (src_mcv.isRegisterOffset() and | 8244 | const dst_mcv = if (src_mcv.isRegisterOffset() and |
| ... | @@ -8247,7 +8246,7 @@ fn airFieldParentPtr(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -8247,7 +8246,7 @@ fn airFieldParentPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 8247 | src_mcv | 8246 | src_mcv |
| 8248 | else | 8247 | else |
| 8249 | try self.copyToRegisterWithInstTracking(inst, inst_ty, src_mcv); | 8248 | try self.copyToRegisterWithInstTracking(inst, inst_ty, src_mcv); |
| 8250 | const result = dst_mcv.offset(-field_offset); | 8249 | const result = dst_mcv.offset(-field_off); |
| 8251 | return self.finishAir(inst, result, .{ extra.field_ptr, .none, .none }); | 8250 | return self.finishAir(inst, result, .{ extra.field_ptr, .none, .none }); |
| 8252 | } | 8251 | } |
| 8253 | 8252 | ||
| ... | @@ -17950,7 +17949,7 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -17950,7 +17949,7 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void { |
| 17950 | .Struct => { | 17949 | .Struct => { |
| 17951 | const frame_index = try self.allocFrameIndex(FrameAlloc.initSpill(result_ty, mod)); | 17950 | const frame_index = try self.allocFrameIndex(FrameAlloc.initSpill(result_ty, mod)); |
| 17952 | if (result_ty.containerLayout(mod) == .@"packed") { | 17951 | if (result_ty.containerLayout(mod) == .@"packed") { |
| 17953 | const struct_type = mod.typeToStruct(result_ty).?; | 17952 | const struct_obj = mod.typeToStruct(result_ty).?; |
| 17954 | try self.genInlineMemset( | 17953 | try self.genInlineMemset( |
| 17955 | .{ .lea_frame = .{ .index = frame_index } }, | 17954 | .{ .lea_frame = .{ .index = frame_index } }, |
| 17956 | .{ .immediate = 0 }, | 17955 | .{ .immediate = 0 }, |
| ... | @@ -17971,7 +17970,7 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -17971,7 +17970,7 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void { |
| 17971 | } | 17970 | } |
| 17972 | const elem_abi_size: u32 = @intCast(elem_ty.abiSize(mod)); | 17971 | const elem_abi_size: u32 = @intCast(elem_ty.abiSize(mod)); |
| 17973 | const elem_abi_bits = elem_abi_size * 8; | 17972 | const elem_abi_bits = elem_abi_size * 8; |
| 17974 | const elem_off = mod.structPackedFieldBitOffset(struct_type, elem_i); | 17973 | const elem_off = mod.structPackedFieldBitOffset(struct_obj, elem_i); |
| 17975 | const elem_byte_off: i32 = @intCast(elem_off / elem_abi_bits * elem_abi_size); | 17974 | const elem_byte_off: i32 = @intCast(elem_off / elem_abi_bits * elem_abi_size); |
| 17976 | const elem_bit_off = elem_off % elem_abi_bits; | 17975 | const elem_bit_off = elem_off % elem_abi_bits; |
| 17977 | const elem_mcv = try self.resolveInst(elem); | 17976 | const elem_mcv = try self.resolveInst(elem); |
| ... | @@ -18959,7 +18958,7 @@ fn resolveCallingConventionValues( | ... | @@ -18959,7 +18958,7 @@ fn resolveCallingConventionValues( |
| 18959 | 18958 | ||
| 18960 | const param_size: u31 = @intCast(ty.abiSize(mod)); | 18959 | const param_size: u31 = @intCast(ty.abiSize(mod)); |
| 18961 | const param_align: u31 = | 18960 | const param_align: u31 = |
| 18962 | @intCast(@max(ty.abiAlignment(mod).toByteUnitsOptional().?, 8)); | 18961 | @intCast(@max(ty.abiAlignment(mod).toByteUnits().?, 8)); |
| 18963 | result.stack_byte_count = | 18962 | result.stack_byte_count = |
| 18964 | mem.alignForward(u31, result.stack_byte_count, param_align); | 18963 | mem.alignForward(u31, result.stack_byte_count, param_align); |
| 18965 | arg.* = .{ .load_frame = .{ | 18964 | arg.* = .{ .load_frame = .{ |
| ... | @@ -19003,7 +19002,7 @@ fn resolveCallingConventionValues( | ... | @@ -19003,7 +19002,7 @@ fn resolveCallingConventionValues( |
| 19003 | continue; | 19002 | continue; |
| 19004 | } | 19003 | } |
| 19005 | const param_size: u31 = @intCast(ty.abiSize(mod)); | 19004 | const param_size: u31 = @intCast(ty.abiSize(mod)); |
| 19006 | const param_align: u31 = @intCast(ty.abiAlignment(mod).toByteUnitsOptional().?); | 19005 | const param_align: u31 = @intCast(ty.abiAlignment(mod).toByteUnits().?); |
| 19007 | result.stack_byte_count = | 19006 | result.stack_byte_count = |
| 19008 | mem.alignForward(u31, result.stack_byte_count, param_align); | 19007 | mem.alignForward(u31, result.stack_byte_count, param_align); |
| 19009 | arg.* = .{ .load_frame = .{ | 19008 | arg.* = .{ .load_frame = .{ |
| ... | @@ -19096,7 +19095,7 @@ fn splitType(self: *Self, ty: Type) ![2]Type { | ... | @@ -19096,7 +19095,7 @@ fn splitType(self: *Self, ty: Type) ![2]Type { |
| 19096 | .integer => switch (part_i) { | 19095 | .integer => switch (part_i) { |
| 19097 | 0 => Type.u64, | 19096 | 0 => Type.u64, |
| 19098 | 1 => part: { | 19097 | 1 => part: { |
| 19099 | const elem_size = ty.abiAlignment(mod).minStrict(.@"8").toByteUnitsOptional().?; | 19098 | const elem_size = ty.abiAlignment(mod).minStrict(.@"8").toByteUnits().?; |
| 19100 | const elem_ty = try mod.intType(.unsigned, @intCast(elem_size * 8)); | 19099 | const elem_ty = try mod.intType(.unsigned, @intCast(elem_size * 8)); |
| 19101 | break :part switch (@divExact(ty.abiSize(mod) - 8, elem_size)) { | 19100 | break :part switch (@divExact(ty.abiSize(mod) - 8, elem_size)) { |
| 19102 | 1 => elem_ty, | 19101 | 1 => elem_ty, |
src/arch/x86_64/Encoding.zig+2-3| ... | @@ -848,9 +848,8 @@ const mnemonic_to_encodings_map = init: { | ... | @@ -848,9 +848,8 @@ const mnemonic_to_encodings_map = init: { |
| 848 | const final_storage = data_storage; | 848 | const final_storage = data_storage; |
| 849 | var final_map: [mnemonic_count][]const Data = .{&.{}} ** mnemonic_count; | 849 | var final_map: [mnemonic_count][]const Data = .{&.{}} ** mnemonic_count; |
| 850 | storage_i = 0; | 850 | storage_i = 0; |
| 851 | for (&final_map, mnemonic_map) |*value, wip_value| { | 851 | for (&final_map, mnemonic_map) |*final_value, value| { |
| 852 | value.ptr = final_storage[storage_i..].ptr; | 852 | final_value.* = final_storage[storage_i..][0..value.len]; |
| 853 | value.len = wip_value.len; | ||
| 854 | storage_i += value.len; | 853 | storage_i += value.len; |
| 855 | } | 854 | } |
| 856 | break :init final_map; | 855 | break :init final_map; |
src/codegen.zig+3-3| ... | @@ -548,7 +548,7 @@ pub fn generateSymbol( | ... | @@ -548,7 +548,7 @@ pub fn generateSymbol( |
| 548 | } | 548 | } |
| 549 | 549 | ||
| 550 | const size = struct_type.size(ip).*; | 550 | const size = struct_type.size(ip).*; |
| 551 | const alignment = struct_type.flagsPtr(ip).alignment.toByteUnitsOptional().?; | 551 | const alignment = struct_type.flagsPtr(ip).alignment.toByteUnits().?; |
| 552 | 552 | ||
| 553 | const padding = math.cast( | 553 | const padding = math.cast( |
| 554 | usize, | 554 | usize, |
| ... | @@ -893,12 +893,12 @@ fn genDeclRef( | ... | @@ -893,12 +893,12 @@ fn genDeclRef( |
| 893 | // TODO this feels clunky. Perhaps we should check for it in `genTypedValue`? | 893 | // TODO this feels clunky. Perhaps we should check for it in `genTypedValue`? |
| 894 | if (ty.castPtrToFn(zcu)) |fn_ty| { | 894 | if (ty.castPtrToFn(zcu)) |fn_ty| { |
| 895 | if (zcu.typeToFunc(fn_ty).?.is_generic) { | 895 | if (zcu.typeToFunc(fn_ty).?.is_generic) { |
| 896 | return GenResult.mcv(.{ .immediate = fn_ty.abiAlignment(zcu).toByteUnitsOptional().? }); | 896 | return GenResult.mcv(.{ .immediate = fn_ty.abiAlignment(zcu).toByteUnits().? }); |
| 897 | } | 897 | } |
| 898 | } else if (ty.zigTypeTag(zcu) == .Pointer) { | 898 | } else if (ty.zigTypeTag(zcu) == .Pointer) { |
| 899 | const elem_ty = ty.elemType2(zcu); | 899 | const elem_ty = ty.elemType2(zcu); |
| 900 | if (!elem_ty.hasRuntimeBits(zcu)) { | 900 | if (!elem_ty.hasRuntimeBits(zcu)) { |
| 901 | return GenResult.mcv(.{ .immediate = elem_ty.abiAlignment(zcu).toByteUnitsOptional().? }); | 901 | return GenResult.mcv(.{ .immediate = elem_ty.abiAlignment(zcu).toByteUnits().? }); |
| 902 | } | 902 | } |
| 903 | } | 903 | } |
| 904 | 904 |
src/codegen/c.zig+1907-1884| ... | @@ -5,12 +5,13 @@ const mem = std.mem; | ... | @@ -5,12 +5,13 @@ const mem = std.mem; |
| 5 | const log = std.log.scoped(.c); | 5 | const log = std.log.scoped(.c); |
| 6 | 6 | ||
| 7 | const link = @import("../link.zig"); | 7 | const link = @import("../link.zig"); |
| 8 | const Module = @import("../Module.zig"); | 8 | const Zcu = @import("../Module.zig"); |
| 9 | const Module = @import("../Package/Module.zig"); | ||
| 9 | const Compilation = @import("../Compilation.zig"); | 10 | const Compilation = @import("../Compilation.zig"); |
| 10 | const Value = @import("../Value.zig"); | 11 | const Value = @import("../Value.zig"); |
| 11 | const Type = @import("../type.zig").Type; | 12 | const Type = @import("../type.zig").Type; |
| 12 | const C = link.File.C; | 13 | const C = link.File.C; |
| 13 | const Decl = Module.Decl; | 14 | const Decl = Zcu.Decl; |
| 14 | const trace = @import("../tracy.zig").trace; | 15 | const trace = @import("../tracy.zig").trace; |
| 15 | const LazySrcLoc = std.zig.LazySrcLoc; | 16 | const LazySrcLoc = std.zig.LazySrcLoc; |
| 16 | const Air = @import("../Air.zig"); | 17 | const Air = @import("../Air.zig"); |
| ... | @@ -21,7 +22,7 @@ const Alignment = InternPool.Alignment; | ... | @@ -21,7 +22,7 @@ const Alignment = InternPool.Alignment; |
| 21 | const BigIntLimb = std.math.big.Limb; | 22 | const BigIntLimb = std.math.big.Limb; |
| 22 | const BigInt = std.math.big.int; | 23 | const BigInt = std.math.big.int; |
| 23 | 24 | ||
| 24 | pub const CType = @import("c/type.zig").CType; | 25 | pub const CType = @import("c/Type.zig"); |
| 25 | 26 | ||
| 26 | pub const CValue = union(enum) { | 27 | pub const CValue = union(enum) { |
| 27 | none: void, | 28 | none: void, |
| ... | @@ -30,7 +31,7 @@ pub const CValue = union(enum) { | ... | @@ -30,7 +31,7 @@ pub const CValue = union(enum) { |
| 30 | /// Address of a local. | 31 | /// Address of a local. |
| 31 | local_ref: LocalIndex, | 32 | local_ref: LocalIndex, |
| 32 | /// A constant instruction, to be rendered inline. | 33 | /// A constant instruction, to be rendered inline. |
| 33 | constant: InternPool.Index, | 34 | constant: Value, |
| 34 | /// Index into the parameters | 35 | /// Index into the parameters |
| 35 | arg: usize, | 36 | arg: usize, |
| 36 | /// The array field of a parameter | 37 | /// The array field of a parameter |
| ... | @@ -61,7 +62,7 @@ pub const LazyFnKey = union(enum) { | ... | @@ -61,7 +62,7 @@ pub const LazyFnKey = union(enum) { |
| 61 | never_inline: InternPool.DeclIndex, | 62 | never_inline: InternPool.DeclIndex, |
| 62 | }; | 63 | }; |
| 63 | pub const LazyFnValue = struct { | 64 | pub const LazyFnValue = struct { |
| 64 | fn_name: []const u8, | 65 | fn_name: CType.String, |
| 65 | data: Data, | 66 | data: Data, |
| 66 | 67 | ||
| 67 | pub const Data = union { | 68 | pub const Data = union { |
| ... | @@ -72,18 +73,20 @@ pub const LazyFnValue = struct { | ... | @@ -72,18 +73,20 @@ pub const LazyFnValue = struct { |
| 72 | }; | 73 | }; |
| 73 | pub const LazyFnMap = std.AutoArrayHashMapUnmanaged(LazyFnKey, LazyFnValue); | 74 | pub const LazyFnMap = std.AutoArrayHashMapUnmanaged(LazyFnKey, LazyFnValue); |
| 74 | 75 | ||
| 75 | const LoopDepth = u16; | ||
| 76 | const Local = struct { | 76 | const Local = struct { |
| 77 | cty_idx: CType.Index, | 77 | ctype: CType, |
| 78 | alignas: CType.AlignAs, | 78 | flags: packed struct(u32) { |
| 79 | alignas: CType.AlignAs, | ||
| 80 | _: u20 = undefined, | ||
| 81 | }, | ||
| 79 | 82 | ||
| 80 | pub fn getType(local: Local) LocalType { | 83 | pub fn getType(local: Local) LocalType { |
| 81 | return .{ .cty_idx = local.cty_idx, .alignas = local.alignas }; | 84 | return .{ .ctype = local.ctype, .alignas = local.flags.alignas }; |
| 82 | } | 85 | } |
| 83 | }; | 86 | }; |
| 84 | 87 | ||
| 85 | const LocalIndex = u16; | 88 | const LocalIndex = u16; |
| 86 | const LocalType = struct { cty_idx: CType.Index, alignas: CType.AlignAs }; | 89 | const LocalType = struct { ctype: CType, alignas: CType.AlignAs }; |
| 87 | const LocalsList = std.AutoArrayHashMapUnmanaged(LocalIndex, void); | 90 | const LocalsList = std.AutoArrayHashMapUnmanaged(LocalIndex, void); |
| 88 | const LocalsMap = std.AutoArrayHashMapUnmanaged(LocalType, LocalsList); | 91 | const LocalsMap = std.AutoArrayHashMapUnmanaged(LocalType, LocalsList); |
| 89 | 92 | ||
| ... | @@ -190,6 +193,7 @@ const reserved_idents = std.ComptimeStringMap(void, .{ | ... | @@ -190,6 +193,7 @@ const reserved_idents = std.ComptimeStringMap(void, .{ |
| 190 | .{ "switch", {} }, | 193 | .{ "switch", {} }, |
| 191 | .{ "thread_local", {} }, | 194 | .{ "thread_local", {} }, |
| 192 | .{ "typedef", {} }, | 195 | .{ "typedef", {} }, |
| 196 | .{ "typeof", {} }, | ||
| 193 | .{ "uint16_t", {} }, | 197 | .{ "uint16_t", {} }, |
| 194 | .{ "uint32_t", {} }, | 198 | .{ "uint32_t", {} }, |
| 195 | .{ "uint64_t", {} }, | 199 | .{ "uint64_t", {} }, |
| ... | @@ -300,30 +304,32 @@ pub const Function = struct { | ... | @@ -300,30 +304,32 @@ pub const Function = struct { |
| 300 | const gop = try f.value_map.getOrPut(ref); | 304 | const gop = try f.value_map.getOrPut(ref); |
| 301 | if (gop.found_existing) return gop.value_ptr.*; | 305 | if (gop.found_existing) return gop.value_ptr.*; |
| 302 | 306 | ||
| 303 | const mod = f.object.dg.module; | 307 | const zcu = f.object.dg.zcu; |
| 304 | const val = (try f.air.value(ref, mod)).?; | 308 | const val = (try f.air.value(ref, zcu)).?; |
| 305 | const ty = f.typeOf(ref); | 309 | const ty = f.typeOf(ref); |
| 306 | 310 | ||
| 307 | const result: CValue = if (lowersToArray(ty, mod)) result: { | 311 | const result: CValue = if (lowersToArray(ty, zcu)) result: { |
| 308 | const writer = f.object.codeHeaderWriter(); | 312 | const writer = f.object.codeHeaderWriter(); |
| 309 | const alignment: Alignment = .none; | 313 | const decl_c_value = try f.allocLocalValue(.{ |
| 310 | const decl_c_value = try f.allocLocalValue(ty, alignment); | 314 | .ctype = try f.ctypeFromType(ty, .complete), |
| 315 | .alignas = CType.AlignAs.fromAbiAlignment(ty.abiAlignment(zcu)), | ||
| 316 | }); | ||
| 311 | const gpa = f.object.dg.gpa; | 317 | const gpa = f.object.dg.gpa; |
| 312 | try f.allocs.put(gpa, decl_c_value.new_local, false); | 318 | try f.allocs.put(gpa, decl_c_value.new_local, false); |
| 313 | try writer.writeAll("static "); | 319 | try writer.writeAll("static "); |
| 314 | try f.object.dg.renderTypeAndName(writer, ty, decl_c_value, Const, alignment, .complete); | 320 | try f.object.dg.renderTypeAndName(writer, ty, decl_c_value, Const, .none, .complete); |
| 315 | try writer.writeAll(" = "); | 321 | try writer.writeAll(" = "); |
| 316 | try f.object.dg.renderValue(writer, ty, val, .StaticInitializer); | 322 | try f.object.dg.renderValue(writer, val, .StaticInitializer); |
| 317 | try writer.writeAll(";\n "); | 323 | try writer.writeAll(";\n "); |
| 318 | break :result decl_c_value; | 324 | break :result decl_c_value; |
| 319 | } else .{ .constant = val.toIntern() }; | 325 | } else .{ .constant = val }; |
| 320 | 326 | ||
| 321 | gop.value_ptr.* = result; | 327 | gop.value_ptr.* = result; |
| 322 | return result; | 328 | return result; |
| 323 | } | 329 | } |
| 324 | 330 | ||
| 325 | fn wantSafety(f: *Function) bool { | 331 | fn wantSafety(f: *Function) bool { |
| 326 | return switch (f.object.dg.module.optimizeMode()) { | 332 | return switch (f.object.dg.zcu.optimizeMode()) { |
| 327 | .Debug, .ReleaseSafe => true, | 333 | .Debug, .ReleaseSafe => true, |
| 328 | .ReleaseFast, .ReleaseSmall => false, | 334 | .ReleaseFast, .ReleaseSmall => false, |
| 329 | }; | 335 | }; |
| ... | @@ -332,159 +338,174 @@ pub const Function = struct { | ... | @@ -332,159 +338,174 @@ pub const Function = struct { |
| 332 | /// Skips the reuse logic. This function should be used for any persistent allocation, i.e. | 338 | /// Skips the reuse logic. This function should be used for any persistent allocation, i.e. |
| 333 | /// those which go into `allocs`. This function does not add the resulting local into `allocs`; | 339 | /// those which go into `allocs`. This function does not add the resulting local into `allocs`; |
| 334 | /// that responsibility lies with the caller. | 340 | /// that responsibility lies with the caller. |
| 335 | fn allocLocalValue(f: *Function, ty: Type, alignment: Alignment) !CValue { | 341 | fn allocLocalValue(f: *Function, local_type: LocalType) !CValue { |
| 336 | const mod = f.object.dg.module; | 342 | try f.locals.ensureUnusedCapacity(f.object.dg.gpa, 1); |
| 337 | const gpa = f.object.dg.gpa; | 343 | defer f.locals.appendAssumeCapacity(.{ |
| 338 | try f.locals.append(gpa, .{ | 344 | .ctype = local_type.ctype, |
| 339 | .cty_idx = try f.typeToIndex(ty, .complete), | 345 | .flags = .{ .alignas = local_type.alignas }, |
| 340 | .alignas = CType.AlignAs.init(alignment, ty.abiAlignment(mod)), | ||
| 341 | }); | 346 | }); |
| 342 | return .{ .new_local = @intCast(f.locals.items.len - 1) }; | 347 | return .{ .new_local = @intCast(f.locals.items.len) }; |
| 343 | } | 348 | } |
| 344 | 349 | ||
| 345 | fn allocLocal(f: *Function, inst: ?Air.Inst.Index, ty: Type) !CValue { | 350 | fn allocLocal(f: *Function, inst: ?Air.Inst.Index, ty: Type) !CValue { |
| 346 | const result = try f.allocAlignedLocal(ty, .{}, .none); | 351 | return f.allocAlignedLocal(inst, .{ |
| 347 | if (inst) |i| { | 352 | .ctype = try f.ctypeFromType(ty, .complete), |
| 348 | log.debug("%{d}: allocating t{d}", .{ i, result.new_local }); | 353 | .alignas = CType.AlignAs.fromAbiAlignment(ty.abiAlignment(f.object.dg.zcu)), |
| 349 | } else { | 354 | }); |
| 350 | log.debug("allocating t{d}", .{result.new_local}); | ||
| 351 | } | ||
| 352 | return result; | ||
| 353 | } | 355 | } |
| 354 | 356 | ||
| 355 | /// Only allocates the local; does not print anything. Will attempt to re-use locals, so should | 357 | /// Only allocates the local; does not print anything. Will attempt to re-use locals, so should |
| 356 | /// not be used for persistent locals (i.e. those in `allocs`). | 358 | /// not be used for persistent locals (i.e. those in `allocs`). |
| 357 | fn allocAlignedLocal(f: *Function, ty: Type, _: CQualifiers, alignment: Alignment) !CValue { | 359 | fn allocAlignedLocal(f: *Function, inst: ?Air.Inst.Index, local_type: LocalType) !CValue { |
| 358 | const mod = f.object.dg.module; | 360 | const result: CValue = result: { |
| 359 | if (f.free_locals_map.getPtr(.{ | 361 | if (f.free_locals_map.getPtr(local_type)) |locals_list| { |
| 360 | .cty_idx = try f.typeToIndex(ty, .complete), | 362 | if (locals_list.popOrNull()) |local_entry| { |
| 361 | .alignas = CType.AlignAs.init(alignment, ty.abiAlignment(mod)), | 363 | break :result .{ .new_local = local_entry.key }; |
| 362 | })) |locals_list| { | 364 | } |
| 363 | if (locals_list.popOrNull()) |local_entry| { | ||
| 364 | return .{ .new_local = local_entry.key }; | ||
| 365 | } | 365 | } |
| 366 | break :result try f.allocLocalValue(local_type); | ||
| 367 | }; | ||
| 368 | if (inst) |i| { | ||
| 369 | log.debug("%{d}: allocating t{d}", .{ i, result.new_local }); | ||
| 370 | } else { | ||
| 371 | log.debug("allocating t{d}", .{result.new_local}); | ||
| 366 | } | 372 | } |
| 367 | 373 | return result; | |
| 368 | return try f.allocLocalValue(ty, alignment); | ||
| 369 | } | 374 | } |
| 370 | 375 | ||
| 371 | fn writeCValue(f: *Function, w: anytype, c_value: CValue, location: ValueRenderLocation) !void { | 376 | fn writeCValue(f: *Function, w: anytype, c_value: CValue, location: ValueRenderLocation) !void { |
| 372 | switch (c_value) { | 377 | switch (c_value) { |
| 373 | .constant => |val| try f.object.dg.renderValue( | 378 | .none => unreachable, |
| 374 | w, | 379 | .new_local, .local => |i| try w.print("t{d}", .{i}), |
| 375 | Type.fromInterned(f.object.dg.module.intern_pool.typeOf(val)), | 380 | .local_ref => |i| { |
| 376 | Value.fromInterned(val), | 381 | const local = &f.locals.items[i]; |
| 377 | location, | 382 | if (local.flags.alignas.abiOrder().compare(.lt)) { |
| 378 | ), | 383 | const gpa = f.object.dg.gpa; |
| 379 | .undef => |ty| try f.object.dg.renderValue(w, ty, Value.undef, location), | 384 | const mod = f.object.dg.mod; |
| 385 | const ctype_pool = &f.object.dg.ctype_pool; | ||
| 386 | |||
| 387 | try w.writeByte('('); | ||
| 388 | try f.renderCType(w, try ctype_pool.getPointer(gpa, .{ | ||
| 389 | .elem_ctype = try ctype_pool.fromIntInfo(gpa, .{ | ||
| 390 | .signedness = .unsigned, | ||
| 391 | .bits = @min( | ||
| 392 | local.flags.alignas.toByteUnits(), | ||
| 393 | mod.resolved_target.result.maxIntAlignment(), | ||
| 394 | ) * 8, | ||
| 395 | }, mod, .forward), | ||
| 396 | })); | ||
| 397 | try w.writeByte(')'); | ||
| 398 | } | ||
| 399 | try w.print("&t{d}", .{i}); | ||
| 400 | }, | ||
| 401 | .constant => |val| try f.object.dg.renderValue(w, val, location), | ||
| 402 | .arg => |i| try w.print("a{d}", .{i}), | ||
| 403 | .arg_array => |i| try f.writeCValueMember(w, .{ .arg = i }, .{ .identifier = "array" }), | ||
| 404 | .undef => |ty| try f.object.dg.renderUndefValue(w, ty, location), | ||
| 380 | else => try f.object.dg.writeCValue(w, c_value), | 405 | else => try f.object.dg.writeCValue(w, c_value), |
| 381 | } | 406 | } |
| 382 | } | 407 | } |
| 383 | 408 | ||
| 384 | fn writeCValueDeref(f: *Function, w: anytype, c_value: CValue) !void { | 409 | fn writeCValueDeref(f: *Function, w: anytype, c_value: CValue) !void { |
| 385 | switch (c_value) { | 410 | switch (c_value) { |
| 386 | .constant => |val| { | 411 | .none => unreachable, |
| 412 | .new_local, .local, .constant => { | ||
| 387 | try w.writeAll("(*"); | 413 | try w.writeAll("(*"); |
| 388 | try f.object.dg.renderValue( | 414 | try f.writeCValue(w, c_value, .Other); |
| 389 | w, | 415 | try w.writeByte(')'); |
| 390 | Type.fromInterned(f.object.dg.module.intern_pool.typeOf(val)), | 416 | }, |
| 391 | Value.fromInterned(val), | 417 | .local_ref => |i| try w.print("t{d}", .{i}), |
| 392 | .Other, | 418 | .arg => |i| try w.print("(*a{d})", .{i}), |
| 393 | ); | 419 | .arg_array => |i| { |
| 420 | try w.writeAll("(*"); | ||
| 421 | try f.writeCValueMember(w, .{ .arg = i }, .{ .identifier = "array" }); | ||
| 394 | try w.writeByte(')'); | 422 | try w.writeByte(')'); |
| 395 | }, | 423 | }, |
| 396 | else => try f.object.dg.writeCValueDeref(w, c_value), | 424 | else => try f.object.dg.writeCValueDeref(w, c_value), |
| 397 | } | 425 | } |
| 398 | } | 426 | } |
| 399 | 427 | ||
| 400 | fn writeCValueMember(f: *Function, w: anytype, c_value: CValue, member: CValue) !void { | 428 | fn writeCValueMember( |
| 429 | f: *Function, | ||
| 430 | writer: anytype, | ||
| 431 | c_value: CValue, | ||
| 432 | member: CValue, | ||
| 433 | ) error{ OutOfMemory, AnalysisFail }!void { | ||
| 401 | switch (c_value) { | 434 | switch (c_value) { |
| 402 | .constant => |val| { | 435 | .new_local, .local, .local_ref, .constant, .arg, .arg_array => { |
| 403 | try f.object.dg.renderValue( | 436 | try f.writeCValue(writer, c_value, .Other); |
| 404 | w, | 437 | try writer.writeByte('.'); |
| 405 | Type.fromInterned(f.object.dg.module.intern_pool.typeOf(val)), | 438 | try f.writeCValue(writer, member, .Other); |
| 406 | Value.fromInterned(val), | ||
| 407 | .Other, | ||
| 408 | ); | ||
| 409 | try w.writeByte('.'); | ||
| 410 | try f.writeCValue(w, member, .Other); | ||
| 411 | }, | 439 | }, |
| 412 | else => try f.object.dg.writeCValueMember(w, c_value, member), | 440 | else => return f.object.dg.writeCValueMember(writer, c_value, member), |
| 413 | } | 441 | } |
| 414 | } | 442 | } |
| 415 | 443 | ||
| 416 | fn writeCValueDerefMember(f: *Function, w: anytype, c_value: CValue, member: CValue) !void { | 444 | fn writeCValueDerefMember(f: *Function, writer: anytype, c_value: CValue, member: CValue) !void { |
| 417 | switch (c_value) { | 445 | switch (c_value) { |
| 418 | .constant => |val| { | 446 | .new_local, .local, .arg, .arg_array => { |
| 419 | try w.writeByte('('); | 447 | try f.writeCValue(writer, c_value, .Other); |
| 420 | try f.object.dg.renderValue( | 448 | try writer.writeAll("->"); |
| 421 | w, | 449 | }, |
| 422 | Type.fromInterned(f.object.dg.module.intern_pool.typeOf(val)), | 450 | .constant => { |
| 423 | Value.fromInterned(val), | 451 | try writer.writeByte('('); |
| 424 | .Other, | 452 | try f.writeCValue(writer, c_value, .Other); |
| 425 | ); | 453 | try writer.writeAll(")->"); |
| 426 | try w.writeAll(")->"); | ||
| 427 | try f.writeCValue(w, member, .Other); | ||
| 428 | }, | 454 | }, |
| 429 | else => try f.object.dg.writeCValueDerefMember(w, c_value, member), | 455 | .local_ref => { |
| 456 | try f.writeCValueDeref(writer, c_value); | ||
| 457 | try writer.writeByte('.'); | ||
| 458 | }, | ||
| 459 | else => return f.object.dg.writeCValueDerefMember(writer, c_value, member), | ||
| 430 | } | 460 | } |
| 461 | try f.writeCValue(writer, member, .Other); | ||
| 431 | } | 462 | } |
| 432 | 463 | ||
| 433 | fn fail(f: *Function, comptime format: []const u8, args: anytype) error{ AnalysisFail, OutOfMemory } { | 464 | fn fail(f: *Function, comptime format: []const u8, args: anytype) error{ AnalysisFail, OutOfMemory } { |
| 434 | return f.object.dg.fail(format, args); | 465 | return f.object.dg.fail(format, args); |
| 435 | } | 466 | } |
| 436 | 467 | ||
| 437 | fn indexToCType(f: *Function, idx: CType.Index) CType { | 468 | fn ctypeFromType(f: *Function, ty: Type, kind: CType.Kind) !CType { |
| 438 | return f.object.dg.indexToCType(idx); | 469 | return f.object.dg.ctypeFromType(ty, kind); |
| 439 | } | 470 | } |
| 440 | 471 | ||
| 441 | fn typeToIndex(f: *Function, ty: Type, kind: CType.Kind) !CType.Index { | 472 | fn byteSize(f: *Function, ctype: CType) u64 { |
| 442 | return f.object.dg.typeToIndex(ty, kind); | 473 | return f.object.dg.byteSize(ctype); |
| 443 | } | 474 | } |
| 444 | 475 | ||
| 445 | fn typeToCType(f: *Function, ty: Type, kind: CType.Kind) !CType { | 476 | fn renderType(f: *Function, w: anytype, ctype: Type) !void { |
| 446 | return f.object.dg.typeToCType(ty, kind); | 477 | return f.object.dg.renderType(w, ctype); |
| 447 | } | 478 | } |
| 448 | 479 | ||
| 449 | fn byteSize(f: *Function, cty: CType) u64 { | 480 | fn renderCType(f: *Function, w: anytype, ctype: CType) !void { |
| 450 | return f.object.dg.byteSize(cty); | 481 | return f.object.dg.renderCType(w, ctype); |
| 451 | } | ||
| 452 | |||
| 453 | fn renderType(f: *Function, w: anytype, t: Type) !void { | ||
| 454 | return f.object.dg.renderType(w, t); | ||
| 455 | } | ||
| 456 | |||
| 457 | fn renderCType(f: *Function, w: anytype, t: CType.Index) !void { | ||
| 458 | return f.object.dg.renderCType(w, t); | ||
| 459 | } | 482 | } |
| 460 | 483 | ||
| 461 | fn renderIntCast(f: *Function, w: anytype, dest_ty: Type, src: CValue, v: Vectorize, src_ty: Type, location: ValueRenderLocation) !void { | 484 | fn renderIntCast(f: *Function, w: anytype, dest_ty: Type, src: CValue, v: Vectorize, src_ty: Type, location: ValueRenderLocation) !void { |
| 462 | return f.object.dg.renderIntCast(w, dest_ty, .{ .c_value = .{ .f = f, .value = src, .v = v } }, src_ty, location); | 485 | return f.object.dg.renderIntCast(w, dest_ty, .{ .c_value = .{ .f = f, .value = src, .v = v } }, src_ty, location); |
| 463 | } | 486 | } |
| 464 | 487 | ||
| 465 | fn fmtIntLiteral(f: *Function, ty: Type, val: Value) !std.fmt.Formatter(formatIntLiteral) { | 488 | fn fmtIntLiteral(f: *Function, val: Value) !std.fmt.Formatter(formatIntLiteral) { |
| 466 | return f.object.dg.fmtIntLiteral(ty, val, .Other); | 489 | return f.object.dg.fmtIntLiteral(val, .Other); |
| 467 | } | 490 | } |
| 468 | 491 | ||
| 469 | fn getLazyFnName(f: *Function, key: LazyFnKey, data: LazyFnValue.Data) ![]const u8 { | 492 | fn getLazyFnName(f: *Function, key: LazyFnKey, data: LazyFnValue.Data) ![]const u8 { |
| 470 | const gpa = f.object.dg.gpa; | 493 | const gpa = f.object.dg.gpa; |
| 494 | const zcu = f.object.dg.zcu; | ||
| 495 | const ctype_pool = &f.object.dg.ctype_pool; | ||
| 496 | |||
| 471 | const gop = try f.lazy_fns.getOrPut(gpa, key); | 497 | const gop = try f.lazy_fns.getOrPut(gpa, key); |
| 472 | if (!gop.found_existing) { | 498 | if (!gop.found_existing) { |
| 473 | errdefer _ = f.lazy_fns.pop(); | 499 | errdefer _ = f.lazy_fns.pop(); |
| 474 | 500 | ||
| 475 | var promoted = f.object.dg.ctypes.promote(gpa); | ||
| 476 | defer f.object.dg.ctypes.demote(promoted); | ||
| 477 | const arena = promoted.arena.allocator(); | ||
| 478 | const mod = f.object.dg.module; | ||
| 479 | |||
| 480 | gop.value_ptr.* = .{ | 501 | gop.value_ptr.* = .{ |
| 481 | .fn_name = switch (key) { | 502 | .fn_name = switch (key) { |
| 482 | .tag_name, | 503 | .tag_name, |
| 483 | .never_tail, | 504 | .never_tail, |
| 484 | .never_inline, | 505 | .never_inline, |
| 485 | => |owner_decl| try std.fmt.allocPrint(arena, "zig_{s}_{}__{d}", .{ | 506 | => |owner_decl| try ctype_pool.fmt(gpa, "zig_{s}_{}__{d}", .{ |
| 486 | @tagName(key), | 507 | @tagName(key), |
| 487 | fmtIdent(mod.intern_pool.stringToSlice(mod.declPtr(owner_decl).name)), | 508 | fmtIdent(zcu.intern_pool.stringToSlice(zcu.declPtr(owner_decl).name)), |
| 488 | @intFromEnum(owner_decl), | 509 | @intFromEnum(owner_decl), |
| 489 | }), | 510 | }), |
| 490 | }, | 511 | }, |
| ... | @@ -495,7 +516,7 @@ pub const Function = struct { | ... | @@ -495,7 +516,7 @@ pub const Function = struct { |
| 495 | }, | 516 | }, |
| 496 | }; | 517 | }; |
| 497 | } | 518 | } |
| 498 | return gop.value_ptr.fn_name; | 519 | return gop.value_ptr.fn_name.slice(ctype_pool); |
| 499 | } | 520 | } |
| 500 | 521 | ||
| 501 | pub fn deinit(f: *Function) void { | 522 | pub fn deinit(f: *Function) void { |
| ... | @@ -506,21 +527,20 @@ pub const Function = struct { | ... | @@ -506,21 +527,20 @@ pub const Function = struct { |
| 506 | f.blocks.deinit(gpa); | 527 | f.blocks.deinit(gpa); |
| 507 | f.value_map.deinit(); | 528 | f.value_map.deinit(); |
| 508 | f.lazy_fns.deinit(gpa); | 529 | f.lazy_fns.deinit(gpa); |
| 509 | f.object.dg.ctypes.deinit(gpa); | ||
| 510 | } | 530 | } |
| 511 | 531 | ||
| 512 | fn typeOf(f: *Function, inst: Air.Inst.Ref) Type { | 532 | fn typeOf(f: *Function, inst: Air.Inst.Ref) Type { |
| 513 | const mod = f.object.dg.module; | 533 | const zcu = f.object.dg.zcu; |
| 514 | return f.air.typeOf(inst, &mod.intern_pool); | 534 | return f.air.typeOf(inst, &zcu.intern_pool); |
| 515 | } | 535 | } |
| 516 | 536 | ||
| 517 | fn typeOfIndex(f: *Function, inst: Air.Inst.Index) Type { | 537 | fn typeOfIndex(f: *Function, inst: Air.Inst.Index) Type { |
| 518 | const mod = f.object.dg.module; | 538 | const zcu = f.object.dg.zcu; |
| 519 | return f.air.typeOfIndex(inst, &mod.intern_pool); | 539 | return f.air.typeOfIndex(inst, &zcu.intern_pool); |
| 520 | } | 540 | } |
| 521 | }; | 541 | }; |
| 522 | 542 | ||
| 523 | /// This data is available when outputting .c code for a `Module`. | 543 | /// This data is available when outputting .c code for a `Zcu`. |
| 524 | /// It is not available when generating .h file. | 544 | /// It is not available when generating .h file. |
| 525 | pub const Object = struct { | 545 | pub const Object = struct { |
| 526 | dg: DeclGen, | 546 | dg: DeclGen, |
| ... | @@ -542,13 +562,15 @@ pub const Object = struct { | ... | @@ -542,13 +562,15 @@ pub const Object = struct { |
| 542 | /// This data is available both when outputting .c code and when outputting an .h file. | 562 | /// This data is available both when outputting .c code and when outputting an .h file. |
| 543 | pub const DeclGen = struct { | 563 | pub const DeclGen = struct { |
| 544 | gpa: mem.Allocator, | 564 | gpa: mem.Allocator, |
| 545 | module: *Module, | 565 | zcu: *Zcu, |
| 566 | mod: *Module, | ||
| 546 | pass: Pass, | 567 | pass: Pass, |
| 547 | is_naked_fn: bool, | 568 | is_naked_fn: bool, |
| 548 | /// This is a borrowed reference from `link.C`. | 569 | /// This is a borrowed reference from `link.C`. |
| 549 | fwd_decl: std.ArrayList(u8), | 570 | fwd_decl: std.ArrayList(u8), |
| 550 | error_msg: ?*Module.ErrorMsg, | 571 | error_msg: ?*Zcu.ErrorMsg, |
| 551 | ctypes: CType.Store, | 572 | ctype_pool: CType.Pool, |
| 573 | scratch: std.ArrayListUnmanaged(u32), | ||
| 552 | /// Keeps track of anonymous decls that need to be rendered before this | 574 | /// Keeps track of anonymous decls that need to be rendered before this |
| 553 | /// (named) Decl in the output C code. | 575 | /// (named) Decl in the output C code. |
| 554 | anon_decl_deps: std.AutoArrayHashMapUnmanaged(InternPool.Index, C.DeclBlock), | 576 | anon_decl_deps: std.AutoArrayHashMapUnmanaged(InternPool.Index, C.DeclBlock), |
| ... | @@ -566,75 +588,71 @@ pub const DeclGen = struct { | ... | @@ -566,75 +588,71 @@ pub const DeclGen = struct { |
| 566 | 588 | ||
| 567 | fn fail(dg: *DeclGen, comptime format: []const u8, args: anytype) error{ AnalysisFail, OutOfMemory } { | 589 | fn fail(dg: *DeclGen, comptime format: []const u8, args: anytype) error{ AnalysisFail, OutOfMemory } { |
| 568 | @setCold(true); | 590 | @setCold(true); |
| 569 | const mod = dg.module; | 591 | const zcu = dg.zcu; |
| 570 | const decl_index = dg.pass.decl; | 592 | const decl_index = dg.pass.decl; |
| 571 | const decl = mod.declPtr(decl_index); | 593 | const decl = zcu.declPtr(decl_index); |
| 572 | const src_loc = decl.srcLoc(mod); | 594 | const src_loc = decl.srcLoc(zcu); |
| 573 | dg.error_msg = try Module.ErrorMsg.create(dg.gpa, src_loc, format, args); | 595 | dg.error_msg = try Zcu.ErrorMsg.create(dg.gpa, src_loc, format, args); |
| 574 | return error.AnalysisFail; | 596 | return error.AnalysisFail; |
| 575 | } | 597 | } |
| 576 | 598 | ||
| 577 | fn renderAnonDeclValue( | 599 | fn renderAnonDeclValue( |
| 578 | dg: *DeclGen, | 600 | dg: *DeclGen, |
| 579 | writer: anytype, | 601 | writer: anytype, |
| 580 | ty: Type, | ||
| 581 | ptr_val: Value, | 602 | ptr_val: Value, |
| 582 | anon_decl: InternPool.Key.Ptr.Addr.AnonDecl, | 603 | anon_decl: InternPool.Key.Ptr.Addr.AnonDecl, |
| 583 | location: ValueRenderLocation, | 604 | location: ValueRenderLocation, |
| 584 | ) error{ OutOfMemory, AnalysisFail }!void { | 605 | ) error{ OutOfMemory, AnalysisFail }!void { |
| 585 | const mod = dg.module; | 606 | const zcu = dg.zcu; |
| 586 | const ip = &mod.intern_pool; | 607 | const ip = &zcu.intern_pool; |
| 587 | const decl_val = anon_decl.val; | 608 | const ctype_pool = &dg.ctype_pool; |
| 588 | const decl_ty = Type.fromInterned(ip.typeOf(decl_val)); | 609 | const decl_val = Value.fromInterned(anon_decl.val); |
| 610 | const decl_ty = decl_val.typeOf(zcu); | ||
| 589 | 611 | ||
| 590 | // Render an undefined pointer if we have a pointer to a zero-bit or comptime type. | 612 | // Render an undefined pointer if we have a pointer to a zero-bit or comptime type. |
| 591 | if (ty.isPtrAtRuntime(mod) and !decl_ty.isFnOrHasRuntimeBits(mod)) { | 613 | const ptr_ty = ptr_val.typeOf(zcu); |
| 592 | return dg.writeCValue(writer, .{ .undef = ty }); | 614 | if (ptr_ty.isPtrAtRuntime(zcu) and !decl_ty.isFnOrHasRuntimeBits(zcu)) { |
| 615 | return dg.writeCValue(writer, .{ .undef = ptr_ty }); | ||
| 593 | } | 616 | } |
| 594 | 617 | ||
| 595 | // Chase function values in order to be able to reference the original function. | 618 | // Chase function values in order to be able to reference the original function. |
| 596 | if (Value.fromInterned(decl_val).getFunction(mod)) |func| { | 619 | if (decl_val.getFunction(zcu)) |func| |
| 597 | _ = func; | 620 | return dg.renderDeclValue(writer, ptr_val, func.owner_decl, location); |
| 598 | _ = ptr_val; | 621 | if (decl_val.getExternFunc(zcu)) |extern_func| |
| 599 | _ = location; | 622 | return dg.renderDeclValue(writer, ptr_val, extern_func.decl, location); |
| 600 | @panic("TODO"); | ||
| 601 | } | ||
| 602 | if (Value.fromInterned(decl_val).getExternFunc(mod)) |extern_func| { | ||
| 603 | _ = extern_func; | ||
| 604 | _ = ptr_val; | ||
| 605 | _ = location; | ||
| 606 | @panic("TODO"); | ||
| 607 | } | ||
| 608 | 623 | ||
| 609 | assert(Value.fromInterned(decl_val).getVariable(mod) == null); | 624 | assert(decl_val.getVariable(zcu) == null); |
| 610 | 625 | ||
| 611 | // We shouldn't cast C function pointers as this is UB (when you call | 626 | // We shouldn't cast C function pointers as this is UB (when you call |
| 612 | // them). The analysis until now should ensure that the C function | 627 | // them). The analysis until now should ensure that the C function |
| 613 | // pointers are compatible. If they are not, then there is a bug | 628 | // pointers are compatible. If they are not, then there is a bug |
| 614 | // somewhere and we should let the C compiler tell us about it. | 629 | // somewhere and we should let the C compiler tell us about it. |
| 615 | const need_typecast = if (ty.castPtrToFn(mod)) |_| false else !ty.childType(mod).eql(decl_ty, mod); | 630 | const elem_ctype = (try dg.ctypeFromType(ptr_ty, .complete)).info(ctype_pool).pointer.elem_ctype; |
| 616 | if (need_typecast) { | 631 | const decl_ctype = try dg.ctypeFromType(decl_ty, .complete); |
| 632 | const need_cast = !elem_ctype.eql(decl_ctype) and | ||
| 633 | (elem_ctype.info(ctype_pool) != .function or decl_ctype.info(ctype_pool) != .function); | ||
| 634 | if (need_cast) { | ||
| 617 | try writer.writeAll("(("); | 635 | try writer.writeAll("(("); |
| 618 | try dg.renderType(writer, ty); | 636 | try dg.renderType(writer, ptr_ty); |
| 619 | try writer.writeByte(')'); | 637 | try writer.writeByte(')'); |
| 620 | } | 638 | } |
| 621 | try writer.writeByte('&'); | 639 | try writer.writeByte('&'); |
| 622 | try renderAnonDeclName(writer, decl_val); | 640 | try renderAnonDeclName(writer, decl_val); |
| 623 | if (need_typecast) try writer.writeByte(')'); | 641 | if (need_cast) try writer.writeByte(')'); |
| 624 | 642 | ||
| 625 | // Indicate that the anon decl should be rendered to the output so that | 643 | // Indicate that the anon decl should be rendered to the output so that |
| 626 | // our reference above is not undefined. | 644 | // our reference above is not undefined. |
| 627 | const ptr_type = ip.indexToKey(anon_decl.orig_ty).ptr_type; | 645 | const ptr_type = ip.indexToKey(anon_decl.orig_ty).ptr_type; |
| 628 | const gop = try dg.anon_decl_deps.getOrPut(dg.gpa, decl_val); | 646 | const gop = try dg.anon_decl_deps.getOrPut(dg.gpa, anon_decl.val); |
| 629 | if (!gop.found_existing) gop.value_ptr.* = .{}; | 647 | if (!gop.found_existing) gop.value_ptr.* = .{}; |
| 630 | 648 | ||
| 631 | // Only insert an alignment entry if the alignment is greater than ABI | 649 | // Only insert an alignment entry if the alignment is greater than ABI |
| 632 | // alignment. If there is already an entry, keep the greater alignment. | 650 | // alignment. If there is already an entry, keep the greater alignment. |
| 633 | const explicit_alignment = ptr_type.flags.alignment; | 651 | const explicit_alignment = ptr_type.flags.alignment; |
| 634 | if (explicit_alignment != .none) { | 652 | if (explicit_alignment != .none) { |
| 635 | const abi_alignment = Type.fromInterned(ptr_type.child).abiAlignment(mod); | 653 | const abi_alignment = Type.fromInterned(ptr_type.child).abiAlignment(zcu); |
| 636 | if (explicit_alignment.compareStrict(.gt, abi_alignment)) { | 654 | if (explicit_alignment.order(abi_alignment).compare(.gt)) { |
| 637 | const aligned_gop = try dg.aligned_anon_decls.getOrPut(dg.gpa, decl_val); | 655 | const aligned_gop = try dg.aligned_anon_decls.getOrPut(dg.gpa, anon_decl.val); |
| 638 | aligned_gop.value_ptr.* = if (aligned_gop.found_existing) | 656 | aligned_gop.value_ptr.* = if (aligned_gop.found_existing) |
| 639 | aligned_gop.value_ptr.maxStrict(explicit_alignment) | 657 | aligned_gop.value_ptr.maxStrict(explicit_alignment) |
| 640 | else | 658 | else |
| ... | @@ -646,41 +664,46 @@ pub const DeclGen = struct { | ... | @@ -646,41 +664,46 @@ pub const DeclGen = struct { |
| 646 | fn renderDeclValue( | 664 | fn renderDeclValue( |
| 647 | dg: *DeclGen, | 665 | dg: *DeclGen, |
| 648 | writer: anytype, | 666 | writer: anytype, |
| 649 | ty: Type, | ||
| 650 | val: Value, | 667 | val: Value, |
| 651 | decl_index: InternPool.DeclIndex, | 668 | decl_index: InternPool.DeclIndex, |
| 652 | location: ValueRenderLocation, | 669 | location: ValueRenderLocation, |
| 653 | ) error{ OutOfMemory, AnalysisFail }!void { | 670 | ) error{ OutOfMemory, AnalysisFail }!void { |
| 654 | const mod = dg.module; | 671 | const zcu = dg.zcu; |
| 655 | const decl = mod.declPtr(decl_index); | 672 | const ctype_pool = &dg.ctype_pool; |
| 673 | const decl = zcu.declPtr(decl_index); | ||
| 656 | assert(decl.has_tv); | 674 | assert(decl.has_tv); |
| 657 | 675 | ||
| 658 | // Render an undefined pointer if we have a pointer to a zero-bit or comptime type. | 676 | // Render an undefined pointer if we have a pointer to a zero-bit or comptime type. |
| 659 | if (ty.isPtrAtRuntime(mod) and !decl.typeOf(mod).isFnOrHasRuntimeBits(mod)) { | 677 | const ty = val.typeOf(zcu); |
| 678 | const decl_ty = decl.typeOf(zcu); | ||
| 679 | if (ty.isPtrAtRuntime(zcu) and !decl_ty.isFnOrHasRuntimeBits(zcu)) { | ||
| 660 | return dg.writeCValue(writer, .{ .undef = ty }); | 680 | return dg.writeCValue(writer, .{ .undef = ty }); |
| 661 | } | 681 | } |
| 662 | 682 | ||
| 663 | // Chase function values in order to be able to reference the original function. | 683 | // Chase function values in order to be able to reference the original function. |
| 664 | if (decl.val.getFunction(mod)) |func| if (func.owner_decl != decl_index) | 684 | if (decl.val.getFunction(zcu)) |func| if (func.owner_decl != decl_index) |
| 665 | return dg.renderDeclValue(writer, ty, val, func.owner_decl, location); | 685 | return dg.renderDeclValue(writer, val, func.owner_decl, location); |
| 666 | if (decl.val.getExternFunc(mod)) |extern_func| if (extern_func.decl != decl_index) | 686 | if (decl.val.getExternFunc(zcu)) |extern_func| if (extern_func.decl != decl_index) |
| 667 | return dg.renderDeclValue(writer, ty, val, extern_func.decl, location); | 687 | return dg.renderDeclValue(writer, val, extern_func.decl, location); |
| 668 | 688 | ||
| 669 | if (decl.val.getVariable(mod)) |variable| try dg.renderFwdDecl(decl_index, variable, .tentative); | 689 | if (decl.val.getVariable(zcu)) |variable| try dg.renderFwdDecl(decl_index, variable, .tentative); |
| 670 | 690 | ||
| 671 | // We shouldn't cast C function pointers as this is UB (when you call | 691 | // We shouldn't cast C function pointers as this is UB (when you call |
| 672 | // them). The analysis until now should ensure that the C function | 692 | // them). The analysis until now should ensure that the C function |
| 673 | // pointers are compatible. If they are not, then there is a bug | 693 | // pointers are compatible. If they are not, then there is a bug |
| 674 | // somewhere and we should let the C compiler tell us about it. | 694 | // somewhere and we should let the C compiler tell us about it. |
| 675 | const need_typecast = if (ty.castPtrToFn(mod)) |_| false else !ty.childType(mod).eql(decl.typeOf(mod), mod); | 695 | const elem_ctype = (try dg.ctypeFromType(ty, .complete)).info(ctype_pool).pointer.elem_ctype; |
| 676 | if (need_typecast) { | 696 | const decl_ctype = try dg.ctypeFromType(decl_ty, .complete); |
| 697 | const need_cast = !elem_ctype.eql(decl_ctype) and | ||
| 698 | (elem_ctype.info(ctype_pool) != .function or decl_ctype.info(ctype_pool) != .function); | ||
| 699 | if (need_cast) { | ||
| 677 | try writer.writeAll("(("); | 700 | try writer.writeAll("(("); |
| 678 | try dg.renderType(writer, ty); | 701 | try dg.renderType(writer, ty); |
| 679 | try writer.writeByte(')'); | 702 | try writer.writeByte(')'); |
| 680 | } | 703 | } |
| 681 | try writer.writeByte('&'); | 704 | try writer.writeByte('&'); |
| 682 | try dg.renderDeclName(writer, decl_index, 0); | 705 | try dg.renderDeclName(writer, decl_index, 0); |
| 683 | if (need_typecast) try writer.writeByte(')'); | 706 | if (need_cast) try writer.writeByte(')'); |
| 684 | } | 707 | } |
| 685 | 708 | ||
| 686 | /// Renders a "parent" pointer by recursing to the root decl/variable | 709 | /// Renders a "parent" pointer by recursing to the root decl/variable |
| ... | @@ -691,33 +714,34 @@ pub const DeclGen = struct { | ... | @@ -691,33 +714,34 @@ pub const DeclGen = struct { |
| 691 | ptr_val: InternPool.Index, | 714 | ptr_val: InternPool.Index, |
| 692 | location: ValueRenderLocation, | 715 | location: ValueRenderLocation, |
| 693 | ) error{ OutOfMemory, AnalysisFail }!void { | 716 | ) error{ OutOfMemory, AnalysisFail }!void { |
| 694 | const mod = dg.module; | 717 | const zcu = dg.zcu; |
| 695 | const ptr_ty = Type.fromInterned(mod.intern_pool.typeOf(ptr_val)); | 718 | const ip = &zcu.intern_pool; |
| 696 | const ptr_cty = try dg.typeToIndex(ptr_ty, .complete); | 719 | const ptr_ty = Type.fromInterned(ip.typeOf(ptr_val)); |
| 697 | const ptr = mod.intern_pool.indexToKey(ptr_val).ptr; | 720 | const ptr_ctype = try dg.ctypeFromType(ptr_ty, .complete); |
| 721 | const ptr_child_ctype = ptr_ctype.info(&dg.ctype_pool).pointer.elem_ctype; | ||
| 722 | const ptr = ip.indexToKey(ptr_val).ptr; | ||
| 698 | switch (ptr.addr) { | 723 | switch (ptr.addr) { |
| 699 | .decl => |d| try dg.renderDeclValue(writer, ptr_ty, Value.fromInterned(ptr_val), d, location), | 724 | .decl => |d| try dg.renderDeclValue(writer, Value.fromInterned(ptr_val), d, location), |
| 700 | .anon_decl => |anon_decl| try dg.renderAnonDeclValue(writer, ptr_ty, Value.fromInterned(ptr_val), anon_decl, location), | 725 | .anon_decl => |anon_decl| try dg.renderAnonDeclValue(writer, Value.fromInterned(ptr_val), anon_decl, location), |
| 701 | .int => |int| { | 726 | .int => |int| { |
| 702 | try writer.writeByte('('); | 727 | try writer.writeByte('('); |
| 703 | try dg.renderCType(writer, ptr_cty); | 728 | try dg.renderCType(writer, ptr_ctype); |
| 704 | try writer.print("){x}", .{try dg.fmtIntLiteral(Type.usize, Value.fromInterned(int), .Other)}); | 729 | try writer.print("){x}", .{try dg.fmtIntLiteral(Value.fromInterned(int), .Other)}); |
| 705 | }, | 730 | }, |
| 706 | .eu_payload, .opt_payload => |base| { | 731 | .eu_payload, .opt_payload => |base| { |
| 707 | const ptr_base_ty = Type.fromInterned(mod.intern_pool.typeOf(base)); | 732 | const ptr_base_ty = Type.fromInterned(ip.typeOf(base)); |
| 708 | const base_ty = ptr_base_ty.childType(mod); | 733 | const base_ty = ptr_base_ty.childType(zcu); |
| 709 | // Ensure complete type definition is visible before accessing fields. | 734 | // Ensure complete type definition is visible before accessing fields. |
| 710 | _ = try dg.typeToIndex(base_ty, .complete); | 735 | _ = try dg.ctypeFromType(base_ty, .complete); |
| 711 | const payload_ty = switch (ptr.addr) { | 736 | const payload_ty = switch (ptr.addr) { |
| 712 | .eu_payload => base_ty.errorUnionPayload(mod), | 737 | .eu_payload => base_ty.errorUnionPayload(zcu), |
| 713 | .opt_payload => base_ty.optionalChild(mod), | 738 | .opt_payload => base_ty.optionalChild(zcu), |
| 714 | else => unreachable, | 739 | else => unreachable, |
| 715 | }; | 740 | }; |
| 716 | const ptr_payload_ty = try mod.adjustPtrTypeChild(ptr_base_ty, payload_ty); | 741 | const payload_ctype = try dg.ctypeFromType(payload_ty, .forward); |
| 717 | const ptr_payload_cty = try dg.typeToIndex(ptr_payload_ty, .complete); | 742 | if (!ptr_child_ctype.eql(payload_ctype)) { |
| 718 | if (ptr_cty != ptr_payload_cty) { | ||
| 719 | try writer.writeByte('('); | 743 | try writer.writeByte('('); |
| 720 | try dg.renderCType(writer, ptr_cty); | 744 | try dg.renderCType(writer, ptr_ctype); |
| 721 | try writer.writeByte(')'); | 745 | try writer.writeByte(')'); |
| 722 | } | 746 | } |
| 723 | try writer.writeAll("&("); | 747 | try writer.writeAll("&("); |
| ... | @@ -725,70 +749,90 @@ pub const DeclGen = struct { | ... | @@ -725,70 +749,90 @@ pub const DeclGen = struct { |
| 725 | try writer.writeAll(")->payload"); | 749 | try writer.writeAll(")->payload"); |
| 726 | }, | 750 | }, |
| 727 | .elem => |elem| { | 751 | .elem => |elem| { |
| 728 | const ptr_base_ty = Type.fromInterned(mod.intern_pool.typeOf(elem.base)); | 752 | const ptr_base_ty = Type.fromInterned(ip.typeOf(elem.base)); |
| 729 | const elem_ty = ptr_base_ty.elemType2(mod); | 753 | const elem_ty = ptr_base_ty.elemType2(zcu); |
| 730 | const ptr_elem_ty = try mod.adjustPtrTypeChild(ptr_base_ty, elem_ty); | 754 | const elem_ctype = try dg.ctypeFromType(elem_ty, .forward); |
| 731 | const ptr_elem_cty = try dg.typeToIndex(ptr_elem_ty, .complete); | 755 | if (!ptr_child_ctype.eql(elem_ctype)) { |
| 732 | if (ptr_cty != ptr_elem_cty) { | ||
| 733 | try writer.writeByte('('); | 756 | try writer.writeByte('('); |
| 734 | try dg.renderCType(writer, ptr_cty); | 757 | try dg.renderCType(writer, ptr_ctype); |
| 735 | try writer.writeByte(')'); | 758 | try writer.writeByte(')'); |
| 736 | } | 759 | } |
| 737 | try writer.writeAll("&("); | 760 | try writer.writeAll("&("); |
| 738 | if (mod.intern_pool.indexToKey(ptr_base_ty.toIntern()).ptr_type.flags.size == .One) | 761 | if (ip.indexToKey(ptr_base_ty.toIntern()).ptr_type.flags.size == .One) |
| 739 | try writer.writeByte('*'); | 762 | try writer.writeByte('*'); |
| 740 | try dg.renderParentPtr(writer, elem.base, location); | 763 | try dg.renderParentPtr(writer, elem.base, location); |
| 741 | try writer.print(")[{d}]", .{elem.index}); | 764 | try writer.print(")[{d}]", .{elem.index}); |
| 742 | }, | 765 | }, |
| 743 | .field => |field| { | 766 | .field => |field| { |
| 744 | const ptr_base_ty = Type.fromInterned(mod.intern_pool.typeOf(field.base)); | 767 | const ptr_base_ty = Type.fromInterned(ip.typeOf(field.base)); |
| 745 | const base_ty = ptr_base_ty.childType(mod); | 768 | const base_ty = ptr_base_ty.childType(zcu); |
| 746 | // Ensure complete type definition is visible before accessing fields. | 769 | // Ensure complete type definition is available before accessing fields. |
| 747 | _ = try dg.typeToIndex(base_ty, .complete); | 770 | _ = try dg.ctypeFromType(base_ty, .complete); |
| 748 | const field_ty = switch (mod.intern_pool.indexToKey(base_ty.toIntern())) { | 771 | switch (fieldLocation(ptr_base_ty, ptr_ty, @as(u32, @intCast(field.index)), zcu)) { |
| 749 | .anon_struct_type, .struct_type, .union_type => base_ty.structFieldType(@as(usize, @intCast(field.index)), mod), | 772 | .begin => { |
| 750 | .ptr_type => |ptr_type| switch (ptr_type.flags.size) { | 773 | const ptr_base_ctype = try dg.ctypeFromType(ptr_base_ty, .complete); |
| 751 | .One, .Many, .C => unreachable, | 774 | if (!ptr_ctype.eql(ptr_base_ctype)) { |
| 752 | .Slice => switch (field.index) { | 775 | try writer.writeByte('('); |
| 753 | Value.slice_ptr_index => base_ty.slicePtrFieldType(mod), | 776 | try dg.renderCType(writer, ptr_ctype); |
| 754 | Value.slice_len_index => Type.usize, | 777 | try writer.writeByte(')'); |
| 755 | else => unreachable, | 778 | } |
| 756 | }, | 779 | try dg.renderParentPtr(writer, field.base, location); |
| 757 | }, | 780 | }, |
| 758 | else => unreachable, | ||
| 759 | }; | ||
| 760 | const ptr_field_ty = try mod.adjustPtrTypeChild(ptr_base_ty, field_ty); | ||
| 761 | const ptr_field_cty = try dg.typeToIndex(ptr_field_ty, .complete); | ||
| 762 | if (ptr_cty != ptr_field_cty) { | ||
| 763 | try writer.writeByte('('); | ||
| 764 | try dg.renderCType(writer, ptr_cty); | ||
| 765 | try writer.writeByte(')'); | ||
| 766 | } | ||
| 767 | switch (fieldLocation(ptr_base_ty, ptr_ty, @as(u32, @intCast(field.index)), mod)) { | ||
| 768 | .begin => try dg.renderParentPtr(writer, field.base, location), | ||
| 769 | .field => |name| { | 781 | .field => |name| { |
| 782 | const field_ty = switch (ip.indexToKey(base_ty.toIntern())) { | ||
| 783 | .anon_struct_type, | ||
| 784 | .struct_type, | ||
| 785 | .union_type, | ||
| 786 | => base_ty.structFieldType(@as(usize, @intCast(field.index)), zcu), | ||
| 787 | .ptr_type => |ptr_type| switch (ptr_type.flags.size) { | ||
| 788 | .One, .Many, .C => unreachable, | ||
| 789 | .Slice => switch (field.index) { | ||
| 790 | Value.slice_ptr_index => base_ty.slicePtrFieldType(zcu), | ||
| 791 | Value.slice_len_index => Type.usize, | ||
| 792 | else => unreachable, | ||
| 793 | }, | ||
| 794 | }, | ||
| 795 | else => unreachable, | ||
| 796 | }; | ||
| 797 | const field_ctype = try dg.ctypeFromType(field_ty, .forward); | ||
| 798 | if (!ptr_child_ctype.eql(field_ctype)) { | ||
| 799 | try writer.writeByte('('); | ||
| 800 | try dg.renderCType(writer, ptr_ctype); | ||
| 801 | try writer.writeByte(')'); | ||
| 802 | } | ||
| 770 | try writer.writeAll("&("); | 803 | try writer.writeAll("&("); |
| 771 | try dg.renderParentPtr(writer, field.base, location); | 804 | try dg.renderParentPtr(writer, field.base, location); |
| 772 | try writer.writeAll(")->"); | 805 | try writer.writeAll(")->"); |
| 773 | try dg.writeCValue(writer, name); | 806 | try dg.writeCValue(writer, name); |
| 774 | }, | 807 | }, |
| 775 | .byte_offset => |byte_offset| { | 808 | .byte_offset => |byte_offset| { |
| 776 | const u8_ptr_ty = try mod.adjustPtrTypeChild(ptr_ty, Type.u8); | 809 | const u8_ptr_ty = try zcu.adjustPtrTypeChild(ptr_ty, Type.u8); |
| 777 | const byte_offset_val = try mod.intValue(Type.usize, byte_offset); | 810 | const u8_ptr_ctype = try dg.ctypeFromType(u8_ptr_ty, .complete); |
| 778 | 811 | ||
| 812 | if (!ptr_ctype.eql(u8_ptr_ctype)) { | ||
| 813 | try writer.writeByte('('); | ||
| 814 | try dg.renderCType(writer, ptr_ctype); | ||
| 815 | try writer.writeByte(')'); | ||
| 816 | } | ||
| 779 | try writer.writeAll("(("); | 817 | try writer.writeAll("(("); |
| 780 | try dg.renderType(writer, u8_ptr_ty); | 818 | try dg.renderCType(writer, u8_ptr_ctype); |
| 781 | try writer.writeByte(')'); | 819 | try writer.writeByte(')'); |
| 782 | try dg.renderParentPtr(writer, field.base, location); | 820 | try dg.renderParentPtr(writer, field.base, location); |
| 783 | try writer.print(" + {})", .{ | 821 | try writer.print(" + {})", .{ |
| 784 | try dg.fmtIntLiteral(Type.usize, byte_offset_val, .Other), | 822 | try dg.fmtIntLiteral(try zcu.intValue(Type.usize, byte_offset), .Other), |
| 785 | }); | 823 | }); |
| 786 | }, | 824 | }, |
| 787 | .end => { | 825 | .end => { |
| 826 | const ptr_base_ctype = try dg.ctypeFromType(ptr_base_ty, .complete); | ||
| 827 | if (!ptr_ctype.eql(ptr_base_ctype)) { | ||
| 828 | try writer.writeByte('('); | ||
| 829 | try dg.renderCType(writer, ptr_ctype); | ||
| 830 | try writer.writeByte(')'); | ||
| 831 | } | ||
| 788 | try writer.writeAll("(("); | 832 | try writer.writeAll("(("); |
| 789 | try dg.renderParentPtr(writer, field.base, location); | 833 | try dg.renderParentPtr(writer, field.base, location); |
| 790 | try writer.print(") + {})", .{ | 834 | try writer.print(") + {})", .{ |
| 791 | try dg.fmtIntLiteral(Type.usize, try mod.intValue(Type.usize, 1), .Other), | 835 | try dg.fmtIntLiteral(try zcu.intValue(Type.usize, 1), .Other), |
| 792 | }); | 836 | }); |
| 793 | }, | 837 | }, |
| 794 | } | 838 | } |
| ... | @@ -800,215 +844,21 @@ pub const DeclGen = struct { | ... | @@ -800,215 +844,21 @@ pub const DeclGen = struct { |
| 800 | fn renderValue( | 844 | fn renderValue( |
| 801 | dg: *DeclGen, | 845 | dg: *DeclGen, |
| 802 | writer: anytype, | 846 | writer: anytype, |
| 803 | ty: Type, | ||
| 804 | val: Value, | 847 | val: Value, |
| 805 | location: ValueRenderLocation, | 848 | location: ValueRenderLocation, |
| 806 | ) error{ OutOfMemory, AnalysisFail }!void { | 849 | ) error{ OutOfMemory, AnalysisFail }!void { |
| 807 | const mod = dg.module; | 850 | const zcu = dg.zcu; |
| 808 | const ip = &mod.intern_pool; | 851 | const ip = &zcu.intern_pool; |
| 852 | const target = &dg.mod.resolved_target.result; | ||
| 809 | 853 | ||
| 810 | const target = mod.getTarget(); | ||
| 811 | const initializer_type: ValueRenderLocation = switch (location) { | 854 | const initializer_type: ValueRenderLocation = switch (location) { |
| 812 | .StaticInitializer => .StaticInitializer, | 855 | .StaticInitializer => .StaticInitializer, |
| 813 | else => .Initializer, | 856 | else => .Initializer, |
| 814 | }; | 857 | }; |
| 815 | 858 | ||
| 816 | const safety_on = switch (mod.optimizeMode()) { | 859 | const ty = val.typeOf(zcu); |
| 817 | .Debug, .ReleaseSafe => true, | 860 | if (val.isUndefDeep(zcu)) return dg.renderUndefValue(writer, ty, location); |
| 818 | .ReleaseFast, .ReleaseSmall => false, | 861 | switch (ip.indexToKey(val.toIntern())) { |
| 819 | }; | ||
| 820 | |||
| 821 | if (val.isUndefDeep(mod)) { | ||
| 822 | switch (ty.zigTypeTag(mod)) { | ||
| 823 | .Bool => { | ||
| 824 | if (safety_on) { | ||
| 825 | return writer.writeAll("0xaa"); | ||
| 826 | } else { | ||
| 827 | return writer.writeAll("false"); | ||
| 828 | } | ||
| 829 | }, | ||
| 830 | .Int, .Enum, .ErrorSet => return writer.print("{x}", .{try dg.fmtIntLiteral(ty, val, location)}), | ||
| 831 | .Float => { | ||
| 832 | const bits = ty.floatBits(target); | ||
| 833 | // All unsigned ints matching float types are pre-allocated. | ||
| 834 | const repr_ty = mod.intType(.unsigned, bits) catch unreachable; | ||
| 835 | |||
| 836 | try writer.writeAll("zig_make_"); | ||
| 837 | try dg.renderTypeForBuiltinFnName(writer, ty); | ||
| 838 | try writer.writeByte('('); | ||
| 839 | switch (bits) { | ||
| 840 | 16 => try writer.print("{x}", .{@as(f16, @bitCast(undefPattern(i16)))}), | ||
| 841 | 32 => try writer.print("{x}", .{@as(f32, @bitCast(undefPattern(i32)))}), | ||
| 842 | 64 => try writer.print("{x}", .{@as(f64, @bitCast(undefPattern(i64)))}), | ||
| 843 | 80 => try writer.print("{x}", .{@as(f80, @bitCast(undefPattern(i80)))}), | ||
| 844 | 128 => try writer.print("{x}", .{@as(f128, @bitCast(undefPattern(i128)))}), | ||
| 845 | else => unreachable, | ||
| 846 | } | ||
| 847 | try writer.writeAll(", "); | ||
| 848 | try dg.renderValue(writer, repr_ty, Value.undef, .FunctionArgument); | ||
| 849 | return writer.writeByte(')'); | ||
| 850 | }, | ||
| 851 | .Pointer => if (ty.isSlice(mod)) { | ||
| 852 | if (!location.isInitializer()) { | ||
| 853 | try writer.writeByte('('); | ||
| 854 | try dg.renderType(writer, ty); | ||
| 855 | try writer.writeByte(')'); | ||
| 856 | } | ||
| 857 | |||
| 858 | try writer.writeAll("{("); | ||
| 859 | const ptr_ty = ty.slicePtrFieldType(mod); | ||
| 860 | try dg.renderType(writer, ptr_ty); | ||
| 861 | return writer.print("){x}, {0x}}}", .{try dg.fmtIntLiteral(Type.usize, val, .Other)}); | ||
| 862 | } else { | ||
| 863 | try writer.writeAll("(("); | ||
| 864 | try dg.renderType(writer, ty); | ||
| 865 | return writer.print("){x})", .{try dg.fmtIntLiteral(Type.usize, val, .Other)}); | ||
| 866 | }, | ||
| 867 | .Optional => { | ||
| 868 | const payload_ty = ty.optionalChild(mod); | ||
| 869 | |||
| 870 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) { | ||
| 871 | return dg.renderValue(writer, Type.bool, val, location); | ||
| 872 | } | ||
| 873 | |||
| 874 | if (ty.optionalReprIsPayload(mod)) { | ||
| 875 | return dg.renderValue(writer, payload_ty, val, location); | ||
| 876 | } | ||
| 877 | |||
| 878 | if (!location.isInitializer()) { | ||
| 879 | try writer.writeByte('('); | ||
| 880 | try dg.renderType(writer, ty); | ||
| 881 | try writer.writeByte(')'); | ||
| 882 | } | ||
| 883 | |||
| 884 | try writer.writeAll("{ .payload = "); | ||
| 885 | try dg.renderValue(writer, payload_ty, val, initializer_type); | ||
| 886 | try writer.writeAll(", .is_null = "); | ||
| 887 | try dg.renderValue(writer, Type.bool, val, initializer_type); | ||
| 888 | return writer.writeAll(" }"); | ||
| 889 | }, | ||
| 890 | .Struct => switch (ty.containerLayout(mod)) { | ||
| 891 | .auto, .@"extern" => { | ||
| 892 | if (!location.isInitializer()) { | ||
| 893 | try writer.writeByte('('); | ||
| 894 | try dg.renderType(writer, ty); | ||
| 895 | try writer.writeByte(')'); | ||
| 896 | } | ||
| 897 | |||
| 898 | try writer.writeByte('{'); | ||
| 899 | var empty = true; | ||
| 900 | for (0..ty.structFieldCount(mod)) |field_index| { | ||
| 901 | if (ty.structFieldIsComptime(field_index, mod)) continue; | ||
| 902 | const field_ty = ty.structFieldType(field_index, mod); | ||
| 903 | if (!field_ty.hasRuntimeBits(mod)) continue; | ||
| 904 | |||
| 905 | if (!empty) try writer.writeByte(','); | ||
| 906 | try dg.renderValue(writer, field_ty, val, initializer_type); | ||
| 907 | |||
| 908 | empty = false; | ||
| 909 | } | ||
| 910 | |||
| 911 | return writer.writeByte('}'); | ||
| 912 | }, | ||
| 913 | .@"packed" => return writer.print("{x}", .{try dg.fmtIntLiteral(ty, Value.undef, .Other)}), | ||
| 914 | }, | ||
| 915 | .Union => { | ||
| 916 | if (!location.isInitializer()) { | ||
| 917 | try writer.writeByte('('); | ||
| 918 | try dg.renderType(writer, ty); | ||
| 919 | try writer.writeByte(')'); | ||
| 920 | } | ||
| 921 | |||
| 922 | try writer.writeByte('{'); | ||
| 923 | if (ty.unionTagTypeSafety(mod)) |tag_ty| { | ||
| 924 | const layout = ty.unionGetLayout(mod); | ||
| 925 | if (layout.tag_size != 0) { | ||
| 926 | try writer.writeAll(" .tag = "); | ||
| 927 | try dg.renderValue(writer, tag_ty, val, initializer_type); | ||
| 928 | } | ||
| 929 | if (ty.unionHasAllZeroBitFieldTypes(mod)) return try writer.writeByte('}'); | ||
| 930 | if (layout.tag_size != 0) try writer.writeByte(','); | ||
| 931 | try writer.writeAll(" .payload = {"); | ||
| 932 | } | ||
| 933 | const union_obj = mod.typeToUnion(ty).?; | ||
| 934 | for (0..union_obj.field_types.len) |field_index| { | ||
| 935 | const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[field_index]); | ||
| 936 | if (!field_ty.hasRuntimeBits(mod)) continue; | ||
| 937 | try dg.renderValue(writer, field_ty, val, initializer_type); | ||
| 938 | break; | ||
| 939 | } | ||
| 940 | if (ty.unionTagTypeSafety(mod)) |_| try writer.writeByte('}'); | ||
| 941 | return writer.writeByte('}'); | ||
| 942 | }, | ||
| 943 | .ErrorUnion => { | ||
| 944 | const payload_ty = ty.errorUnionPayload(mod); | ||
| 945 | const error_ty = ty.errorUnionSet(mod); | ||
| 946 | |||
| 947 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) { | ||
| 948 | return dg.renderValue(writer, error_ty, val, location); | ||
| 949 | } | ||
| 950 | |||
| 951 | if (!location.isInitializer()) { | ||
| 952 | try writer.writeByte('('); | ||
| 953 | try dg.renderType(writer, ty); | ||
| 954 | try writer.writeByte(')'); | ||
| 955 | } | ||
| 956 | |||
| 957 | try writer.writeAll("{ .payload = "); | ||
| 958 | try dg.renderValue(writer, payload_ty, val, initializer_type); | ||
| 959 | try writer.writeAll(", .error = "); | ||
| 960 | try dg.renderValue(writer, error_ty, val, initializer_type); | ||
| 961 | return writer.writeAll(" }"); | ||
| 962 | }, | ||
| 963 | .Array, .Vector => { | ||
| 964 | const ai = ty.arrayInfo(mod); | ||
| 965 | if (ai.elem_type.eql(Type.u8, mod)) { | ||
| 966 | const c_len = ty.arrayLenIncludingSentinel(mod); | ||
| 967 | var literal = stringLiteral(writer, c_len); | ||
| 968 | try literal.start(); | ||
| 969 | var index: u64 = 0; | ||
| 970 | while (index < c_len) : (index += 1) | ||
| 971 | try literal.writeChar(0xaa); | ||
| 972 | return literal.end(); | ||
| 973 | } else { | ||
| 974 | if (!location.isInitializer()) { | ||
| 975 | try writer.writeByte('('); | ||
| 976 | try dg.renderType(writer, ty); | ||
| 977 | try writer.writeByte(')'); | ||
| 978 | } | ||
| 979 | |||
| 980 | try writer.writeByte('{'); | ||
| 981 | const c_len = ty.arrayLenIncludingSentinel(mod); | ||
| 982 | var index: u64 = 0; | ||
| 983 | while (index < c_len) : (index += 1) { | ||
| 984 | if (index > 0) try writer.writeAll(", "); | ||
| 985 | try dg.renderValue(writer, ty.childType(mod), val, initializer_type); | ||
| 986 | } | ||
| 987 | return writer.writeByte('}'); | ||
| 988 | } | ||
| 989 | }, | ||
| 990 | .ComptimeInt, | ||
| 991 | .ComptimeFloat, | ||
| 992 | .Type, | ||
| 993 | .EnumLiteral, | ||
| 994 | .Void, | ||
| 995 | .NoReturn, | ||
| 996 | .Undefined, | ||
| 997 | .Null, | ||
| 998 | .Opaque, | ||
| 999 | => unreachable, | ||
| 1000 | |||
| 1001 | .Fn, | ||
| 1002 | .Frame, | ||
| 1003 | .AnyFrame, | ||
| 1004 | => |tag| return dg.fail("TODO: C backend: implement value of type {s}", .{ | ||
| 1005 | @tagName(tag), | ||
| 1006 | }), | ||
| 1007 | } | ||
| 1008 | unreachable; | ||
| 1009 | } | ||
| 1010 | |||
| 1011 | switch (ip.indexToKey(val.ip_index)) { | ||
| 1012 | // types, not values | 862 | // types, not values |
| 1013 | .int_type, | 863 | .int_type, |
| 1014 | .ptr_type, | 864 | .ptr_type, |
| ... | @@ -1050,26 +900,28 @@ pub const DeclGen = struct { | ... | @@ -1050,26 +900,28 @@ pub const DeclGen = struct { |
| 1050 | .empty_enum_value, | 900 | .empty_enum_value, |
| 1051 | => unreachable, // non-runtime values | 901 | => unreachable, // non-runtime values |
| 1052 | .int => |int| switch (int.storage) { | 902 | .int => |int| switch (int.storage) { |
| 1053 | .u64, .i64, .big_int => try writer.print("{}", .{try dg.fmtIntLiteral(ty, val, location)}), | 903 | .u64, .i64, .big_int => try writer.print("{}", .{try dg.fmtIntLiteral(val, location)}), |
| 1054 | .lazy_align, .lazy_size => { | 904 | .lazy_align, .lazy_size => { |
| 1055 | try writer.writeAll("(("); | 905 | try writer.writeAll("(("); |
| 1056 | try dg.renderType(writer, ty); | 906 | try dg.renderType(writer, ty); |
| 1057 | return writer.print("){x})", .{try dg.fmtIntLiteral(Type.usize, val, .Other)}); | 907 | try writer.print("){x})", .{try dg.fmtIntLiteral( |
| 908 | try zcu.intValue(Type.usize, val.toUnsignedInt(zcu)), | ||
| 909 | .Other, | ||
| 910 | )}); | ||
| 1058 | }, | 911 | }, |
| 1059 | }, | 912 | }, |
| 1060 | .err => |err| try writer.print("zig_error_{}", .{ | 913 | .err => |err| try writer.print("zig_error_{}", .{ |
| 1061 | fmtIdent(ip.stringToSlice(err.name)), | 914 | fmtIdent(ip.stringToSlice(err.name)), |
| 1062 | }), | 915 | }), |
| 1063 | .error_union => |error_union| { | 916 | .error_union => |error_union| { |
| 1064 | const payload_ty = ty.errorUnionPayload(mod); | 917 | const payload_ty = ty.errorUnionPayload(zcu); |
| 1065 | const error_ty = ty.errorUnionSet(mod); | 918 | const error_ty = ty.errorUnionSet(zcu); |
| 1066 | const err_int_ty = try mod.errorIntType(); | 919 | const err_int_ty = try zcu.errorIntType(); |
| 1067 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) { | 920 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { |
| 1068 | switch (error_union.val) { | 921 | switch (error_union.val) { |
| 1069 | .err_name => |err_name| return dg.renderValue( | 922 | .err_name => |err_name| return dg.renderValue( |
| 1070 | writer, | 923 | writer, |
| 1071 | error_ty, | 924 | Value.fromInterned((try zcu.intern(.{ .err = .{ |
| 1072 | Value.fromInterned((try mod.intern(.{ .err = .{ | ||
| 1073 | .ty = error_ty.toIntern(), | 925 | .ty = error_ty.toIntern(), |
| 1074 | .name = err_name, | 926 | .name = err_name, |
| 1075 | } }))), | 927 | } }))), |
| ... | @@ -1077,8 +929,7 @@ pub const DeclGen = struct { | ... | @@ -1077,8 +929,7 @@ pub const DeclGen = struct { |
| 1077 | ), | 929 | ), |
| 1078 | .payload => return dg.renderValue( | 930 | .payload => return dg.renderValue( |
| 1079 | writer, | 931 | writer, |
| 1080 | err_int_ty, | 932 | try zcu.intValue(err_int_ty, 0), |
| 1081 | try mod.intValue(err_int_ty, 0), | ||
| 1082 | location, | 933 | location, |
| 1083 | ), | 934 | ), |
| 1084 | } | 935 | } |
| ... | @@ -1093,9 +944,8 @@ pub const DeclGen = struct { | ... | @@ -1093,9 +944,8 @@ pub const DeclGen = struct { |
| 1093 | try writer.writeAll("{ .payload = "); | 944 | try writer.writeAll("{ .payload = "); |
| 1094 | try dg.renderValue( | 945 | try dg.renderValue( |
| 1095 | writer, | 946 | writer, |
| 1096 | payload_ty, | ||
| 1097 | Value.fromInterned(switch (error_union.val) { | 947 | Value.fromInterned(switch (error_union.val) { |
| 1098 | .err_name => try mod.intern(.{ .undef = payload_ty.ip_index }), | 948 | .err_name => (try zcu.undefValue(payload_ty)).toIntern(), |
| 1099 | .payload => |payload| payload, | 949 | .payload => |payload| payload, |
| 1100 | }), | 950 | }), |
| 1101 | initializer_type, | 951 | initializer_type, |
| ... | @@ -1104,8 +954,7 @@ pub const DeclGen = struct { | ... | @@ -1104,8 +954,7 @@ pub const DeclGen = struct { |
| 1104 | switch (error_union.val) { | 954 | switch (error_union.val) { |
| 1105 | .err_name => |err_name| try dg.renderValue( | 955 | .err_name => |err_name| try dg.renderValue( |
| 1106 | writer, | 956 | writer, |
| 1107 | error_ty, | 957 | Value.fromInterned((try zcu.intern(.{ .err = .{ |
| 1108 | Value.fromInterned((try mod.intern(.{ .err = .{ | ||
| 1109 | .ty = error_ty.toIntern(), | 958 | .ty = error_ty.toIntern(), |
| 1110 | .name = err_name, | 959 | .name = err_name, |
| 1111 | } }))), | 960 | } }))), |
| ... | @@ -1113,24 +962,23 @@ pub const DeclGen = struct { | ... | @@ -1113,24 +962,23 @@ pub const DeclGen = struct { |
| 1113 | ), | 962 | ), |
| 1114 | .payload => try dg.renderValue( | 963 | .payload => try dg.renderValue( |
| 1115 | writer, | 964 | writer, |
| 1116 | err_int_ty, | 965 | try zcu.intValue(err_int_ty, 0), |
| 1117 | try mod.intValue(err_int_ty, 0), | ||
| 1118 | location, | 966 | location, |
| 1119 | ), | 967 | ), |
| 1120 | } | 968 | } |
| 1121 | try writer.writeAll(" }"); | 969 | try writer.writeAll(" }"); |
| 1122 | }, | 970 | }, |
| 1123 | .enum_tag => { | 971 | .enum_tag => |enum_tag| try dg.renderValue( |
| 1124 | const enum_tag = ip.indexToKey(val.ip_index).enum_tag; | 972 | writer, |
| 1125 | const int_tag_ty = ip.typeOf(enum_tag.int); | 973 | Value.fromInterned(enum_tag.int), |
| 1126 | try dg.renderValue(writer, Type.fromInterned(int_tag_ty), Value.fromInterned(enum_tag.int), location); | 974 | location, |
| 1127 | }, | 975 | ), |
| 1128 | .float => { | 976 | .float => { |
| 1129 | const bits = ty.floatBits(target); | 977 | const bits = ty.floatBits(target.*); |
| 1130 | const f128_val = val.toFloat(f128, mod); | 978 | const f128_val = val.toFloat(f128, zcu); |
| 1131 | 979 | ||
| 1132 | // All unsigned ints matching float types are pre-allocated. | 980 | // All unsigned ints matching float types are pre-allocated. |
| 1133 | const repr_ty = mod.intType(.unsigned, bits) catch unreachable; | 981 | const repr_ty = zcu.intType(.unsigned, bits) catch unreachable; |
| 1134 | 982 | ||
| 1135 | assert(bits <= 128); | 983 | assert(bits <= 128); |
| 1136 | var repr_val_limbs: [BigInt.calcTwosCompLimbCount(128)]BigIntLimb = undefined; | 984 | var repr_val_limbs: [BigInt.calcTwosCompLimbCount(128)]BigIntLimb = undefined; |
| ... | @@ -1141,26 +989,24 @@ pub const DeclGen = struct { | ... | @@ -1141,26 +989,24 @@ pub const DeclGen = struct { |
| 1141 | }; | 989 | }; |
| 1142 | 990 | ||
| 1143 | switch (bits) { | 991 | switch (bits) { |
| 1144 | 16 => repr_val_big.set(@as(u16, @bitCast(val.toFloat(f16, mod)))), | 992 | 16 => repr_val_big.set(@as(u16, @bitCast(val.toFloat(f16, zcu)))), |
| 1145 | 32 => repr_val_big.set(@as(u32, @bitCast(val.toFloat(f32, mod)))), | 993 | 32 => repr_val_big.set(@as(u32, @bitCast(val.toFloat(f32, zcu)))), |
| 1146 | 64 => repr_val_big.set(@as(u64, @bitCast(val.toFloat(f64, mod)))), | 994 | 64 => repr_val_big.set(@as(u64, @bitCast(val.toFloat(f64, zcu)))), |
| 1147 | 80 => repr_val_big.set(@as(u80, @bitCast(val.toFloat(f80, mod)))), | 995 | 80 => repr_val_big.set(@as(u80, @bitCast(val.toFloat(f80, zcu)))), |
| 1148 | 128 => repr_val_big.set(@as(u128, @bitCast(f128_val))), | 996 | 128 => repr_val_big.set(@as(u128, @bitCast(f128_val))), |
| 1149 | else => unreachable, | 997 | else => unreachable, |
| 1150 | } | 998 | } |
| 1151 | 999 | ||
| 1152 | const repr_val = try mod.intValue_big(repr_ty, repr_val_big.toConst()); | ||
| 1153 | |||
| 1154 | var empty = true; | 1000 | var empty = true; |
| 1155 | if (std.math.isFinite(f128_val)) { | 1001 | if (std.math.isFinite(f128_val)) { |
| 1156 | try writer.writeAll("zig_make_"); | 1002 | try writer.writeAll("zig_make_"); |
| 1157 | try dg.renderTypeForBuiltinFnName(writer, ty); | 1003 | try dg.renderTypeForBuiltinFnName(writer, ty); |
| 1158 | try writer.writeByte('('); | 1004 | try writer.writeByte('('); |
| 1159 | switch (bits) { | 1005 | switch (bits) { |
| 1160 | 16 => try writer.print("{x}", .{val.toFloat(f16, mod)}), | 1006 | 16 => try writer.print("{x}", .{val.toFloat(f16, zcu)}), |
| 1161 | 32 => try writer.print("{x}", .{val.toFloat(f32, mod)}), | 1007 | 32 => try writer.print("{x}", .{val.toFloat(f32, zcu)}), |
| 1162 | 64 => try writer.print("{x}", .{val.toFloat(f64, mod)}), | 1008 | 64 => try writer.print("{x}", .{val.toFloat(f64, zcu)}), |
| 1163 | 80 => try writer.print("{x}", .{val.toFloat(f80, mod)}), | 1009 | 80 => try writer.print("{x}", .{val.toFloat(f80, zcu)}), |
| 1164 | 128 => try writer.print("{x}", .{f128_val}), | 1010 | 128 => try writer.print("{x}", .{f128_val}), |
| 1165 | else => unreachable, | 1011 | else => unreachable, |
| 1166 | } | 1012 | } |
| ... | @@ -1200,17 +1046,20 @@ pub const DeclGen = struct { | ... | @@ -1200,17 +1046,20 @@ pub const DeclGen = struct { |
| 1200 | if (std.math.isNan(f128_val)) switch (bits) { | 1046 | if (std.math.isNan(f128_val)) switch (bits) { |
| 1201 | // We only actually need to pass the significand, but it will get | 1047 | // We only actually need to pass the significand, but it will get |
| 1202 | // properly masked anyway, so just pass the whole value. | 1048 | // properly masked anyway, so just pass the whole value. |
| 1203 | 16 => try writer.print("\"0x{x}\"", .{@as(u16, @bitCast(val.toFloat(f16, mod)))}), | 1049 | 16 => try writer.print("\"0x{x}\"", .{@as(u16, @bitCast(val.toFloat(f16, zcu)))}), |
| 1204 | 32 => try writer.print("\"0x{x}\"", .{@as(u32, @bitCast(val.toFloat(f32, mod)))}), | 1050 | 32 => try writer.print("\"0x{x}\"", .{@as(u32, @bitCast(val.toFloat(f32, zcu)))}), |
| 1205 | 64 => try writer.print("\"0x{x}\"", .{@as(u64, @bitCast(val.toFloat(f64, mod)))}), | 1051 | 64 => try writer.print("\"0x{x}\"", .{@as(u64, @bitCast(val.toFloat(f64, zcu)))}), |
| 1206 | 80 => try writer.print("\"0x{x}\"", .{@as(u80, @bitCast(val.toFloat(f80, mod)))}), | 1052 | 80 => try writer.print("\"0x{x}\"", .{@as(u80, @bitCast(val.toFloat(f80, zcu)))}), |
| 1207 | 128 => try writer.print("\"0x{x}\"", .{@as(u128, @bitCast(f128_val))}), | 1053 | 128 => try writer.print("\"0x{x}\"", .{@as(u128, @bitCast(f128_val))}), |
| 1208 | else => unreachable, | 1054 | else => unreachable, |
| 1209 | }; | 1055 | }; |
| 1210 | try writer.writeAll(", "); | 1056 | try writer.writeAll(", "); |
| 1211 | empty = false; | 1057 | empty = false; |
| 1212 | } | 1058 | } |
| 1213 | try writer.print("{x}", .{try dg.fmtIntLiteral(repr_ty, repr_val, location)}); | 1059 | try writer.print("{x}", .{try dg.fmtIntLiteral( |
| 1060 | try zcu.intValue_big(repr_ty, repr_val_big.toConst()), | ||
| 1061 | location, | ||
| 1062 | )}); | ||
| 1214 | if (!empty) try writer.writeByte(')'); | 1063 | if (!empty) try writer.writeByte(')'); |
| 1215 | }, | 1064 | }, |
| 1216 | .slice => |slice| { | 1065 | .slice => |slice| { |
| ... | @@ -1220,42 +1069,39 @@ pub const DeclGen = struct { | ... | @@ -1220,42 +1069,39 @@ pub const DeclGen = struct { |
| 1220 | try writer.writeByte(')'); | 1069 | try writer.writeByte(')'); |
| 1221 | } | 1070 | } |
| 1222 | try writer.writeByte('{'); | 1071 | try writer.writeByte('{'); |
| 1223 | try dg.renderValue(writer, ty.slicePtrFieldType(mod), Value.fromInterned(slice.ptr), initializer_type); | 1072 | try dg.renderValue(writer, Value.fromInterned(slice.ptr), initializer_type); |
| 1224 | try writer.writeAll(", "); | 1073 | try writer.writeAll(", "); |
| 1225 | try dg.renderValue(writer, Type.usize, Value.fromInterned(slice.len), initializer_type); | 1074 | try dg.renderValue(writer, Value.fromInterned(slice.len), initializer_type); |
| 1226 | try writer.writeByte('}'); | 1075 | try writer.writeByte('}'); |
| 1227 | }, | 1076 | }, |
| 1228 | .ptr => |ptr| switch (ptr.addr) { | 1077 | .ptr => |ptr| switch (ptr.addr) { |
| 1229 | .decl => |d| try dg.renderDeclValue(writer, ty, val, d, location), | 1078 | .decl => |d| try dg.renderDeclValue(writer, val, d, location), |
| 1230 | .anon_decl => |decl_val| try dg.renderAnonDeclValue(writer, ty, val, decl_val, location), | 1079 | .anon_decl => |decl_val| try dg.renderAnonDeclValue(writer, val, decl_val, location), |
| 1231 | .int => |int| { | 1080 | .int => |int| { |
| 1232 | try writer.writeAll("(("); | 1081 | try writer.writeAll("(("); |
| 1233 | try dg.renderType(writer, ty); | 1082 | try dg.renderType(writer, ty); |
| 1234 | try writer.print("){x})", .{ | 1083 | try writer.print("){x})", .{try dg.fmtIntLiteral(Value.fromInterned(int), location)}); |
| 1235 | try dg.fmtIntLiteral(Type.usize, Value.fromInterned(int), location), | ||
| 1236 | }); | ||
| 1237 | }, | 1084 | }, |
| 1238 | .eu_payload, | 1085 | .eu_payload, |
| 1239 | .opt_payload, | 1086 | .opt_payload, |
| 1240 | .elem, | 1087 | .elem, |
| 1241 | .field, | 1088 | .field, |
| 1242 | => try dg.renderParentPtr(writer, val.ip_index, location), | 1089 | => try dg.renderParentPtr(writer, val.toIntern(), location), |
| 1243 | .comptime_field, .comptime_alloc => unreachable, | 1090 | .comptime_field, .comptime_alloc => unreachable, |
| 1244 | }, | 1091 | }, |
| 1245 | .opt => |opt| { | 1092 | .opt => |opt| { |
| 1246 | const payload_ty = ty.optionalChild(mod); | 1093 | const payload_ty = ty.optionalChild(zcu); |
| 1247 | 1094 | ||
| 1248 | const is_null_val = Value.makeBool(opt.val == .none); | 1095 | const is_null_val = Value.makeBool(opt.val == .none); |
| 1249 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) | 1096 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) |
| 1250 | return dg.renderValue(writer, Type.bool, is_null_val, location); | 1097 | return dg.renderValue(writer, is_null_val, location); |
| 1251 | 1098 | ||
| 1252 | if (ty.optionalReprIsPayload(mod)) return dg.renderValue( | 1099 | if (ty.optionalReprIsPayload(zcu)) return dg.renderValue( |
| 1253 | writer, | 1100 | writer, |
| 1254 | payload_ty, | ||
| 1255 | switch (opt.val) { | 1101 | switch (opt.val) { |
| 1256 | .none => switch (payload_ty.zigTypeTag(mod)) { | 1102 | .none => switch (payload_ty.zigTypeTag(zcu)) { |
| 1257 | .ErrorSet => try mod.intValue(try mod.errorIntType(), 0), | 1103 | .ErrorSet => try zcu.intValue(try zcu.errorIntType(), 0), |
| 1258 | .Pointer => try mod.getCoerced(val, payload_ty), | 1104 | .Pointer => try zcu.getCoerced(val, payload_ty), |
| 1259 | else => unreachable, | 1105 | else => unreachable, |
| 1260 | }, | 1106 | }, |
| 1261 | else => |payload| Value.fromInterned(payload), | 1107 | else => |payload| Value.fromInterned(payload), |
| ... | @@ -1270,15 +1116,19 @@ pub const DeclGen = struct { | ... | @@ -1270,15 +1116,19 @@ pub const DeclGen = struct { |
| 1270 | } | 1116 | } |
| 1271 | 1117 | ||
| 1272 | try writer.writeAll("{ .payload = "); | 1118 | try writer.writeAll("{ .payload = "); |
| 1273 | try dg.renderValue(writer, payload_ty, Value.fromInterned(switch (opt.val) { | 1119 | switch (opt.val) { |
| 1274 | .none => try mod.intern(.{ .undef = payload_ty.ip_index }), | 1120 | .none => try dg.renderUndefValue(writer, payload_ty, initializer_type), |
| 1275 | else => |payload| payload, | 1121 | else => |payload| try dg.renderValue( |
| 1276 | }), initializer_type); | 1122 | writer, |
| 1123 | Value.fromInterned(payload), | ||
| 1124 | initializer_type, | ||
| 1125 | ), | ||
| 1126 | } | ||
| 1277 | try writer.writeAll(", .is_null = "); | 1127 | try writer.writeAll(", .is_null = "); |
| 1278 | try dg.renderValue(writer, Type.bool, is_null_val, initializer_type); | 1128 | try dg.renderValue(writer, is_null_val, initializer_type); |
| 1279 | try writer.writeAll(" }"); | 1129 | try writer.writeAll(" }"); |
| 1280 | }, | 1130 | }, |
| 1281 | .aggregate => switch (ip.indexToKey(ty.ip_index)) { | 1131 | .aggregate => switch (ip.indexToKey(ty.toIntern())) { |
| 1282 | .array_type, .vector_type => { | 1132 | .array_type, .vector_type => { |
| 1283 | if (location == .FunctionArgument) { | 1133 | if (location == .FunctionArgument) { |
| 1284 | try writer.writeByte('('); | 1134 | try writer.writeByte('('); |
| ... | @@ -1287,21 +1137,21 @@ pub const DeclGen = struct { | ... | @@ -1287,21 +1137,21 @@ pub const DeclGen = struct { |
| 1287 | } | 1137 | } |
| 1288 | // Fall back to generic implementation. | 1138 | // Fall back to generic implementation. |
| 1289 | 1139 | ||
| 1290 | const ai = ty.arrayInfo(mod); | 1140 | const ai = ty.arrayInfo(zcu); |
| 1291 | if (ai.elem_type.eql(Type.u8, mod)) { | 1141 | if (ai.elem_type.eql(Type.u8, zcu)) { |
| 1292 | var literal = stringLiteral(writer, ty.arrayLenIncludingSentinel(mod)); | 1142 | var literal = stringLiteral(writer, ty.arrayLenIncludingSentinel(zcu)); |
| 1293 | try literal.start(); | 1143 | try literal.start(); |
| 1294 | var index: usize = 0; | 1144 | var index: usize = 0; |
| 1295 | while (index < ai.len) : (index += 1) { | 1145 | while (index < ai.len) : (index += 1) { |
| 1296 | const elem_val = try val.elemValue(mod, index); | 1146 | const elem_val = try val.elemValue(zcu, index); |
| 1297 | const elem_val_u8: u8 = if (elem_val.isUndef(mod)) | 1147 | const elem_val_u8: u8 = if (elem_val.isUndef(zcu)) |
| 1298 | undefPattern(u8) | 1148 | undefPattern(u8) |
| 1299 | else | 1149 | else |
| 1300 | @intCast(elem_val.toUnsignedInt(mod)); | 1150 | @intCast(elem_val.toUnsignedInt(zcu)); |
| 1301 | try literal.writeChar(elem_val_u8); | 1151 | try literal.writeChar(elem_val_u8); |
| 1302 | } | 1152 | } |
| 1303 | if (ai.sentinel) |s| { | 1153 | if (ai.sentinel) |s| { |
| 1304 | const s_u8: u8 = @intCast(s.toUnsignedInt(mod)); | 1154 | const s_u8: u8 = @intCast(s.toUnsignedInt(zcu)); |
| 1305 | if (s_u8 != 0) try literal.writeChar(s_u8); | 1155 | if (s_u8 != 0) try literal.writeChar(s_u8); |
| 1306 | } | 1156 | } |
| 1307 | try literal.end(); | 1157 | try literal.end(); |
| ... | @@ -1310,12 +1160,12 @@ pub const DeclGen = struct { | ... | @@ -1310,12 +1160,12 @@ pub const DeclGen = struct { |
| 1310 | var index: usize = 0; | 1160 | var index: usize = 0; |
| 1311 | while (index < ai.len) : (index += 1) { | 1161 | while (index < ai.len) : (index += 1) { |
| 1312 | if (index != 0) try writer.writeByte(','); | 1162 | if (index != 0) try writer.writeByte(','); |
| 1313 | const elem_val = try val.elemValue(mod, index); | 1163 | const elem_val = try val.elemValue(zcu, index); |
| 1314 | try dg.renderValue(writer, ai.elem_type, elem_val, initializer_type); | 1164 | try dg.renderValue(writer, elem_val, initializer_type); |
| 1315 | } | 1165 | } |
| 1316 | if (ai.sentinel) |s| { | 1166 | if (ai.sentinel) |s| { |
| 1317 | if (index != 0) try writer.writeByte(','); | 1167 | if (index != 0) try writer.writeByte(','); |
| 1318 | try dg.renderValue(writer, ai.elem_type, s, initializer_type); | 1168 | try dg.renderValue(writer, s, initializer_type); |
| 1319 | } | 1169 | } |
| 1320 | try writer.writeByte('}'); | 1170 | try writer.writeByte('}'); |
| 1321 | } | 1171 | } |
| ... | @@ -1333,27 +1183,29 @@ pub const DeclGen = struct { | ... | @@ -1333,27 +1183,29 @@ pub const DeclGen = struct { |
| 1333 | const comptime_val = tuple.values.get(ip)[field_index]; | 1183 | const comptime_val = tuple.values.get(ip)[field_index]; |
| 1334 | if (comptime_val != .none) continue; | 1184 | if (comptime_val != .none) continue; |
| 1335 | const field_ty = Type.fromInterned(tuple.types.get(ip)[field_index]); | 1185 | const field_ty = Type.fromInterned(tuple.types.get(ip)[field_index]); |
| 1336 | if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; | 1186 | if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; |
| 1337 | 1187 | ||
| 1338 | if (!empty) try writer.writeByte(','); | 1188 | if (!empty) try writer.writeByte(','); |
| 1339 | 1189 | ||
| 1340 | const field_val = Value.fromInterned(switch (ip.indexToKey(val.ip_index).aggregate.storage) { | 1190 | const field_val = Value.fromInterned( |
| 1341 | .bytes => |bytes| try ip.get(mod.gpa, .{ .int = .{ | 1191 | switch (ip.indexToKey(val.toIntern()).aggregate.storage) { |
| 1342 | .ty = field_ty.toIntern(), | 1192 | .bytes => |bytes| try ip.get(zcu.gpa, .{ .int = .{ |
| 1343 | .storage = .{ .u64 = bytes[field_index] }, | 1193 | .ty = field_ty.toIntern(), |
| 1344 | } }), | 1194 | .storage = .{ .u64 = bytes[field_index] }, |
| 1345 | .elems => |elems| elems[field_index], | 1195 | } }), |
| 1346 | .repeated_elem => |elem| elem, | 1196 | .elems => |elems| elems[field_index], |
| 1347 | }); | 1197 | .repeated_elem => |elem| elem, |
| 1348 | try dg.renderValue(writer, field_ty, field_val, initializer_type); | 1198 | }, |
| 1199 | ); | ||
| 1200 | try dg.renderValue(writer, field_val, initializer_type); | ||
| 1349 | 1201 | ||
| 1350 | empty = false; | 1202 | empty = false; |
| 1351 | } | 1203 | } |
| 1352 | try writer.writeByte('}'); | 1204 | try writer.writeByte('}'); |
| 1353 | }, | 1205 | }, |
| 1354 | .struct_type => { | 1206 | .struct_type => { |
| 1355 | const struct_type = ip.loadStructType(ty.toIntern()); | 1207 | const loaded_struct = ip.loadStructType(ty.toIntern()); |
| 1356 | switch (struct_type.layout) { | 1208 | switch (loaded_struct.layout) { |
| 1357 | .auto, .@"extern" => { | 1209 | .auto, .@"extern" => { |
| 1358 | if (!location.isInitializer()) { | 1210 | if (!location.isInitializer()) { |
| 1359 | try writer.writeByte('('); | 1211 | try writer.writeByte('('); |
| ... | @@ -1362,47 +1214,46 @@ pub const DeclGen = struct { | ... | @@ -1362,47 +1214,46 @@ pub const DeclGen = struct { |
| 1362 | } | 1214 | } |
| 1363 | 1215 | ||
| 1364 | try writer.writeByte('{'); | 1216 | try writer.writeByte('{'); |
| 1365 | var empty = true; | 1217 | var field_it = loaded_struct.iterateRuntimeOrder(ip); |
| 1366 | for (0..struct_type.field_types.len) |field_index| { | 1218 | var need_comma = false; |
| 1367 | const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[field_index]); | 1219 | while (field_it.next()) |field_index| { |
| 1368 | if (struct_type.fieldIsComptime(ip, field_index)) continue; | 1220 | const field_ty = Type.fromInterned(loaded_struct.field_types.get(ip)[field_index]); |
| 1369 | if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; | 1221 | if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; |
| 1370 | 1222 | ||
| 1371 | if (!empty) try writer.writeByte(','); | 1223 | if (need_comma) try writer.writeByte(','); |
| 1372 | const field_val = switch (ip.indexToKey(val.ip_index).aggregate.storage) { | 1224 | need_comma = true; |
| 1373 | .bytes => |bytes| try ip.get(mod.gpa, .{ .int = .{ | 1225 | const field_val = switch (ip.indexToKey(val.toIntern()).aggregate.storage) { |
| 1226 | .bytes => |bytes| try ip.get(zcu.gpa, .{ .int = .{ | ||
| 1374 | .ty = field_ty.toIntern(), | 1227 | .ty = field_ty.toIntern(), |
| 1375 | .storage = .{ .u64 = bytes[field_index] }, | 1228 | .storage = .{ .u64 = bytes[field_index] }, |
| 1376 | } }), | 1229 | } }), |
| 1377 | .elems => |elems| elems[field_index], | 1230 | .elems => |elems| elems[field_index], |
| 1378 | .repeated_elem => |elem| elem, | 1231 | .repeated_elem => |elem| elem, |
| 1379 | }; | 1232 | }; |
| 1380 | try dg.renderValue(writer, field_ty, Value.fromInterned(field_val), initializer_type); | 1233 | try dg.renderValue(writer, Value.fromInterned(field_val), initializer_type); |
| 1381 | |||
| 1382 | empty = false; | ||
| 1383 | } | 1234 | } |
| 1384 | try writer.writeByte('}'); | 1235 | try writer.writeByte('}'); |
| 1385 | }, | 1236 | }, |
| 1386 | .@"packed" => { | 1237 | .@"packed" => { |
| 1387 | const int_info = ty.intInfo(mod); | 1238 | const int_info = ty.intInfo(zcu); |
| 1388 | 1239 | ||
| 1389 | const bits = Type.smallestUnsignedBits(int_info.bits - 1); | 1240 | const bits = Type.smallestUnsignedBits(int_info.bits - 1); |
| 1390 | const bit_offset_ty = try mod.intType(.unsigned, bits); | 1241 | const bit_offset_ty = try zcu.intType(.unsigned, bits); |
| 1391 | 1242 | ||
| 1392 | var bit_offset: u64 = 0; | 1243 | var bit_offset: u64 = 0; |
| 1393 | var eff_num_fields: usize = 0; | 1244 | var eff_num_fields: usize = 0; |
| 1394 | 1245 | ||
| 1395 | for (0..struct_type.field_types.len) |field_index| { | 1246 | for (0..loaded_struct.field_types.len) |field_index| { |
| 1396 | const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[field_index]); | 1247 | const field_ty = Type.fromInterned(loaded_struct.field_types.get(ip)[field_index]); |
| 1397 | if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; | 1248 | if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; |
| 1398 | eff_num_fields += 1; | 1249 | eff_num_fields += 1; |
| 1399 | } | 1250 | } |
| 1400 | 1251 | ||
| 1401 | if (eff_num_fields == 0) { | 1252 | if (eff_num_fields == 0) { |
| 1402 | try writer.writeByte('('); | 1253 | try writer.writeByte('('); |
| 1403 | try dg.renderValue(writer, ty, Value.undef, initializer_type); | 1254 | try dg.renderUndefValue(writer, ty, initializer_type); |
| 1404 | try writer.writeByte(')'); | 1255 | try writer.writeByte(')'); |
| 1405 | } else if (ty.bitSize(mod) > 64) { | 1256 | } else if (ty.bitSize(zcu) > 64) { |
| 1406 | // zig_or_u128(zig_or_u128(zig_shl_u128(a, a_off), zig_shl_u128(b, b_off)), zig_shl_u128(c, c_off)) | 1257 | // zig_or_u128(zig_or_u128(zig_shl_u128(a, a_off), zig_shl_u128(b, b_off)), zig_shl_u128(c, c_off)) |
| 1407 | var num_or = eff_num_fields - 1; | 1258 | var num_or = eff_num_fields - 1; |
| 1408 | while (num_or > 0) : (num_or -= 1) { | 1259 | while (num_or > 0) : (num_or -= 1) { |
| ... | @@ -1413,12 +1264,12 @@ pub const DeclGen = struct { | ... | @@ -1413,12 +1264,12 @@ pub const DeclGen = struct { |
| 1413 | 1264 | ||
| 1414 | var eff_index: usize = 0; | 1265 | var eff_index: usize = 0; |
| 1415 | var needs_closing_paren = false; | 1266 | var needs_closing_paren = false; |
| 1416 | for (0..struct_type.field_types.len) |field_index| { | 1267 | for (0..loaded_struct.field_types.len) |field_index| { |
| 1417 | const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[field_index]); | 1268 | const field_ty = Type.fromInterned(loaded_struct.field_types.get(ip)[field_index]); |
| 1418 | if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; | 1269 | if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; |
| 1419 | 1270 | ||
| 1420 | const field_val = switch (ip.indexToKey(val.ip_index).aggregate.storage) { | 1271 | const field_val = switch (ip.indexToKey(val.toIntern()).aggregate.storage) { |
| 1421 | .bytes => |bytes| try ip.get(mod.gpa, .{ .int = .{ | 1272 | .bytes => |bytes| try ip.get(zcu.gpa, .{ .int = .{ |
| 1422 | .ty = field_ty.toIntern(), | 1273 | .ty = field_ty.toIntern(), |
| 1423 | .storage = .{ .u64 = bytes[field_index] }, | 1274 | .storage = .{ .u64 = bytes[field_index] }, |
| 1424 | } }), | 1275 | } }), |
| ... | @@ -1432,8 +1283,7 @@ pub const DeclGen = struct { | ... | @@ -1432,8 +1283,7 @@ pub const DeclGen = struct { |
| 1432 | try writer.writeByte('('); | 1283 | try writer.writeByte('('); |
| 1433 | try dg.renderIntCast(writer, ty, cast_context, field_ty, .FunctionArgument); | 1284 | try dg.renderIntCast(writer, ty, cast_context, field_ty, .FunctionArgument); |
| 1434 | try writer.writeAll(", "); | 1285 | try writer.writeAll(", "); |
| 1435 | const bit_offset_val = try mod.intValue(bit_offset_ty, bit_offset); | 1286 | try dg.renderValue(writer, try zcu.intValue(bit_offset_ty, bit_offset), .FunctionArgument); |
| 1436 | try dg.renderValue(writer, bit_offset_ty, bit_offset_val, .FunctionArgument); | ||
| 1437 | try writer.writeByte(')'); | 1287 | try writer.writeByte(')'); |
| 1438 | } else { | 1288 | } else { |
| 1439 | try dg.renderIntCast(writer, ty, cast_context, field_ty, .FunctionArgument); | 1289 | try dg.renderIntCast(writer, ty, cast_context, field_ty, .FunctionArgument); |
| ... | @@ -1442,7 +1292,7 @@ pub const DeclGen = struct { | ... | @@ -1442,7 +1292,7 @@ pub const DeclGen = struct { |
| 1442 | if (needs_closing_paren) try writer.writeByte(')'); | 1292 | if (needs_closing_paren) try writer.writeByte(')'); |
| 1443 | if (eff_index != eff_num_fields - 1) try writer.writeAll(", "); | 1293 | if (eff_index != eff_num_fields - 1) try writer.writeAll(", "); |
| 1444 | 1294 | ||
| 1445 | bit_offset += field_ty.bitSize(mod); | 1295 | bit_offset += field_ty.bitSize(zcu); |
| 1446 | needs_closing_paren = true; | 1296 | needs_closing_paren = true; |
| 1447 | eff_index += 1; | 1297 | eff_index += 1; |
| 1448 | } | 1298 | } |
| ... | @@ -1450,17 +1300,17 @@ pub const DeclGen = struct { | ... | @@ -1450,17 +1300,17 @@ pub const DeclGen = struct { |
| 1450 | try writer.writeByte('('); | 1300 | try writer.writeByte('('); |
| 1451 | // a << a_off | b << b_off | c << c_off | 1301 | // a << a_off | b << b_off | c << c_off |
| 1452 | var empty = true; | 1302 | var empty = true; |
| 1453 | for (0..struct_type.field_types.len) |field_index| { | 1303 | for (0..loaded_struct.field_types.len) |field_index| { |
| 1454 | const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[field_index]); | 1304 | const field_ty = Type.fromInterned(loaded_struct.field_types.get(ip)[field_index]); |
| 1455 | if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; | 1305 | if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; |
| 1456 | 1306 | ||
| 1457 | if (!empty) try writer.writeAll(" | "); | 1307 | if (!empty) try writer.writeAll(" | "); |
| 1458 | try writer.writeByte('('); | 1308 | try writer.writeByte('('); |
| 1459 | try dg.renderType(writer, ty); | 1309 | try dg.renderType(writer, ty); |
| 1460 | try writer.writeByte(')'); | 1310 | try writer.writeByte(')'); |
| 1461 | 1311 | ||
| 1462 | const field_val = switch (ip.indexToKey(val.ip_index).aggregate.storage) { | 1312 | const field_val = switch (ip.indexToKey(val.toIntern()).aggregate.storage) { |
| 1463 | .bytes => |bytes| try ip.get(mod.gpa, .{ .int = .{ | 1313 | .bytes => |bytes| try ip.get(zcu.gpa, .{ .int = .{ |
| 1464 | .ty = field_ty.toIntern(), | 1314 | .ty = field_ty.toIntern(), |
| 1465 | .storage = .{ .u64 = bytes[field_index] }, | 1315 | .storage = .{ .u64 = bytes[field_index] }, |
| 1466 | } }), | 1316 | } }), |
| ... | @@ -1469,15 +1319,14 @@ pub const DeclGen = struct { | ... | @@ -1469,15 +1319,14 @@ pub const DeclGen = struct { |
| 1469 | }; | 1319 | }; |
| 1470 | 1320 | ||
| 1471 | if (bit_offset != 0) { | 1321 | if (bit_offset != 0) { |
| 1472 | try dg.renderValue(writer, field_ty, Value.fromInterned(field_val), .Other); | 1322 | try dg.renderValue(writer, Value.fromInterned(field_val), .Other); |
| 1473 | try writer.writeAll(" << "); | 1323 | try writer.writeAll(" << "); |
| 1474 | const bit_offset_val = try mod.intValue(bit_offset_ty, bit_offset); | 1324 | try dg.renderValue(writer, try zcu.intValue(bit_offset_ty, bit_offset), .FunctionArgument); |
| 1475 | try dg.renderValue(writer, bit_offset_ty, bit_offset_val, .FunctionArgument); | ||
| 1476 | } else { | 1325 | } else { |
| 1477 | try dg.renderValue(writer, field_ty, Value.fromInterned(field_val), .Other); | 1326 | try dg.renderValue(writer, Value.fromInterned(field_val), .Other); |
| 1478 | } | 1327 | } |
| 1479 | 1328 | ||
| 1480 | bit_offset += field_ty.bitSize(mod); | 1329 | bit_offset += field_ty.bitSize(zcu); |
| 1481 | empty = false; | 1330 | empty = false; |
| 1482 | } | 1331 | } |
| 1483 | try writer.writeByte(')'); | 1332 | try writer.writeByte(')'); |
| ... | @@ -1488,30 +1337,30 @@ pub const DeclGen = struct { | ... | @@ -1488,30 +1337,30 @@ pub const DeclGen = struct { |
| 1488 | else => unreachable, | 1337 | else => unreachable, |
| 1489 | }, | 1338 | }, |
| 1490 | .un => |un| { | 1339 | .un => |un| { |
| 1491 | const union_obj = mod.typeToUnion(ty).?; | 1340 | const loaded_union = ip.loadUnionType(ty.toIntern()); |
| 1492 | if (un.tag == .none) { | 1341 | if (un.tag == .none) { |
| 1493 | const backing_ty = try ty.unionBackingType(mod); | 1342 | const backing_ty = try ty.unionBackingType(zcu); |
| 1494 | switch (union_obj.getLayout(ip)) { | 1343 | switch (loaded_union.getLayout(ip)) { |
| 1495 | .@"packed" => { | 1344 | .@"packed" => { |
| 1496 | if (!location.isInitializer()) { | 1345 | if (!location.isInitializer()) { |
| 1497 | try writer.writeByte('('); | 1346 | try writer.writeByte('('); |
| 1498 | try dg.renderType(writer, backing_ty); | 1347 | try dg.renderType(writer, backing_ty); |
| 1499 | try writer.writeByte(')'); | 1348 | try writer.writeByte(')'); |
| 1500 | } | 1349 | } |
| 1501 | try dg.renderValue(writer, backing_ty, Value.fromInterned(un.val), initializer_type); | 1350 | try dg.renderValue(writer, Value.fromInterned(un.val), initializer_type); |
| 1502 | }, | 1351 | }, |
| 1503 | .@"extern" => { | 1352 | .@"extern" => { |
| 1504 | if (location == .StaticInitializer) { | 1353 | if (location == .StaticInitializer) { |
| 1505 | return dg.fail("TODO: C backend: implement extern union backing type rendering in static initializers", .{}); | 1354 | return dg.fail("TODO: C backend: implement extern union backing type rendering in static initializers", .{}); |
| 1506 | } | 1355 | } |
| 1507 | 1356 | ||
| 1508 | const ptr_ty = try mod.singleConstPtrType(ty); | 1357 | const ptr_ty = try zcu.singleConstPtrType(ty); |
| 1509 | try writer.writeAll("*(("); | 1358 | try writer.writeAll("*(("); |
| 1510 | try dg.renderType(writer, ptr_ty); | 1359 | try dg.renderType(writer, ptr_ty); |
| 1511 | try writer.writeAll(")("); | 1360 | try writer.writeAll(")("); |
| 1512 | try dg.renderType(writer, backing_ty); | 1361 | try dg.renderType(writer, backing_ty); |
| 1513 | try writer.writeAll("){"); | 1362 | try writer.writeAll("){"); |
| 1514 | try dg.renderValue(writer, backing_ty, Value.fromInterned(un.val), initializer_type); | 1363 | try dg.renderValue(writer, Value.fromInterned(un.val), initializer_type); |
| 1515 | try writer.writeAll("})"); | 1364 | try writer.writeAll("})"); |
| 1516 | }, | 1365 | }, |
| 1517 | else => unreachable, | 1366 | else => unreachable, |
| ... | @@ -1523,21 +1372,21 @@ pub const DeclGen = struct { | ... | @@ -1523,21 +1372,21 @@ pub const DeclGen = struct { |
| 1523 | try writer.writeByte(')'); | 1372 | try writer.writeByte(')'); |
| 1524 | } | 1373 | } |
| 1525 | 1374 | ||
| 1526 | const field_index = mod.unionTagFieldIndex(union_obj, Value.fromInterned(un.tag)).?; | 1375 | const field_index = zcu.unionTagFieldIndex(loaded_union, Value.fromInterned(un.tag)).?; |
| 1527 | const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[field_index]); | 1376 | const field_ty = Type.fromInterned(loaded_union.field_types.get(ip)[field_index]); |
| 1528 | const field_name = union_obj.loadTagType(ip).names.get(ip)[field_index]; | 1377 | const field_name = loaded_union.loadTagType(ip).names.get(ip)[field_index]; |
| 1529 | if (union_obj.getLayout(ip) == .@"packed") { | 1378 | if (loaded_union.getLayout(ip) == .@"packed") { |
| 1530 | if (field_ty.hasRuntimeBits(mod)) { | 1379 | if (field_ty.hasRuntimeBits(zcu)) { |
| 1531 | if (field_ty.isPtrAtRuntime(mod)) { | 1380 | if (field_ty.isPtrAtRuntime(zcu)) { |
| 1532 | try writer.writeByte('('); | 1381 | try writer.writeByte('('); |
| 1533 | try dg.renderType(writer, ty); | 1382 | try dg.renderType(writer, ty); |
| 1534 | try writer.writeByte(')'); | 1383 | try writer.writeByte(')'); |
| 1535 | } else if (field_ty.zigTypeTag(mod) == .Float) { | 1384 | } else if (field_ty.zigTypeTag(zcu) == .Float) { |
| 1536 | try writer.writeByte('('); | 1385 | try writer.writeByte('('); |
| 1537 | try dg.renderType(writer, ty); | 1386 | try dg.renderType(writer, ty); |
| 1538 | try writer.writeByte(')'); | 1387 | try writer.writeByte(')'); |
| 1539 | } | 1388 | } |
| 1540 | try dg.renderValue(writer, field_ty, Value.fromInterned(un.val), initializer_type); | 1389 | try dg.renderValue(writer, Value.fromInterned(un.val), initializer_type); |
| 1541 | } else { | 1390 | } else { |
| 1542 | try writer.writeAll("0"); | 1391 | try writer.writeAll("0"); |
| 1543 | } | 1392 | } |
| ... | @@ -1545,33 +1394,291 @@ pub const DeclGen = struct { | ... | @@ -1545,33 +1394,291 @@ pub const DeclGen = struct { |
| 1545 | } | 1394 | } |
| 1546 | 1395 | ||
| 1547 | try writer.writeByte('{'); | 1396 | try writer.writeByte('{'); |
| 1548 | if (ty.unionTagTypeSafety(mod)) |tag_ty| { | 1397 | if (ty.unionTagTypeSafety(zcu)) |_| { |
| 1549 | const layout = mod.getUnionLayout(union_obj); | 1398 | const layout = zcu.getUnionLayout(loaded_union); |
| 1550 | if (layout.tag_size != 0) { | 1399 | if (layout.tag_size != 0) { |
| 1551 | try writer.writeAll(" .tag = "); | 1400 | try writer.writeAll(" .tag = "); |
| 1552 | try dg.renderValue(writer, tag_ty, Value.fromInterned(un.tag), initializer_type); | 1401 | try dg.renderValue(writer, Value.fromInterned(un.tag), initializer_type); |
| 1553 | } | 1402 | } |
| 1554 | if (ty.unionHasAllZeroBitFieldTypes(mod)) return try writer.writeByte('}'); | 1403 | if (ty.unionHasAllZeroBitFieldTypes(zcu)) return try writer.writeByte('}'); |
| 1555 | if (layout.tag_size != 0) try writer.writeByte(','); | 1404 | if (layout.tag_size != 0) try writer.writeByte(','); |
| 1556 | try writer.writeAll(" .payload = {"); | 1405 | try writer.writeAll(" .payload = {"); |
| 1557 | } | 1406 | } |
| 1558 | if (field_ty.hasRuntimeBits(mod)) { | 1407 | if (field_ty.hasRuntimeBits(zcu)) { |
| 1559 | try writer.print(" .{ } = ", .{fmtIdent(ip.stringToSlice(field_name))}); | 1408 | try writer.print(" .{ } = ", .{fmtIdent(ip.stringToSlice(field_name))}); |
| 1560 | try dg.renderValue(writer, field_ty, Value.fromInterned(un.val), initializer_type); | 1409 | try dg.renderValue(writer, Value.fromInterned(un.val), initializer_type); |
| 1561 | try writer.writeByte(' '); | 1410 | try writer.writeByte(' '); |
| 1562 | } else for (0..union_obj.field_types.len) |this_field_index| { | 1411 | } else for (0..loaded_union.field_types.len) |this_field_index| { |
| 1563 | const this_field_ty = Type.fromInterned(union_obj.field_types.get(ip)[this_field_index]); | 1412 | const this_field_ty = Type.fromInterned(loaded_union.field_types.get(ip)[this_field_index]); |
| 1564 | if (!this_field_ty.hasRuntimeBits(mod)) continue; | 1413 | if (!this_field_ty.hasRuntimeBits(zcu)) continue; |
| 1565 | try dg.renderValue(writer, this_field_ty, Value.undef, initializer_type); | 1414 | try dg.renderUndefValue(writer, this_field_ty, initializer_type); |
| 1566 | break; | 1415 | break; |
| 1567 | } | 1416 | } |
| 1568 | if (ty.unionTagTypeSafety(mod)) |_| try writer.writeByte('}'); | 1417 | if (ty.unionTagTypeSafety(zcu)) |_| try writer.writeByte('}'); |
| 1569 | try writer.writeByte('}'); | 1418 | try writer.writeByte('}'); |
| 1570 | } | 1419 | } |
| 1571 | }, | 1420 | }, |
| 1572 | } | 1421 | } |
| 1573 | } | 1422 | } |
| 1574 | 1423 | ||
| 1424 | fn renderUndefValue( | ||
| 1425 | dg: *DeclGen, | ||
| 1426 | writer: anytype, | ||
| 1427 | ty: Type, | ||
| 1428 | location: ValueRenderLocation, | ||
| 1429 | ) error{ OutOfMemory, AnalysisFail }!void { | ||
| 1430 | const zcu = dg.zcu; | ||
| 1431 | const ip = &zcu.intern_pool; | ||
| 1432 | const target = &dg.mod.resolved_target.result; | ||
| 1433 | |||
| 1434 | const initializer_type: ValueRenderLocation = switch (location) { | ||
| 1435 | .StaticInitializer => .StaticInitializer, | ||
| 1436 | else => .Initializer, | ||
| 1437 | }; | ||
| 1438 | |||
| 1439 | const safety_on = switch (zcu.optimizeMode()) { | ||
| 1440 | .Debug, .ReleaseSafe => true, | ||
| 1441 | .ReleaseFast, .ReleaseSmall => false, | ||
| 1442 | }; | ||
| 1443 | |||
| 1444 | switch (ty.toIntern()) { | ||
| 1445 | .c_longdouble_type, | ||
| 1446 | .f16_type, | ||
| 1447 | .f32_type, | ||
| 1448 | .f64_type, | ||
| 1449 | .f80_type, | ||
| 1450 | .f128_type, | ||
| 1451 | => { | ||
| 1452 | const bits = ty.floatBits(target.*); | ||
| 1453 | // All unsigned ints matching float types are pre-allocated. | ||
| 1454 | const repr_ty = zcu.intType(.unsigned, bits) catch unreachable; | ||
| 1455 | |||
| 1456 | try writer.writeAll("zig_make_"); | ||
| 1457 | try dg.renderTypeForBuiltinFnName(writer, ty); | ||
| 1458 | try writer.writeByte('('); | ||
| 1459 | switch (bits) { | ||
| 1460 | 16 => try writer.print("{x}", .{@as(f16, @bitCast(undefPattern(i16)))}), | ||
| 1461 | 32 => try writer.print("{x}", .{@as(f32, @bitCast(undefPattern(i32)))}), | ||
| 1462 | 64 => try writer.print("{x}", .{@as(f64, @bitCast(undefPattern(i64)))}), | ||
| 1463 | 80 => try writer.print("{x}", .{@as(f80, @bitCast(undefPattern(i80)))}), | ||
| 1464 | 128 => try writer.print("{x}", .{@as(f128, @bitCast(undefPattern(i128)))}), | ||
| 1465 | else => unreachable, | ||
| 1466 | } | ||
| 1467 | try writer.writeAll(", "); | ||
| 1468 | try dg.renderUndefValue(writer, repr_ty, .FunctionArgument); | ||
| 1469 | return writer.writeByte(')'); | ||
| 1470 | }, | ||
| 1471 | .bool_type => try writer.writeAll(if (safety_on) "0xaa" else "false"), | ||
| 1472 | else => switch (ip.indexToKey(ty.toIntern())) { | ||
| 1473 | .simple_type, | ||
| 1474 | .int_type, | ||
| 1475 | .enum_type, | ||
| 1476 | .error_set_type, | ||
| 1477 | .inferred_error_set_type, | ||
| 1478 | => return writer.print("{x}", .{ | ||
| 1479 | try dg.fmtIntLiteral(try zcu.undefValue(ty), location), | ||
| 1480 | }), | ||
| 1481 | .ptr_type => if (ty.isSlice(zcu)) { | ||
| 1482 | if (!location.isInitializer()) { | ||
| 1483 | try writer.writeByte('('); | ||
| 1484 | try dg.renderType(writer, ty); | ||
| 1485 | try writer.writeByte(')'); | ||
| 1486 | } | ||
| 1487 | |||
| 1488 | try writer.writeAll("{("); | ||
| 1489 | const ptr_ty = ty.slicePtrFieldType(zcu); | ||
| 1490 | try dg.renderType(writer, ptr_ty); | ||
| 1491 | return writer.print("){x}, {0x}}}", .{ | ||
| 1492 | try dg.fmtIntLiteral(try zcu.undefValue(Type.usize), .Other), | ||
| 1493 | }); | ||
| 1494 | } else { | ||
| 1495 | try writer.writeAll("(("); | ||
| 1496 | try dg.renderType(writer, ty); | ||
| 1497 | return writer.print("){x})", .{ | ||
| 1498 | try dg.fmtIntLiteral(try zcu.undefValue(Type.usize), .Other), | ||
| 1499 | }); | ||
| 1500 | }, | ||
| 1501 | .opt_type => { | ||
| 1502 | const payload_ty = ty.optionalChild(zcu); | ||
| 1503 | |||
| 1504 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { | ||
| 1505 | return dg.renderUndefValue(writer, Type.bool, location); | ||
| 1506 | } | ||
| 1507 | |||
| 1508 | if (ty.optionalReprIsPayload(zcu)) { | ||
| 1509 | return dg.renderUndefValue(writer, payload_ty, location); | ||
| 1510 | } | ||
| 1511 | |||
| 1512 | if (!location.isInitializer()) { | ||
| 1513 | try writer.writeByte('('); | ||
| 1514 | try dg.renderType(writer, ty); | ||
| 1515 | try writer.writeByte(')'); | ||
| 1516 | } | ||
| 1517 | |||
| 1518 | try writer.writeAll("{ .payload = "); | ||
| 1519 | try dg.renderUndefValue(writer, payload_ty, initializer_type); | ||
| 1520 | try writer.writeAll(", .is_null = "); | ||
| 1521 | try dg.renderUndefValue(writer, Type.bool, initializer_type); | ||
| 1522 | return writer.writeAll(" }"); | ||
| 1523 | }, | ||
| 1524 | .struct_type => { | ||
| 1525 | const loaded_struct = ip.loadStructType(ty.toIntern()); | ||
| 1526 | switch (loaded_struct.layout) { | ||
| 1527 | .auto, .@"extern" => { | ||
| 1528 | if (!location.isInitializer()) { | ||
| 1529 | try writer.writeByte('('); | ||
| 1530 | try dg.renderType(writer, ty); | ||
| 1531 | try writer.writeByte(')'); | ||
| 1532 | } | ||
| 1533 | |||
| 1534 | try writer.writeByte('{'); | ||
| 1535 | var field_it = loaded_struct.iterateRuntimeOrder(ip); | ||
| 1536 | var need_comma = false; | ||
| 1537 | while (field_it.next()) |field_index| { | ||
| 1538 | const field_ty = Type.fromInterned(loaded_struct.field_types.get(ip)[field_index]); | ||
| 1539 | if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; | ||
| 1540 | |||
| 1541 | if (need_comma) try writer.writeByte(','); | ||
| 1542 | need_comma = true; | ||
| 1543 | try dg.renderUndefValue(writer, field_ty, initializer_type); | ||
| 1544 | } | ||
| 1545 | return writer.writeByte('}'); | ||
| 1546 | }, | ||
| 1547 | .@"packed" => return writer.print("{x}", .{ | ||
| 1548 | try dg.fmtIntLiteral(try zcu.undefValue(ty), .Other), | ||
| 1549 | }), | ||
| 1550 | } | ||
| 1551 | }, | ||
| 1552 | .anon_struct_type => |anon_struct_info| { | ||
| 1553 | if (!location.isInitializer()) { | ||
| 1554 | try writer.writeByte('('); | ||
| 1555 | try dg.renderType(writer, ty); | ||
| 1556 | try writer.writeByte(')'); | ||
| 1557 | } | ||
| 1558 | |||
| 1559 | try writer.writeByte('{'); | ||
| 1560 | var need_comma = false; | ||
| 1561 | for (0..anon_struct_info.types.len) |field_index| { | ||
| 1562 | if (anon_struct_info.values.get(ip)[field_index] != .none) continue; | ||
| 1563 | const field_ty = Type.fromInterned(anon_struct_info.types.get(ip)[field_index]); | ||
| 1564 | if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; | ||
| 1565 | |||
| 1566 | if (need_comma) try writer.writeByte(','); | ||
| 1567 | need_comma = true; | ||
| 1568 | try dg.renderUndefValue(writer, field_ty, initializer_type); | ||
| 1569 | } | ||
| 1570 | return writer.writeByte('}'); | ||
| 1571 | }, | ||
| 1572 | .union_type => { | ||
| 1573 | const loaded_union = ip.loadUnionType(ty.toIntern()); | ||
| 1574 | switch (loaded_union.getLayout(ip)) { | ||
| 1575 | .auto, .@"extern" => { | ||
| 1576 | if (!location.isInitializer()) { | ||
| 1577 | try writer.writeByte('('); | ||
| 1578 | try dg.renderType(writer, ty); | ||
| 1579 | try writer.writeByte(')'); | ||
| 1580 | } | ||
| 1581 | |||
| 1582 | try writer.writeByte('{'); | ||
| 1583 | if (ty.unionTagTypeSafety(zcu)) |tag_ty| { | ||
| 1584 | const layout = ty.unionGetLayout(zcu); | ||
| 1585 | if (layout.tag_size != 0) { | ||
| 1586 | try writer.writeAll(" .tag = "); | ||
| 1587 | try dg.renderUndefValue(writer, tag_ty, initializer_type); | ||
| 1588 | } | ||
| 1589 | if (ty.unionHasAllZeroBitFieldTypes(zcu)) return try writer.writeByte('}'); | ||
| 1590 | if (layout.tag_size != 0) try writer.writeByte(','); | ||
| 1591 | try writer.writeAll(" .payload = {"); | ||
| 1592 | } | ||
| 1593 | for (0..loaded_union.field_types.len) |field_index| { | ||
| 1594 | const field_ty = Type.fromInterned(loaded_union.field_types.get(ip)[field_index]); | ||
| 1595 | if (!field_ty.hasRuntimeBits(zcu)) continue; | ||
| 1596 | try dg.renderUndefValue(writer, field_ty, initializer_type); | ||
| 1597 | break; | ||
| 1598 | } | ||
| 1599 | if (ty.unionTagTypeSafety(zcu)) |_| try writer.writeByte('}'); | ||
| 1600 | return writer.writeByte('}'); | ||
| 1601 | }, | ||
| 1602 | .@"packed" => return writer.print("{x}", .{ | ||
| 1603 | try dg.fmtIntLiteral(try zcu.undefValue(ty), .Other), | ||
| 1604 | }), | ||
| 1605 | } | ||
| 1606 | }, | ||
| 1607 | .error_union_type => { | ||
| 1608 | const payload_ty = ty.errorUnionPayload(zcu); | ||
| 1609 | const error_ty = ty.errorUnionSet(zcu); | ||
| 1610 | |||
| 1611 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { | ||
| 1612 | return dg.renderUndefValue(writer, error_ty, location); | ||
| 1613 | } | ||
| 1614 | |||
| 1615 | if (!location.isInitializer()) { | ||
| 1616 | try writer.writeByte('('); | ||
| 1617 | try dg.renderType(writer, ty); | ||
| 1618 | try writer.writeByte(')'); | ||
| 1619 | } | ||
| 1620 | |||
| 1621 | try writer.writeAll("{ .payload = "); | ||
| 1622 | try dg.renderUndefValue(writer, payload_ty, initializer_type); | ||
| 1623 | try writer.writeAll(", .error = "); | ||
| 1624 | try dg.renderUndefValue(writer, error_ty, initializer_type); | ||
| 1625 | return writer.writeAll(" }"); | ||
| 1626 | }, | ||
| 1627 | .array_type, .vector_type => { | ||
| 1628 | const ai = ty.arrayInfo(zcu); | ||
| 1629 | if (ai.elem_type.eql(Type.u8, zcu)) { | ||
| 1630 | const c_len = ty.arrayLenIncludingSentinel(zcu); | ||
| 1631 | var literal = stringLiteral(writer, c_len); | ||
| 1632 | try literal.start(); | ||
| 1633 | var index: u64 = 0; | ||
| 1634 | while (index < c_len) : (index += 1) | ||
| 1635 | try literal.writeChar(0xaa); | ||
| 1636 | return literal.end(); | ||
| 1637 | } else { | ||
| 1638 | if (!location.isInitializer()) { | ||
| 1639 | try writer.writeByte('('); | ||
| 1640 | try dg.renderType(writer, ty); | ||
| 1641 | try writer.writeByte(')'); | ||
| 1642 | } | ||
| 1643 | |||
| 1644 | try writer.writeByte('{'); | ||
| 1645 | const c_len = ty.arrayLenIncludingSentinel(zcu); | ||
| 1646 | var index: u64 = 0; | ||
| 1647 | while (index < c_len) : (index += 1) { | ||
| 1648 | if (index > 0) try writer.writeAll(", "); | ||
| 1649 | try dg.renderUndefValue(writer, ty.childType(zcu), initializer_type); | ||
| 1650 | } | ||
| 1651 | return writer.writeByte('}'); | ||
| 1652 | } | ||
| 1653 | }, | ||
| 1654 | .anyframe_type, | ||
| 1655 | .opaque_type, | ||
| 1656 | .func_type, | ||
| 1657 | => unreachable, | ||
| 1658 | |||
| 1659 | .undef, | ||
| 1660 | .simple_value, | ||
| 1661 | .variable, | ||
| 1662 | .extern_func, | ||
| 1663 | .func, | ||
| 1664 | .int, | ||
| 1665 | .err, | ||
| 1666 | .error_union, | ||
| 1667 | .enum_literal, | ||
| 1668 | .enum_tag, | ||
| 1669 | .empty_enum_value, | ||
| 1670 | .float, | ||
| 1671 | .ptr, | ||
| 1672 | .slice, | ||
| 1673 | .opt, | ||
| 1674 | .aggregate, | ||
| 1675 | .un, | ||
| 1676 | .memoized_call, | ||
| 1677 | => unreachable, | ||
| 1678 | }, | ||
| 1679 | } | ||
| 1680 | } | ||
| 1681 | |||
| 1575 | fn renderFunctionSignature( | 1682 | fn renderFunctionSignature( |
| 1576 | dg: *DeclGen, | 1683 | dg: *DeclGen, |
| 1577 | w: anytype, | 1684 | w: anytype, |
| ... | @@ -1582,15 +1689,14 @@ pub const DeclGen = struct { | ... | @@ -1582,15 +1689,14 @@ pub const DeclGen = struct { |
| 1582 | ident: []const u8, | 1689 | ident: []const u8, |
| 1583 | }, | 1690 | }, |
| 1584 | ) !void { | 1691 | ) !void { |
| 1585 | const store = &dg.ctypes.set; | 1692 | const zcu = dg.zcu; |
| 1586 | const mod = dg.module; | 1693 | const ip = &zcu.intern_pool; |
| 1587 | const ip = &mod.intern_pool; | ||
| 1588 | 1694 | ||
| 1589 | const fn_decl = mod.declPtr(fn_decl_index); | 1695 | const fn_decl = zcu.declPtr(fn_decl_index); |
| 1590 | const fn_ty = fn_decl.typeOf(mod); | 1696 | const fn_ty = fn_decl.typeOf(zcu); |
| 1591 | const fn_cty_idx = try dg.typeToIndex(fn_ty, kind); | 1697 | const fn_ctype = try dg.ctypeFromType(fn_ty, kind); |
| 1592 | 1698 | ||
| 1593 | const fn_info = mod.typeToFunc(fn_ty).?; | 1699 | const fn_info = zcu.typeToFunc(fn_ty).?; |
| 1594 | if (fn_info.cc == .Naked) { | 1700 | if (fn_info.cc == .Naked) { |
| 1595 | switch (kind) { | 1701 | switch (kind) { |
| 1596 | .forward => try w.writeAll("zig_naked_decl "), | 1702 | .forward => try w.writeAll("zig_naked_decl "), |
| ... | @@ -1598,11 +1704,11 @@ pub const DeclGen = struct { | ... | @@ -1598,11 +1704,11 @@ pub const DeclGen = struct { |
| 1598 | else => unreachable, | 1704 | else => unreachable, |
| 1599 | } | 1705 | } |
| 1600 | } | 1706 | } |
| 1601 | if (fn_decl.val.getFunction(mod)) |func| if (func.analysis(ip).is_cold) | 1707 | if (fn_decl.val.getFunction(zcu)) |func| if (func.analysis(ip).is_cold) |
| 1602 | try w.writeAll("zig_cold "); | 1708 | try w.writeAll("zig_cold "); |
| 1603 | if (fn_info.return_type == .noreturn_type) try w.writeAll("zig_noreturn "); | 1709 | if (fn_info.return_type == .noreturn_type) try w.writeAll("zig_noreturn "); |
| 1604 | 1710 | ||
| 1605 | var trailing = try renderTypePrefix(dg.pass, store.*, mod, w, fn_cty_idx, .suffix, .{}); | 1711 | var trailing = try renderTypePrefix(dg.pass, &dg.ctype_pool, zcu, w, fn_ctype, .suffix, .{}); |
| 1606 | 1712 | ||
| 1607 | if (toCallingConvention(fn_info.cc)) |call_conv| { | 1713 | if (toCallingConvention(fn_info.cc)) |call_conv| { |
| 1608 | try w.print("{}zig_callconv({s})", .{ trailing, call_conv }); | 1714 | try w.print("{}zig_callconv({s})", .{ trailing, call_conv }); |
| ... | @@ -1611,7 +1717,7 @@ pub const DeclGen = struct { | ... | @@ -1611,7 +1717,7 @@ pub const DeclGen = struct { |
| 1611 | 1717 | ||
| 1612 | switch (kind) { | 1718 | switch (kind) { |
| 1613 | .forward => {}, | 1719 | .forward => {}, |
| 1614 | .complete => if (fn_decl.alignment.toByteUnitsOptional()) |a| { | 1720 | .complete => if (fn_decl.alignment.toByteUnits()) |a| { |
| 1615 | try w.print("{}zig_align_fn({})", .{ trailing, a }); | 1721 | try w.print("{}zig_align_fn({})", .{ trailing, a }); |
| 1616 | trailing = .maybe_space; | 1722 | trailing = .maybe_space; |
| 1617 | }, | 1723 | }, |
| ... | @@ -1628,10 +1734,10 @@ pub const DeclGen = struct { | ... | @@ -1628,10 +1734,10 @@ pub const DeclGen = struct { |
| 1628 | 1734 | ||
| 1629 | try renderTypeSuffix( | 1735 | try renderTypeSuffix( |
| 1630 | dg.pass, | 1736 | dg.pass, |
| 1631 | store.*, | 1737 | &dg.ctype_pool, |
| 1632 | mod, | 1738 | zcu, |
| 1633 | w, | 1739 | w, |
| 1634 | fn_cty_idx, | 1740 | fn_ctype, |
| 1635 | .suffix, | 1741 | .suffix, |
| 1636 | CQualifiers.init(.{ .@"const" = switch (kind) { | 1742 | CQualifiers.init(.{ .@"const" = switch (kind) { |
| 1637 | .forward => false, | 1743 | .forward => false, |
| ... | @@ -1642,16 +1748,16 @@ pub const DeclGen = struct { | ... | @@ -1642,16 +1748,16 @@ pub const DeclGen = struct { |
| 1642 | 1748 | ||
| 1643 | switch (kind) { | 1749 | switch (kind) { |
| 1644 | .forward => { | 1750 | .forward => { |
| 1645 | if (fn_decl.alignment.toByteUnitsOptional()) |a| { | 1751 | if (fn_decl.alignment.toByteUnits()) |a| { |
| 1646 | try w.print(" zig_align_fn({})", .{a}); | 1752 | try w.print(" zig_align_fn({})", .{a}); |
| 1647 | } | 1753 | } |
| 1648 | switch (name) { | 1754 | switch (name) { |
| 1649 | .export_index => |export_index| mangled: { | 1755 | .export_index => |export_index| mangled: { |
| 1650 | const maybe_exports = mod.decl_exports.get(fn_decl_index); | 1756 | const maybe_exports = zcu.decl_exports.get(fn_decl_index); |
| 1651 | const external_name = ip.stringToSlice( | 1757 | const external_name = ip.stringToSlice( |
| 1652 | if (maybe_exports) |exports| | 1758 | if (maybe_exports) |exports| |
| 1653 | exports.items[export_index].opts.name | 1759 | exports.items[export_index].opts.name |
| 1654 | else if (fn_decl.isExtern(mod)) | 1760 | else if (fn_decl.isExtern(zcu)) |
| 1655 | fn_decl.name | 1761 | fn_decl.name |
| 1656 | else | 1762 | else |
| 1657 | break :mangled, | 1763 | break :mangled, |
| ... | @@ -1689,20 +1795,13 @@ pub const DeclGen = struct { | ... | @@ -1689,20 +1795,13 @@ pub const DeclGen = struct { |
| 1689 | } | 1795 | } |
| 1690 | } | 1796 | } |
| 1691 | 1797 | ||
| 1692 | fn indexToCType(dg: *DeclGen, idx: CType.Index) CType { | 1798 | fn ctypeFromType(dg: *DeclGen, ty: Type, kind: CType.Kind) !CType { |
| 1693 | return dg.ctypes.indexToCType(idx); | 1799 | defer std.debug.assert(dg.scratch.items.len == 0); |
| 1800 | return dg.ctype_pool.fromType(dg.gpa, &dg.scratch, ty, dg.zcu, dg.mod, kind); | ||
| 1694 | } | 1801 | } |
| 1695 | 1802 | ||
| 1696 | fn typeToIndex(dg: *DeclGen, ty: Type, kind: CType.Kind) !CType.Index { | 1803 | fn byteSize(dg: *DeclGen, ctype: CType) u64 { |
| 1697 | return dg.ctypes.typeToIndex(dg.gpa, ty, dg.module, kind); | 1804 | return ctype.byteSize(&dg.ctype_pool, dg.mod); |
| 1698 | } | ||
| 1699 | |||
| 1700 | fn typeToCType(dg: *DeclGen, ty: Type, kind: CType.Kind) !CType { | ||
| 1701 | return dg.ctypes.typeToCType(dg.gpa, ty, dg.module, kind); | ||
| 1702 | } | ||
| 1703 | |||
| 1704 | fn byteSize(dg: *DeclGen, cty: CType) u64 { | ||
| 1705 | return cty.byteSize(dg.ctypes.set, dg.module.getTarget()); | ||
| 1706 | } | 1805 | } |
| 1707 | 1806 | ||
| 1708 | /// Renders a type as a single identifier, generating intermediate typedefs | 1807 | /// Renders a type as a single identifier, generating intermediate typedefs |
| ... | @@ -1717,14 +1816,12 @@ pub const DeclGen = struct { | ... | @@ -1717,14 +1816,12 @@ pub const DeclGen = struct { |
| 1717 | /// | `renderType` | "uint8_t *" | "uint8_t *[10]" | | 1816 | /// | `renderType` | "uint8_t *" | "uint8_t *[10]" | |
| 1718 | /// | 1817 | /// |
| 1719 | fn renderType(dg: *DeclGen, w: anytype, t: Type) error{ OutOfMemory, AnalysisFail }!void { | 1818 | fn renderType(dg: *DeclGen, w: anytype, t: Type) error{ OutOfMemory, AnalysisFail }!void { |
| 1720 | try dg.renderCType(w, try dg.typeToIndex(t, .complete)); | 1819 | try dg.renderCType(w, try dg.ctypeFromType(t, .complete)); |
| 1721 | } | 1820 | } |
| 1722 | 1821 | ||
| 1723 | fn renderCType(dg: *DeclGen, w: anytype, idx: CType.Index) error{ OutOfMemory, AnalysisFail }!void { | 1822 | fn renderCType(dg: *DeclGen, w: anytype, ctype: CType) error{ OutOfMemory, AnalysisFail }!void { |
| 1724 | const store = &dg.ctypes.set; | 1823 | _ = try renderTypePrefix(dg.pass, &dg.ctype_pool, dg.zcu, w, ctype, .suffix, .{}); |
| 1725 | const mod = dg.module; | 1824 | try renderTypeSuffix(dg.pass, &dg.ctype_pool, dg.zcu, w, ctype, .suffix, .{}); |
| 1726 | _ = try renderTypePrefix(dg.pass, store.*, mod, w, idx, .suffix, .{}); | ||
| 1727 | try renderTypeSuffix(dg.pass, store.*, mod, w, idx, .suffix, .{}); | ||
| 1728 | } | 1825 | } |
| 1729 | 1826 | ||
| 1730 | const IntCastContext = union(enum) { | 1827 | const IntCastContext = union(enum) { |
| ... | @@ -1737,15 +1834,13 @@ pub const DeclGen = struct { | ... | @@ -1737,15 +1834,13 @@ pub const DeclGen = struct { |
| 1737 | value: Value, | 1834 | value: Value, |
| 1738 | }, | 1835 | }, |
| 1739 | 1836 | ||
| 1740 | pub fn writeValue(self: *const IntCastContext, dg: *DeclGen, w: anytype, value_ty: Type, location: ValueRenderLocation) !void { | 1837 | pub fn writeValue(self: *const IntCastContext, dg: *DeclGen, w: anytype, location: ValueRenderLocation) !void { |
| 1741 | switch (self.*) { | 1838 | switch (self.*) { |
| 1742 | .c_value => |v| { | 1839 | .c_value => |v| { |
| 1743 | try v.f.writeCValue(w, v.value, location); | 1840 | try v.f.writeCValue(w, v.value, location); |
| 1744 | try v.v.elem(v.f, w); | 1841 | try v.v.elem(v.f, w); |
| 1745 | }, | 1842 | }, |
| 1746 | .value => |v| { | 1843 | .value => |v| try dg.renderValue(w, v.value, location), |
| 1747 | try dg.renderValue(w, value_ty, v.value, location); | ||
| 1748 | }, | ||
| 1749 | } | 1844 | } |
| 1750 | } | 1845 | } |
| 1751 | }; | 1846 | }; |
| ... | @@ -1764,18 +1859,18 @@ pub const DeclGen = struct { | ... | @@ -1764,18 +1859,18 @@ pub const DeclGen = struct { |
| 1764 | /// | > 64 bit integer | < 64 bit integer | zig_make_<dest_ty>(0, src) | 1859 | /// | > 64 bit integer | < 64 bit integer | zig_make_<dest_ty>(0, src) |
| 1765 | /// | > 64 bit integer | > 64 bit integer | zig_make_<dest_ty>(zig_hi_<src_ty>(src), zig_lo_<src_ty>(src)) | 1860 | /// | > 64 bit integer | > 64 bit integer | zig_make_<dest_ty>(zig_hi_<src_ty>(src), zig_lo_<src_ty>(src)) |
| 1766 | fn renderIntCast(dg: *DeclGen, w: anytype, dest_ty: Type, context: IntCastContext, src_ty: Type, location: ValueRenderLocation) !void { | 1861 | fn renderIntCast(dg: *DeclGen, w: anytype, dest_ty: Type, context: IntCastContext, src_ty: Type, location: ValueRenderLocation) !void { |
| 1767 | const mod = dg.module; | 1862 | const zcu = dg.zcu; |
| 1768 | const dest_bits = dest_ty.bitSize(mod); | 1863 | const dest_bits = dest_ty.bitSize(zcu); |
| 1769 | const dest_int_info = dest_ty.intInfo(mod); | 1864 | const dest_int_info = dest_ty.intInfo(zcu); |
| 1770 | 1865 | ||
| 1771 | const src_is_ptr = src_ty.isPtrAtRuntime(mod); | 1866 | const src_is_ptr = src_ty.isPtrAtRuntime(zcu); |
| 1772 | const src_eff_ty: Type = if (src_is_ptr) switch (dest_int_info.signedness) { | 1867 | const src_eff_ty: Type = if (src_is_ptr) switch (dest_int_info.signedness) { |
| 1773 | .unsigned => Type.usize, | 1868 | .unsigned => Type.usize, |
| 1774 | .signed => Type.isize, | 1869 | .signed => Type.isize, |
| 1775 | } else src_ty; | 1870 | } else src_ty; |
| 1776 | 1871 | ||
| 1777 | const src_bits = src_eff_ty.bitSize(mod); | 1872 | const src_bits = src_eff_ty.bitSize(zcu); |
| 1778 | const src_int_info = if (src_eff_ty.isAbiInt(mod)) src_eff_ty.intInfo(mod) else null; | 1873 | const src_int_info = if (src_eff_ty.isAbiInt(zcu)) src_eff_ty.intInfo(zcu) else null; |
| 1779 | if (dest_bits <= 64 and src_bits <= 64) { | 1874 | if (dest_bits <= 64 and src_bits <= 64) { |
| 1780 | const needs_cast = src_int_info == null or | 1875 | const needs_cast = src_int_info == null or |
| 1781 | (toCIntBits(dest_int_info.bits) != toCIntBits(src_int_info.?.bits) or | 1876 | (toCIntBits(dest_int_info.bits) != toCIntBits(src_int_info.?.bits) or |
| ... | @@ -1791,7 +1886,7 @@ pub const DeclGen = struct { | ... | @@ -1791,7 +1886,7 @@ pub const DeclGen = struct { |
| 1791 | try dg.renderType(w, src_eff_ty); | 1886 | try dg.renderType(w, src_eff_ty); |
| 1792 | try w.writeByte(')'); | 1887 | try w.writeByte(')'); |
| 1793 | } | 1888 | } |
| 1794 | try context.writeValue(dg, w, src_ty, location); | 1889 | try context.writeValue(dg, w, location); |
| 1795 | } else if (dest_bits <= 64 and src_bits > 64) { | 1890 | } else if (dest_bits <= 64 and src_bits > 64) { |
| 1796 | assert(!src_is_ptr); | 1891 | assert(!src_is_ptr); |
| 1797 | if (dest_bits < 64) { | 1892 | if (dest_bits < 64) { |
| ... | @@ -1802,7 +1897,7 @@ pub const DeclGen = struct { | ... | @@ -1802,7 +1897,7 @@ pub const DeclGen = struct { |
| 1802 | try w.writeAll("zig_lo_"); | 1897 | try w.writeAll("zig_lo_"); |
| 1803 | try dg.renderTypeForBuiltinFnName(w, src_eff_ty); | 1898 | try dg.renderTypeForBuiltinFnName(w, src_eff_ty); |
| 1804 | try w.writeByte('('); | 1899 | try w.writeByte('('); |
| 1805 | try context.writeValue(dg, w, src_ty, .FunctionArgument); | 1900 | try context.writeValue(dg, w, .FunctionArgument); |
| 1806 | try w.writeByte(')'); | 1901 | try w.writeByte(')'); |
| 1807 | } else if (dest_bits > 64 and src_bits <= 64) { | 1902 | } else if (dest_bits > 64 and src_bits <= 64) { |
| 1808 | try w.writeAll("zig_make_"); | 1903 | try w.writeAll("zig_make_"); |
| ... | @@ -1813,7 +1908,7 @@ pub const DeclGen = struct { | ... | @@ -1813,7 +1908,7 @@ pub const DeclGen = struct { |
| 1813 | try dg.renderType(w, src_eff_ty); | 1908 | try dg.renderType(w, src_eff_ty); |
| 1814 | try w.writeByte(')'); | 1909 | try w.writeByte(')'); |
| 1815 | } | 1910 | } |
| 1816 | try context.writeValue(dg, w, src_ty, .FunctionArgument); | 1911 | try context.writeValue(dg, w, .FunctionArgument); |
| 1817 | try w.writeByte(')'); | 1912 | try w.writeByte(')'); |
| 1818 | } else { | 1913 | } else { |
| 1819 | assert(!src_is_ptr); | 1914 | assert(!src_is_ptr); |
| ... | @@ -1822,11 +1917,11 @@ pub const DeclGen = struct { | ... | @@ -1822,11 +1917,11 @@ pub const DeclGen = struct { |
| 1822 | try w.writeAll("(zig_hi_"); | 1917 | try w.writeAll("(zig_hi_"); |
| 1823 | try dg.renderTypeForBuiltinFnName(w, src_eff_ty); | 1918 | try dg.renderTypeForBuiltinFnName(w, src_eff_ty); |
| 1824 | try w.writeByte('('); | 1919 | try w.writeByte('('); |
| 1825 | try context.writeValue(dg, w, src_ty, .FunctionArgument); | 1920 | try context.writeValue(dg, w, .FunctionArgument); |
| 1826 | try w.writeAll("), zig_lo_"); | 1921 | try w.writeAll("), zig_lo_"); |
| 1827 | try dg.renderTypeForBuiltinFnName(w, src_eff_ty); | 1922 | try dg.renderTypeForBuiltinFnName(w, src_eff_ty); |
| 1828 | try w.writeByte('('); | 1923 | try w.writeByte('('); |
| 1829 | try context.writeValue(dg, w, src_ty, .FunctionArgument); | 1924 | try context.writeValue(dg, w, .FunctionArgument); |
| 1830 | try w.writeAll("))"); | 1925 | try w.writeAll("))"); |
| 1831 | } | 1926 | } |
| 1832 | } | 1927 | } |
| ... | @@ -1848,61 +1943,73 @@ pub const DeclGen = struct { | ... | @@ -1848,61 +1943,73 @@ pub const DeclGen = struct { |
| 1848 | alignment: Alignment, | 1943 | alignment: Alignment, |
| 1849 | kind: CType.Kind, | 1944 | kind: CType.Kind, |
| 1850 | ) error{ OutOfMemory, AnalysisFail }!void { | 1945 | ) error{ OutOfMemory, AnalysisFail }!void { |
| 1851 | const mod = dg.module; | 1946 | try dg.renderCTypeAndName( |
| 1852 | const alignas = CType.AlignAs.init(alignment, ty.abiAlignment(mod)); | 1947 | w, |
| 1853 | try dg.renderCTypeAndName(w, try dg.typeToIndex(ty, kind), name, qualifiers, alignas); | 1948 | try dg.ctypeFromType(ty, kind), |
| 1949 | name, | ||
| 1950 | qualifiers, | ||
| 1951 | CType.AlignAs.fromAlignment(.{ | ||
| 1952 | .@"align" = alignment, | ||
| 1953 | .abi = ty.abiAlignment(dg.zcu), | ||
| 1954 | }), | ||
| 1955 | ); | ||
| 1854 | } | 1956 | } |
| 1855 | 1957 | ||
| 1856 | fn renderCTypeAndName( | 1958 | fn renderCTypeAndName( |
| 1857 | dg: *DeclGen, | 1959 | dg: *DeclGen, |
| 1858 | w: anytype, | 1960 | w: anytype, |
| 1859 | cty_idx: CType.Index, | 1961 | ctype: CType, |
| 1860 | name: CValue, | 1962 | name: CValue, |
| 1861 | qualifiers: CQualifiers, | 1963 | qualifiers: CQualifiers, |
| 1862 | alignas: CType.AlignAs, | 1964 | alignas: CType.AlignAs, |
| 1863 | ) error{ OutOfMemory, AnalysisFail }!void { | 1965 | ) error{ OutOfMemory, AnalysisFail }!void { |
| 1864 | const store = &dg.ctypes.set; | ||
| 1865 | const mod = dg.module; | ||
| 1866 | |||
| 1867 | switch (alignas.abiOrder()) { | 1966 | switch (alignas.abiOrder()) { |
| 1868 | .lt => try w.print("zig_under_align({}) ", .{alignas.toByteUnits()}), | 1967 | .lt => try w.print("zig_under_align({}) ", .{alignas.toByteUnits()}), |
| 1869 | .eq => {}, | 1968 | .eq => {}, |
| 1870 | .gt => try w.print("zig_align({}) ", .{alignas.toByteUnits()}), | 1969 | .gt => try w.print("zig_align({}) ", .{alignas.toByteUnits()}), |
| 1871 | } | 1970 | } |
| 1872 | 1971 | ||
| 1873 | const trailing = try renderTypePrefix(dg.pass, store.*, mod, w, cty_idx, .suffix, qualifiers); | 1972 | try w.print("{}", .{ |
| 1874 | try w.print("{}", .{trailing}); | 1973 | try renderTypePrefix(dg.pass, &dg.ctype_pool, dg.zcu, w, ctype, .suffix, qualifiers), |
| 1875 | try dg.writeCValue(w, name); | 1974 | }); |
| 1876 | try renderTypeSuffix(dg.pass, store.*, mod, w, cty_idx, .suffix, .{}); | 1975 | try dg.writeName(w, name); |
| 1976 | try renderTypeSuffix(dg.pass, &dg.ctype_pool, dg.zcu, w, ctype, .suffix, .{}); | ||
| 1877 | } | 1977 | } |
| 1878 | 1978 | ||
| 1879 | fn declIsGlobal(dg: *DeclGen, val: Value) bool { | 1979 | fn declIsGlobal(dg: *DeclGen, val: Value) bool { |
| 1880 | const mod = dg.module; | 1980 | const zcu = dg.zcu; |
| 1881 | return switch (mod.intern_pool.indexToKey(val.ip_index)) { | 1981 | return switch (zcu.intern_pool.indexToKey(val.toIntern())) { |
| 1882 | .variable => |variable| mod.decl_exports.contains(variable.decl), | 1982 | .variable => |variable| zcu.decl_exports.contains(variable.decl), |
| 1883 | .extern_func => true, | 1983 | .extern_func => true, |
| 1884 | .func => |func| mod.decl_exports.contains(func.owner_decl), | 1984 | .func => |func| zcu.decl_exports.contains(func.owner_decl), |
| 1885 | else => unreachable, | 1985 | else => unreachable, |
| 1886 | }; | 1986 | }; |
| 1887 | } | 1987 | } |
| 1888 | 1988 | ||
| 1989 | fn writeName(dg: *DeclGen, w: anytype, c_value: CValue) !void { | ||
| 1990 | switch (c_value) { | ||
| 1991 | .new_local, .local => |i| try w.print("t{d}", .{i}), | ||
| 1992 | .constant => |val| try renderAnonDeclName(w, val), | ||
| 1993 | .decl => |decl| try dg.renderDeclName(w, decl, 0), | ||
| 1994 | .identifier => |ident| try w.print("{ }", .{fmtIdent(ident)}), | ||
| 1995 | else => unreachable, | ||
| 1996 | } | ||
| 1997 | } | ||
| 1998 | |||
| 1889 | fn writeCValue(dg: *DeclGen, w: anytype, c_value: CValue) !void { | 1999 | fn writeCValue(dg: *DeclGen, w: anytype, c_value: CValue) !void { |
| 1890 | switch (c_value) { | 2000 | switch (c_value) { |
| 1891 | .none => unreachable, | 2001 | .none, .new_local, .local, .local_ref => unreachable, |
| 1892 | .local, .new_local => |i| return w.print("t{d}", .{i}), | 2002 | .constant => |val| try renderAnonDeclName(w, val), |
| 1893 | .local_ref => |i| return w.print("&t{d}", .{i}), | 2003 | .arg, .arg_array => unreachable, |
| 1894 | .constant => |val| return renderAnonDeclName(w, val), | 2004 | .field => |i| try w.print("f{d}", .{i}), |
| 1895 | .arg => |i| return w.print("a{d}", .{i}), | 2005 | .decl => |decl| try dg.renderDeclName(w, decl, 0), |
| 1896 | .arg_array => |i| return dg.writeCValueMember(w, .{ .arg = i }, .{ .identifier = "array" }), | ||
| 1897 | .field => |i| return w.print("f{d}", .{i}), | ||
| 1898 | .decl => |decl| return dg.renderDeclName(w, decl, 0), | ||
| 1899 | .decl_ref => |decl| { | 2006 | .decl_ref => |decl| { |
| 1900 | try w.writeByte('&'); | 2007 | try w.writeByte('&'); |
| 1901 | return dg.renderDeclName(w, decl, 0); | 2008 | try dg.renderDeclName(w, decl, 0); |
| 1902 | }, | 2009 | }, |
| 1903 | .undef => |ty| return dg.renderValue(w, ty, Value.undef, .Other), | 2010 | .undef => |ty| try dg.renderUndefValue(w, ty, .Other), |
| 1904 | .identifier => |ident| return w.print("{ }", .{fmtIdent(ident)}), | 2011 | .identifier => |ident| try w.print("{ }", .{fmtIdent(ident)}), |
| 1905 | .payload_identifier => |ident| return w.print("{ }.{ }", .{ | 2012 | .payload_identifier => |ident| try w.print("{ }.{ }", .{ |
| 1906 | fmtIdent("payload"), | 2013 | fmtIdent("payload"), |
| 1907 | fmtIdent(ident), | 2014 | fmtIdent(ident), |
| 1908 | }), | 2015 | }), |
| ... | @@ -1911,26 +2018,17 @@ pub const DeclGen = struct { | ... | @@ -1911,26 +2018,17 @@ pub const DeclGen = struct { |
| 1911 | 2018 | ||
| 1912 | fn writeCValueDeref(dg: *DeclGen, w: anytype, c_value: CValue) !void { | 2019 | fn writeCValueDeref(dg: *DeclGen, w: anytype, c_value: CValue) !void { |
| 1913 | switch (c_value) { | 2020 | switch (c_value) { |
| 1914 | .none => unreachable, | 2021 | .none, .new_local, .local, .local_ref, .constant, .arg, .arg_array => unreachable, |
| 1915 | .local, .new_local => |i| return w.print("(*t{d})", .{i}), | 2022 | .field => |i| try w.print("f{d}", .{i}), |
| 1916 | .local_ref => |i| return w.print("t{d}", .{i}), | ||
| 1917 | .constant => unreachable, | ||
| 1918 | .arg => |i| return w.print("(*a{d})", .{i}), | ||
| 1919 | .arg_array => |i| { | ||
| 1920 | try w.writeAll("(*"); | ||
| 1921 | try dg.writeCValueMember(w, .{ .arg = i }, .{ .identifier = "array" }); | ||
| 1922 | return w.writeByte(')'); | ||
| 1923 | }, | ||
| 1924 | .field => |i| return w.print("f{d}", .{i}), | ||
| 1925 | .decl => |decl| { | 2023 | .decl => |decl| { |
| 1926 | try w.writeAll("(*"); | 2024 | try w.writeAll("(*"); |
| 1927 | try dg.renderDeclName(w, decl, 0); | 2025 | try dg.renderDeclName(w, decl, 0); |
| 1928 | return w.writeByte(')'); | 2026 | try w.writeByte(')'); |
| 1929 | }, | 2027 | }, |
| 1930 | .decl_ref => |decl| return dg.renderDeclName(w, decl, 0), | 2028 | .decl_ref => |decl| try dg.renderDeclName(w, decl, 0), |
| 1931 | .undef => unreachable, | 2029 | .undef => unreachable, |
| 1932 | .identifier => |ident| return w.print("(*{ })", .{fmtIdent(ident)}), | 2030 | .identifier => |ident| try w.print("(*{ })", .{fmtIdent(ident)}), |
| 1933 | .payload_identifier => |ident| return w.print("(*{ }.{ })", .{ | 2031 | .payload_identifier => |ident| try w.print("(*{ }.{ })", .{ |
| 1934 | fmtIdent("payload"), | 2032 | fmtIdent("payload"), |
| 1935 | fmtIdent(ident), | 2033 | fmtIdent(ident), |
| 1936 | }), | 2034 | }), |
| ... | @@ -1950,12 +2048,12 @@ pub const DeclGen = struct { | ... | @@ -1950,12 +2048,12 @@ pub const DeclGen = struct { |
| 1950 | 2048 | ||
| 1951 | fn writeCValueDerefMember(dg: *DeclGen, writer: anytype, c_value: CValue, member: CValue) !void { | 2049 | fn writeCValueDerefMember(dg: *DeclGen, writer: anytype, c_value: CValue, member: CValue) !void { |
| 1952 | switch (c_value) { | 2050 | switch (c_value) { |
| 1953 | .none, .constant, .field, .undef => unreachable, | 2051 | .none, .new_local, .local, .local_ref, .constant, .field, .undef, .arg, .arg_array => unreachable, |
| 1954 | .new_local, .local, .arg, .arg_array, .decl, .identifier, .payload_identifier => { | 2052 | .decl, .identifier, .payload_identifier => { |
| 1955 | try dg.writeCValue(writer, c_value); | 2053 | try dg.writeCValue(writer, c_value); |
| 1956 | try writer.writeAll("->"); | 2054 | try writer.writeAll("->"); |
| 1957 | }, | 2055 | }, |
| 1958 | .local_ref, .decl_ref => { | 2056 | .decl_ref => { |
| 1959 | try dg.writeCValueDeref(writer, c_value); | 2057 | try dg.writeCValueDeref(writer, c_value); |
| 1960 | try writer.writeByte('.'); | 2058 | try writer.writeByte('.'); |
| 1961 | }, | 2059 | }, |
| ... | @@ -1969,11 +2067,12 @@ pub const DeclGen = struct { | ... | @@ -1969,11 +2067,12 @@ pub const DeclGen = struct { |
| 1969 | variable: InternPool.Key.Variable, | 2067 | variable: InternPool.Key.Variable, |
| 1970 | fwd_kind: enum { tentative, final }, | 2068 | fwd_kind: enum { tentative, final }, |
| 1971 | ) !void { | 2069 | ) !void { |
| 1972 | const decl = dg.module.declPtr(decl_index); | 2070 | const zcu = dg.zcu; |
| 2071 | const decl = zcu.declPtr(decl_index); | ||
| 1973 | const fwd = dg.fwdDeclWriter(); | 2072 | const fwd = dg.fwdDeclWriter(); |
| 1974 | const is_global = variable.is_extern or dg.declIsGlobal(decl.val); | 2073 | const is_global = variable.is_extern or dg.declIsGlobal(decl.val); |
| 1975 | try fwd.writeAll(if (is_global) "zig_extern " else "static "); | 2074 | try fwd.writeAll(if (is_global) "zig_extern " else "static "); |
| 1976 | const maybe_exports = dg.module.decl_exports.get(decl_index); | 2075 | const maybe_exports = zcu.decl_exports.get(decl_index); |
| 1977 | const export_weak_linkage = if (maybe_exports) |exports| | 2076 | const export_weak_linkage = if (maybe_exports) |exports| |
| 1978 | exports.items[0].opts.linkage == .weak | 2077 | exports.items[0].opts.linkage == .weak |
| 1979 | else | 2078 | else |
| ... | @@ -1982,14 +2081,14 @@ pub const DeclGen = struct { | ... | @@ -1982,14 +2081,14 @@ pub const DeclGen = struct { |
| 1982 | if (variable.is_threadlocal) try fwd.writeAll("zig_threadlocal "); | 2081 | if (variable.is_threadlocal) try fwd.writeAll("zig_threadlocal "); |
| 1983 | try dg.renderTypeAndName( | 2082 | try dg.renderTypeAndName( |
| 1984 | fwd, | 2083 | fwd, |
| 1985 | decl.typeOf(dg.module), | 2084 | decl.typeOf(zcu), |
| 1986 | .{ .decl = decl_index }, | 2085 | .{ .decl = decl_index }, |
| 1987 | CQualifiers.init(.{ .@"const" = variable.is_const }), | 2086 | CQualifiers.init(.{ .@"const" = variable.is_const }), |
| 1988 | decl.alignment, | 2087 | decl.alignment, |
| 1989 | .complete, | 2088 | .complete, |
| 1990 | ); | 2089 | ); |
| 1991 | mangled: { | 2090 | mangled: { |
| 1992 | const external_name = dg.module.intern_pool.stringToSlice(if (maybe_exports) |exports| | 2091 | const external_name = zcu.intern_pool.stringToSlice(if (maybe_exports) |exports| |
| 1993 | exports.items[0].opts.name | 2092 | exports.items[0].opts.name |
| 1994 | else if (variable.is_extern) | 2093 | else if (variable.is_extern) |
| 1995 | decl.name | 2094 | decl.name |
| ... | @@ -2007,23 +2106,23 @@ pub const DeclGen = struct { | ... | @@ -2007,23 +2106,23 @@ pub const DeclGen = struct { |
| 2007 | } | 2106 | } |
| 2008 | 2107 | ||
| 2009 | fn renderDeclName(dg: *DeclGen, writer: anytype, decl_index: InternPool.DeclIndex, export_index: u32) !void { | 2108 | fn renderDeclName(dg: *DeclGen, writer: anytype, decl_index: InternPool.DeclIndex, export_index: u32) !void { |
| 2010 | const mod = dg.module; | 2109 | const zcu = dg.zcu; |
| 2011 | const decl = mod.declPtr(decl_index); | 2110 | const decl = zcu.declPtr(decl_index); |
| 2012 | 2111 | ||
| 2013 | if (mod.decl_exports.get(decl_index)) |exports| { | 2112 | if (zcu.decl_exports.get(decl_index)) |exports| { |
| 2014 | try writer.print("{ }", .{ | 2113 | try writer.print("{ }", .{ |
| 2015 | fmtIdent(mod.intern_pool.stringToSlice(exports.items[export_index].opts.name)), | 2114 | fmtIdent(zcu.intern_pool.stringToSlice(exports.items[export_index].opts.name)), |
| 2016 | }); | 2115 | }); |
| 2017 | } else if (decl.getExternDecl(mod).unwrap()) |extern_decl_index| { | 2116 | } else if (decl.getExternDecl(zcu).unwrap()) |extern_decl_index| { |
| 2018 | try writer.print("{ }", .{ | 2117 | try writer.print("{ }", .{ |
| 2019 | fmtIdent(mod.intern_pool.stringToSlice(mod.declPtr(extern_decl_index).name)), | 2118 | fmtIdent(zcu.intern_pool.stringToSlice(zcu.declPtr(extern_decl_index).name)), |
| 2020 | }); | 2119 | }); |
| 2021 | } else { | 2120 | } else { |
| 2022 | // MSVC has a limit of 4095 character token length limit, and fmtIdent can (worst case), | 2121 | // MSVC has a limit of 4095 character token length limit, and fmtIdent can (worst case), |
| 2023 | // expand to 3x the length of its input, but let's cut it off at a much shorter limit. | 2122 | // expand to 3x the length of its input, but let's cut it off at a much shorter limit. |
| 2024 | var name: [100]u8 = undefined; | 2123 | var name: [100]u8 = undefined; |
| 2025 | var name_stream = std.io.fixedBufferStream(&name); | 2124 | var name_stream = std.io.fixedBufferStream(&name); |
| 2026 | decl.renderFullyQualifiedName(mod, name_stream.writer()) catch |err| switch (err) { | 2125 | decl.renderFullyQualifiedName(zcu, name_stream.writer()) catch |err| switch (err) { |
| 2027 | error.NoSpaceLeft => {}, | 2126 | error.NoSpaceLeft => {}, |
| 2028 | }; | 2127 | }; |
| 2029 | try writer.print("{}__{d}", .{ | 2128 | try writer.print("{}__{d}", .{ |
| ... | @@ -2033,77 +2132,71 @@ pub const DeclGen = struct { | ... | @@ -2033,77 +2132,71 @@ pub const DeclGen = struct { |
| 2033 | } | 2132 | } |
| 2034 | } | 2133 | } |
| 2035 | 2134 | ||
| 2036 | fn renderAnonDeclName(writer: anytype, anon_decl_val: InternPool.Index) !void { | 2135 | fn renderAnonDeclName(writer: anytype, anon_decl_val: Value) !void { |
| 2037 | return writer.print("__anon_{d}", .{@intFromEnum(anon_decl_val)}); | 2136 | try writer.print("__anon_{d}", .{@intFromEnum(anon_decl_val.toIntern())}); |
| 2038 | } | 2137 | } |
| 2039 | 2138 | ||
| 2040 | fn renderTypeForBuiltinFnName(dg: *DeclGen, writer: anytype, ty: Type) !void { | 2139 | fn renderTypeForBuiltinFnName(dg: *DeclGen, writer: anytype, ty: Type) !void { |
| 2041 | try dg.renderCTypeForBuiltinFnName(writer, try dg.typeToCType(ty, .complete)); | 2140 | try dg.renderCTypeForBuiltinFnName(writer, try dg.ctypeFromType(ty, .complete)); |
| 2042 | } | 2141 | } |
| 2043 | 2142 | ||
| 2044 | fn renderCTypeForBuiltinFnName(dg: *DeclGen, writer: anytype, cty: CType) !void { | 2143 | fn renderCTypeForBuiltinFnName(dg: *DeclGen, writer: anytype, ctype: CType) !void { |
| 2045 | switch (cty.tag()) { | 2144 | switch (ctype.info(&dg.ctype_pool)) { |
| 2046 | else => try writer.print("{c}{d}", .{ | 2145 | else => |ctype_info| try writer.print("{c}{d}", .{ |
| 2047 | if (cty.isBool()) | 2146 | if (ctype.isBool()) |
| 2048 | signAbbrev(.unsigned) | 2147 | signAbbrev(.unsigned) |
| 2049 | else if (cty.isInteger()) | 2148 | else if (ctype.isInteger()) |
| 2050 | signAbbrev(cty.signedness(dg.module.getTarget())) | 2149 | signAbbrev(ctype.signedness(dg.mod)) |
| 2051 | else if (cty.isFloat()) | 2150 | else if (ctype.isFloat()) |
| 2052 | @as(u8, 'f') | 2151 | @as(u8, 'f') |
| 2053 | else if (cty.isPointer()) | 2152 | else if (ctype_info == .pointer) |
| 2054 | @as(u8, 'p') | 2153 | @as(u8, 'p') |
| 2055 | else | 2154 | else |
| 2056 | return dg.fail("TODO: CBE: implement renderTypeForBuiltinFnName for type {}", .{ | 2155 | return dg.fail("TODO: CBE: implement renderTypeForBuiltinFnName for {s} type", .{@tagName(ctype_info)}), |
| 2057 | cty.tag(), | 2156 | if (ctype.isFloat()) ctype.floatActiveBits(dg.mod) else dg.byteSize(ctype) * 8, |
| 2058 | }), | ||
| 2059 | if (cty.isFloat()) cty.floatActiveBits(dg.module.getTarget()) else dg.byteSize(cty) * 8, | ||
| 2060 | }), | 2157 | }), |
| 2061 | .array => try writer.writeAll("big"), | 2158 | .array => try writer.writeAll("big"), |
| 2062 | } | 2159 | } |
| 2063 | } | 2160 | } |
| 2064 | 2161 | ||
| 2065 | fn renderBuiltinInfo(dg: *DeclGen, writer: anytype, ty: Type, info: BuiltinInfo) !void { | 2162 | fn renderBuiltinInfo(dg: *DeclGen, writer: anytype, ty: Type, info: BuiltinInfo) !void { |
| 2066 | const cty = try dg.typeToCType(ty, .complete); | 2163 | const ctype = try dg.ctypeFromType(ty, .complete); |
| 2067 | const is_big = cty.tag() == .array; | 2164 | const is_big = ctype.info(&dg.ctype_pool) == .array; |
| 2068 | |||
| 2069 | switch (info) { | 2165 | switch (info) { |
| 2070 | .none => if (!is_big) return, | 2166 | .none => if (!is_big) return, |
| 2071 | .bits => {}, | 2167 | .bits => {}, |
| 2072 | } | 2168 | } |
| 2073 | 2169 | ||
| 2074 | const mod = dg.module; | 2170 | const zcu = dg.zcu; |
| 2075 | const int_info = if (ty.isAbiInt(mod)) ty.intInfo(mod) else std.builtin.Type.Int{ | 2171 | const int_info = if (ty.isAbiInt(zcu)) ty.intInfo(zcu) else std.builtin.Type.Int{ |
| 2076 | .signedness = .unsigned, | 2172 | .signedness = .unsigned, |
| 2077 | .bits = @as(u16, @intCast(ty.bitSize(mod))), | 2173 | .bits = @as(u16, @intCast(ty.bitSize(zcu))), |
| 2078 | }; | 2174 | }; |
| 2079 | 2175 | ||
| 2080 | if (is_big) try writer.print(", {}", .{int_info.signedness == .signed}); | 2176 | if (is_big) try writer.print(", {}", .{int_info.signedness == .signed}); |
| 2081 | |||
| 2082 | const bits_ty = if (is_big) Type.u16 else Type.u8; | ||
| 2083 | try writer.print(", {}", .{try dg.fmtIntLiteral( | 2177 | try writer.print(", {}", .{try dg.fmtIntLiteral( |
| 2084 | bits_ty, | 2178 | try zcu.intValue(if (is_big) Type.u16 else Type.u8, int_info.bits), |
| 2085 | try mod.intValue(bits_ty, int_info.bits), | ||
| 2086 | .FunctionArgument, | 2179 | .FunctionArgument, |
| 2087 | )}); | 2180 | )}); |
| 2088 | } | 2181 | } |
| 2089 | 2182 | ||
| 2090 | fn fmtIntLiteral( | 2183 | fn fmtIntLiteral( |
| 2091 | dg: *DeclGen, | 2184 | dg: *DeclGen, |
| 2092 | ty: Type, | ||
| 2093 | val: Value, | 2185 | val: Value, |
| 2094 | loc: ValueRenderLocation, | 2186 | loc: ValueRenderLocation, |
| 2095 | ) !std.fmt.Formatter(formatIntLiteral) { | 2187 | ) !std.fmt.Formatter(formatIntLiteral) { |
| 2096 | const mod = dg.module; | 2188 | const zcu = dg.zcu; |
| 2097 | const kind: CType.Kind = switch (loc) { | 2189 | const kind: CType.Kind = switch (loc) { |
| 2098 | .FunctionArgument => .parameter, | 2190 | .FunctionArgument => .parameter, |
| 2099 | .Initializer, .Other => .complete, | 2191 | .Initializer, .Other => .complete, |
| 2100 | .StaticInitializer => .global, | 2192 | .StaticInitializer => .global, |
| 2101 | }; | 2193 | }; |
| 2194 | const ty = val.typeOf(zcu); | ||
| 2102 | return std.fmt.Formatter(formatIntLiteral){ .data = .{ | 2195 | return std.fmt.Formatter(formatIntLiteral){ .data = .{ |
| 2103 | .dg = dg, | 2196 | .dg = dg, |
| 2104 | .int_info = ty.intInfo(mod), | 2197 | .int_info = ty.intInfo(zcu), |
| 2105 | .kind = kind, | 2198 | .kind = kind, |
| 2106 | .cty = try dg.typeToCType(ty, kind), | 2199 | .ctype = try dg.ctypeFromType(ty, kind), |
| 2107 | .val = val, | 2200 | .val = val, |
| 2108 | } }; | 2201 | } }; |
| 2109 | } | 2202 | } |
| ... | @@ -2132,122 +2225,74 @@ const RenderCTypeTrailing = enum { | ... | @@ -2132,122 +2225,74 @@ const RenderCTypeTrailing = enum { |
| 2132 | } | 2225 | } |
| 2133 | } | 2226 | } |
| 2134 | }; | 2227 | }; |
| 2135 | fn renderTypeName( | 2228 | fn renderAlignedTypeName(w: anytype, ctype: CType) !void { |
| 2136 | mod: *Module, | 2229 | try w.print("anon__aligned_{d}", .{@intFromEnum(ctype.index)}); |
| 2230 | } | ||
| 2231 | fn renderFwdDeclTypeName( | ||
| 2232 | zcu: *Zcu, | ||
| 2137 | w: anytype, | 2233 | w: anytype, |
| 2138 | idx: CType.Index, | 2234 | ctype: CType, |
| 2139 | cty: CType, | 2235 | fwd_decl: CType.Info.FwdDecl, |
| 2140 | attributes: []const u8, | 2236 | attributes: []const u8, |
| 2141 | ) !void { | 2237 | ) !void { |
| 2142 | switch (cty.tag()) { | 2238 | try w.print("{s} {s}", .{ @tagName(fwd_decl.tag), attributes }); |
| 2143 | else => unreachable, | 2239 | switch (fwd_decl.name) { |
| 2144 | 2240 | .anon => try w.print("anon__lazy_{d}", .{@intFromEnum(ctype.index)}), | |
| 2145 | .fwd_anon_struct, | 2241 | .owner_decl => |owner_decl| try w.print("{}__{d}", .{ |
| 2146 | .fwd_anon_union, | 2242 | fmtIdent(zcu.intern_pool.stringToSlice(zcu.declPtr(owner_decl).name)), |
| 2147 | => |tag| try w.print("{s} {s}anon__lazy_{d}", .{ | 2243 | @intFromEnum(owner_decl), |
| 2148 | @tagName(tag)["fwd_anon_".len..], | ||
| 2149 | attributes, | ||
| 2150 | idx, | ||
| 2151 | }), | 2244 | }), |
| 2152 | |||
| 2153 | .fwd_struct, | ||
| 2154 | .fwd_union, | ||
| 2155 | => |tag| { | ||
| 2156 | const owner_decl = cty.cast(CType.Payload.FwdDecl).?.data; | ||
| 2157 | try w.print("{s} {s}{}__{d}", .{ | ||
| 2158 | @tagName(tag)["fwd_".len..], | ||
| 2159 | attributes, | ||
| 2160 | fmtIdent(mod.intern_pool.stringToSlice(mod.declPtr(owner_decl).name)), | ||
| 2161 | @intFromEnum(owner_decl), | ||
| 2162 | }); | ||
| 2163 | }, | ||
| 2164 | } | 2245 | } |
| 2165 | } | 2246 | } |
| 2166 | fn renderTypePrefix( | 2247 | fn renderTypePrefix( |
| 2167 | pass: DeclGen.Pass, | 2248 | pass: DeclGen.Pass, |
| 2168 | store: CType.Store.Set, | 2249 | ctype_pool: *const CType.Pool, |
| 2169 | mod: *Module, | 2250 | zcu: *Zcu, |
| 2170 | w: anytype, | 2251 | w: anytype, |
| 2171 | idx: CType.Index, | 2252 | ctype: CType, |
| 2172 | parent_fix: CTypeFix, | 2253 | parent_fix: CTypeFix, |
| 2173 | qualifiers: CQualifiers, | 2254 | qualifiers: CQualifiers, |
| 2174 | ) @TypeOf(w).Error!RenderCTypeTrailing { | 2255 | ) @TypeOf(w).Error!RenderCTypeTrailing { |
| 2175 | var trailing = RenderCTypeTrailing.maybe_space; | 2256 | var trailing = RenderCTypeTrailing.maybe_space; |
| 2257 | switch (ctype.info(ctype_pool)) { | ||
| 2258 | .basic => |basic_info| try w.writeAll(@tagName(basic_info)), | ||
| 2176 | 2259 | ||
| 2177 | const cty = store.indexToCType(idx); | 2260 | .pointer => |pointer_info| { |
| 2178 | switch (cty.tag()) { | 2261 | try w.print("{}*", .{try renderTypePrefix( |
| 2179 | .void, | ||
| 2180 | .char, | ||
| 2181 | .@"signed char", | ||
| 2182 | .short, | ||
| 2183 | .int, | ||
| 2184 | .long, | ||
| 2185 | .@"long long", | ||
| 2186 | ._Bool, | ||
| 2187 | .@"unsigned char", | ||
| 2188 | .@"unsigned short", | ||
| 2189 | .@"unsigned int", | ||
| 2190 | .@"unsigned long", | ||
| 2191 | .@"unsigned long long", | ||
| 2192 | .float, | ||
| 2193 | .double, | ||
| 2194 | .@"long double", | ||
| 2195 | .bool, | ||
| 2196 | .size_t, | ||
| 2197 | .ptrdiff_t, | ||
| 2198 | .uint8_t, | ||
| 2199 | .int8_t, | ||
| 2200 | .uint16_t, | ||
| 2201 | .int16_t, | ||
| 2202 | .uint32_t, | ||
| 2203 | .int32_t, | ||
| 2204 | .uint64_t, | ||
| 2205 | .int64_t, | ||
| 2206 | .uintptr_t, | ||
| 2207 | .intptr_t, | ||
| 2208 | .zig_u128, | ||
| 2209 | .zig_i128, | ||
| 2210 | .zig_f16, | ||
| 2211 | .zig_f32, | ||
| 2212 | .zig_f64, | ||
| 2213 | .zig_f80, | ||
| 2214 | .zig_f128, | ||
| 2215 | .zig_c_longdouble, | ||
| 2216 | => |tag| try w.writeAll(@tagName(tag)), | ||
| 2217 | |||
| 2218 | .pointer, | ||
| 2219 | .pointer_const, | ||
| 2220 | .pointer_volatile, | ||
| 2221 | .pointer_const_volatile, | ||
| 2222 | => |tag| { | ||
| 2223 | const child_idx = cty.cast(CType.Payload.Child).?.data; | ||
| 2224 | const child_trailing = try renderTypePrefix( | ||
| 2225 | pass, | 2262 | pass, |
| 2226 | store, | 2263 | ctype_pool, |
| 2227 | mod, | 2264 | zcu, |
| 2228 | w, | 2265 | w, |
| 2229 | child_idx, | 2266 | pointer_info.elem_ctype, |
| 2230 | .prefix, | 2267 | .prefix, |
| 2231 | CQualifiers.init(.{ .@"const" = switch (tag) { | 2268 | CQualifiers.init(.{ |
| 2232 | .pointer, .pointer_volatile => false, | 2269 | .@"const" = pointer_info.@"const", |
| 2233 | .pointer_const, .pointer_const_volatile => true, | 2270 | .@"volatile" = pointer_info.@"volatile", |
| 2234 | else => unreachable, | 2271 | }), |
| 2235 | }, .@"volatile" = switch (tag) { | 2272 | )}); |
| 2236 | .pointer, .pointer_const => false, | ||
| 2237 | .pointer_volatile, .pointer_const_volatile => true, | ||
| 2238 | else => unreachable, | ||
| 2239 | } }), | ||
| 2240 | ); | ||
| 2241 | try w.print("{}*", .{child_trailing}); | ||
| 2242 | trailing = .no_space; | 2273 | trailing = .no_space; |
| 2243 | }, | 2274 | }, |
| 2244 | 2275 | ||
| 2245 | .array, | 2276 | .aligned => switch (pass) { |
| 2246 | .vector, | 2277 | .decl => |decl_index| try w.print("decl__{d}_{d}", .{ |
| 2247 | => { | 2278 | @intFromEnum(decl_index), @intFromEnum(ctype.index), |
| 2248 | const child_idx = cty.cast(CType.Payload.Sequence).?.data.elem_type; | 2279 | }), |
| 2249 | const child_trailing = | 2280 | .anon => |anon_decl| try w.print("anon__{d}_{d}", .{ |
| 2250 | try renderTypePrefix(pass, store, mod, w, child_idx, .suffix, qualifiers); | 2281 | @intFromEnum(anon_decl), @intFromEnum(ctype.index), |
| 2282 | }), | ||
| 2283 | .flush => try renderAlignedTypeName(w, ctype), | ||
| 2284 | }, | ||
| 2285 | |||
| 2286 | .array, .vector => |sequence_info| { | ||
| 2287 | const child_trailing = try renderTypePrefix( | ||
| 2288 | pass, | ||
| 2289 | ctype_pool, | ||
| 2290 | zcu, | ||
| 2291 | w, | ||
| 2292 | sequence_info.elem_ctype, | ||
| 2293 | .suffix, | ||
| 2294 | qualifiers, | ||
| 2295 | ); | ||
| 2251 | switch (parent_fix) { | 2296 | switch (parent_fix) { |
| 2252 | .prefix => { | 2297 | .prefix => { |
| 2253 | try w.print("{}(", .{child_trailing}); | 2298 | try w.print("{}(", .{child_trailing}); |
| ... | @@ -2257,56 +2302,46 @@ fn renderTypePrefix( | ... | @@ -2257,56 +2302,46 @@ fn renderTypePrefix( |
| 2257 | } | 2302 | } |
| 2258 | }, | 2303 | }, |
| 2259 | 2304 | ||
| 2260 | .fwd_anon_struct, | 2305 | .fwd_decl => |fwd_decl_info| switch (fwd_decl_info.name) { |
| 2261 | .fwd_anon_union, | 2306 | .anon => switch (pass) { |
| 2262 | => switch (pass) { | 2307 | .decl => |decl_index| try w.print("decl__{d}_{d}", .{ |
| 2263 | .decl => |decl_index| try w.print("decl__{d}_{d}", .{ @intFromEnum(decl_index), idx }), | 2308 | @intFromEnum(decl_index), @intFromEnum(ctype.index), |
| 2264 | .anon => |anon_decl| try w.print("anon__{d}_{d}", .{ @intFromEnum(anon_decl), idx }), | 2309 | }), |
| 2265 | .flush => try renderTypeName(mod, w, idx, cty, ""), | 2310 | .anon => |anon_decl| try w.print("anon__{d}_{d}", .{ |
| 2311 | @intFromEnum(anon_decl), @intFromEnum(ctype.index), | ||
| 2312 | }), | ||
| 2313 | .flush => try renderFwdDeclTypeName(zcu, w, ctype, fwd_decl_info, ""), | ||
| 2314 | }, | ||
| 2315 | .owner_decl => try renderFwdDeclTypeName(zcu, w, ctype, fwd_decl_info, ""), | ||
| 2266 | }, | 2316 | }, |
| 2267 | 2317 | ||
| 2268 | .fwd_struct, | 2318 | .aggregate => |aggregate_info| switch (aggregate_info.name) { |
| 2269 | .fwd_union, | 2319 | .anon => { |
| 2270 | => try renderTypeName(mod, w, idx, cty, ""), | 2320 | try w.print("{s} {s}", .{ |
| 2271 | 2321 | @tagName(aggregate_info.tag), | |
| 2272 | .unnamed_struct, | 2322 | if (aggregate_info.@"packed") "zig_packed(" else "", |
| 2273 | .unnamed_union, | 2323 | }); |
| 2274 | .packed_unnamed_struct, | 2324 | try renderFields(zcu, w, ctype_pool, aggregate_info, 1); |
| 2275 | .packed_unnamed_union, | 2325 | if (aggregate_info.@"packed") try w.writeByte(')'); |
| 2276 | => |tag| { | 2326 | }, |
| 2277 | try w.print("{s} {s}", .{ | 2327 | .fwd_decl => |fwd_decl| return renderTypePrefix( |
| 2278 | @tagName(tag)["unnamed_".len..], | 2328 | pass, |
| 2279 | if (cty.isPacked()) "zig_packed(" else "", | 2329 | ctype_pool, |
| 2280 | }); | 2330 | zcu, |
| 2281 | try renderAggregateFields(mod, w, store, cty, 1); | 2331 | w, |
| 2282 | if (cty.isPacked()) try w.writeByte(')'); | 2332 | fwd_decl, |
| 2333 | parent_fix, | ||
| 2334 | qualifiers, | ||
| 2335 | ), | ||
| 2283 | }, | 2336 | }, |
| 2284 | 2337 | ||
| 2285 | .anon_struct, | 2338 | .function => |function_info| { |
| 2286 | .anon_union, | ||
| 2287 | .@"struct", | ||
| 2288 | .@"union", | ||
| 2289 | .packed_struct, | ||
| 2290 | .packed_union, | ||
| 2291 | => return renderTypePrefix( | ||
| 2292 | pass, | ||
| 2293 | store, | ||
| 2294 | mod, | ||
| 2295 | w, | ||
| 2296 | cty.cast(CType.Payload.Aggregate).?.data.fwd_decl, | ||
| 2297 | parent_fix, | ||
| 2298 | qualifiers, | ||
| 2299 | ), | ||
| 2300 | |||
| 2301 | .function, | ||
| 2302 | .varargs_function, | ||
| 2303 | => { | ||
| 2304 | const child_trailing = try renderTypePrefix( | 2339 | const child_trailing = try renderTypePrefix( |
| 2305 | pass, | 2340 | pass, |
| 2306 | store, | 2341 | ctype_pool, |
| 2307 | mod, | 2342 | zcu, |
| 2308 | w, | 2343 | w, |
| 2309 | cty.cast(CType.Payload.Function).?.data.return_type, | 2344 | function_info.return_ctype, |
| 2310 | .suffix, | 2345 | .suffix, |
| 2311 | .{}, | 2346 | .{}, |
| 2312 | ); | 2347 | ); |
| ... | @@ -2319,170 +2354,107 @@ fn renderTypePrefix( | ... | @@ -2319,170 +2354,107 @@ fn renderTypePrefix( |
| 2319 | } | 2354 | } |
| 2320 | }, | 2355 | }, |
| 2321 | } | 2356 | } |
| 2322 | |||
| 2323 | var qualifier_it = qualifiers.iterator(); | 2357 | var qualifier_it = qualifiers.iterator(); |
| 2324 | while (qualifier_it.next()) |qualifier| { | 2358 | while (qualifier_it.next()) |qualifier| { |
| 2325 | try w.print("{}{s}", .{ trailing, @tagName(qualifier) }); | 2359 | try w.print("{}{s}", .{ trailing, @tagName(qualifier) }); |
| 2326 | trailing = .maybe_space; | 2360 | trailing = .maybe_space; |
| 2327 | } | 2361 | } |
| 2328 | |||
| 2329 | return trailing; | 2362 | return trailing; |
| 2330 | } | 2363 | } |
| 2331 | fn renderTypeSuffix( | 2364 | fn renderTypeSuffix( |
| 2332 | pass: DeclGen.Pass, | 2365 | pass: DeclGen.Pass, |
| 2333 | store: CType.Store.Set, | 2366 | ctype_pool: *const CType.Pool, |
| 2334 | mod: *Module, | 2367 | zcu: *Zcu, |
| 2335 | w: anytype, | 2368 | w: anytype, |
| 2336 | idx: CType.Index, | 2369 | ctype: CType, |
| 2337 | parent_fix: CTypeFix, | 2370 | parent_fix: CTypeFix, |
| 2338 | qualifiers: CQualifiers, | 2371 | qualifiers: CQualifiers, |
| 2339 | ) @TypeOf(w).Error!void { | 2372 | ) @TypeOf(w).Error!void { |
| 2340 | const cty = store.indexToCType(idx); | 2373 | switch (ctype.info(ctype_pool)) { |
| 2341 | switch (cty.tag()) { | 2374 | .basic, .aligned, .fwd_decl, .aggregate => {}, |
| 2342 | .void, | 2375 | .pointer => |pointer_info| try renderTypeSuffix( |
| 2343 | .char, | ||
| 2344 | .@"signed char", | ||
| 2345 | .short, | ||
| 2346 | .int, | ||
| 2347 | .long, | ||
| 2348 | .@"long long", | ||
| 2349 | ._Bool, | ||
| 2350 | .@"unsigned char", | ||
| 2351 | .@"unsigned short", | ||
| 2352 | .@"unsigned int", | ||
| 2353 | .@"unsigned long", | ||
| 2354 | .@"unsigned long long", | ||
| 2355 | .float, | ||
| 2356 | .double, | ||
| 2357 | .@"long double", | ||
| 2358 | .bool, | ||
| 2359 | .size_t, | ||
| 2360 | .ptrdiff_t, | ||
| 2361 | .uint8_t, | ||
| 2362 | .int8_t, | ||
| 2363 | .uint16_t, | ||
| 2364 | .int16_t, | ||
| 2365 | .uint32_t, | ||
| 2366 | .int32_t, | ||
| 2367 | .uint64_t, | ||
| 2368 | .int64_t, | ||
| 2369 | .uintptr_t, | ||
| 2370 | .intptr_t, | ||
| 2371 | .zig_u128, | ||
| 2372 | .zig_i128, | ||
| 2373 | .zig_f16, | ||
| 2374 | .zig_f32, | ||
| 2375 | .zig_f64, | ||
| 2376 | .zig_f80, | ||
| 2377 | .zig_f128, | ||
| 2378 | .zig_c_longdouble, | ||
| 2379 | => {}, | ||
| 2380 | |||
| 2381 | .pointer, | ||
| 2382 | .pointer_const, | ||
| 2383 | .pointer_volatile, | ||
| 2384 | .pointer_const_volatile, | ||
| 2385 | => try renderTypeSuffix( | ||
| 2386 | pass, | 2376 | pass, |
| 2387 | store, | 2377 | ctype_pool, |
| 2388 | mod, | 2378 | zcu, |
| 2389 | w, | 2379 | w, |
| 2390 | cty.cast(CType.Payload.Child).?.data, | 2380 | pointer_info.elem_ctype, |
| 2391 | .prefix, | 2381 | .prefix, |
| 2392 | .{}, | 2382 | .{}, |
| 2393 | ), | 2383 | ), |
| 2394 | 2384 | .array, .vector => |sequence_info| { | |
| 2395 | .array, | ||
| 2396 | .vector, | ||
| 2397 | => { | ||
| 2398 | switch (parent_fix) { | 2385 | switch (parent_fix) { |
| 2399 | .prefix => try w.writeByte(')'), | 2386 | .prefix => try w.writeByte(')'), |
| 2400 | .suffix => {}, | 2387 | .suffix => {}, |
| 2401 | } | 2388 | } |
| 2402 | 2389 | ||
| 2403 | try w.print("[{}]", .{cty.cast(CType.Payload.Sequence).?.data.len}); | 2390 | try w.print("[{}]", .{sequence_info.len}); |
| 2404 | try renderTypeSuffix( | 2391 | try renderTypeSuffix(pass, ctype_pool, zcu, w, sequence_info.elem_ctype, .suffix, .{}); |
| 2405 | pass, | ||
| 2406 | store, | ||
| 2407 | mod, | ||
| 2408 | w, | ||
| 2409 | cty.cast(CType.Payload.Sequence).?.data.elem_type, | ||
| 2410 | .suffix, | ||
| 2411 | .{}, | ||
| 2412 | ); | ||
| 2413 | }, | 2392 | }, |
| 2414 | 2393 | .function => |function_info| { | |
| 2415 | .fwd_anon_struct, | ||
| 2416 | .fwd_anon_union, | ||
| 2417 | .fwd_struct, | ||
| 2418 | .fwd_union, | ||
| 2419 | .unnamed_struct, | ||
| 2420 | .unnamed_union, | ||
| 2421 | .packed_unnamed_struct, | ||
| 2422 | .packed_unnamed_union, | ||
| 2423 | .anon_struct, | ||
| 2424 | .anon_union, | ||
| 2425 | .@"struct", | ||
| 2426 | .@"union", | ||
| 2427 | .packed_struct, | ||
| 2428 | .packed_union, | ||
| 2429 | => {}, | ||
| 2430 | |||
| 2431 | .function, | ||
| 2432 | .varargs_function, | ||
| 2433 | => |tag| { | ||
| 2434 | switch (parent_fix) { | 2394 | switch (parent_fix) { |
| 2435 | .prefix => try w.writeByte(')'), | 2395 | .prefix => try w.writeByte(')'), |
| 2436 | .suffix => {}, | 2396 | .suffix => {}, |
| 2437 | } | 2397 | } |
| 2438 | 2398 | ||
| 2439 | const data = cty.cast(CType.Payload.Function).?.data; | ||
| 2440 | |||
| 2441 | try w.writeByte('('); | 2399 | try w.writeByte('('); |
| 2442 | var need_comma = false; | 2400 | var need_comma = false; |
| 2443 | for (data.param_types, 0..) |param_type, param_i| { | 2401 | for (0..function_info.param_ctypes.len) |param_index| { |
| 2402 | const param_type = function_info.param_ctypes.at(param_index, ctype_pool); | ||
| 2444 | if (need_comma) try w.writeAll(", "); | 2403 | if (need_comma) try w.writeAll(", "); |
| 2445 | need_comma = true; | 2404 | need_comma = true; |
| 2446 | const trailing = | 2405 | const trailing = |
| 2447 | try renderTypePrefix(pass, store, mod, w, param_type, .suffix, qualifiers); | 2406 | try renderTypePrefix(pass, ctype_pool, zcu, w, param_type, .suffix, qualifiers); |
| 2448 | if (qualifiers.contains(.@"const")) try w.print("{}a{d}", .{ trailing, param_i }); | 2407 | if (qualifiers.contains(.@"const")) try w.print("{}a{d}", .{ trailing, param_index }); |
| 2449 | try renderTypeSuffix(pass, store, mod, w, param_type, .suffix, .{}); | 2408 | try renderTypeSuffix(pass, ctype_pool, zcu, w, param_type, .suffix, .{}); |
| 2450 | } | 2409 | } |
| 2451 | switch (tag) { | 2410 | if (function_info.varargs) { |
| 2452 | .function => {}, | 2411 | if (need_comma) try w.writeAll(", "); |
| 2453 | .varargs_function => { | 2412 | need_comma = true; |
| 2454 | if (need_comma) try w.writeAll(", "); | 2413 | try w.writeAll("..."); |
| 2455 | need_comma = true; | ||
| 2456 | try w.writeAll("..."); | ||
| 2457 | }, | ||
| 2458 | else => unreachable, | ||
| 2459 | } | 2414 | } |
| 2460 | if (!need_comma) try w.writeAll("void"); | 2415 | if (!need_comma) try w.writeAll("void"); |
| 2461 | try w.writeByte(')'); | 2416 | try w.writeByte(')'); |
| 2462 | 2417 | ||
| 2463 | try renderTypeSuffix(pass, store, mod, w, data.return_type, .suffix, .{}); | 2418 | try renderTypeSuffix(pass, ctype_pool, zcu, w, function_info.return_ctype, .suffix, .{}); |
| 2464 | }, | 2419 | }, |
| 2465 | } | 2420 | } |
| 2466 | } | 2421 | } |
| 2467 | fn renderAggregateFields( | 2422 | fn renderFields( |
| 2468 | mod: *Module, | 2423 | zcu: *Zcu, |
| 2469 | writer: anytype, | 2424 | writer: anytype, |
| 2470 | store: CType.Store.Set, | 2425 | ctype_pool: *const CType.Pool, |
| 2471 | cty: CType, | 2426 | aggregate_info: CType.Info.Aggregate, |
| 2472 | indent: usize, | 2427 | indent: usize, |
| 2473 | ) !void { | 2428 | ) !void { |
| 2474 | try writer.writeAll("{\n"); | 2429 | try writer.writeAll("{\n"); |
| 2475 | const fields = cty.fields(); | 2430 | for (0..aggregate_info.fields.len) |field_index| { |
| 2476 | for (fields) |field| { | 2431 | const field_info = aggregate_info.fields.at(field_index, ctype_pool); |
| 2477 | try writer.writeByteNTimes(' ', indent + 1); | 2432 | try writer.writeByteNTimes(' ', indent + 1); |
| 2478 | switch (field.alignas.abiOrder()) { | 2433 | switch (field_info.alignas.abiOrder()) { |
| 2479 | .lt => try writer.print("zig_under_align({}) ", .{field.alignas.toByteUnits()}), | 2434 | .lt => { |
| 2480 | .eq => {}, | 2435 | std.debug.assert(aggregate_info.@"packed"); |
| 2481 | .gt => try writer.print("zig_align({}) ", .{field.alignas.toByteUnits()}), | 2436 | if (field_info.alignas.@"align" != .@"1") try writer.print("zig_under_align({}) ", .{ |
| 2437 | field_info.alignas.toByteUnits(), | ||
| 2438 | }); | ||
| 2439 | }, | ||
| 2440 | .eq => if (aggregate_info.@"packed" and field_info.alignas.@"align" != .@"1") | ||
| 2441 | try writer.print("zig_align({}) ", .{field_info.alignas.toByteUnits()}), | ||
| 2442 | .gt => { | ||
| 2443 | std.debug.assert(field_info.alignas.@"align" != .@"1"); | ||
| 2444 | try writer.print("zig_align({}) ", .{field_info.alignas.toByteUnits()}); | ||
| 2445 | }, | ||
| 2482 | } | 2446 | } |
| 2483 | const trailing = try renderTypePrefix(.flush, store, mod, writer, field.type, .suffix, .{}); | 2447 | const trailing = try renderTypePrefix( |
| 2484 | try writer.print("{}{ }", .{ trailing, fmtIdent(mem.span(field.name)) }); | 2448 | .flush, |
| 2485 | try renderTypeSuffix(.flush, store, mod, writer, field.type, .suffix, .{}); | 2449 | ctype_pool, |
| 2450 | zcu, | ||
| 2451 | writer, | ||
| 2452 | field_info.ctype, | ||
| 2453 | .suffix, | ||
| 2454 | .{}, | ||
| 2455 | ); | ||
| 2456 | try writer.print("{}{ }", .{ trailing, fmtIdent(field_info.name.slice(ctype_pool)) }); | ||
| 2457 | try renderTypeSuffix(.flush, ctype_pool, zcu, writer, field_info.ctype, .suffix, .{}); | ||
| 2486 | try writer.writeAll(";\n"); | 2458 | try writer.writeAll(";\n"); |
| 2487 | } | 2459 | } |
| 2488 | try writer.writeByteNTimes(' ', indent); | 2460 | try writer.writeByteNTimes(' ', indent); |
| ... | @@ -2490,106 +2462,112 @@ fn renderAggregateFields( | ... | @@ -2490,106 +2462,112 @@ fn renderAggregateFields( |
| 2490 | } | 2462 | } |
| 2491 | 2463 | ||
| 2492 | pub fn genTypeDecl( | 2464 | pub fn genTypeDecl( |
| 2493 | mod: *Module, | 2465 | zcu: *Zcu, |
| 2494 | writer: anytype, | 2466 | writer: anytype, |
| 2495 | global_store: CType.Store.Set, | 2467 | global_ctype_pool: *const CType.Pool, |
| 2496 | global_idx: CType.Index, | 2468 | global_ctype: CType, |
| 2497 | pass: DeclGen.Pass, | 2469 | pass: DeclGen.Pass, |
| 2498 | decl_store: CType.Store.Set, | 2470 | decl_ctype_pool: *const CType.Pool, |
| 2499 | decl_idx: CType.Index, | 2471 | decl_ctype: CType, |
| 2500 | found_existing: bool, | 2472 | found_existing: bool, |
| 2501 | ) !void { | 2473 | ) !void { |
| 2502 | const global_cty = global_store.indexToCType(global_idx); | 2474 | switch (global_ctype.info(global_ctype_pool)) { |
| 2503 | switch (global_cty.tag()) { | 2475 | .basic, .pointer, .array, .vector, .function => {}, |
| 2504 | .fwd_anon_struct => if (pass != .flush) { | 2476 | .aligned => |aligned_info| { |
| 2505 | try writer.writeAll("typedef "); | 2477 | if (!found_existing) { |
| 2506 | _ = try renderTypePrefix(.flush, global_store, mod, writer, global_idx, .suffix, .{}); | 2478 | std.debug.assert(aligned_info.alignas.abiOrder().compare(.lt)); |
| 2507 | try writer.writeByte(' '); | 2479 | try writer.print("typedef zig_under_align({d}) ", .{aligned_info.alignas.toByteUnits()}); |
| 2508 | _ = try renderTypePrefix(pass, decl_store, mod, writer, decl_idx, .suffix, .{}); | 2480 | try writer.print("{}", .{try renderTypePrefix( |
| 2509 | try writer.writeAll(";\n"); | 2481 | .flush, |
| 2510 | }, | 2482 | global_ctype_pool, |
| 2511 | 2483 | zcu, | |
| 2512 | .fwd_struct, | 2484 | writer, |
| 2513 | .fwd_union, | 2485 | aligned_info.ctype, |
| 2514 | .anon_struct, | 2486 | .suffix, |
| 2515 | .anon_union, | 2487 | .{}, |
| 2516 | .@"struct", | 2488 | )}); |
| 2517 | .@"union", | 2489 | try renderAlignedTypeName(writer, global_ctype); |
| 2518 | .packed_struct, | 2490 | try renderTypeSuffix(.flush, global_ctype_pool, zcu, writer, aligned_info.ctype, .suffix, .{}); |
| 2519 | .packed_union, | 2491 | try writer.writeAll(";\n"); |
| 2520 | => |tag| if (!found_existing) { | 2492 | } |
| 2521 | switch (tag) { | 2493 | switch (pass) { |
| 2522 | .fwd_struct, | 2494 | .decl, .anon => { |
| 2523 | .fwd_union, | 2495 | try writer.writeAll("typedef "); |
| 2524 | => { | 2496 | _ = try renderTypePrefix(.flush, global_ctype_pool, zcu, writer, global_ctype, .suffix, .{}); |
| 2525 | const owner_decl = global_cty.cast(CType.Payload.FwdDecl).?.data; | ||
| 2526 | _ = try renderTypePrefix( | ||
| 2527 | .flush, | ||
| 2528 | global_store, | ||
| 2529 | mod, | ||
| 2530 | writer, | ||
| 2531 | global_idx, | ||
| 2532 | .suffix, | ||
| 2533 | .{}, | ||
| 2534 | ); | ||
| 2535 | try writer.writeAll("; /* "); | ||
| 2536 | try mod.declPtr(owner_decl).renderFullyQualifiedName(mod, writer); | ||
| 2537 | try writer.writeAll(" */\n"); | ||
| 2538 | }, | ||
| 2539 | |||
| 2540 | .anon_struct, | ||
| 2541 | .anon_union, | ||
| 2542 | .@"struct", | ||
| 2543 | .@"union", | ||
| 2544 | .packed_struct, | ||
| 2545 | .packed_union, | ||
| 2546 | => { | ||
| 2547 | const fwd_idx = global_cty.cast(CType.Payload.Aggregate).?.data.fwd_decl; | ||
| 2548 | try renderTypeName( | ||
| 2549 | mod, | ||
| 2550 | writer, | ||
| 2551 | fwd_idx, | ||
| 2552 | global_store.indexToCType(fwd_idx), | ||
| 2553 | if (global_cty.isPacked()) "zig_packed(" else "", | ||
| 2554 | ); | ||
| 2555 | try writer.writeByte(' '); | 2497 | try writer.writeByte(' '); |
| 2556 | try renderAggregateFields(mod, writer, global_store, global_cty, 0); | 2498 | _ = try renderTypePrefix(pass, decl_ctype_pool, zcu, writer, decl_ctype, .suffix, .{}); |
| 2557 | if (global_cty.isPacked()) try writer.writeByte(')'); | ||
| 2558 | try writer.writeAll(";\n"); | 2499 | try writer.writeAll(";\n"); |
| 2559 | }, | 2500 | }, |
| 2560 | 2501 | .flush => {}, | |
| 2561 | else => unreachable, | ||
| 2562 | } | 2502 | } |
| 2563 | }, | 2503 | }, |
| 2564 | 2504 | .fwd_decl => |fwd_decl_info| switch (fwd_decl_info.name) { | |
| 2565 | else => {}, | 2505 | .anon => switch (pass) { |
| 2506 | .decl, .anon => { | ||
| 2507 | try writer.writeAll("typedef "); | ||
| 2508 | _ = try renderTypePrefix(.flush, global_ctype_pool, zcu, writer, global_ctype, .suffix, .{}); | ||
| 2509 | try writer.writeByte(' '); | ||
| 2510 | _ = try renderTypePrefix(pass, decl_ctype_pool, zcu, writer, decl_ctype, .suffix, .{}); | ||
| 2511 | try writer.writeAll(";\n"); | ||
| 2512 | }, | ||
| 2513 | .flush => {}, | ||
| 2514 | }, | ||
| 2515 | .owner_decl => |owner_decl_index| if (!found_existing) { | ||
| 2516 | _ = try renderTypePrefix(.flush, global_ctype_pool, zcu, writer, global_ctype, .suffix, .{}); | ||
| 2517 | try writer.writeByte(';'); | ||
| 2518 | const owner_decl = zcu.declPtr(owner_decl_index); | ||
| 2519 | const owner_mod = zcu.namespacePtr(owner_decl.src_namespace).file_scope.mod; | ||
| 2520 | if (!owner_mod.strip) { | ||
| 2521 | try writer.writeAll(" /* "); | ||
| 2522 | try owner_decl.renderFullyQualifiedName(zcu, writer); | ||
| 2523 | try writer.writeAll(" */"); | ||
| 2524 | } | ||
| 2525 | try writer.writeByte('\n'); | ||
| 2526 | }, | ||
| 2527 | }, | ||
| 2528 | .aggregate => |aggregate_info| switch (aggregate_info.name) { | ||
| 2529 | .anon => {}, | ||
| 2530 | .fwd_decl => |fwd_decl| if (!found_existing) { | ||
| 2531 | try renderFwdDeclTypeName( | ||
| 2532 | zcu, | ||
| 2533 | writer, | ||
| 2534 | fwd_decl, | ||
| 2535 | fwd_decl.info(global_ctype_pool).fwd_decl, | ||
| 2536 | if (aggregate_info.@"packed") "zig_packed(" else "", | ||
| 2537 | ); | ||
| 2538 | try writer.writeByte(' '); | ||
| 2539 | try renderFields(zcu, writer, global_ctype_pool, aggregate_info, 0); | ||
| 2540 | if (aggregate_info.@"packed") try writer.writeByte(')'); | ||
| 2541 | try writer.writeAll(";\n"); | ||
| 2542 | }, | ||
| 2543 | }, | ||
| 2566 | } | 2544 | } |
| 2567 | } | 2545 | } |
| 2568 | 2546 | ||
| 2569 | pub fn genGlobalAsm(mod: *Module, writer: anytype) !void { | 2547 | pub fn genGlobalAsm(zcu: *Zcu, writer: anytype) !void { |
| 2570 | for (mod.global_assembly.values()) |asm_source| { | 2548 | for (zcu.global_assembly.values()) |asm_source| { |
| 2571 | try writer.print("__asm({s});\n", .{fmtStringLiteral(asm_source, null)}); | 2549 | try writer.print("__asm({s});\n", .{fmtStringLiteral(asm_source, null)}); |
| 2572 | } | 2550 | } |
| 2573 | } | 2551 | } |
| 2574 | 2552 | ||
| 2575 | pub fn genErrDecls(o: *Object) !void { | 2553 | pub fn genErrDecls(o: *Object) !void { |
| 2576 | const mod = o.dg.module; | 2554 | const zcu = o.dg.zcu; |
| 2577 | const ip = &mod.intern_pool; | 2555 | const ip = &zcu.intern_pool; |
| 2578 | const writer = o.writer(); | 2556 | const writer = o.writer(); |
| 2579 | 2557 | ||
| 2580 | var max_name_len: usize = 0; | 2558 | var max_name_len: usize = 0; |
| 2581 | // do not generate an invalid empty enum when the global error set is empty | 2559 | // do not generate an invalid empty enum when the global error set is empty |
| 2582 | if (mod.global_error_set.keys().len > 1) { | 2560 | if (zcu.global_error_set.keys().len > 1) { |
| 2583 | try writer.writeAll("enum {\n"); | 2561 | try writer.writeAll("enum {\n"); |
| 2584 | o.indent_writer.pushIndent(); | 2562 | o.indent_writer.pushIndent(); |
| 2585 | for (mod.global_error_set.keys()[1..], 1..) |name_nts, value| { | 2563 | for (zcu.global_error_set.keys()[1..], 1..) |name_nts, value| { |
| 2586 | const name = ip.stringToSlice(name_nts); | 2564 | const name = ip.stringToSlice(name_nts); |
| 2587 | max_name_len = @max(name.len, max_name_len); | 2565 | max_name_len = @max(name.len, max_name_len); |
| 2588 | const err_val = try mod.intern(.{ .err = .{ | 2566 | const err_val = try zcu.intern(.{ .err = .{ |
| 2589 | .ty = .anyerror_type, | 2567 | .ty = .anyerror_type, |
| 2590 | .name = name_nts, | 2568 | .name = name_nts, |
| 2591 | } }); | 2569 | } }); |
| 2592 | try o.dg.renderValue(writer, Type.anyerror, Value.fromInterned(err_val), .Other); | 2570 | try o.dg.renderValue(writer, Value.fromInterned(err_val), .Other); |
| 2593 | try writer.print(" = {d}u,\n", .{value}); | 2571 | try writer.print(" = {d}u,\n", .{value}); |
| 2594 | } | 2572 | } |
| 2595 | o.indent_writer.popIndent(); | 2573 | o.indent_writer.popIndent(); |
| ... | @@ -2601,44 +2579,56 @@ pub fn genErrDecls(o: *Object) !void { | ... | @@ -2601,44 +2579,56 @@ pub fn genErrDecls(o: *Object) !void { |
| 2601 | defer o.dg.gpa.free(name_buf); | 2579 | defer o.dg.gpa.free(name_buf); |
| 2602 | 2580 | ||
| 2603 | @memcpy(name_buf[0..name_prefix.len], name_prefix); | 2581 | @memcpy(name_buf[0..name_prefix.len], name_prefix); |
| 2604 | for (mod.global_error_set.keys()) |name_ip| { | 2582 | for (zcu.global_error_set.keys()) |name_ip| { |
| 2605 | const name = ip.stringToSlice(name_ip); | 2583 | const name = ip.stringToSlice(name_ip); |
| 2606 | @memcpy(name_buf[name_prefix.len..][0..name.len], name); | 2584 | @memcpy(name_buf[name_prefix.len..][0..name.len], name); |
| 2607 | const identifier = name_buf[0 .. name_prefix.len + name.len]; | 2585 | const identifier = name_buf[0 .. name_prefix.len + name.len]; |
| 2608 | 2586 | ||
| 2609 | const name_ty = try mod.arrayType(.{ | 2587 | const name_ty = try zcu.arrayType(.{ |
| 2610 | .len = name.len, | 2588 | .len = name.len, |
| 2611 | .child = .u8_type, | 2589 | .child = .u8_type, |
| 2612 | .sentinel = .zero_u8, | 2590 | .sentinel = .zero_u8, |
| 2613 | }); | 2591 | }); |
| 2614 | const name_val = try mod.intern(.{ .aggregate = .{ | 2592 | const name_val = try zcu.intern(.{ .aggregate = .{ |
| 2615 | .ty = name_ty.toIntern(), | 2593 | .ty = name_ty.toIntern(), |
| 2616 | .storage = .{ .bytes = name }, | 2594 | .storage = .{ .bytes = name }, |
| 2617 | } }); | 2595 | } }); |
| 2618 | 2596 | ||
| 2619 | try writer.writeAll("static "); | 2597 | try writer.writeAll("static "); |
| 2620 | try o.dg.renderTypeAndName(writer, name_ty, .{ .identifier = identifier }, Const, .none, .complete); | 2598 | try o.dg.renderTypeAndName( |
| 2599 | writer, | ||
| 2600 | name_ty, | ||
| 2601 | .{ .identifier = identifier }, | ||
| 2602 | Const, | ||
| 2603 | .none, | ||
| 2604 | .complete, | ||
| 2605 | ); | ||
| 2621 | try writer.writeAll(" = "); | 2606 | try writer.writeAll(" = "); |
| 2622 | try o.dg.renderValue(writer, name_ty, Value.fromInterned(name_val), .StaticInitializer); | 2607 | try o.dg.renderValue(writer, Value.fromInterned(name_val), .StaticInitializer); |
| 2623 | try writer.writeAll(";\n"); | 2608 | try writer.writeAll(";\n"); |
| 2624 | } | 2609 | } |
| 2625 | 2610 | ||
| 2626 | const name_array_ty = try mod.arrayType(.{ | 2611 | const name_array_ty = try zcu.arrayType(.{ |
| 2627 | .len = mod.global_error_set.count(), | 2612 | .len = zcu.global_error_set.count(), |
| 2628 | .child = .slice_const_u8_sentinel_0_type, | 2613 | .child = .slice_const_u8_sentinel_0_type, |
| 2629 | }); | 2614 | }); |
| 2630 | 2615 | ||
| 2631 | try writer.writeAll("static "); | 2616 | try writer.writeAll("static "); |
| 2632 | try o.dg.renderTypeAndName(writer, name_array_ty, .{ .identifier = array_identifier }, Const, .none, .complete); | 2617 | try o.dg.renderTypeAndName( |
| 2618 | writer, | ||
| 2619 | name_array_ty, | ||
| 2620 | .{ .identifier = array_identifier }, | ||
| 2621 | Const, | ||
| 2622 | .none, | ||
| 2623 | .complete, | ||
| 2624 | ); | ||
| 2633 | try writer.writeAll(" = {"); | 2625 | try writer.writeAll(" = {"); |
| 2634 | for (mod.global_error_set.keys(), 0..) |name_nts, value| { | 2626 | for (zcu.global_error_set.keys(), 0..) |name_nts, value| { |
| 2635 | const name = ip.stringToSlice(name_nts); | 2627 | const name = ip.stringToSlice(name_nts); |
| 2636 | if (value != 0) try writer.writeByte(','); | 2628 | if (value != 0) try writer.writeByte(','); |
| 2637 | |||
| 2638 | const len_val = try mod.intValue(Type.usize, name.len); | ||
| 2639 | |||
| 2640 | try writer.print("{{" ++ name_prefix ++ "{}, {}}}", .{ | 2629 | try writer.print("{{" ++ name_prefix ++ "{}, {}}}", .{ |
| 2641 | fmtIdent(name), try o.dg.fmtIntLiteral(Type.usize, len_val, .StaticInitializer), | 2630 | fmtIdent(name), |
| 2631 | try o.dg.fmtIntLiteral(try zcu.intValue(Type.usize, name.len), .StaticInitializer), | ||
| 2642 | }); | 2632 | }); |
| 2643 | } | 2633 | } |
| 2644 | try writer.writeAll("};\n"); | 2634 | try writer.writeAll("};\n"); |
| ... | @@ -2648,16 +2638,16 @@ fn genExports(o: *Object) !void { | ... | @@ -2648,16 +2638,16 @@ fn genExports(o: *Object) !void { |
| 2648 | const tracy = trace(@src()); | 2638 | const tracy = trace(@src()); |
| 2649 | defer tracy.end(); | 2639 | defer tracy.end(); |
| 2650 | 2640 | ||
| 2651 | const mod = o.dg.module; | 2641 | const zcu = o.dg.zcu; |
| 2652 | const ip = &mod.intern_pool; | 2642 | const ip = &zcu.intern_pool; |
| 2653 | const decl_index = switch (o.dg.pass) { | 2643 | const decl_index = switch (o.dg.pass) { |
| 2654 | .decl => |decl| decl, | 2644 | .decl => |decl| decl, |
| 2655 | .anon, .flush => return, | 2645 | .anon, .flush => return, |
| 2656 | }; | 2646 | }; |
| 2657 | const decl = mod.declPtr(decl_index); | 2647 | const decl = zcu.declPtr(decl_index); |
| 2658 | const fwd = o.dg.fwdDeclWriter(); | 2648 | const fwd = o.dg.fwdDeclWriter(); |
| 2659 | 2649 | ||
| 2660 | const exports = mod.decl_exports.get(decl_index) orelse return; | 2650 | const exports = zcu.decl_exports.get(decl_index) orelse return; |
| 2661 | if (exports.items.len < 2) return; | 2651 | if (exports.items.len < 2) return; |
| 2662 | 2652 | ||
| 2663 | const is_variable_const = switch (ip.indexToKey(decl.val.toIntern())) { | 2653 | const is_variable_const = switch (ip.indexToKey(decl.val.toIntern())) { |
| ... | @@ -2685,7 +2675,7 @@ fn genExports(o: *Object) !void { | ... | @@ -2685,7 +2675,7 @@ fn genExports(o: *Object) !void { |
| 2685 | const export_name = ip.stringToSlice(@"export".opts.name); | 2675 | const export_name = ip.stringToSlice(@"export".opts.name); |
| 2686 | try o.dg.renderTypeAndName( | 2676 | try o.dg.renderTypeAndName( |
| 2687 | fwd, | 2677 | fwd, |
| 2688 | decl.typeOf(mod), | 2678 | decl.typeOf(zcu), |
| 2689 | .{ .identifier = export_name }, | 2679 | .{ .identifier = export_name }, |
| 2690 | CQualifiers.init(.{ .@"const" = is_variable_const }), | 2680 | CQualifiers.init(.{ .@"const" = is_variable_const }), |
| 2691 | decl.alignment, | 2681 | decl.alignment, |
| ... | @@ -2707,13 +2697,13 @@ fn genExports(o: *Object) !void { | ... | @@ -2707,13 +2697,13 @@ fn genExports(o: *Object) !void { |
| 2707 | } | 2697 | } |
| 2708 | } | 2698 | } |
| 2709 | 2699 | ||
| 2710 | pub fn genLazyFn(o: *Object, lazy_fn: LazyFnMap.Entry) !void { | 2700 | pub fn genLazyFn(o: *Object, lazy_ctype_pool: *const CType.Pool, lazy_fn: LazyFnMap.Entry) !void { |
| 2711 | const mod = o.dg.module; | 2701 | const zcu = o.dg.zcu; |
| 2712 | const ip = &mod.intern_pool; | 2702 | const ip = &zcu.intern_pool; |
| 2703 | const ctype_pool = &o.dg.ctype_pool; | ||
| 2713 | const w = o.writer(); | 2704 | const w = o.writer(); |
| 2714 | const key = lazy_fn.key_ptr.*; | 2705 | const key = lazy_fn.key_ptr.*; |
| 2715 | const val = lazy_fn.value_ptr; | 2706 | const val = lazy_fn.value_ptr; |
| 2716 | const fn_name = val.fn_name; | ||
| 2717 | switch (key) { | 2707 | switch (key) { |
| 2718 | .tag_name => { | 2708 | .tag_name => { |
| 2719 | const enum_ty = val.data.tag_name; | 2709 | const enum_ty = val.data.tag_name; |
| ... | @@ -2723,52 +2713,51 @@ pub fn genLazyFn(o: *Object, lazy_fn: LazyFnMap.Entry) !void { | ... | @@ -2723,52 +2713,51 @@ pub fn genLazyFn(o: *Object, lazy_fn: LazyFnMap.Entry) !void { |
| 2723 | try w.writeAll("static "); | 2713 | try w.writeAll("static "); |
| 2724 | try o.dg.renderType(w, name_slice_ty); | 2714 | try o.dg.renderType(w, name_slice_ty); |
| 2725 | try w.writeByte(' '); | 2715 | try w.writeByte(' '); |
| 2726 | try w.writeAll(fn_name); | 2716 | try w.writeAll(val.fn_name.slice(lazy_ctype_pool)); |
| 2727 | try w.writeByte('('); | 2717 | try w.writeByte('('); |
| 2728 | try o.dg.renderTypeAndName(w, enum_ty, .{ .identifier = "tag" }, Const, .none, .complete); | 2718 | try o.dg.renderTypeAndName(w, enum_ty, .{ .identifier = "tag" }, Const, .none, .complete); |
| 2729 | try w.writeAll(") {\n switch (tag) {\n"); | 2719 | try w.writeAll(") {\n switch (tag) {\n"); |
| 2730 | const tag_names = enum_ty.enumFields(mod); | 2720 | const tag_names = enum_ty.enumFields(zcu); |
| 2731 | for (0..tag_names.len) |tag_index| { | 2721 | for (0..tag_names.len) |tag_index| { |
| 2732 | const tag_name = ip.stringToSlice(tag_names.get(ip)[tag_index]); | 2722 | const tag_name = ip.stringToSlice(tag_names.get(ip)[tag_index]); |
| 2733 | const tag_val = try mod.enumValueFieldIndex(enum_ty, @intCast(tag_index)); | 2723 | const tag_val = try zcu.enumValueFieldIndex(enum_ty, @intCast(tag_index)); |
| 2734 | 2724 | ||
| 2735 | const int_val = try tag_val.intFromEnum(enum_ty, mod); | 2725 | const name_ty = try zcu.arrayType(.{ |
| 2736 | |||
| 2737 | const name_ty = try mod.arrayType(.{ | ||
| 2738 | .len = tag_name.len, | 2726 | .len = tag_name.len, |
| 2739 | .child = .u8_type, | 2727 | .child = .u8_type, |
| 2740 | .sentinel = .zero_u8, | 2728 | .sentinel = .zero_u8, |
| 2741 | }); | 2729 | }); |
| 2742 | const name_val = try mod.intern(.{ .aggregate = .{ | 2730 | const name_val = try zcu.intern(.{ .aggregate = .{ |
| 2743 | .ty = name_ty.toIntern(), | 2731 | .ty = name_ty.toIntern(), |
| 2744 | .storage = .{ .bytes = tag_name }, | 2732 | .storage = .{ .bytes = tag_name }, |
| 2745 | } }); | 2733 | } }); |
| 2746 | const len_val = try mod.intValue(Type.usize, tag_name.len); | ||
| 2747 | 2734 | ||
| 2748 | try w.print(" case {}: {{\n static ", .{ | 2735 | try w.print(" case {}: {{\n static ", .{ |
| 2749 | try o.dg.fmtIntLiteral(enum_ty, int_val, .Other), | 2736 | try o.dg.fmtIntLiteral(try tag_val.intFromEnum(enum_ty, zcu), .Other), |
| 2750 | }); | 2737 | }); |
| 2751 | try o.dg.renderTypeAndName(w, name_ty, .{ .identifier = "name" }, Const, .none, .complete); | 2738 | try o.dg.renderTypeAndName(w, name_ty, .{ .identifier = "name" }, Const, .none, .complete); |
| 2752 | try w.writeAll(" = "); | 2739 | try w.writeAll(" = "); |
| 2753 | try o.dg.renderValue(w, name_ty, Value.fromInterned(name_val), .Initializer); | 2740 | try o.dg.renderValue(w, Value.fromInterned(name_val), .Initializer); |
| 2754 | try w.writeAll(";\n return ("); | 2741 | try w.writeAll(";\n return ("); |
| 2755 | try o.dg.renderType(w, name_slice_ty); | 2742 | try o.dg.renderType(w, name_slice_ty); |
| 2756 | try w.print("){{{}, {}}};\n", .{ | 2743 | try w.print("){{{}, {}}};\n", .{ |
| 2757 | fmtIdent("name"), try o.dg.fmtIntLiteral(Type.usize, len_val, .Other), | 2744 | fmtIdent("name"), |
| 2745 | try o.dg.fmtIntLiteral(try zcu.intValue(Type.usize, tag_name.len), .Other), | ||
| 2758 | }); | 2746 | }); |
| 2759 | 2747 | ||
| 2760 | try w.writeAll(" }\n"); | 2748 | try w.writeAll(" }\n"); |
| 2761 | } | 2749 | } |
| 2762 | try w.writeAll(" }\n while ("); | 2750 | try w.writeAll(" }\n while ("); |
| 2763 | try o.dg.renderValue(w, Type.bool, Value.true, .Other); | 2751 | try o.dg.renderValue(w, Value.true, .Other); |
| 2764 | try w.writeAll(") "); | 2752 | try w.writeAll(") "); |
| 2765 | _ = try airBreakpoint(w); | 2753 | _ = try airBreakpoint(w); |
| 2766 | try w.writeAll("}\n"); | 2754 | try w.writeAll("}\n"); |
| 2767 | }, | 2755 | }, |
| 2768 | .never_tail, .never_inline => |fn_decl_index| { | 2756 | .never_tail, .never_inline => |fn_decl_index| { |
| 2769 | const fn_decl = mod.declPtr(fn_decl_index); | 2757 | const fn_decl = zcu.declPtr(fn_decl_index); |
| 2770 | const fn_cty = try o.dg.typeToCType(fn_decl.typeOf(mod), .complete); | 2758 | const fn_ctype = try o.dg.ctypeFromType(fn_decl.typeOf(zcu), .complete); |
| 2771 | const fn_info = fn_cty.cast(CType.Payload.Function).?.data; | 2759 | const fn_info = fn_ctype.info(ctype_pool).function; |
| 2760 | const fn_name = val.fn_name.slice(lazy_ctype_pool); | ||
| 2772 | 2761 | ||
| 2773 | const fwd_decl_writer = o.dg.fwdDeclWriter(); | 2762 | const fwd_decl_writer = o.dg.fwdDeclWriter(); |
| 2774 | try fwd_decl_writer.print("static zig_{s} ", .{@tagName(key)}); | 2763 | try fwd_decl_writer.print("static zig_{s} ", .{@tagName(key)}); |
| ... | @@ -2781,11 +2770,13 @@ pub fn genLazyFn(o: *Object, lazy_fn: LazyFnMap.Entry) !void { | ... | @@ -2781,11 +2770,13 @@ pub fn genLazyFn(o: *Object, lazy_fn: LazyFnMap.Entry) !void { |
| 2781 | try fwd_decl_writer.writeAll(";\n"); | 2770 | try fwd_decl_writer.writeAll(";\n"); |
| 2782 | 2771 | ||
| 2783 | try w.print("static zig_{s} ", .{@tagName(key)}); | 2772 | try w.print("static zig_{s} ", .{@tagName(key)}); |
| 2784 | try o.dg.renderFunctionSignature(w, fn_decl_index, .complete, .{ .ident = fn_name }); | 2773 | try o.dg.renderFunctionSignature(w, fn_decl_index, .complete, .{ |
| 2774 | .ident = fn_name, | ||
| 2775 | }); | ||
| 2785 | try w.writeAll(" {\n return "); | 2776 | try w.writeAll(" {\n return "); |
| 2786 | try o.dg.renderDeclName(w, fn_decl_index, 0); | 2777 | try o.dg.renderDeclName(w, fn_decl_index, 0); |
| 2787 | try w.writeByte('('); | 2778 | try w.writeByte('('); |
| 2788 | for (0..fn_info.param_types.len) |arg| { | 2779 | for (0..fn_info.param_ctypes.len) |arg| { |
| 2789 | if (arg > 0) try w.writeAll(", "); | 2780 | if (arg > 0) try w.writeAll(", "); |
| 2790 | try o.dg.writeCValue(w, .{ .arg = arg }); | 2781 | try o.dg.writeCValue(w, .{ .arg = arg }); |
| 2791 | } | 2782 | } |
| ... | @@ -2799,10 +2790,10 @@ pub fn genFunc(f: *Function) !void { | ... | @@ -2799,10 +2790,10 @@ pub fn genFunc(f: *Function) !void { |
| 2799 | defer tracy.end(); | 2790 | defer tracy.end(); |
| 2800 | 2791 | ||
| 2801 | const o = &f.object; | 2792 | const o = &f.object; |
| 2802 | const mod = o.dg.module; | 2793 | const zcu = o.dg.zcu; |
| 2803 | const gpa = o.dg.gpa; | 2794 | const gpa = o.dg.gpa; |
| 2804 | const decl_index = o.dg.pass.decl; | 2795 | const decl_index = o.dg.pass.decl; |
| 2805 | const decl = mod.declPtr(decl_index); | 2796 | const decl = zcu.declPtr(decl_index); |
| 2806 | 2797 | ||
| 2807 | o.code_header = std.ArrayList(u8).init(gpa); | 2798 | o.code_header = std.ArrayList(u8).init(gpa); |
| 2808 | defer o.code_header.deinit(); | 2799 | defer o.code_header.deinit(); |
| ... | @@ -2811,7 +2802,7 @@ pub fn genFunc(f: *Function) !void { | ... | @@ -2811,7 +2802,7 @@ pub fn genFunc(f: *Function) !void { |
| 2811 | const fwd_decl_writer = o.dg.fwdDeclWriter(); | 2802 | const fwd_decl_writer = o.dg.fwdDeclWriter(); |
| 2812 | try fwd_decl_writer.writeAll(if (is_global) "zig_extern " else "static "); | 2803 | try fwd_decl_writer.writeAll(if (is_global) "zig_extern " else "static "); |
| 2813 | 2804 | ||
| 2814 | if (mod.decl_exports.get(decl_index)) |exports| | 2805 | if (zcu.decl_exports.get(decl_index)) |exports| |
| 2815 | if (exports.items[0].opts.linkage == .weak) try fwd_decl_writer.writeAll("zig_weak_linkage_fn "); | 2806 | if (exports.items[0].opts.linkage == .weak) try fwd_decl_writer.writeAll("zig_weak_linkage_fn "); |
| 2816 | try o.dg.renderFunctionSignature(fwd_decl_writer, decl_index, .forward, .{ .export_index = 0 }); | 2807 | try o.dg.renderFunctionSignature(fwd_decl_writer, decl_index, .forward, .{ .export_index = 0 }); |
| 2817 | try fwd_decl_writer.writeAll(";\n"); | 2808 | try fwd_decl_writer.writeAll(";\n"); |
| ... | @@ -2819,6 +2810,8 @@ pub fn genFunc(f: *Function) !void { | ... | @@ -2819,6 +2810,8 @@ pub fn genFunc(f: *Function) !void { |
| 2819 | 2810 | ||
| 2820 | try o.indent_writer.insertNewline(); | 2811 | try o.indent_writer.insertNewline(); |
| 2821 | if (!is_global) try o.writer().writeAll("static "); | 2812 | if (!is_global) try o.writer().writeAll("static "); |
| 2813 | if (zcu.intern_pool.stringToSliceUnwrap(decl.@"linksection")) |s| | ||
| 2814 | try o.writer().print("zig_linksection_fn({s}) ", .{fmtStringLiteral(s, null)}); | ||
| 2822 | try o.dg.renderFunctionSignature(o.writer(), decl_index, .complete, .{ .export_index = 0 }); | 2815 | try o.dg.renderFunctionSignature(o.writer(), decl_index, .complete, .{ .export_index = 0 }); |
| 2823 | try o.writer().writeByte(' '); | 2816 | try o.writer().writeByte(' '); |
| 2824 | 2817 | ||
| ... | @@ -2867,7 +2860,7 @@ pub fn genFunc(f: *Function) !void { | ... | @@ -2867,7 +2860,7 @@ pub fn genFunc(f: *Function) !void { |
| 2867 | for (free_locals.values()) |list| { | 2860 | for (free_locals.values()) |list| { |
| 2868 | for (list.keys()) |local_index| { | 2861 | for (list.keys()) |local_index| { |
| 2869 | const local = f.locals.items[local_index]; | 2862 | const local = f.locals.items[local_index]; |
| 2870 | try o.dg.renderCTypeAndName(w, local.cty_idx, .{ .local = local_index }, .{}, local.alignas); | 2863 | try o.dg.renderCTypeAndName(w, local.ctype, .{ .local = local_index }, .{}, local.flags.alignas); |
| 2871 | try w.writeAll(";\n "); | 2864 | try w.writeAll(";\n "); |
| 2872 | } | 2865 | } |
| 2873 | } | 2866 | } |
| ... | @@ -2884,43 +2877,41 @@ pub fn genDecl(o: *Object) !void { | ... | @@ -2884,43 +2877,41 @@ pub fn genDecl(o: *Object) !void { |
| 2884 | const tracy = trace(@src()); | 2877 | const tracy = trace(@src()); |
| 2885 | defer tracy.end(); | 2878 | defer tracy.end(); |
| 2886 | 2879 | ||
| 2887 | const mod = o.dg.module; | 2880 | const zcu = o.dg.zcu; |
| 2888 | const decl_index = o.dg.pass.decl; | 2881 | const decl_index = o.dg.pass.decl; |
| 2889 | const decl = mod.declPtr(decl_index); | 2882 | const decl = zcu.declPtr(decl_index); |
| 2890 | const decl_val = decl.val; | 2883 | const decl_ty = decl.typeOf(zcu); |
| 2891 | const decl_ty = decl_val.typeOf(mod); | ||
| 2892 | 2884 | ||
| 2893 | if (!decl_ty.isFnOrHasRuntimeBitsIgnoreComptime(mod)) return; | 2885 | if (!decl_ty.isFnOrHasRuntimeBitsIgnoreComptime(zcu)) return; |
| 2894 | if (decl_val.getExternFunc(mod)) |_| { | 2886 | if (decl.val.getExternFunc(zcu)) |_| { |
| 2895 | const fwd_decl_writer = o.dg.fwdDeclWriter(); | 2887 | const fwd_decl_writer = o.dg.fwdDeclWriter(); |
| 2896 | try fwd_decl_writer.writeAll("zig_extern "); | 2888 | try fwd_decl_writer.writeAll("zig_extern "); |
| 2897 | try o.dg.renderFunctionSignature(fwd_decl_writer, decl_index, .forward, .{ .export_index = 0 }); | 2889 | try o.dg.renderFunctionSignature(fwd_decl_writer, decl_index, .forward, .{ .export_index = 0 }); |
| 2898 | try fwd_decl_writer.writeAll(";\n"); | 2890 | try fwd_decl_writer.writeAll(";\n"); |
| 2899 | try genExports(o); | 2891 | try genExports(o); |
| 2900 | } else if (decl_val.getVariable(mod)) |variable| { | 2892 | } else if (decl.val.getVariable(zcu)) |variable| { |
| 2901 | try o.dg.renderFwdDecl(decl_index, variable, .final); | 2893 | try o.dg.renderFwdDecl(decl_index, variable, .final); |
| 2902 | try genExports(o); | 2894 | try genExports(o); |
| 2903 | 2895 | ||
| 2904 | if (variable.is_extern) return; | 2896 | if (variable.is_extern) return; |
| 2905 | 2897 | ||
| 2906 | const is_global = variable.is_extern or o.dg.declIsGlobal(decl_val); | 2898 | const is_global = variable.is_extern or o.dg.declIsGlobal(decl.val); |
| 2907 | const w = o.writer(); | 2899 | const w = o.writer(); |
| 2908 | if (!is_global) try w.writeAll("static "); | 2900 | if (!is_global) try w.writeAll("static "); |
| 2909 | if (variable.is_weak_linkage) try w.writeAll("zig_weak_linkage "); | 2901 | if (variable.is_weak_linkage) try w.writeAll("zig_weak_linkage "); |
| 2910 | if (variable.is_threadlocal) try w.writeAll("zig_threadlocal "); | 2902 | if (variable.is_threadlocal) try w.writeAll("zig_threadlocal "); |
| 2911 | if (mod.intern_pool.stringToSliceUnwrap(decl.@"linksection")) |s| | 2903 | if (zcu.intern_pool.stringToSliceUnwrap(decl.@"linksection")) |s| |
| 2912 | try w.print("zig_linksection(\"{s}\", ", .{s}); | 2904 | try w.print("zig_linksection({s}) ", .{fmtStringLiteral(s, null)}); |
| 2913 | const decl_c_value = .{ .decl = decl_index }; | 2905 | const decl_c_value = .{ .decl = decl_index }; |
| 2914 | try o.dg.renderTypeAndName(w, decl_ty, decl_c_value, .{}, decl.alignment, .complete); | 2906 | try o.dg.renderTypeAndName(w, decl_ty, decl_c_value, .{}, decl.alignment, .complete); |
| 2915 | if (decl.@"linksection" != .none) try w.writeAll(", read, write)"); | ||
| 2916 | try w.writeAll(" = "); | 2907 | try w.writeAll(" = "); |
| 2917 | try o.dg.renderValue(w, decl_ty, Value.fromInterned(variable.init), .StaticInitializer); | 2908 | try o.dg.renderValue(w, Value.fromInterned(variable.init), .StaticInitializer); |
| 2918 | try w.writeByte(';'); | 2909 | try w.writeByte(';'); |
| 2919 | try o.indent_writer.insertNewline(); | 2910 | try o.indent_writer.insertNewline(); |
| 2920 | } else { | 2911 | } else { |
| 2921 | const is_global = o.dg.module.decl_exports.contains(decl_index); | 2912 | const is_global = o.dg.zcu.decl_exports.contains(decl_index); |
| 2922 | const decl_c_value = .{ .decl = decl_index }; | 2913 | const decl_c_value = .{ .decl = decl_index }; |
| 2923 | try genDeclValue(o, decl_val, is_global, decl_c_value, decl.alignment, decl.@"linksection"); | 2914 | try genDeclValue(o, decl.val, is_global, decl_c_value, decl.alignment, decl.@"linksection"); |
| 2924 | } | 2915 | } |
| 2925 | } | 2916 | } |
| 2926 | 2917 | ||
| ... | @@ -2930,19 +2921,19 @@ pub fn genDeclValue( | ... | @@ -2930,19 +2921,19 @@ pub fn genDeclValue( |
| 2930 | is_global: bool, | 2921 | is_global: bool, |
| 2931 | decl_c_value: CValue, | 2922 | decl_c_value: CValue, |
| 2932 | alignment: Alignment, | 2923 | alignment: Alignment, |
| 2933 | link_section: InternPool.OptionalNullTerminatedString, | 2924 | @"linksection": InternPool.OptionalNullTerminatedString, |
| 2934 | ) !void { | 2925 | ) !void { |
| 2935 | const mod = o.dg.module; | 2926 | const zcu = o.dg.zcu; |
| 2936 | const fwd_decl_writer = o.dg.fwdDeclWriter(); | 2927 | const fwd_decl_writer = o.dg.fwdDeclWriter(); |
| 2937 | 2928 | ||
| 2938 | const ty = val.typeOf(mod); | 2929 | const ty = val.typeOf(zcu); |
| 2939 | 2930 | ||
| 2940 | try fwd_decl_writer.writeAll(if (is_global) "zig_extern " else "static "); | 2931 | try fwd_decl_writer.writeAll(if (is_global) "zig_extern " else "static "); |
| 2941 | try o.dg.renderTypeAndName(fwd_decl_writer, ty, decl_c_value, Const, alignment, .complete); | 2932 | try o.dg.renderTypeAndName(fwd_decl_writer, ty, decl_c_value, Const, alignment, .complete); |
| 2942 | switch (o.dg.pass) { | 2933 | switch (o.dg.pass) { |
| 2943 | .decl => |decl_index| { | 2934 | .decl => |decl_index| { |
| 2944 | if (mod.decl_exports.get(decl_index)) |exports| { | 2935 | if (zcu.decl_exports.get(decl_index)) |exports| { |
| 2945 | const export_name = mod.intern_pool.stringToSlice(exports.items[0].opts.name); | 2936 | const export_name = zcu.intern_pool.stringToSlice(exports.items[0].opts.name); |
| 2946 | if (isMangledIdent(export_name, true)) { | 2937 | if (isMangledIdent(export_name, true)) { |
| 2947 | try fwd_decl_writer.print(" zig_mangled_final({ }, {s})", .{ | 2938 | try fwd_decl_writer.print(" zig_mangled_final({ }, {s})", .{ |
| 2948 | fmtIdent(export_name), fmtStringLiteral(export_name, null), | 2939 | fmtIdent(export_name), fmtStringLiteral(export_name, null), |
| ... | @@ -2958,13 +2949,11 @@ pub fn genDeclValue( | ... | @@ -2958,13 +2949,11 @@ pub fn genDeclValue( |
| 2958 | 2949 | ||
| 2959 | const w = o.writer(); | 2950 | const w = o.writer(); |
| 2960 | if (!is_global) try w.writeAll("static "); | 2951 | if (!is_global) try w.writeAll("static "); |
| 2961 | 2952 | if (zcu.intern_pool.stringToSliceUnwrap(@"linksection")) |s| | |
| 2962 | if (mod.intern_pool.stringToSliceUnwrap(link_section)) |s| | 2953 | try w.print("zig_linksection({s}) ", .{fmtStringLiteral(s, null)}); |
| 2963 | try w.print("zig_linksection(\"{s}\", ", .{s}); | ||
| 2964 | try o.dg.renderTypeAndName(w, ty, decl_c_value, Const, alignment, .complete); | 2954 | try o.dg.renderTypeAndName(w, ty, decl_c_value, Const, alignment, .complete); |
| 2965 | if (link_section != .none) try w.writeAll(", read)"); | ||
| 2966 | try w.writeAll(" = "); | 2955 | try w.writeAll(" = "); |
| 2967 | try o.dg.renderValue(w, ty, val, .StaticInitializer); | 2956 | try o.dg.renderValue(w, val, .StaticInitializer); |
| 2968 | try w.writeAll(";\n"); | 2957 | try w.writeAll(";\n"); |
| 2969 | } | 2958 | } |
| 2970 | 2959 | ||
| ... | @@ -2972,12 +2961,12 @@ pub fn genHeader(dg: *DeclGen) error{ AnalysisFail, OutOfMemory }!void { | ... | @@ -2972,12 +2961,12 @@ pub fn genHeader(dg: *DeclGen) error{ AnalysisFail, OutOfMemory }!void { |
| 2972 | const tracy = trace(@src()); | 2961 | const tracy = trace(@src()); |
| 2973 | defer tracy.end(); | 2962 | defer tracy.end(); |
| 2974 | 2963 | ||
| 2975 | const mod = dg.module; | 2964 | const zcu = dg.zcu; |
| 2976 | const decl_index = dg.pass.decl; | 2965 | const decl_index = dg.pass.decl; |
| 2977 | const decl = mod.declPtr(decl_index); | 2966 | const decl = zcu.declPtr(decl_index); |
| 2978 | const writer = dg.fwdDeclWriter(); | 2967 | const writer = dg.fwdDeclWriter(); |
| 2979 | 2968 | ||
| 2980 | switch (decl.val.typeOf(mod).zigTypeTag(mod)) { | 2969 | switch (decl.typeOf(zcu).zigTypeTag(zcu)) { |
| 2981 | .Fn => if (dg.declIsGlobal(decl.val)) { | 2970 | .Fn => if (dg.declIsGlobal(decl.val)) { |
| 2982 | try writer.writeAll("zig_extern "); | 2971 | try writer.writeAll("zig_extern "); |
| 2983 | try dg.renderFunctionSignature(writer, dg.pass.decl, .complete, .{ .export_index = 0 }); | 2972 | try dg.renderFunctionSignature(writer, dg.pass.decl, .complete, .{ .export_index = 0 }); |
| ... | @@ -3060,8 +3049,8 @@ fn genBodyResolveState(f: *Function, inst: Air.Inst.Index, leading_deaths: []con | ... | @@ -3060,8 +3049,8 @@ fn genBodyResolveState(f: *Function, inst: Air.Inst.Index, leading_deaths: []con |
| 3060 | } | 3049 | } |
| 3061 | 3050 | ||
| 3062 | fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutOfMemory }!void { | 3051 | fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutOfMemory }!void { |
| 3063 | const mod = f.object.dg.module; | 3052 | const zcu = f.object.dg.zcu; |
| 3064 | const ip = &mod.intern_pool; | 3053 | const ip = &zcu.intern_pool; |
| 3065 | const air_tags = f.air.instructions.items(.tag); | 3054 | const air_tags = f.air.instructions.items(.tag); |
| 3066 | 3055 | ||
| 3067 | for (body) |inst| { | 3056 | for (body) |inst| { |
| ... | @@ -3096,10 +3085,10 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, | ... | @@ -3096,10 +3085,10 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, |
| 3096 | .div_trunc, .div_exact => try airBinOp(f, inst, "/", "div_trunc", .none), | 3085 | .div_trunc, .div_exact => try airBinOp(f, inst, "/", "div_trunc", .none), |
| 3097 | .rem => blk: { | 3086 | .rem => blk: { |
| 3098 | const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; | 3087 | const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| 3099 | const lhs_scalar_ty = f.typeOf(bin_op.lhs).scalarType(mod); | 3088 | const lhs_scalar_ty = f.typeOf(bin_op.lhs).scalarType(zcu); |
| 3100 | // For binary operations @TypeOf(lhs)==@TypeOf(rhs), | 3089 | // For binary operations @TypeOf(lhs)==@TypeOf(rhs), |
| 3101 | // so we only check one. | 3090 | // so we only check one. |
| 3102 | break :blk if (lhs_scalar_ty.isInt(mod)) | 3091 | break :blk if (lhs_scalar_ty.isInt(zcu)) |
| 3103 | try airBinOp(f, inst, "%", "rem", .none) | 3092 | try airBinOp(f, inst, "%", "rem", .none) |
| 3104 | else | 3093 | else |
| 3105 | try airBinFloatOp(f, inst, "fmod"); | 3094 | try airBinFloatOp(f, inst, "fmod"); |
| ... | @@ -3359,10 +3348,10 @@ fn airSliceField(f: *Function, inst: Air.Inst.Index, is_ptr: bool, field_name: [ | ... | @@ -3359,10 +3348,10 @@ fn airSliceField(f: *Function, inst: Air.Inst.Index, is_ptr: bool, field_name: [ |
| 3359 | } | 3348 | } |
| 3360 | 3349 | ||
| 3361 | fn airPtrElemVal(f: *Function, inst: Air.Inst.Index) !CValue { | 3350 | fn airPtrElemVal(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3362 | const mod = f.object.dg.module; | 3351 | const zcu = f.object.dg.zcu; |
| 3363 | const inst_ty = f.typeOfIndex(inst); | 3352 | const inst_ty = f.typeOfIndex(inst); |
| 3364 | const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; | 3353 | const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| 3365 | if (!inst_ty.hasRuntimeBitsIgnoreComptime(mod)) { | 3354 | if (!inst_ty.hasRuntimeBitsIgnoreComptime(zcu)) { |
| 3366 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); | 3355 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); |
| 3367 | return .none; | 3356 | return .none; |
| 3368 | } | 3357 | } |
| ... | @@ -3385,14 +3374,13 @@ fn airPtrElemVal(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -3385,14 +3374,13 @@ fn airPtrElemVal(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3385 | } | 3374 | } |
| 3386 | 3375 | ||
| 3387 | fn airPtrElemPtr(f: *Function, inst: Air.Inst.Index) !CValue { | 3376 | fn airPtrElemPtr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3388 | const mod = f.object.dg.module; | 3377 | const zcu = f.object.dg.zcu; |
| 3389 | const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; | 3378 | const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| 3390 | const bin_op = f.air.extraData(Air.Bin, ty_pl.payload).data; | 3379 | const bin_op = f.air.extraData(Air.Bin, ty_pl.payload).data; |
| 3391 | 3380 | ||
| 3392 | const inst_ty = f.typeOfIndex(inst); | 3381 | const inst_ty = f.typeOfIndex(inst); |
| 3393 | const ptr_ty = f.typeOf(bin_op.lhs); | 3382 | const ptr_ty = f.typeOf(bin_op.lhs); |
| 3394 | const elem_ty = ptr_ty.childType(mod); | 3383 | const elem_has_bits = ptr_ty.elemType2(zcu).hasRuntimeBitsIgnoreComptime(zcu); |
| 3395 | const elem_has_bits = elem_ty.hasRuntimeBitsIgnoreComptime(mod); | ||
| 3396 | 3384 | ||
| 3397 | const ptr = try f.resolveInst(bin_op.lhs); | 3385 | const ptr = try f.resolveInst(bin_op.lhs); |
| 3398 | const index = try f.resolveInst(bin_op.rhs); | 3386 | const index = try f.resolveInst(bin_op.rhs); |
| ... | @@ -3407,7 +3395,7 @@ fn airPtrElemPtr(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -3407,7 +3395,7 @@ fn airPtrElemPtr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3407 | try f.renderType(writer, inst_ty); | 3395 | try f.renderType(writer, inst_ty); |
| 3408 | try writer.writeByte(')'); | 3396 | try writer.writeByte(')'); |
| 3409 | if (elem_has_bits) try writer.writeByte('&'); | 3397 | if (elem_has_bits) try writer.writeByte('&'); |
| 3410 | if (elem_has_bits and ptr_ty.ptrSize(mod) == .One) { | 3398 | if (elem_has_bits and ptr_ty.ptrSize(zcu) == .One) { |
| 3411 | // It's a pointer to an array, so we need to de-reference. | 3399 | // It's a pointer to an array, so we need to de-reference. |
| 3412 | try f.writeCValueDeref(writer, ptr); | 3400 | try f.writeCValueDeref(writer, ptr); |
| 3413 | } else try f.writeCValue(writer, ptr, .Other); | 3401 | } else try f.writeCValue(writer, ptr, .Other); |
| ... | @@ -3421,10 +3409,10 @@ fn airPtrElemPtr(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -3421,10 +3409,10 @@ fn airPtrElemPtr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3421 | } | 3409 | } |
| 3422 | 3410 | ||
| 3423 | fn airSliceElemVal(f: *Function, inst: Air.Inst.Index) !CValue { | 3411 | fn airSliceElemVal(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3424 | const mod = f.object.dg.module; | 3412 | const zcu = f.object.dg.zcu; |
| 3425 | const inst_ty = f.typeOfIndex(inst); | 3413 | const inst_ty = f.typeOfIndex(inst); |
| 3426 | const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; | 3414 | const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| 3427 | if (!inst_ty.hasRuntimeBitsIgnoreComptime(mod)) { | 3415 | if (!inst_ty.hasRuntimeBitsIgnoreComptime(zcu)) { |
| 3428 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); | 3416 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); |
| 3429 | return .none; | 3417 | return .none; |
| 3430 | } | 3418 | } |
| ... | @@ -3447,14 +3435,14 @@ fn airSliceElemVal(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -3447,14 +3435,14 @@ fn airSliceElemVal(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3447 | } | 3435 | } |
| 3448 | 3436 | ||
| 3449 | fn airSliceElemPtr(f: *Function, inst: Air.Inst.Index) !CValue { | 3437 | fn airSliceElemPtr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3450 | const mod = f.object.dg.module; | 3438 | const zcu = f.object.dg.zcu; |
| 3451 | const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; | 3439 | const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| 3452 | const bin_op = f.air.extraData(Air.Bin, ty_pl.payload).data; | 3440 | const bin_op = f.air.extraData(Air.Bin, ty_pl.payload).data; |
| 3453 | 3441 | ||
| 3454 | const inst_ty = f.typeOfIndex(inst); | 3442 | const inst_ty = f.typeOfIndex(inst); |
| 3455 | const slice_ty = f.typeOf(bin_op.lhs); | 3443 | const slice_ty = f.typeOf(bin_op.lhs); |
| 3456 | const elem_ty = slice_ty.elemType2(mod); | 3444 | const elem_ty = slice_ty.elemType2(zcu); |
| 3457 | const elem_has_bits = elem_ty.hasRuntimeBitsIgnoreComptime(mod); | 3445 | const elem_has_bits = elem_ty.hasRuntimeBitsIgnoreComptime(zcu); |
| 3458 | 3446 | ||
| 3459 | const slice = try f.resolveInst(bin_op.lhs); | 3447 | const slice = try f.resolveInst(bin_op.lhs); |
| 3460 | const index = try f.resolveInst(bin_op.rhs); | 3448 | const index = try f.resolveInst(bin_op.rhs); |
| ... | @@ -3477,10 +3465,10 @@ fn airSliceElemPtr(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -3477,10 +3465,10 @@ fn airSliceElemPtr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3477 | } | 3465 | } |
| 3478 | 3466 | ||
| 3479 | fn airArrayElemVal(f: *Function, inst: Air.Inst.Index) !CValue { | 3467 | fn airArrayElemVal(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3480 | const mod = f.object.dg.module; | 3468 | const zcu = f.object.dg.zcu; |
| 3481 | const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; | 3469 | const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| 3482 | const inst_ty = f.typeOfIndex(inst); | 3470 | const inst_ty = f.typeOfIndex(inst); |
| 3483 | if (!inst_ty.hasRuntimeBitsIgnoreComptime(mod)) { | 3471 | if (!inst_ty.hasRuntimeBitsIgnoreComptime(zcu)) { |
| 3484 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); | 3472 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); |
| 3485 | return .none; | 3473 | return .none; |
| 3486 | } | 3474 | } |
| ... | @@ -3503,47 +3491,53 @@ fn airArrayElemVal(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -3503,47 +3491,53 @@ fn airArrayElemVal(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3503 | } | 3491 | } |
| 3504 | 3492 | ||
| 3505 | fn airAlloc(f: *Function, inst: Air.Inst.Index) !CValue { | 3493 | fn airAlloc(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3506 | const mod = f.object.dg.module; | 3494 | const zcu = f.object.dg.zcu; |
| 3507 | const inst_ty = f.typeOfIndex(inst); | 3495 | const inst_ty = f.typeOfIndex(inst); |
| 3508 | const elem_type = inst_ty.childType(mod); | 3496 | const elem_ty = inst_ty.childType(zcu); |
| 3509 | if (!elem_type.isFnOrHasRuntimeBitsIgnoreComptime(mod)) return .{ .undef = inst_ty }; | 3497 | if (!elem_ty.isFnOrHasRuntimeBitsIgnoreComptime(zcu)) return .{ .undef = inst_ty }; |
| 3510 | 3498 | ||
| 3511 | const local = try f.allocLocalValue( | 3499 | const local = try f.allocLocalValue(.{ |
| 3512 | elem_type, | 3500 | .ctype = try f.ctypeFromType(elem_ty, .complete), |
| 3513 | inst_ty.ptrAlignment(mod), | 3501 | .alignas = CType.AlignAs.fromAlignment(.{ |
| 3514 | ); | 3502 | .@"align" = inst_ty.ptrInfo(zcu).flags.alignment, |
| 3503 | .abi = elem_ty.abiAlignment(zcu), | ||
| 3504 | }), | ||
| 3505 | }); | ||
| 3515 | log.debug("%{d}: allocated unfreeable t{d}", .{ inst, local.new_local }); | 3506 | log.debug("%{d}: allocated unfreeable t{d}", .{ inst, local.new_local }); |
| 3516 | const gpa = f.object.dg.module.gpa; | 3507 | const gpa = f.object.dg.zcu.gpa; |
| 3517 | try f.allocs.put(gpa, local.new_local, true); | 3508 | try f.allocs.put(gpa, local.new_local, true); |
| 3518 | return .{ .local_ref = local.new_local }; | 3509 | return .{ .local_ref = local.new_local }; |
| 3519 | } | 3510 | } |
| 3520 | 3511 | ||
| 3521 | fn airRetPtr(f: *Function, inst: Air.Inst.Index) !CValue { | 3512 | fn airRetPtr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3522 | const mod = f.object.dg.module; | 3513 | const zcu = f.object.dg.zcu; |
| 3523 | const inst_ty = f.typeOfIndex(inst); | 3514 | const inst_ty = f.typeOfIndex(inst); |
| 3524 | const elem_ty = inst_ty.childType(mod); | 3515 | const elem_ty = inst_ty.childType(zcu); |
| 3525 | if (!elem_ty.isFnOrHasRuntimeBitsIgnoreComptime(mod)) return .{ .undef = inst_ty }; | 3516 | if (!elem_ty.isFnOrHasRuntimeBitsIgnoreComptime(zcu)) return .{ .undef = inst_ty }; |
| 3526 | 3517 | ||
| 3527 | const local = try f.allocLocalValue( | 3518 | const local = try f.allocLocalValue(.{ |
| 3528 | elem_ty, | 3519 | .ctype = try f.ctypeFromType(elem_ty, .complete), |
| 3529 | inst_ty.ptrAlignment(mod), | 3520 | .alignas = CType.AlignAs.fromAlignment(.{ |
| 3530 | ); | 3521 | .@"align" = inst_ty.ptrInfo(zcu).flags.alignment, |
| 3522 | .abi = elem_ty.abiAlignment(zcu), | ||
| 3523 | }), | ||
| 3524 | }); | ||
| 3531 | log.debug("%{d}: allocated unfreeable t{d}", .{ inst, local.new_local }); | 3525 | log.debug("%{d}: allocated unfreeable t{d}", .{ inst, local.new_local }); |
| 3532 | const gpa = f.object.dg.module.gpa; | 3526 | const gpa = f.object.dg.zcu.gpa; |
| 3533 | try f.allocs.put(gpa, local.new_local, true); | 3527 | try f.allocs.put(gpa, local.new_local, true); |
| 3534 | return .{ .local_ref = local.new_local }; | 3528 | return .{ .local_ref = local.new_local }; |
| 3535 | } | 3529 | } |
| 3536 | 3530 | ||
| 3537 | fn airArg(f: *Function, inst: Air.Inst.Index) !CValue { | 3531 | fn airArg(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3538 | const inst_ty = f.typeOfIndex(inst); | 3532 | const inst_ty = f.typeOfIndex(inst); |
| 3539 | const inst_cty = try f.typeToIndex(inst_ty, .parameter); | 3533 | const inst_ctype = try f.ctypeFromType(inst_ty, .parameter); |
| 3540 | 3534 | ||
| 3541 | const i = f.next_arg_index; | 3535 | const i = f.next_arg_index; |
| 3542 | f.next_arg_index += 1; | 3536 | f.next_arg_index += 1; |
| 3543 | const result: CValue = if (inst_cty != try f.typeToIndex(inst_ty, .complete)) | 3537 | const result: CValue = if (inst_ctype.eql(try f.ctypeFromType(inst_ty, .complete))) |
| 3544 | .{ .arg_array = i } | 3538 | .{ .arg = i } |
| 3545 | else | 3539 | else |
| 3546 | .{ .arg = i }; | 3540 | .{ .arg_array = i }; |
| 3547 | 3541 | ||
| 3548 | if (f.liveness.isUnused(inst)) { | 3542 | if (f.liveness.isUnused(inst)) { |
| 3549 | const writer = f.object.writer(); | 3543 | const writer = f.object.writer(); |
| ... | @@ -3559,15 +3553,15 @@ fn airArg(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -3559,15 +3553,15 @@ fn airArg(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3559 | } | 3553 | } |
| 3560 | 3554 | ||
| 3561 | fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue { | 3555 | fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3562 | const mod = f.object.dg.module; | 3556 | const zcu = f.object.dg.zcu; |
| 3563 | const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; | 3557 | const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 3564 | 3558 | ||
| 3565 | const ptr_ty = f.typeOf(ty_op.operand); | 3559 | const ptr_ty = f.typeOf(ty_op.operand); |
| 3566 | const ptr_scalar_ty = ptr_ty.scalarType(mod); | 3560 | const ptr_scalar_ty = ptr_ty.scalarType(zcu); |
| 3567 | const ptr_info = ptr_scalar_ty.ptrInfo(mod); | 3561 | const ptr_info = ptr_scalar_ty.ptrInfo(zcu); |
| 3568 | const src_ty = Type.fromInterned(ptr_info.child); | 3562 | const src_ty = Type.fromInterned(ptr_info.child); |
| 3569 | 3563 | ||
| 3570 | if (!src_ty.hasRuntimeBitsIgnoreComptime(mod)) { | 3564 | if (!src_ty.hasRuntimeBitsIgnoreComptime(zcu)) { |
| 3571 | try reap(f, inst, &.{ty_op.operand}); | 3565 | try reap(f, inst, &.{ty_op.operand}); |
| 3572 | return .none; | 3566 | return .none; |
| 3573 | } | 3567 | } |
| ... | @@ -3577,10 +3571,10 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -3577,10 +3571,10 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3577 | try reap(f, inst, &.{ty_op.operand}); | 3571 | try reap(f, inst, &.{ty_op.operand}); |
| 3578 | 3572 | ||
| 3579 | const is_aligned = if (ptr_info.flags.alignment != .none) | 3573 | const is_aligned = if (ptr_info.flags.alignment != .none) |
| 3580 | ptr_info.flags.alignment.compare(.gte, src_ty.abiAlignment(mod)) | 3574 | ptr_info.flags.alignment.order(src_ty.abiAlignment(zcu)).compare(.gte) |
| 3581 | else | 3575 | else |
| 3582 | true; | 3576 | true; |
| 3583 | const is_array = lowersToArray(src_ty, mod); | 3577 | const is_array = lowersToArray(src_ty, zcu); |
| 3584 | const need_memcpy = !is_aligned or is_array; | 3578 | const need_memcpy = !is_aligned or is_array; |
| 3585 | 3579 | ||
| 3586 | const writer = f.object.writer(); | 3580 | const writer = f.object.writer(); |
| ... | @@ -3600,12 +3594,12 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -3600,12 +3594,12 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3600 | try writer.writeAll("))"); | 3594 | try writer.writeAll("))"); |
| 3601 | } else if (ptr_info.packed_offset.host_size > 0 and ptr_info.flags.vector_index == .none) { | 3595 | } else if (ptr_info.packed_offset.host_size > 0 and ptr_info.flags.vector_index == .none) { |
| 3602 | const host_bits: u16 = ptr_info.packed_offset.host_size * 8; | 3596 | const host_bits: u16 = ptr_info.packed_offset.host_size * 8; |
| 3603 | const host_ty = try mod.intType(.unsigned, host_bits); | 3597 | const host_ty = try zcu.intType(.unsigned, host_bits); |
| 3604 | 3598 | ||
| 3605 | const bit_offset_ty = try mod.intType(.unsigned, Type.smallestUnsignedBits(host_bits - 1)); | 3599 | const bit_offset_ty = try zcu.intType(.unsigned, Type.smallestUnsignedBits(host_bits - 1)); |
| 3606 | const bit_offset_val = try mod.intValue(bit_offset_ty, ptr_info.packed_offset.bit_offset); | 3600 | const bit_offset_val = try zcu.intValue(bit_offset_ty, ptr_info.packed_offset.bit_offset); |
| 3607 | 3601 | ||
| 3608 | const field_ty = try mod.intType(.unsigned, @as(u16, @intCast(src_ty.bitSize(mod)))); | 3602 | const field_ty = try zcu.intType(.unsigned, @as(u16, @intCast(src_ty.bitSize(zcu)))); |
| 3609 | 3603 | ||
| 3610 | try f.writeCValue(writer, local, .Other); | 3604 | try f.writeCValue(writer, local, .Other); |
| 3611 | try v.elem(f, writer); | 3605 | try v.elem(f, writer); |
| ... | @@ -3616,9 +3610,9 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -3616,9 +3610,9 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3616 | try writer.writeAll("(("); | 3610 | try writer.writeAll("(("); |
| 3617 | try f.renderType(writer, field_ty); | 3611 | try f.renderType(writer, field_ty); |
| 3618 | try writer.writeByte(')'); | 3612 | try writer.writeByte(')'); |
| 3619 | const cant_cast = host_ty.isInt(mod) and host_ty.bitSize(mod) > 64; | 3613 | const cant_cast = host_ty.isInt(zcu) and host_ty.bitSize(zcu) > 64; |
| 3620 | if (cant_cast) { | 3614 | if (cant_cast) { |
| 3621 | if (field_ty.bitSize(mod) > 64) return f.fail("TODO: C backend: implement casting between types > 64 bits", .{}); | 3615 | if (field_ty.bitSize(zcu) > 64) return f.fail("TODO: C backend: implement casting between types > 64 bits", .{}); |
| 3622 | try writer.writeAll("zig_lo_"); | 3616 | try writer.writeAll("zig_lo_"); |
| 3623 | try f.object.dg.renderTypeForBuiltinFnName(writer, host_ty); | 3617 | try f.object.dg.renderTypeForBuiltinFnName(writer, host_ty); |
| 3624 | try writer.writeByte('('); | 3618 | try writer.writeByte('('); |
| ... | @@ -3628,7 +3622,7 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -3628,7 +3622,7 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3628 | try writer.writeByte('('); | 3622 | try writer.writeByte('('); |
| 3629 | try f.writeCValueDeref(writer, operand); | 3623 | try f.writeCValueDeref(writer, operand); |
| 3630 | try v.elem(f, writer); | 3624 | try v.elem(f, writer); |
| 3631 | try writer.print(", {})", .{try f.fmtIntLiteral(bit_offset_ty, bit_offset_val)}); | 3625 | try writer.print(", {})", .{try f.fmtIntLiteral(bit_offset_val)}); |
| 3632 | if (cant_cast) try writer.writeByte(')'); | 3626 | if (cant_cast) try writer.writeByte(')'); |
| 3633 | try f.object.dg.renderBuiltinInfo(writer, field_ty, .bits); | 3627 | try f.object.dg.renderBuiltinInfo(writer, field_ty, .bits); |
| 3634 | try writer.writeByte(')'); | 3628 | try writer.writeByte(')'); |
| ... | @@ -3646,24 +3640,27 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -3646,24 +3640,27 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3646 | } | 3640 | } |
| 3647 | 3641 | ||
| 3648 | fn airRet(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValue { | 3642 | fn airRet(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValue { |
| 3649 | const mod = f.object.dg.module; | 3643 | const zcu = f.object.dg.zcu; |
| 3650 | const un_op = f.air.instructions.items(.data)[@intFromEnum(inst)].un_op; | 3644 | const un_op = f.air.instructions.items(.data)[@intFromEnum(inst)].un_op; |
| 3651 | const writer = f.object.writer(); | 3645 | const writer = f.object.writer(); |
| 3652 | const op_inst = un_op.toIndex(); | 3646 | const op_inst = un_op.toIndex(); |
| 3653 | const op_ty = f.typeOf(un_op); | 3647 | const op_ty = f.typeOf(un_op); |
| 3654 | const ret_ty = if (is_ptr) op_ty.childType(mod) else op_ty; | 3648 | const ret_ty = if (is_ptr) op_ty.childType(zcu) else op_ty; |
| 3655 | const lowered_ret_ty = try lowerFnRetTy(ret_ty, mod); | 3649 | const ret_ctype = try f.ctypeFromType(ret_ty, .parameter); |
| 3656 | 3650 | ||
| 3657 | if (op_inst != null and f.air.instructions.items(.tag)[@intFromEnum(op_inst.?)] == .call_always_tail) { | 3651 | if (op_inst != null and f.air.instructions.items(.tag)[@intFromEnum(op_inst.?)] == .call_always_tail) { |
| 3658 | try reap(f, inst, &.{un_op}); | 3652 | try reap(f, inst, &.{un_op}); |
| 3659 | _ = try airCall(f, op_inst.?, .always_tail); | 3653 | _ = try airCall(f, op_inst.?, .always_tail); |
| 3660 | } else if (lowered_ret_ty.hasRuntimeBitsIgnoreComptime(mod)) { | 3654 | } else if (ret_ctype.index != .void) { |
| 3661 | const operand = try f.resolveInst(un_op); | 3655 | const operand = try f.resolveInst(un_op); |
| 3662 | try reap(f, inst, &.{un_op}); | 3656 | try reap(f, inst, &.{un_op}); |
| 3663 | var deref = is_ptr; | 3657 | var deref = is_ptr; |
| 3664 | const is_array = lowersToArray(ret_ty, mod); | 3658 | const is_array = lowersToArray(ret_ty, zcu); |
| 3665 | const ret_val = if (is_array) ret_val: { | 3659 | const ret_val = if (is_array) ret_val: { |
| 3666 | const array_local = try f.allocLocal(inst, lowered_ret_ty); | 3660 | const array_local = try f.allocAlignedLocal(inst, .{ |
| 3661 | .ctype = ret_ctype, | ||
| 3662 | .alignas = CType.AlignAs.fromAbiAlignment(ret_ty.abiAlignment(f.object.dg.zcu)), | ||
| 3663 | }); | ||
| 3667 | try writer.writeAll("memcpy("); | 3664 | try writer.writeAll("memcpy("); |
| 3668 | try f.writeCValueMember(writer, array_local, .{ .identifier = "array" }); | 3665 | try f.writeCValueMember(writer, array_local, .{ .identifier = "array" }); |
| 3669 | try writer.writeAll(", "); | 3666 | try writer.writeAll(", "); |
| ... | @@ -3696,16 +3693,16 @@ fn airRet(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValue { | ... | @@ -3696,16 +3693,16 @@ fn airRet(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValue { |
| 3696 | } | 3693 | } |
| 3697 | 3694 | ||
| 3698 | fn airIntCast(f: *Function, inst: Air.Inst.Index) !CValue { | 3695 | fn airIntCast(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3699 | const mod = f.object.dg.module; | 3696 | const zcu = f.object.dg.zcu; |
| 3700 | const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; | 3697 | const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 3701 | 3698 | ||
| 3702 | const operand = try f.resolveInst(ty_op.operand); | 3699 | const operand = try f.resolveInst(ty_op.operand); |
| 3703 | try reap(f, inst, &.{ty_op.operand}); | 3700 | try reap(f, inst, &.{ty_op.operand}); |
| 3704 | 3701 | ||
| 3705 | const inst_ty = f.typeOfIndex(inst); | 3702 | const inst_ty = f.typeOfIndex(inst); |
| 3706 | const inst_scalar_ty = inst_ty.scalarType(mod); | 3703 | const inst_scalar_ty = inst_ty.scalarType(zcu); |
| 3707 | const operand_ty = f.typeOf(ty_op.operand); | 3704 | const operand_ty = f.typeOf(ty_op.operand); |
| 3708 | const scalar_ty = operand_ty.scalarType(mod); | 3705 | const scalar_ty = operand_ty.scalarType(zcu); |
| 3709 | 3706 | ||
| 3710 | const writer = f.object.writer(); | 3707 | const writer = f.object.writer(); |
| 3711 | const local = try f.allocLocal(inst, inst_ty); | 3708 | const local = try f.allocLocal(inst, inst_ty); |
| ... | @@ -3722,20 +3719,20 @@ fn airIntCast(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -3722,20 +3719,20 @@ fn airIntCast(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3722 | } | 3719 | } |
| 3723 | 3720 | ||
| 3724 | fn airTrunc(f: *Function, inst: Air.Inst.Index) !CValue { | 3721 | fn airTrunc(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3725 | const mod = f.object.dg.module; | 3722 | const zcu = f.object.dg.zcu; |
| 3726 | const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; | 3723 | const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 3727 | 3724 | ||
| 3728 | const operand = try f.resolveInst(ty_op.operand); | 3725 | const operand = try f.resolveInst(ty_op.operand); |
| 3729 | try reap(f, inst, &.{ty_op.operand}); | 3726 | try reap(f, inst, &.{ty_op.operand}); |
| 3730 | const inst_ty = f.typeOfIndex(inst); | 3727 | const inst_ty = f.typeOfIndex(inst); |
| 3731 | const inst_scalar_ty = inst_ty.scalarType(mod); | 3728 | const inst_scalar_ty = inst_ty.scalarType(zcu); |
| 3732 | const dest_int_info = inst_scalar_ty.intInfo(mod); | 3729 | const dest_int_info = inst_scalar_ty.intInfo(zcu); |
| 3733 | const dest_bits = dest_int_info.bits; | 3730 | const dest_bits = dest_int_info.bits; |
| 3734 | const dest_c_bits = toCIntBits(dest_int_info.bits) orelse | 3731 | const dest_c_bits = toCIntBits(dest_int_info.bits) orelse |
| 3735 | return f.fail("TODO: C backend: implement integer types larger than 128 bits", .{}); | 3732 | return f.fail("TODO: C backend: implement integer types larger than 128 bits", .{}); |
| 3736 | const operand_ty = f.typeOf(ty_op.operand); | 3733 | const operand_ty = f.typeOf(ty_op.operand); |
| 3737 | const scalar_ty = operand_ty.scalarType(mod); | 3734 | const scalar_ty = operand_ty.scalarType(zcu); |
| 3738 | const scalar_int_info = scalar_ty.intInfo(mod); | 3735 | const scalar_int_info = scalar_ty.intInfo(zcu); |
| 3739 | 3736 | ||
| 3740 | const writer = f.object.writer(); | 3737 | const writer = f.object.writer(); |
| 3741 | const local = try f.allocLocal(inst, inst_ty); | 3738 | const local = try f.allocLocal(inst, inst_ty); |
| ... | @@ -3763,18 +3760,19 @@ fn airTrunc(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -3763,18 +3760,19 @@ fn airTrunc(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3763 | try v.elem(f, writer); | 3760 | try v.elem(f, writer); |
| 3764 | } else switch (dest_int_info.signedness) { | 3761 | } else switch (dest_int_info.signedness) { |
| 3765 | .unsigned => { | 3762 | .unsigned => { |
| 3766 | const mask_val = try inst_scalar_ty.maxIntScalar(mod, scalar_ty); | ||
| 3767 | try writer.writeAll("zig_and_"); | 3763 | try writer.writeAll("zig_and_"); |
| 3768 | try f.object.dg.renderTypeForBuiltinFnName(writer, scalar_ty); | 3764 | try f.object.dg.renderTypeForBuiltinFnName(writer, scalar_ty); |
| 3769 | try writer.writeByte('('); | 3765 | try writer.writeByte('('); |
| 3770 | try f.writeCValue(writer, operand, .FunctionArgument); | 3766 | try f.writeCValue(writer, operand, .FunctionArgument); |
| 3771 | try v.elem(f, writer); | 3767 | try v.elem(f, writer); |
| 3772 | try writer.print(", {x})", .{try f.fmtIntLiteral(scalar_ty, mask_val)}); | 3768 | try writer.print(", {x})", .{ |
| 3769 | try f.fmtIntLiteral(try inst_scalar_ty.maxIntScalar(zcu, scalar_ty)), | ||
| 3770 | }); | ||
| 3773 | }, | 3771 | }, |
| 3774 | .signed => { | 3772 | .signed => { |
| 3775 | const c_bits = toCIntBits(scalar_int_info.bits) orelse | 3773 | const c_bits = toCIntBits(scalar_int_info.bits) orelse |
| 3776 | return f.fail("TODO: C backend: implement integer types larger than 128 bits", .{}); | 3774 | return f.fail("TODO: C backend: implement integer types larger than 128 bits", .{}); |
| 3777 | const shift_val = try mod.intValue(Type.u8, c_bits - dest_bits); | 3775 | const shift_val = try zcu.intValue(Type.u8, c_bits - dest_bits); |
| 3778 | 3776 | ||
| 3779 | try writer.writeAll("zig_shr_"); | 3777 | try writer.writeAll("zig_shr_"); |
| 3780 | try f.object.dg.renderTypeForBuiltinFnName(writer, scalar_ty); | 3778 | try f.object.dg.renderTypeForBuiltinFnName(writer, scalar_ty); |
| ... | @@ -3792,9 +3790,9 @@ fn airTrunc(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -3792,9 +3790,9 @@ fn airTrunc(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3792 | try f.writeCValue(writer, operand, .FunctionArgument); | 3790 | try f.writeCValue(writer, operand, .FunctionArgument); |
| 3793 | try v.elem(f, writer); | 3791 | try v.elem(f, writer); |
| 3794 | if (c_bits == 128) try writer.writeByte(')'); | 3792 | if (c_bits == 128) try writer.writeByte(')'); |
| 3795 | try writer.print(", {})", .{try f.fmtIntLiteral(Type.u8, shift_val)}); | 3793 | try writer.print(", {})", .{try f.fmtIntLiteral(shift_val)}); |
| 3796 | if (c_bits == 128) try writer.writeByte(')'); | 3794 | if (c_bits == 128) try writer.writeByte(')'); |
| 3797 | try writer.print(", {})", .{try f.fmtIntLiteral(Type.u8, shift_val)}); | 3795 | try writer.print(", {})", .{try f.fmtIntLiteral(shift_val)}); |
| 3798 | }, | 3796 | }, |
| 3799 | } | 3797 | } |
| 3800 | 3798 | ||
| ... | @@ -3821,18 +3819,18 @@ fn airIntFromBool(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -3821,18 +3819,18 @@ fn airIntFromBool(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3821 | } | 3819 | } |
| 3822 | 3820 | ||
| 3823 | fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { | 3821 | fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { |
| 3824 | const mod = f.object.dg.module; | 3822 | const zcu = f.object.dg.zcu; |
| 3825 | // *a = b; | 3823 | // *a = b; |
| 3826 | const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; | 3824 | const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| 3827 | 3825 | ||
| 3828 | const ptr_ty = f.typeOf(bin_op.lhs); | 3826 | const ptr_ty = f.typeOf(bin_op.lhs); |
| 3829 | const ptr_scalar_ty = ptr_ty.scalarType(mod); | 3827 | const ptr_scalar_ty = ptr_ty.scalarType(zcu); |
| 3830 | const ptr_info = ptr_scalar_ty.ptrInfo(mod); | 3828 | const ptr_info = ptr_scalar_ty.ptrInfo(zcu); |
| 3831 | 3829 | ||
| 3832 | const ptr_val = try f.resolveInst(bin_op.lhs); | 3830 | const ptr_val = try f.resolveInst(bin_op.lhs); |
| 3833 | const src_ty = f.typeOf(bin_op.rhs); | 3831 | const src_ty = f.typeOf(bin_op.rhs); |
| 3834 | 3832 | ||
| 3835 | const val_is_undef = if (try f.air.value(bin_op.rhs, mod)) |v| v.isUndefDeep(mod) else false; | 3833 | const val_is_undef = if (try f.air.value(bin_op.rhs, zcu)) |v| v.isUndefDeep(zcu) else false; |
| 3836 | 3834 | ||
| 3837 | if (val_is_undef) { | 3835 | if (val_is_undef) { |
| 3838 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); | 3836 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); |
| ... | @@ -3848,10 +3846,10 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { | ... | @@ -3848,10 +3846,10 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { |
| 3848 | } | 3846 | } |
| 3849 | 3847 | ||
| 3850 | const is_aligned = if (ptr_info.flags.alignment != .none) | 3848 | const is_aligned = if (ptr_info.flags.alignment != .none) |
| 3851 | ptr_info.flags.alignment.compare(.gte, src_ty.abiAlignment(mod)) | 3849 | ptr_info.flags.alignment.order(src_ty.abiAlignment(zcu)).compare(.gte) |
| 3852 | else | 3850 | else |
| 3853 | true; | 3851 | true; |
| 3854 | const is_array = lowersToArray(Type.fromInterned(ptr_info.child), mod); | 3852 | const is_array = lowersToArray(Type.fromInterned(ptr_info.child), zcu); |
| 3855 | const need_memcpy = !is_aligned or is_array; | 3853 | const need_memcpy = !is_aligned or is_array; |
| 3856 | 3854 | ||
| 3857 | const src_val = try f.resolveInst(bin_op.rhs); | 3855 | const src_val = try f.resolveInst(bin_op.rhs); |
| ... | @@ -3863,7 +3861,7 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { | ... | @@ -3863,7 +3861,7 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { |
| 3863 | if (need_memcpy) { | 3861 | if (need_memcpy) { |
| 3864 | // For this memcpy to safely work we need the rhs to have the same | 3862 | // For this memcpy to safely work we need the rhs to have the same |
| 3865 | // underlying type as the lhs (i.e. they must both be arrays of the same underlying type). | 3863 | // underlying type as the lhs (i.e. they must both be arrays of the same underlying type). |
| 3866 | assert(src_ty.eql(Type.fromInterned(ptr_info.child), f.object.dg.module)); | 3864 | assert(src_ty.eql(Type.fromInterned(ptr_info.child), f.object.dg.zcu)); |
| 3867 | 3865 | ||
| 3868 | // If the source is a constant, writeCValue will emit a brace initialization | 3866 | // If the source is a constant, writeCValue will emit a brace initialization |
| 3869 | // so work around this by initializing into new local. | 3867 | // so work around this by initializing into new local. |
| ... | @@ -3893,12 +3891,12 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { | ... | @@ -3893,12 +3891,12 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { |
| 3893 | } | 3891 | } |
| 3894 | } else if (ptr_info.packed_offset.host_size > 0 and ptr_info.flags.vector_index == .none) { | 3892 | } else if (ptr_info.packed_offset.host_size > 0 and ptr_info.flags.vector_index == .none) { |
| 3895 | const host_bits = ptr_info.packed_offset.host_size * 8; | 3893 | const host_bits = ptr_info.packed_offset.host_size * 8; |
| 3896 | const host_ty = try mod.intType(.unsigned, host_bits); | 3894 | const host_ty = try zcu.intType(.unsigned, host_bits); |
| 3897 | 3895 | ||
| 3898 | const bit_offset_ty = try mod.intType(.unsigned, Type.smallestUnsignedBits(host_bits - 1)); | 3896 | const bit_offset_ty = try zcu.intType(.unsigned, Type.smallestUnsignedBits(host_bits - 1)); |
| 3899 | const bit_offset_val = try mod.intValue(bit_offset_ty, ptr_info.packed_offset.bit_offset); | 3897 | const bit_offset_val = try zcu.intValue(bit_offset_ty, ptr_info.packed_offset.bit_offset); |
| 3900 | 3898 | ||
| 3901 | const src_bits = src_ty.bitSize(mod); | 3899 | const src_bits = src_ty.bitSize(zcu); |
| 3902 | 3900 | ||
| 3903 | const ExpectedContents = [BigInt.Managed.default_capacity]BigIntLimb; | 3901 | const ExpectedContents = [BigInt.Managed.default_capacity]BigIntLimb; |
| 3904 | var stack align(@alignOf(ExpectedContents)) = | 3902 | var stack align(@alignOf(ExpectedContents)) = |
| ... | @@ -3911,7 +3909,7 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { | ... | @@ -3911,7 +3909,7 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { |
| 3911 | try mask.shiftLeft(&mask, ptr_info.packed_offset.bit_offset); | 3909 | try mask.shiftLeft(&mask, ptr_info.packed_offset.bit_offset); |
| 3912 | try mask.bitNotWrap(&mask, .unsigned, host_bits); | 3910 | try mask.bitNotWrap(&mask, .unsigned, host_bits); |
| 3913 | 3911 | ||
| 3914 | const mask_val = try mod.intValue_big(host_ty, mask.toConst()); | 3912 | const mask_val = try zcu.intValue_big(host_ty, mask.toConst()); |
| 3915 | 3913 | ||
| 3916 | try f.writeCValueDeref(writer, ptr_val); | 3914 | try f.writeCValueDeref(writer, ptr_val); |
| 3917 | try v.elem(f, writer); | 3915 | try v.elem(f, writer); |
| ... | @@ -3922,12 +3920,12 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { | ... | @@ -3922,12 +3920,12 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { |
| 3922 | try writer.writeByte('('); | 3920 | try writer.writeByte('('); |
| 3923 | try f.writeCValueDeref(writer, ptr_val); | 3921 | try f.writeCValueDeref(writer, ptr_val); |
| 3924 | try v.elem(f, writer); | 3922 | try v.elem(f, writer); |
| 3925 | try writer.print(", {x}), zig_shl_", .{try f.fmtIntLiteral(host_ty, mask_val)}); | 3923 | try writer.print(", {x}), zig_shl_", .{try f.fmtIntLiteral(mask_val)}); |
| 3926 | try f.object.dg.renderTypeForBuiltinFnName(writer, host_ty); | 3924 | try f.object.dg.renderTypeForBuiltinFnName(writer, host_ty); |
| 3927 | try writer.writeByte('('); | 3925 | try writer.writeByte('('); |
| 3928 | const cant_cast = host_ty.isInt(mod) and host_ty.bitSize(mod) > 64; | 3926 | const cant_cast = host_ty.isInt(zcu) and host_ty.bitSize(zcu) > 64; |
| 3929 | if (cant_cast) { | 3927 | if (cant_cast) { |
| 3930 | if (src_ty.bitSize(mod) > 64) return f.fail("TODO: C backend: implement casting between types > 64 bits", .{}); | 3928 | if (src_ty.bitSize(zcu) > 64) return f.fail("TODO: C backend: implement casting between types > 64 bits", .{}); |
| 3931 | try writer.writeAll("zig_make_"); | 3929 | try writer.writeAll("zig_make_"); |
| 3932 | try f.object.dg.renderTypeForBuiltinFnName(writer, host_ty); | 3930 | try f.object.dg.renderTypeForBuiltinFnName(writer, host_ty); |
| 3933 | try writer.writeAll("(0, "); | 3931 | try writer.writeAll("(0, "); |
| ... | @@ -3937,7 +3935,7 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { | ... | @@ -3937,7 +3935,7 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { |
| 3937 | try writer.writeByte(')'); | 3935 | try writer.writeByte(')'); |
| 3938 | } | 3936 | } |
| 3939 | 3937 | ||
| 3940 | if (src_ty.isPtrAtRuntime(mod)) { | 3938 | if (src_ty.isPtrAtRuntime(zcu)) { |
| 3941 | try writer.writeByte('('); | 3939 | try writer.writeByte('('); |
| 3942 | try f.renderType(writer, Type.usize); | 3940 | try f.renderType(writer, Type.usize); |
| 3943 | try writer.writeByte(')'); | 3941 | try writer.writeByte(')'); |
| ... | @@ -3945,7 +3943,7 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { | ... | @@ -3945,7 +3943,7 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { |
| 3945 | try f.writeCValue(writer, src_val, .Other); | 3943 | try f.writeCValue(writer, src_val, .Other); |
| 3946 | try v.elem(f, writer); | 3944 | try v.elem(f, writer); |
| 3947 | if (cant_cast) try writer.writeByte(')'); | 3945 | if (cant_cast) try writer.writeByte(')'); |
| 3948 | try writer.print(", {}))", .{try f.fmtIntLiteral(bit_offset_ty, bit_offset_val)}); | 3946 | try writer.print(", {}))", .{try f.fmtIntLiteral(bit_offset_val)}); |
| 3949 | } else { | 3947 | } else { |
| 3950 | try f.writeCValueDeref(writer, ptr_val); | 3948 | try f.writeCValueDeref(writer, ptr_val); |
| 3951 | try v.elem(f, writer); | 3949 | try v.elem(f, writer); |
| ... | @@ -3960,7 +3958,7 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { | ... | @@ -3960,7 +3958,7 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { |
| 3960 | } | 3958 | } |
| 3961 | 3959 | ||
| 3962 | fn airOverflow(f: *Function, inst: Air.Inst.Index, operation: []const u8, info: BuiltinInfo) !CValue { | 3960 | fn airOverflow(f: *Function, inst: Air.Inst.Index, operation: []const u8, info: BuiltinInfo) !CValue { |
| 3963 | const mod = f.object.dg.module; | 3961 | const zcu = f.object.dg.zcu; |
| 3964 | const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; | 3962 | const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| 3965 | const bin_op = f.air.extraData(Air.Bin, ty_pl.payload).data; | 3963 | const bin_op = f.air.extraData(Air.Bin, ty_pl.payload).data; |
| 3966 | 3964 | ||
| ... | @@ -3970,7 +3968,7 @@ fn airOverflow(f: *Function, inst: Air.Inst.Index, operation: []const u8, info: | ... | @@ -3970,7 +3968,7 @@ fn airOverflow(f: *Function, inst: Air.Inst.Index, operation: []const u8, info: |
| 3970 | 3968 | ||
| 3971 | const inst_ty = f.typeOfIndex(inst); | 3969 | const inst_ty = f.typeOfIndex(inst); |
| 3972 | const operand_ty = f.typeOf(bin_op.lhs); | 3970 | const operand_ty = f.typeOf(bin_op.lhs); |
| 3973 | const scalar_ty = operand_ty.scalarType(mod); | 3971 | const scalar_ty = operand_ty.scalarType(zcu); |
| 3974 | 3972 | ||
| 3975 | const w = f.object.writer(); | 3973 | const w = f.object.writer(); |
| 3976 | const local = try f.allocLocal(inst, inst_ty); | 3974 | const local = try f.allocLocal(inst, inst_ty); |
| ... | @@ -3998,11 +3996,11 @@ fn airOverflow(f: *Function, inst: Air.Inst.Index, operation: []const u8, info: | ... | @@ -3998,11 +3996,11 @@ fn airOverflow(f: *Function, inst: Air.Inst.Index, operation: []const u8, info: |
| 3998 | } | 3996 | } |
| 3999 | 3997 | ||
| 4000 | fn airNot(f: *Function, inst: Air.Inst.Index) !CValue { | 3998 | fn airNot(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4001 | const mod = f.object.dg.module; | 3999 | const zcu = f.object.dg.zcu; |
| 4002 | const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; | 4000 | const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 4003 | const operand_ty = f.typeOf(ty_op.operand); | 4001 | const operand_ty = f.typeOf(ty_op.operand); |
| 4004 | const scalar_ty = operand_ty.scalarType(mod); | 4002 | const scalar_ty = operand_ty.scalarType(zcu); |
| 4005 | if (scalar_ty.ip_index != .bool_type) return try airUnBuiltinCall(f, inst, "not", .bits); | 4003 | if (scalar_ty.toIntern() != .bool_type) return try airUnBuiltinCall(f, inst, "not", .bits); |
| 4006 | 4004 | ||
| 4007 | const op = try f.resolveInst(ty_op.operand); | 4005 | const op = try f.resolveInst(ty_op.operand); |
| 4008 | try reap(f, inst, &.{ty_op.operand}); | 4006 | try reap(f, inst, &.{ty_op.operand}); |
| ... | @@ -4031,11 +4029,11 @@ fn airBinOp( | ... | @@ -4031,11 +4029,11 @@ fn airBinOp( |
| 4031 | operation: []const u8, | 4029 | operation: []const u8, |
| 4032 | info: BuiltinInfo, | 4030 | info: BuiltinInfo, |
| 4033 | ) !CValue { | 4031 | ) !CValue { |
| 4034 | const mod = f.object.dg.module; | 4032 | const zcu = f.object.dg.zcu; |
| 4035 | const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; | 4033 | const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| 4036 | const operand_ty = f.typeOf(bin_op.lhs); | 4034 | const operand_ty = f.typeOf(bin_op.lhs); |
| 4037 | const scalar_ty = operand_ty.scalarType(mod); | 4035 | const scalar_ty = operand_ty.scalarType(zcu); |
| 4038 | if ((scalar_ty.isInt(mod) and scalar_ty.bitSize(mod) > 64) or scalar_ty.isRuntimeFloat()) | 4036 | if ((scalar_ty.isInt(zcu) and scalar_ty.bitSize(zcu) > 64) or scalar_ty.isRuntimeFloat()) |
| 4039 | return try airBinBuiltinCall(f, inst, operation, info); | 4037 | return try airBinBuiltinCall(f, inst, operation, info); |
| 4040 | 4038 | ||
| 4041 | const lhs = try f.resolveInst(bin_op.lhs); | 4039 | const lhs = try f.resolveInst(bin_op.lhs); |
| ... | @@ -4069,12 +4067,12 @@ fn airCmpOp( | ... | @@ -4069,12 +4067,12 @@ fn airCmpOp( |
| 4069 | data: anytype, | 4067 | data: anytype, |
| 4070 | operator: std.math.CompareOperator, | 4068 | operator: std.math.CompareOperator, |
| 4071 | ) !CValue { | 4069 | ) !CValue { |
| 4072 | const mod = f.object.dg.module; | 4070 | const zcu = f.object.dg.zcu; |
| 4073 | const lhs_ty = f.typeOf(data.lhs); | 4071 | const lhs_ty = f.typeOf(data.lhs); |
| 4074 | const scalar_ty = lhs_ty.scalarType(mod); | 4072 | const scalar_ty = lhs_ty.scalarType(zcu); |
| 4075 | 4073 | ||
| 4076 | const scalar_bits = scalar_ty.bitSize(mod); | 4074 | const scalar_bits = scalar_ty.bitSize(zcu); |
| 4077 | if (scalar_ty.isInt(mod) and scalar_bits > 64) | 4075 | if (scalar_ty.isInt(zcu) and scalar_bits > 64) |
| 4078 | return airCmpBuiltinCall( | 4076 | return airCmpBuiltinCall( |
| 4079 | f, | 4077 | f, |
| 4080 | inst, | 4078 | inst, |
| ... | @@ -4092,7 +4090,7 @@ fn airCmpOp( | ... | @@ -4092,7 +4090,7 @@ fn airCmpOp( |
| 4092 | try reap(f, inst, &.{ data.lhs, data.rhs }); | 4090 | try reap(f, inst, &.{ data.lhs, data.rhs }); |
| 4093 | 4091 | ||
| 4094 | const rhs_ty = f.typeOf(data.rhs); | 4092 | const rhs_ty = f.typeOf(data.rhs); |
| 4095 | const need_cast = lhs_ty.isSinglePointer(mod) or rhs_ty.isSinglePointer(mod); | 4093 | const need_cast = lhs_ty.isSinglePointer(zcu) or rhs_ty.isSinglePointer(zcu); |
| 4096 | const writer = f.object.writer(); | 4094 | const writer = f.object.writer(); |
| 4097 | const local = try f.allocLocal(inst, inst_ty); | 4095 | const local = try f.allocLocal(inst, inst_ty); |
| 4098 | const v = try Vectorize.start(f, inst, writer, lhs_ty); | 4096 | const v = try Vectorize.start(f, inst, writer, lhs_ty); |
| ... | @@ -4117,12 +4115,12 @@ fn airEquality( | ... | @@ -4117,12 +4115,12 @@ fn airEquality( |
| 4117 | inst: Air.Inst.Index, | 4115 | inst: Air.Inst.Index, |
| 4118 | operator: std.math.CompareOperator, | 4116 | operator: std.math.CompareOperator, |
| 4119 | ) !CValue { | 4117 | ) !CValue { |
| 4120 | const mod = f.object.dg.module; | 4118 | const zcu = f.object.dg.zcu; |
| 4121 | const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; | 4119 | const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| 4122 | 4120 | ||
| 4123 | const operand_ty = f.typeOf(bin_op.lhs); | 4121 | const operand_ty = f.typeOf(bin_op.lhs); |
| 4124 | const operand_bits = operand_ty.bitSize(mod); | 4122 | const operand_bits = operand_ty.bitSize(zcu); |
| 4125 | if (operand_ty.isInt(mod) and operand_bits > 64) | 4123 | if (operand_ty.isInt(zcu) and operand_bits > 64) |
| 4126 | return airCmpBuiltinCall( | 4124 | return airCmpBuiltinCall( |
| 4127 | f, | 4125 | f, |
| 4128 | inst, | 4126 | inst, |
| ... | @@ -4145,7 +4143,7 @@ fn airEquality( | ... | @@ -4145,7 +4143,7 @@ fn airEquality( |
| 4145 | try f.writeCValue(writer, local, .Other); | 4143 | try f.writeCValue(writer, local, .Other); |
| 4146 | try a.assign(f, writer); | 4144 | try a.assign(f, writer); |
| 4147 | 4145 | ||
| 4148 | if (operand_ty.zigTypeTag(mod) == .Optional and !operand_ty.optionalReprIsPayload(mod)) { | 4146 | if (operand_ty.zigTypeTag(zcu) == .Optional and !operand_ty.optionalReprIsPayload(zcu)) { |
| 4149 | try f.writeCValueMember(writer, lhs, .{ .identifier = "is_null" }); | 4147 | try f.writeCValueMember(writer, lhs, .{ .identifier = "is_null" }); |
| 4150 | try writer.writeAll(" || "); | 4148 | try writer.writeAll(" || "); |
| 4151 | try f.writeCValueMember(writer, rhs, .{ .identifier = "is_null" }); | 4149 | try f.writeCValueMember(writer, rhs, .{ .identifier = "is_null" }); |
| ... | @@ -4184,7 +4182,7 @@ fn airCmpLtErrorsLen(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -4184,7 +4182,7 @@ fn airCmpLtErrorsLen(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4184 | } | 4182 | } |
| 4185 | 4183 | ||
| 4186 | fn airPtrAddSub(f: *Function, inst: Air.Inst.Index, operator: u8) !CValue { | 4184 | fn airPtrAddSub(f: *Function, inst: Air.Inst.Index, operator: u8) !CValue { |
| 4187 | const mod = f.object.dg.module; | 4185 | const zcu = f.object.dg.zcu; |
| 4188 | const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; | 4186 | const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| 4189 | const bin_op = f.air.extraData(Air.Bin, ty_pl.payload).data; | 4187 | const bin_op = f.air.extraData(Air.Bin, ty_pl.payload).data; |
| 4190 | 4188 | ||
| ... | @@ -4193,8 +4191,8 @@ fn airPtrAddSub(f: *Function, inst: Air.Inst.Index, operator: u8) !CValue { | ... | @@ -4193,8 +4191,8 @@ fn airPtrAddSub(f: *Function, inst: Air.Inst.Index, operator: u8) !CValue { |
| 4193 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); | 4191 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); |
| 4194 | 4192 | ||
| 4195 | const inst_ty = f.typeOfIndex(inst); | 4193 | const inst_ty = f.typeOfIndex(inst); |
| 4196 | const inst_scalar_ty = inst_ty.scalarType(mod); | 4194 | const inst_scalar_ty = inst_ty.scalarType(zcu); |
| 4197 | const elem_ty = inst_scalar_ty.elemType2(mod); | 4195 | const elem_ty = inst_scalar_ty.elemType2(zcu); |
| 4198 | 4196 | ||
| 4199 | const local = try f.allocLocal(inst, inst_ty); | 4197 | const local = try f.allocLocal(inst, inst_ty); |
| 4200 | const writer = f.object.writer(); | 4198 | const writer = f.object.writer(); |
| ... | @@ -4203,7 +4201,7 @@ fn airPtrAddSub(f: *Function, inst: Air.Inst.Index, operator: u8) !CValue { | ... | @@ -4203,7 +4201,7 @@ fn airPtrAddSub(f: *Function, inst: Air.Inst.Index, operator: u8) !CValue { |
| 4203 | try v.elem(f, writer); | 4201 | try v.elem(f, writer); |
| 4204 | try writer.writeAll(" = "); | 4202 | try writer.writeAll(" = "); |
| 4205 | 4203 | ||
| 4206 | if (elem_ty.hasRuntimeBitsIgnoreComptime(mod)) { | 4204 | if (elem_ty.hasRuntimeBitsIgnoreComptime(zcu)) { |
| 4207 | // We must convert to and from integer types to prevent UB if the operation | 4205 | // We must convert to and from integer types to prevent UB if the operation |
| 4208 | // results in a NULL pointer, or if LHS is NULL. The operation is only UB | 4206 | // results in a NULL pointer, or if LHS is NULL. The operation is only UB |
| 4209 | // if the result is NULL and then dereferenced. | 4207 | // if the result is NULL and then dereferenced. |
| ... | @@ -4232,13 +4230,13 @@ fn airPtrAddSub(f: *Function, inst: Air.Inst.Index, operator: u8) !CValue { | ... | @@ -4232,13 +4230,13 @@ fn airPtrAddSub(f: *Function, inst: Air.Inst.Index, operator: u8) !CValue { |
| 4232 | } | 4230 | } |
| 4233 | 4231 | ||
| 4234 | fn airMinMax(f: *Function, inst: Air.Inst.Index, operator: u8, operation: []const u8) !CValue { | 4232 | fn airMinMax(f: *Function, inst: Air.Inst.Index, operator: u8, operation: []const u8) !CValue { |
| 4235 | const mod = f.object.dg.module; | 4233 | const zcu = f.object.dg.zcu; |
| 4236 | const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; | 4234 | const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| 4237 | 4235 | ||
| 4238 | const inst_ty = f.typeOfIndex(inst); | 4236 | const inst_ty = f.typeOfIndex(inst); |
| 4239 | const inst_scalar_ty = inst_ty.scalarType(mod); | 4237 | const inst_scalar_ty = inst_ty.scalarType(zcu); |
| 4240 | 4238 | ||
| 4241 | if (inst_scalar_ty.isInt(mod) and inst_scalar_ty.bitSize(mod) > 64) | 4239 | if (inst_scalar_ty.isInt(zcu) and inst_scalar_ty.bitSize(zcu) > 64) |
| 4242 | return try airBinBuiltinCall(f, inst, operation[1..], .none); | 4240 | return try airBinBuiltinCall(f, inst, operation[1..], .none); |
| 4243 | if (inst_scalar_ty.isRuntimeFloat()) | 4241 | if (inst_scalar_ty.isRuntimeFloat()) |
| 4244 | return try airBinFloatOp(f, inst, operation); | 4242 | return try airBinFloatOp(f, inst, operation); |
| ... | @@ -4274,7 +4272,7 @@ fn airMinMax(f: *Function, inst: Air.Inst.Index, operator: u8, operation: []cons | ... | @@ -4274,7 +4272,7 @@ fn airMinMax(f: *Function, inst: Air.Inst.Index, operator: u8, operation: []cons |
| 4274 | } | 4272 | } |
| 4275 | 4273 | ||
| 4276 | fn airSlice(f: *Function, inst: Air.Inst.Index) !CValue { | 4274 | fn airSlice(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4277 | const mod = f.object.dg.module; | 4275 | const zcu = f.object.dg.zcu; |
| 4278 | const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; | 4276 | const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| 4279 | const bin_op = f.air.extraData(Air.Bin, ty_pl.payload).data; | 4277 | const bin_op = f.air.extraData(Air.Bin, ty_pl.payload).data; |
| 4280 | 4278 | ||
| ... | @@ -4283,7 +4281,7 @@ fn airSlice(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -4283,7 +4281,7 @@ fn airSlice(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4283 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); | 4281 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); |
| 4284 | 4282 | ||
| 4285 | const inst_ty = f.typeOfIndex(inst); | 4283 | const inst_ty = f.typeOfIndex(inst); |
| 4286 | const ptr_ty = inst_ty.slicePtrFieldType(mod); | 4284 | const ptr_ty = inst_ty.slicePtrFieldType(zcu); |
| 4287 | 4285 | ||
| 4288 | const writer = f.object.writer(); | 4286 | const writer = f.object.writer(); |
| 4289 | const local = try f.allocLocal(inst, inst_ty); | 4287 | const local = try f.allocLocal(inst, inst_ty); |
| ... | @@ -4291,9 +4289,6 @@ fn airSlice(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -4291,9 +4289,6 @@ fn airSlice(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4291 | const a = try Assignment.start(f, writer, ptr_ty); | 4289 | const a = try Assignment.start(f, writer, ptr_ty); |
| 4292 | try f.writeCValueMember(writer, local, .{ .identifier = "ptr" }); | 4290 | try f.writeCValueMember(writer, local, .{ .identifier = "ptr" }); |
| 4293 | try a.assign(f, writer); | 4291 | try a.assign(f, writer); |
| 4294 | try writer.writeByte('('); | ||
| 4295 | try f.renderType(writer, ptr_ty); | ||
| 4296 | try writer.writeByte(')'); | ||
| 4297 | try f.writeCValue(writer, ptr, .Other); | 4292 | try f.writeCValue(writer, ptr, .Other); |
| 4298 | try a.end(f, writer); | 4293 | try a.end(f, writer); |
| 4299 | } | 4294 | } |
| ... | @@ -4301,7 +4296,7 @@ fn airSlice(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -4301,7 +4296,7 @@ fn airSlice(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4301 | const a = try Assignment.start(f, writer, Type.usize); | 4296 | const a = try Assignment.start(f, writer, Type.usize); |
| 4302 | try f.writeCValueMember(writer, local, .{ .identifier = "len" }); | 4297 | try f.writeCValueMember(writer, local, .{ .identifier = "len" }); |
| 4303 | try a.assign(f, writer); | 4298 | try a.assign(f, writer); |
| 4304 | try f.writeCValue(writer, len, .Other); | 4299 | try f.writeCValue(writer, len, .Initializer); |
| 4305 | try a.end(f, writer); | 4300 | try a.end(f, writer); |
| 4306 | } | 4301 | } |
| 4307 | return local; | 4302 | return local; |
| ... | @@ -4312,7 +4307,7 @@ fn airCall( | ... | @@ -4312,7 +4307,7 @@ fn airCall( |
| 4312 | inst: Air.Inst.Index, | 4307 | inst: Air.Inst.Index, |
| 4313 | modifier: std.builtin.CallModifier, | 4308 | modifier: std.builtin.CallModifier, |
| 4314 | ) !CValue { | 4309 | ) !CValue { |
| 4315 | const mod = f.object.dg.module; | 4310 | const zcu = f.object.dg.zcu; |
| 4316 | // Not even allowed to call panic in a naked function. | 4311 | // Not even allowed to call panic in a naked function. |
| 4317 | if (f.object.dg.is_naked_fn) return .none; | 4312 | if (f.object.dg.is_naked_fn) return .none; |
| 4318 | 4313 | ||
| ... | @@ -4327,22 +4322,23 @@ fn airCall( | ... | @@ -4327,22 +4322,23 @@ fn airCall( |
| 4327 | defer gpa.free(resolved_args); | 4322 | defer gpa.free(resolved_args); |
| 4328 | for (resolved_args, args) |*resolved_arg, arg| { | 4323 | for (resolved_args, args) |*resolved_arg, arg| { |
| 4329 | const arg_ty = f.typeOf(arg); | 4324 | const arg_ty = f.typeOf(arg); |
| 4330 | const arg_cty = try f.typeToIndex(arg_ty, .parameter); | 4325 | const arg_ctype = try f.ctypeFromType(arg_ty, .parameter); |
| 4331 | if (f.indexToCType(arg_cty).tag() == .void) { | 4326 | if (arg_ctype.index == .void) { |
| 4332 | resolved_arg.* = .none; | 4327 | resolved_arg.* = .none; |
| 4333 | continue; | 4328 | continue; |
| 4334 | } | 4329 | } |
| 4335 | resolved_arg.* = try f.resolveInst(arg); | 4330 | resolved_arg.* = try f.resolveInst(arg); |
| 4336 | if (arg_cty != try f.typeToIndex(arg_ty, .complete)) { | 4331 | if (!arg_ctype.eql(try f.ctypeFromType(arg_ty, .complete))) { |
| 4337 | const lowered_arg_ty = try lowerFnRetTy(arg_ty, mod); | 4332 | const array_local = try f.allocAlignedLocal(inst, .{ |
| 4338 | 4333 | .ctype = arg_ctype, | |
| 4339 | const array_local = try f.allocLocal(inst, lowered_arg_ty); | 4334 | .alignas = CType.AlignAs.fromAbiAlignment(arg_ty.abiAlignment(zcu)), |
| 4335 | }); | ||
| 4340 | try writer.writeAll("memcpy("); | 4336 | try writer.writeAll("memcpy("); |
| 4341 | try f.writeCValueMember(writer, array_local, .{ .identifier = "array" }); | 4337 | try f.writeCValueMember(writer, array_local, .{ .identifier = "array" }); |
| 4342 | try writer.writeAll(", "); | 4338 | try writer.writeAll(", "); |
| 4343 | try f.writeCValue(writer, resolved_arg.*, .FunctionArgument); | 4339 | try f.writeCValue(writer, resolved_arg.*, .FunctionArgument); |
| 4344 | try writer.writeAll(", sizeof("); | 4340 | try writer.writeAll(", sizeof("); |
| 4345 | try f.renderType(writer, lowered_arg_ty); | 4341 | try f.renderCType(writer, arg_ctype); |
| 4346 | try writer.writeAll("));\n"); | 4342 | try writer.writeAll("));\n"); |
| 4347 | resolved_arg.* = array_local; | 4343 | resolved_arg.* = array_local; |
| 4348 | } | 4344 | } |
| ... | @@ -4357,28 +4353,33 @@ fn airCall( | ... | @@ -4357,28 +4353,33 @@ fn airCall( |
| 4357 | } | 4353 | } |
| 4358 | 4354 | ||
| 4359 | const callee_ty = f.typeOf(pl_op.operand); | 4355 | const callee_ty = f.typeOf(pl_op.operand); |
| 4360 | const fn_ty = switch (callee_ty.zigTypeTag(mod)) { | 4356 | const fn_info = zcu.typeToFunc(switch (callee_ty.zigTypeTag(zcu)) { |
| 4361 | .Fn => callee_ty, | 4357 | .Fn => callee_ty, |
| 4362 | .Pointer => callee_ty.childType(mod), | 4358 | .Pointer => callee_ty.childType(zcu), |
| 4363 | else => unreachable, | 4359 | else => unreachable, |
| 4364 | }; | 4360 | }).?; |
| 4365 | 4361 | const ret_ty = Type.fromInterned(fn_info.return_type); | |
| 4366 | const ret_ty = fn_ty.fnReturnType(mod); | 4362 | const ret_ctype: CType = if (ret_ty.isNoReturn(zcu)) |
| 4367 | const lowered_ret_ty = try lowerFnRetTy(ret_ty, mod); | 4363 | .{ .index = .void } |
| 4364 | else | ||
| 4365 | try f.ctypeFromType(ret_ty, .parameter); | ||
| 4368 | 4366 | ||
| 4369 | const result_local = result: { | 4367 | const result_local = result: { |
| 4370 | if (modifier == .always_tail) { | 4368 | if (modifier == .always_tail) { |
| 4371 | try writer.writeAll("zig_always_tail return "); | 4369 | try writer.writeAll("zig_always_tail return "); |
| 4372 | break :result .none; | 4370 | break :result .none; |
| 4373 | } else if (!lowered_ret_ty.hasRuntimeBitsIgnoreComptime(mod)) { | 4371 | } else if (ret_ctype.index == .void) { |
| 4374 | break :result .none; | 4372 | break :result .none; |
| 4375 | } else if (f.liveness.isUnused(inst)) { | 4373 | } else if (f.liveness.isUnused(inst)) { |
| 4376 | try writer.writeByte('('); | 4374 | try writer.writeByte('('); |
| 4377 | try f.renderType(writer, Type.void); | 4375 | try f.renderCType(writer, .{ .index = .void }); |
| 4378 | try writer.writeByte(')'); | 4376 | try writer.writeByte(')'); |
| 4379 | break :result .none; | 4377 | break :result .none; |
| 4380 | } else { | 4378 | } else { |
| 4381 | const local = try f.allocLocal(inst, lowered_ret_ty); | 4379 | const local = try f.allocAlignedLocal(inst, .{ |
| 4380 | .ctype = ret_ctype, | ||
| 4381 | .alignas = CType.AlignAs.fromAbiAlignment(ret_ty.abiAlignment(zcu)), | ||
| 4382 | }); | ||
| 4382 | try f.writeCValue(writer, local, .Other); | 4383 | try f.writeCValue(writer, local, .Other); |
| 4383 | try writer.writeAll(" = "); | 4384 | try writer.writeAll(" = "); |
| 4384 | break :result local; | 4385 | break :result local; |
| ... | @@ -4388,8 +4389,8 @@ fn airCall( | ... | @@ -4388,8 +4389,8 @@ fn airCall( |
| 4388 | callee: { | 4389 | callee: { |
| 4389 | known: { | 4390 | known: { |
| 4390 | const fn_decl = fn_decl: { | 4391 | const fn_decl = fn_decl: { |
| 4391 | const callee_val = (try f.air.value(pl_op.operand, mod)) orelse break :known; | 4392 | const callee_val = (try f.air.value(pl_op.operand, zcu)) orelse break :known; |
| 4392 | break :fn_decl switch (mod.intern_pool.indexToKey(callee_val.ip_index)) { | 4393 | break :fn_decl switch (zcu.intern_pool.indexToKey(callee_val.toIntern())) { |
| 4393 | .extern_func => |extern_func| extern_func.decl, | 4394 | .extern_func => |extern_func| extern_func.decl, |
| 4394 | .func => |func| func.owner_decl, | 4395 | .func => |func| func.owner_decl, |
| 4395 | .ptr => |ptr| switch (ptr.addr) { | 4396 | .ptr => |ptr| switch (ptr.addr) { |
| ... | @@ -4420,18 +4421,21 @@ fn airCall( | ... | @@ -4420,18 +4421,21 @@ fn airCall( |
| 4420 | } | 4421 | } |
| 4421 | 4422 | ||
| 4422 | try writer.writeByte('('); | 4423 | try writer.writeByte('('); |
| 4423 | var args_written: usize = 0; | 4424 | var need_comma = false; |
| 4424 | for (resolved_args) |resolved_arg| { | 4425 | for (resolved_args) |resolved_arg| { |
| 4425 | if (resolved_arg == .none) continue; | 4426 | if (resolved_arg == .none) continue; |
| 4426 | if (args_written != 0) try writer.writeAll(", "); | 4427 | if (need_comma) try writer.writeAll(", "); |
| 4428 | need_comma = true; | ||
| 4427 | try f.writeCValue(writer, resolved_arg, .FunctionArgument); | 4429 | try f.writeCValue(writer, resolved_arg, .FunctionArgument); |
| 4428 | if (resolved_arg == .new_local) try freeLocal(f, inst, resolved_arg.new_local, null); | 4430 | switch (resolved_arg) { |
| 4429 | args_written += 1; | 4431 | .new_local => |local| try freeLocal(f, inst, local, null), |
| 4432 | else => {}, | ||
| 4433 | } | ||
| 4430 | } | 4434 | } |
| 4431 | try writer.writeAll(");\n"); | 4435 | try writer.writeAll(");\n"); |
| 4432 | 4436 | ||
| 4433 | const result = result: { | 4437 | const result = result: { |
| 4434 | if (result_local == .none or !lowersToArray(ret_ty, mod)) | 4438 | if (result_local == .none or !lowersToArray(ret_ty, zcu)) |
| 4435 | break :result result_local; | 4439 | break :result result_local; |
| 4436 | 4440 | ||
| 4437 | const array_local = try f.allocLocal(inst, ret_ty); | 4441 | const array_local = try f.allocLocal(inst, ret_ty); |
| ... | @@ -4465,22 +4469,22 @@ fn airDbgStmt(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -4465,22 +4469,22 @@ fn airDbgStmt(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4465 | } | 4469 | } |
| 4466 | 4470 | ||
| 4467 | fn airDbgInlineBlock(f: *Function, inst: Air.Inst.Index) !CValue { | 4471 | fn airDbgInlineBlock(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4468 | const mod = f.object.dg.module; | 4472 | const zcu = f.object.dg.zcu; |
| 4469 | const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; | 4473 | const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| 4470 | const extra = f.air.extraData(Air.DbgInlineBlock, ty_pl.payload); | 4474 | const extra = f.air.extraData(Air.DbgInlineBlock, ty_pl.payload); |
| 4471 | const owner_decl = mod.funcOwnerDeclPtr(extra.data.func); | 4475 | const owner_decl = zcu.funcOwnerDeclPtr(extra.data.func); |
| 4472 | const writer = f.object.writer(); | 4476 | const writer = f.object.writer(); |
| 4473 | try writer.writeAll("/* "); | 4477 | try writer.writeAll("/* "); |
| 4474 | try owner_decl.renderFullyQualifiedName(mod, writer); | 4478 | try owner_decl.renderFullyQualifiedName(zcu, writer); |
| 4475 | try writer.writeAll(" */ "); | 4479 | try writer.writeAll(" */ "); |
| 4476 | return lowerBlock(f, inst, @ptrCast(f.air.extra[extra.end..][0..extra.data.body_len])); | 4480 | return lowerBlock(f, inst, @ptrCast(f.air.extra[extra.end..][0..extra.data.body_len])); |
| 4477 | } | 4481 | } |
| 4478 | 4482 | ||
| 4479 | fn airDbgVar(f: *Function, inst: Air.Inst.Index) !CValue { | 4483 | fn airDbgVar(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4480 | const mod = f.object.dg.module; | 4484 | const zcu = f.object.dg.zcu; |
| 4481 | const pl_op = f.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; | 4485 | const pl_op = f.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; |
| 4482 | const name = f.air.nullTerminatedString(pl_op.payload); | 4486 | const name = f.air.nullTerminatedString(pl_op.payload); |
| 4483 | const operand_is_undef = if (try f.air.value(pl_op.operand, mod)) |v| v.isUndefDeep(mod) else false; | 4487 | const operand_is_undef = if (try f.air.value(pl_op.operand, zcu)) |v| v.isUndefDeep(zcu) else false; |
| 4484 | if (!operand_is_undef) _ = try f.resolveInst(pl_op.operand); | 4488 | if (!operand_is_undef) _ = try f.resolveInst(pl_op.operand); |
| 4485 | 4489 | ||
| 4486 | try reap(f, inst, &.{pl_op.operand}); | 4490 | try reap(f, inst, &.{pl_op.operand}); |
| ... | @@ -4496,7 +4500,7 @@ fn airBlock(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -4496,7 +4500,7 @@ fn airBlock(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4496 | } | 4500 | } |
| 4497 | 4501 | ||
| 4498 | fn lowerBlock(f: *Function, inst: Air.Inst.Index, body: []const Air.Inst.Index) !CValue { | 4502 | fn lowerBlock(f: *Function, inst: Air.Inst.Index, body: []const Air.Inst.Index) !CValue { |
| 4499 | const mod = f.object.dg.module; | 4503 | const zcu = f.object.dg.zcu; |
| 4500 | const liveness_block = f.liveness.getBlock(inst); | 4504 | const liveness_block = f.liveness.getBlock(inst); |
| 4501 | 4505 | ||
| 4502 | const block_id: usize = f.next_block_index; | 4506 | const block_id: usize = f.next_block_index; |
| ... | @@ -4504,7 +4508,7 @@ fn lowerBlock(f: *Function, inst: Air.Inst.Index, body: []const Air.Inst.Index) | ... | @@ -4504,7 +4508,7 @@ fn lowerBlock(f: *Function, inst: Air.Inst.Index, body: []const Air.Inst.Index) |
| 4504 | const writer = f.object.writer(); | 4508 | const writer = f.object.writer(); |
| 4505 | 4509 | ||
| 4506 | const inst_ty = f.typeOfIndex(inst); | 4510 | const inst_ty = f.typeOfIndex(inst); |
| 4507 | const result = if (inst_ty.hasRuntimeBitsIgnoreComptime(mod) and !f.liveness.isUnused(inst)) | 4511 | const result = if (inst_ty.hasRuntimeBitsIgnoreComptime(zcu) and !f.liveness.isUnused(inst)) |
| 4508 | try f.allocLocal(inst, inst_ty) | 4512 | try f.allocLocal(inst, inst_ty) |
| 4509 | else | 4513 | else |
| 4510 | .none; | 4514 | .none; |
| ... | @@ -4526,7 +4530,7 @@ fn lowerBlock(f: *Function, inst: Air.Inst.Index, body: []const Air.Inst.Index) | ... | @@ -4526,7 +4530,7 @@ fn lowerBlock(f: *Function, inst: Air.Inst.Index, body: []const Air.Inst.Index) |
| 4526 | try f.object.indent_writer.insertNewline(); | 4530 | try f.object.indent_writer.insertNewline(); |
| 4527 | 4531 | ||
| 4528 | // noreturn blocks have no `br` instructions reaching them, so we don't want a label | 4532 | // noreturn blocks have no `br` instructions reaching them, so we don't want a label |
| 4529 | if (!f.typeOfIndex(inst).isNoReturn(mod)) { | 4533 | if (!f.typeOfIndex(inst).isNoReturn(zcu)) { |
| 4530 | // label must be followed by an expression, include an empty one. | 4534 | // label must be followed by an expression, include an empty one. |
| 4531 | try writer.print("zig_block_{d}:;\n", .{block_id}); | 4535 | try writer.print("zig_block_{d}:;\n", .{block_id}); |
| 4532 | } | 4536 | } |
| ... | @@ -4543,11 +4547,11 @@ fn airTry(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -4543,11 +4547,11 @@ fn airTry(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4543 | } | 4547 | } |
| 4544 | 4548 | ||
| 4545 | fn airTryPtr(f: *Function, inst: Air.Inst.Index) !CValue { | 4549 | fn airTryPtr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4546 | const mod = f.object.dg.module; | 4550 | const zcu = f.object.dg.zcu; |
| 4547 | const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; | 4551 | const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| 4548 | const extra = f.air.extraData(Air.TryPtr, ty_pl.payload); | 4552 | const extra = f.air.extraData(Air.TryPtr, ty_pl.payload); |
| 4549 | const body: []const Air.Inst.Index = @ptrCast(f.air.extra[extra.end..][0..extra.data.body_len]); | 4553 | const body: []const Air.Inst.Index = @ptrCast(f.air.extra[extra.end..][0..extra.data.body_len]); |
| 4550 | const err_union_ty = f.typeOf(extra.data.ptr).childType(mod); | 4554 | const err_union_ty = f.typeOf(extra.data.ptr).childType(zcu); |
| 4551 | return lowerTry(f, inst, extra.data.ptr, body, err_union_ty, true); | 4555 | return lowerTry(f, inst, extra.data.ptr, body, err_union_ty, true); |
| 4552 | } | 4556 | } |
| 4553 | 4557 | ||
| ... | @@ -4559,15 +4563,15 @@ fn lowerTry( | ... | @@ -4559,15 +4563,15 @@ fn lowerTry( |
| 4559 | err_union_ty: Type, | 4563 | err_union_ty: Type, |
| 4560 | is_ptr: bool, | 4564 | is_ptr: bool, |
| 4561 | ) !CValue { | 4565 | ) !CValue { |
| 4562 | const mod = f.object.dg.module; | 4566 | const zcu = f.object.dg.zcu; |
| 4563 | const err_union = try f.resolveInst(operand); | 4567 | const err_union = try f.resolveInst(operand); |
| 4564 | const inst_ty = f.typeOfIndex(inst); | 4568 | const inst_ty = f.typeOfIndex(inst); |
| 4565 | const liveness_condbr = f.liveness.getCondBr(inst); | 4569 | const liveness_condbr = f.liveness.getCondBr(inst); |
| 4566 | const writer = f.object.writer(); | 4570 | const writer = f.object.writer(); |
| 4567 | const payload_ty = err_union_ty.errorUnionPayload(mod); | 4571 | const payload_ty = err_union_ty.errorUnionPayload(zcu); |
| 4568 | const payload_has_bits = payload_ty.hasRuntimeBitsIgnoreComptime(mod); | 4572 | const payload_has_bits = payload_ty.hasRuntimeBitsIgnoreComptime(zcu); |
| 4569 | 4573 | ||
| 4570 | if (!err_union_ty.errorUnionSet(mod).errorSetIsEmpty(mod)) { | 4574 | if (!err_union_ty.errorUnionSet(zcu).errorSetIsEmpty(zcu)) { |
| 4571 | try writer.writeAll("if ("); | 4575 | try writer.writeAll("if ("); |
| 4572 | if (!payload_has_bits) { | 4576 | if (!payload_has_bits) { |
| 4573 | if (is_ptr) | 4577 | if (is_ptr) |
| ... | @@ -4661,7 +4665,7 @@ const LocalResult = struct { | ... | @@ -4661,7 +4665,7 @@ const LocalResult = struct { |
| 4661 | need_free: bool, | 4665 | need_free: bool, |
| 4662 | 4666 | ||
| 4663 | fn move(lr: LocalResult, f: *Function, inst: Air.Inst.Index, dest_ty: Type) !CValue { | 4667 | fn move(lr: LocalResult, f: *Function, inst: Air.Inst.Index, dest_ty: Type) !CValue { |
| 4664 | const mod = f.object.dg.module; | 4668 | const zcu = f.object.dg.zcu; |
| 4665 | 4669 | ||
| 4666 | if (lr.need_free) { | 4670 | if (lr.need_free) { |
| 4667 | // Move the freshly allocated local to be owned by this instruction, | 4671 | // Move the freshly allocated local to be owned by this instruction, |
| ... | @@ -4673,7 +4677,7 @@ const LocalResult = struct { | ... | @@ -4673,7 +4677,7 @@ const LocalResult = struct { |
| 4673 | try lr.free(f); | 4677 | try lr.free(f); |
| 4674 | const writer = f.object.writer(); | 4678 | const writer = f.object.writer(); |
| 4675 | try f.writeCValue(writer, local, .Other); | 4679 | try f.writeCValue(writer, local, .Other); |
| 4676 | if (dest_ty.isAbiInt(mod)) { | 4680 | if (dest_ty.isAbiInt(zcu)) { |
| 4677 | try writer.writeAll(" = "); | 4681 | try writer.writeAll(" = "); |
| 4678 | } else { | 4682 | } else { |
| 4679 | try writer.writeAll(" = ("); | 4683 | try writer.writeAll(" = ("); |
| ... | @@ -4693,13 +4697,14 @@ const LocalResult = struct { | ... | @@ -4693,13 +4697,14 @@ const LocalResult = struct { |
| 4693 | }; | 4697 | }; |
| 4694 | 4698 | ||
| 4695 | fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !LocalResult { | 4699 | fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !LocalResult { |
| 4696 | const mod = f.object.dg.module; | 4700 | const zcu = f.object.dg.zcu; |
| 4697 | const target = mod.getTarget(); | 4701 | const target = &f.object.dg.mod.resolved_target.result; |
| 4702 | const ctype_pool = &f.object.dg.ctype_pool; | ||
| 4698 | const writer = f.object.writer(); | 4703 | const writer = f.object.writer(); |
| 4699 | 4704 | ||
| 4700 | if (operand_ty.isAbiInt(mod) and dest_ty.isAbiInt(mod)) { | 4705 | if (operand_ty.isAbiInt(zcu) and dest_ty.isAbiInt(zcu)) { |
| 4701 | const src_info = dest_ty.intInfo(mod); | 4706 | const src_info = dest_ty.intInfo(zcu); |
| 4702 | const dest_info = operand_ty.intInfo(mod); | 4707 | const dest_info = operand_ty.intInfo(zcu); |
| 4703 | if (src_info.signedness == dest_info.signedness and | 4708 | if (src_info.signedness == dest_info.signedness and |
| 4704 | src_info.bits == dest_info.bits) | 4709 | src_info.bits == dest_info.bits) |
| 4705 | { | 4710 | { |
| ... | @@ -4710,7 +4715,7 @@ fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !Loca | ... | @@ -4710,7 +4715,7 @@ fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !Loca |
| 4710 | } | 4715 | } |
| 4711 | } | 4716 | } |
| 4712 | 4717 | ||
| 4713 | if (dest_ty.isPtrAtRuntime(mod) and operand_ty.isPtrAtRuntime(mod)) { | 4718 | if (dest_ty.isPtrAtRuntime(zcu) and operand_ty.isPtrAtRuntime(zcu)) { |
| 4714 | const local = try f.allocLocal(null, dest_ty); | 4719 | const local = try f.allocLocal(null, dest_ty); |
| 4715 | try f.writeCValue(writer, local, .Other); | 4720 | try f.writeCValue(writer, local, .Other); |
| 4716 | try writer.writeAll(" = ("); | 4721 | try writer.writeAll(" = ("); |
| ... | @@ -4727,7 +4732,7 @@ fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !Loca | ... | @@ -4727,7 +4732,7 @@ fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !Loca |
| 4727 | const operand_lval = if (operand == .constant) blk: { | 4732 | const operand_lval = if (operand == .constant) blk: { |
| 4728 | const operand_local = try f.allocLocal(null, operand_ty); | 4733 | const operand_local = try f.allocLocal(null, operand_ty); |
| 4729 | try f.writeCValue(writer, operand_local, .Other); | 4734 | try f.writeCValue(writer, operand_local, .Other); |
| 4730 | if (operand_ty.isAbiInt(mod)) { | 4735 | if (operand_ty.isAbiInt(zcu)) { |
| 4731 | try writer.writeAll(" = "); | 4736 | try writer.writeAll(" = "); |
| 4732 | } else { | 4737 | } else { |
| 4733 | try writer.writeAll(" = ("); | 4738 | try writer.writeAll(" = ("); |
| ... | @@ -4747,55 +4752,60 @@ fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !Loca | ... | @@ -4747,55 +4752,60 @@ fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !Loca |
| 4747 | try writer.writeAll(", sizeof("); | 4752 | try writer.writeAll(", sizeof("); |
| 4748 | try f.renderType( | 4753 | try f.renderType( |
| 4749 | writer, | 4754 | writer, |
| 4750 | if (dest_ty.abiSize(mod) <= operand_ty.abiSize(mod)) dest_ty else operand_ty, | 4755 | if (dest_ty.abiSize(zcu) <= operand_ty.abiSize(zcu)) dest_ty else operand_ty, |
| 4751 | ); | 4756 | ); |
| 4752 | try writer.writeAll("));\n"); | 4757 | try writer.writeAll("));\n"); |
| 4753 | 4758 | ||
| 4754 | // Ensure padding bits have the expected value. | 4759 | // Ensure padding bits have the expected value. |
| 4755 | if (dest_ty.isAbiInt(mod)) { | 4760 | if (dest_ty.isAbiInt(zcu)) { |
| 4756 | const dest_cty = try f.typeToCType(dest_ty, .complete); | 4761 | const dest_ctype = try f.ctypeFromType(dest_ty, .complete); |
| 4757 | const dest_info = dest_ty.intInfo(mod); | 4762 | const dest_info = dest_ty.intInfo(zcu); |
| 4758 | var bits: u16 = dest_info.bits; | 4763 | var bits: u16 = dest_info.bits; |
| 4759 | var wrap_cty: ?CType = null; | 4764 | var wrap_ctype: ?CType = null; |
| 4760 | var need_bitcasts = false; | 4765 | var need_bitcasts = false; |
| 4761 | 4766 | ||
| 4762 | try f.writeCValue(writer, local, .Other); | 4767 | try f.writeCValue(writer, local, .Other); |
| 4763 | if (dest_cty.castTag(.array)) |pl| { | 4768 | switch (dest_ctype.info(ctype_pool)) { |
| 4764 | try writer.print("[{d}]", .{switch (target.cpu.arch.endian()) { | 4769 | else => {}, |
| 4765 | .little => pl.data.len - 1, | 4770 | .array => |array_info| { |
| 4766 | .big => 0, | 4771 | try writer.print("[{d}]", .{switch (target.cpu.arch.endian()) { |
| 4767 | }}); | 4772 | .little => array_info.len - 1, |
| 4768 | const elem_cty = f.indexToCType(pl.data.elem_type); | 4773 | .big => 0, |
| 4769 | wrap_cty = elem_cty.toSignedness(dest_info.signedness); | 4774 | }}); |
| 4770 | need_bitcasts = wrap_cty.?.tag() == .zig_i128; | 4775 | wrap_ctype = array_info.elem_ctype.toSignedness(dest_info.signedness); |
| 4771 | bits -= 1; | 4776 | need_bitcasts = wrap_ctype.?.index == .zig_i128; |
| 4772 | bits %= @as(u16, @intCast(f.byteSize(elem_cty) * 8)); | 4777 | bits -= 1; |
| 4773 | bits += 1; | 4778 | bits %= @as(u16, @intCast(f.byteSize(array_info.elem_ctype) * 8)); |
| 4779 | bits += 1; | ||
| 4780 | }, | ||
| 4774 | } | 4781 | } |
| 4775 | try writer.writeAll(" = "); | 4782 | try writer.writeAll(" = "); |
| 4776 | if (need_bitcasts) { | 4783 | if (need_bitcasts) { |
| 4777 | try writer.writeAll("zig_bitCast_"); | 4784 | try writer.writeAll("zig_bitCast_"); |
| 4778 | try f.object.dg.renderCTypeForBuiltinFnName(writer, wrap_cty.?.toUnsigned()); | 4785 | try f.object.dg.renderCTypeForBuiltinFnName(writer, wrap_ctype.?.toUnsigned()); |
| 4779 | try writer.writeByte('('); | 4786 | try writer.writeByte('('); |
| 4780 | } | 4787 | } |
| 4781 | try writer.writeAll("zig_wrap_"); | 4788 | try writer.writeAll("zig_wrap_"); |
| 4782 | const info_ty = try mod.intType(dest_info.signedness, bits); | 4789 | const info_ty = try zcu.intType(dest_info.signedness, bits); |
| 4783 | if (wrap_cty) |cty| | 4790 | if (wrap_ctype) |ctype| |
| 4784 | try f.object.dg.renderCTypeForBuiltinFnName(writer, cty) | 4791 | try f.object.dg.renderCTypeForBuiltinFnName(writer, ctype) |
| 4785 | else | 4792 | else |
| 4786 | try f.object.dg.renderTypeForBuiltinFnName(writer, info_ty); | 4793 | try f.object.dg.renderTypeForBuiltinFnName(writer, info_ty); |
| 4787 | try writer.writeByte('('); | 4794 | try writer.writeByte('('); |
| 4788 | if (need_bitcasts) { | 4795 | if (need_bitcasts) { |
| 4789 | try writer.writeAll("zig_bitCast_"); | 4796 | try writer.writeAll("zig_bitCast_"); |
| 4790 | try f.object.dg.renderCTypeForBuiltinFnName(writer, wrap_cty.?); | 4797 | try f.object.dg.renderCTypeForBuiltinFnName(writer, wrap_ctype.?); |
| 4791 | try writer.writeByte('('); | 4798 | try writer.writeByte('('); |
| 4792 | } | 4799 | } |
| 4793 | try f.writeCValue(writer, local, .Other); | 4800 | try f.writeCValue(writer, local, .Other); |
| 4794 | if (dest_cty.castTag(.array)) |pl| { | 4801 | switch (dest_ctype.info(ctype_pool)) { |
| 4795 | try writer.print("[{d}]", .{switch (target.cpu.arch.endian()) { | 4802 | else => {}, |
| 4796 | .little => pl.data.len - 1, | 4803 | .array => |array_info| try writer.print("[{d}]", .{ |
| 4797 | .big => 0, | 4804 | switch (target.cpu.arch.endian()) { |
| 4798 | }}); | 4805 | .little => array_info.len - 1, |
| 4806 | .big => 0, | ||
| 4807 | }, | ||
| 4808 | }), | ||
| 4799 | } | 4809 | } |
| 4800 | if (need_bitcasts) try writer.writeByte(')'); | 4810 | if (need_bitcasts) try writer.writeByte(')'); |
| 4801 | try f.object.dg.renderBuiltinInfo(writer, info_ty, .bits); | 4811 | try f.object.dg.renderBuiltinInfo(writer, info_ty, .bits); |
| ... | @@ -4912,7 +4922,7 @@ fn airCondBr(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -4912,7 +4922,7 @@ fn airCondBr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4912 | } | 4922 | } |
| 4913 | 4923 | ||
| 4914 | fn airSwitchBr(f: *Function, inst: Air.Inst.Index) !CValue { | 4924 | fn airSwitchBr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4915 | const mod = f.object.dg.module; | 4925 | const zcu = f.object.dg.zcu; |
| 4916 | const pl_op = f.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; | 4926 | const pl_op = f.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; |
| 4917 | const condition = try f.resolveInst(pl_op.operand); | 4927 | const condition = try f.resolveInst(pl_op.operand); |
| 4918 | try reap(f, inst, &.{pl_op.operand}); | 4928 | try reap(f, inst, &.{pl_op.operand}); |
| ... | @@ -4921,11 +4931,11 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -4921,11 +4931,11 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4921 | const writer = f.object.writer(); | 4931 | const writer = f.object.writer(); |
| 4922 | 4932 | ||
| 4923 | try writer.writeAll("switch ("); | 4933 | try writer.writeAll("switch ("); |
| 4924 | if (condition_ty.zigTypeTag(mod) == .Bool) { | 4934 | if (condition_ty.zigTypeTag(zcu) == .Bool) { |
| 4925 | try writer.writeByte('('); | 4935 | try writer.writeByte('('); |
| 4926 | try f.renderType(writer, Type.u1); | 4936 | try f.renderType(writer, Type.u1); |
| 4927 | try writer.writeByte(')'); | 4937 | try writer.writeByte(')'); |
| 4928 | } else if (condition_ty.isPtrAtRuntime(mod)) { | 4938 | } else if (condition_ty.isPtrAtRuntime(zcu)) { |
| 4929 | try writer.writeByte('('); | 4939 | try writer.writeByte('('); |
| 4930 | try f.renderType(writer, Type.usize); | 4940 | try f.renderType(writer, Type.usize); |
| 4931 | try writer.writeByte(')'); | 4941 | try writer.writeByte(')'); |
| ... | @@ -4952,12 +4962,12 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -4952,12 +4962,12 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4952 | for (items) |item| { | 4962 | for (items) |item| { |
| 4953 | try f.object.indent_writer.insertNewline(); | 4963 | try f.object.indent_writer.insertNewline(); |
| 4954 | try writer.writeAll("case "); | 4964 | try writer.writeAll("case "); |
| 4955 | if (condition_ty.isPtrAtRuntime(mod)) { | 4965 | if (condition_ty.isPtrAtRuntime(zcu)) { |
| 4956 | try writer.writeByte('('); | 4966 | try writer.writeByte('('); |
| 4957 | try f.renderType(writer, Type.usize); | 4967 | try f.renderType(writer, Type.usize); |
| 4958 | try writer.writeByte(')'); | 4968 | try writer.writeByte(')'); |
| 4959 | } | 4969 | } |
| 4960 | try f.object.dg.renderValue(writer, condition_ty, (try f.air.value(item, mod)).?, .Other); | 4970 | try f.object.dg.renderValue(writer, (try f.air.value(item, zcu)).?, .Other); |
| 4961 | try writer.writeByte(':'); | 4971 | try writer.writeByte(':'); |
| 4962 | } | 4972 | } |
| 4963 | try writer.writeByte(' '); | 4973 | try writer.writeByte(' '); |
| ... | @@ -4994,13 +5004,13 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -4994,13 +5004,13 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4994 | } | 5004 | } |
| 4995 | 5005 | ||
| 4996 | fn asmInputNeedsLocal(f: *Function, constraint: []const u8, value: CValue) bool { | 5006 | fn asmInputNeedsLocal(f: *Function, constraint: []const u8, value: CValue) bool { |
| 4997 | const target = f.object.dg.module.getTarget(); | 5007 | const target = &f.object.dg.mod.resolved_target.result; |
| 4998 | return switch (constraint[0]) { | 5008 | return switch (constraint[0]) { |
| 4999 | '{' => true, | 5009 | '{' => true, |
| 5000 | 'i', 'r' => false, | 5010 | 'i', 'r' => false, |
| 5001 | 'I' => !target.cpu.arch.isArmOrThumb(), | 5011 | 'I' => !target.cpu.arch.isArmOrThumb(), |
| 5002 | else => switch (value) { | 5012 | else => switch (value) { |
| 5003 | .constant => |val| switch (f.object.dg.module.intern_pool.indexToKey(val)) { | 5013 | .constant => |val| switch (f.object.dg.zcu.intern_pool.indexToKey(val.toIntern())) { |
| 5004 | .ptr => |ptr| switch (ptr.addr) { | 5014 | .ptr => |ptr| switch (ptr.addr) { |
| 5005 | .decl => false, | 5015 | .decl => false, |
| 5006 | else => true, | 5016 | else => true, |
| ... | @@ -5013,7 +5023,7 @@ fn asmInputNeedsLocal(f: *Function, constraint: []const u8, value: CValue) bool | ... | @@ -5013,7 +5023,7 @@ fn asmInputNeedsLocal(f: *Function, constraint: []const u8, value: CValue) bool |
| 5013 | } | 5023 | } |
| 5014 | 5024 | ||
| 5015 | fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { | 5025 | fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5016 | const mod = f.object.dg.module; | 5026 | const zcu = f.object.dg.zcu; |
| 5017 | const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; | 5027 | const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| 5018 | const extra = f.air.extraData(Air.Asm, ty_pl.payload); | 5028 | const extra = f.air.extraData(Air.Asm, ty_pl.payload); |
| 5019 | const is_volatile = @as(u1, @truncate(extra.data.flags >> 31)) != 0; | 5029 | const is_volatile = @as(u1, @truncate(extra.data.flags >> 31)) != 0; |
| ... | @@ -5028,15 +5038,18 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -5028,15 +5038,18 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5028 | const result = result: { | 5038 | const result = result: { |
| 5029 | const writer = f.object.writer(); | 5039 | const writer = f.object.writer(); |
| 5030 | const inst_ty = f.typeOfIndex(inst); | 5040 | const inst_ty = f.typeOfIndex(inst); |
| 5031 | const local = if (inst_ty.hasRuntimeBitsIgnoreComptime(mod)) local: { | 5041 | const inst_local = if (inst_ty.hasRuntimeBitsIgnoreComptime(zcu)) local: { |
| 5032 | const local = try f.allocLocal(inst, inst_ty); | 5042 | const inst_local = try f.allocLocalValue(.{ |
| 5043 | .ctype = try f.ctypeFromType(inst_ty, .complete), | ||
| 5044 | .alignas = CType.AlignAs.fromAbiAlignment(inst_ty.abiAlignment(zcu)), | ||
| 5045 | }); | ||
| 5033 | if (f.wantSafety()) { | 5046 | if (f.wantSafety()) { |
| 5034 | try f.writeCValue(writer, local, .Other); | 5047 | try f.writeCValue(writer, inst_local, .Other); |
| 5035 | try writer.writeAll(" = "); | 5048 | try writer.writeAll(" = "); |
| 5036 | try f.writeCValue(writer, .{ .undef = inst_ty }, .Other); | 5049 | try f.writeCValue(writer, .{ .undef = inst_ty }, .Other); |
| 5037 | try writer.writeAll(";\n"); | 5050 | try writer.writeAll(";\n"); |
| 5038 | } | 5051 | } |
| 5039 | break :local local; | 5052 | break :local inst_local; |
| 5040 | } else .none; | 5053 | } else .none; |
| 5041 | 5054 | ||
| 5042 | const locals_begin = @as(LocalIndex, @intCast(f.locals.items.len)); | 5055 | const locals_begin = @as(LocalIndex, @intCast(f.locals.items.len)); |
| ... | @@ -5057,12 +5070,14 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -5057,12 +5070,14 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5057 | 5070 | ||
| 5058 | const is_reg = constraint[1] == '{'; | 5071 | const is_reg = constraint[1] == '{'; |
| 5059 | if (is_reg) { | 5072 | if (is_reg) { |
| 5060 | const output_ty = if (output == .none) inst_ty else f.typeOf(output).childType(mod); | 5073 | const output_ty = if (output == .none) inst_ty else f.typeOf(output).childType(zcu); |
| 5061 | try writer.writeAll("register "); | 5074 | try writer.writeAll("register "); |
| 5062 | const alignment: Alignment = .none; | 5075 | const output_local = try f.allocLocalValue(.{ |
| 5063 | const local_value = try f.allocLocalValue(output_ty, alignment); | 5076 | .ctype = try f.ctypeFromType(output_ty, .complete), |
| 5064 | try f.allocs.put(gpa, local_value.new_local, false); | 5077 | .alignas = CType.AlignAs.fromAbiAlignment(output_ty.abiAlignment(zcu)), |
| 5065 | try f.object.dg.renderTypeAndName(writer, output_ty, local_value, .{}, alignment, .complete); | 5078 | }); |
| 5079 | try f.allocs.put(gpa, output_local.new_local, false); | ||
| 5080 | try f.object.dg.renderTypeAndName(writer, output_ty, output_local, .{}, .none, .complete); | ||
| 5066 | try writer.writeAll(" __asm(\""); | 5081 | try writer.writeAll(" __asm(\""); |
| 5067 | try writer.writeAll(constraint["={".len .. constraint.len - "}".len]); | 5082 | try writer.writeAll(constraint["={".len .. constraint.len - "}".len]); |
| 5068 | try writer.writeAll("\")"); | 5083 | try writer.writeAll("\")"); |
| ... | @@ -5092,10 +5107,12 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -5092,10 +5107,12 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5092 | if (asmInputNeedsLocal(f, constraint, input_val)) { | 5107 | if (asmInputNeedsLocal(f, constraint, input_val)) { |
| 5093 | const input_ty = f.typeOf(input); | 5108 | const input_ty = f.typeOf(input); |
| 5094 | if (is_reg) try writer.writeAll("register "); | 5109 | if (is_reg) try writer.writeAll("register "); |
| 5095 | const alignment: Alignment = .none; | 5110 | const input_local = try f.allocLocalValue(.{ |
| 5096 | const local_value = try f.allocLocalValue(input_ty, alignment); | 5111 | .ctype = try f.ctypeFromType(input_ty, .complete), |
| 5097 | try f.allocs.put(gpa, local_value.new_local, false); | 5112 | .alignas = CType.AlignAs.fromAbiAlignment(input_ty.abiAlignment(zcu)), |
| 5098 | try f.object.dg.renderTypeAndName(writer, input_ty, local_value, Const, alignment, .complete); | 5113 | }); |
| 5114 | try f.allocs.put(gpa, input_local.new_local, false); | ||
| 5115 | try f.object.dg.renderTypeAndName(writer, input_ty, input_local, Const, .none, .complete); | ||
| 5099 | if (is_reg) { | 5116 | if (is_reg) { |
| 5100 | try writer.writeAll(" __asm(\""); | 5117 | try writer.writeAll(" __asm(\""); |
| 5101 | try writer.writeAll(constraint["{".len .. constraint.len - "}".len]); | 5118 | try writer.writeAll(constraint["{".len .. constraint.len - "}".len]); |
| ... | @@ -5188,7 +5205,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -5188,7 +5205,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5188 | try f.writeCValue(writer, .{ .local = locals_index }, .Other); | 5205 | try f.writeCValue(writer, .{ .local = locals_index }, .Other); |
| 5189 | locals_index += 1; | 5206 | locals_index += 1; |
| 5190 | } else if (output == .none) { | 5207 | } else if (output == .none) { |
| 5191 | try f.writeCValue(writer, local, .FunctionArgument); | 5208 | try f.writeCValue(writer, inst_local, .FunctionArgument); |
| 5192 | } else { | 5209 | } else { |
| 5193 | try f.writeCValueDeref(writer, try f.resolveInst(output)); | 5210 | try f.writeCValueDeref(writer, try f.resolveInst(output)); |
| 5194 | } | 5211 | } |
| ... | @@ -5244,7 +5261,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -5244,7 +5261,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5244 | const is_reg = constraint[1] == '{'; | 5261 | const is_reg = constraint[1] == '{'; |
| 5245 | if (is_reg) { | 5262 | if (is_reg) { |
| 5246 | try f.writeCValueDeref(writer, if (output == .none) | 5263 | try f.writeCValueDeref(writer, if (output == .none) |
| 5247 | .{ .local_ref = local.new_local } | 5264 | .{ .local_ref = inst_local.new_local } |
| 5248 | else | 5265 | else |
| 5249 | try f.resolveInst(output)); | 5266 | try f.resolveInst(output)); |
| 5250 | try writer.writeAll(" = "); | 5267 | try writer.writeAll(" = "); |
| ... | @@ -5254,7 +5271,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -5254,7 +5271,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5254 | } | 5271 | } |
| 5255 | } | 5272 | } |
| 5256 | 5273 | ||
| 5257 | break :result if (f.liveness.isUnused(inst)) .none else local; | 5274 | break :result if (f.liveness.isUnused(inst)) .none else inst_local; |
| 5258 | }; | 5275 | }; |
| 5259 | 5276 | ||
| 5260 | var bt = iterateBigTomb(f, inst); | 5277 | var bt = iterateBigTomb(f, inst); |
| ... | @@ -5275,7 +5292,7 @@ fn airIsNull( | ... | @@ -5275,7 +5292,7 @@ fn airIsNull( |
| 5275 | operator: []const u8, | 5292 | operator: []const u8, |
| 5276 | is_ptr: bool, | 5293 | is_ptr: bool, |
| 5277 | ) !CValue { | 5294 | ) !CValue { |
| 5278 | const mod = f.object.dg.module; | 5295 | const zcu = f.object.dg.zcu; |
| 5279 | const un_op = f.air.instructions.items(.data)[@intFromEnum(inst)].un_op; | 5296 | const un_op = f.air.instructions.items(.data)[@intFromEnum(inst)].un_op; |
| 5280 | 5297 | ||
| 5281 | const writer = f.object.writer(); | 5298 | const writer = f.object.writer(); |
| ... | @@ -5292,22 +5309,22 @@ fn airIsNull( | ... | @@ -5292,22 +5309,22 @@ fn airIsNull( |
| 5292 | } | 5309 | } |
| 5293 | 5310 | ||
| 5294 | const operand_ty = f.typeOf(un_op); | 5311 | const operand_ty = f.typeOf(un_op); |
| 5295 | const optional_ty = if (is_ptr) operand_ty.childType(mod) else operand_ty; | 5312 | const optional_ty = if (is_ptr) operand_ty.childType(zcu) else operand_ty; |
| 5296 | const payload_ty = optional_ty.optionalChild(mod); | 5313 | const payload_ty = optional_ty.optionalChild(zcu); |
| 5297 | const err_int_ty = try mod.errorIntType(); | 5314 | const err_int_ty = try zcu.errorIntType(); |
| 5298 | 5315 | ||
| 5299 | const rhs = if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) | 5316 | const rhs = if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) |
| 5300 | Value.true | 5317 | Value.true |
| 5301 | else if (optional_ty.isPtrLikeOptional(mod)) | 5318 | else if (optional_ty.isPtrLikeOptional(zcu)) |
| 5302 | // operand is a regular pointer, test `operand !=/== NULL` | 5319 | // operand is a regular pointer, test `operand !=/== NULL` |
| 5303 | try mod.getCoerced(Value.null, optional_ty) | 5320 | try zcu.getCoerced(Value.null, optional_ty) |
| 5304 | else if (payload_ty.zigTypeTag(mod) == .ErrorSet) | 5321 | else if (payload_ty.zigTypeTag(zcu) == .ErrorSet) |
| 5305 | try mod.intValue(err_int_ty, 0) | 5322 | try zcu.intValue(err_int_ty, 0) |
| 5306 | else if (payload_ty.isSlice(mod) and optional_ty.optionalReprIsPayload(mod)) rhs: { | 5323 | else if (payload_ty.isSlice(zcu) and optional_ty.optionalReprIsPayload(zcu)) rhs: { |
| 5307 | try writer.writeAll(".ptr"); | 5324 | try writer.writeAll(".ptr"); |
| 5308 | const slice_ptr_ty = payload_ty.slicePtrFieldType(mod); | 5325 | const slice_ptr_ty = payload_ty.slicePtrFieldType(zcu); |
| 5309 | const opt_slice_ptr_ty = try mod.optionalType(slice_ptr_ty.toIntern()); | 5326 | const opt_slice_ptr_ty = try zcu.optionalType(slice_ptr_ty.toIntern()); |
| 5310 | break :rhs try mod.nullValue(opt_slice_ptr_ty); | 5327 | break :rhs try zcu.nullValue(opt_slice_ptr_ty); |
| 5311 | } else rhs: { | 5328 | } else rhs: { |
| 5312 | try writer.writeAll(".is_null"); | 5329 | try writer.writeAll(".is_null"); |
| 5313 | break :rhs Value.true; | 5330 | break :rhs Value.true; |
| ... | @@ -5315,22 +5332,22 @@ fn airIsNull( | ... | @@ -5315,22 +5332,22 @@ fn airIsNull( |
| 5315 | try writer.writeByte(' '); | 5332 | try writer.writeByte(' '); |
| 5316 | try writer.writeAll(operator); | 5333 | try writer.writeAll(operator); |
| 5317 | try writer.writeByte(' '); | 5334 | try writer.writeByte(' '); |
| 5318 | try f.object.dg.renderValue(writer, rhs.typeOf(mod), rhs, .Other); | 5335 | try f.object.dg.renderValue(writer, rhs, .Other); |
| 5319 | try writer.writeAll(";\n"); | 5336 | try writer.writeAll(";\n"); |
| 5320 | return local; | 5337 | return local; |
| 5321 | } | 5338 | } |
| 5322 | 5339 | ||
| 5323 | fn airOptionalPayload(f: *Function, inst: Air.Inst.Index) !CValue { | 5340 | fn airOptionalPayload(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5324 | const mod = f.object.dg.module; | 5341 | const zcu = f.object.dg.zcu; |
| 5325 | const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; | 5342 | const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 5326 | 5343 | ||
| 5327 | const operand = try f.resolveInst(ty_op.operand); | 5344 | const operand = try f.resolveInst(ty_op.operand); |
| 5328 | try reap(f, inst, &.{ty_op.operand}); | 5345 | try reap(f, inst, &.{ty_op.operand}); |
| 5329 | const opt_ty = f.typeOf(ty_op.operand); | 5346 | const opt_ty = f.typeOf(ty_op.operand); |
| 5330 | 5347 | ||
| 5331 | const payload_ty = opt_ty.optionalChild(mod); | 5348 | const payload_ty = opt_ty.optionalChild(zcu); |
| 5332 | 5349 | ||
| 5333 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) { | 5350 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { |
| 5334 | return .none; | 5351 | return .none; |
| 5335 | } | 5352 | } |
| 5336 | 5353 | ||
| ... | @@ -5338,7 +5355,7 @@ fn airOptionalPayload(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -5338,7 +5355,7 @@ fn airOptionalPayload(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5338 | const writer = f.object.writer(); | 5355 | const writer = f.object.writer(); |
| 5339 | const local = try f.allocLocal(inst, inst_ty); | 5356 | const local = try f.allocLocal(inst, inst_ty); |
| 5340 | 5357 | ||
| 5341 | if (opt_ty.optionalReprIsPayload(mod)) { | 5358 | if (opt_ty.optionalReprIsPayload(zcu)) { |
| 5342 | try f.writeCValue(writer, local, .Other); | 5359 | try f.writeCValue(writer, local, .Other); |
| 5343 | try writer.writeAll(" = "); | 5360 | try writer.writeAll(" = "); |
| 5344 | try f.writeCValue(writer, operand, .Other); | 5361 | try f.writeCValue(writer, operand, .Other); |
| ... | @@ -5355,24 +5372,24 @@ fn airOptionalPayload(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -5355,24 +5372,24 @@ fn airOptionalPayload(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5355 | } | 5372 | } |
| 5356 | 5373 | ||
| 5357 | fn airOptionalPayloadPtr(f: *Function, inst: Air.Inst.Index) !CValue { | 5374 | fn airOptionalPayloadPtr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5358 | const mod = f.object.dg.module; | 5375 | const zcu = f.object.dg.zcu; |
| 5359 | const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; | 5376 | const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 5360 | 5377 | ||
| 5361 | const writer = f.object.writer(); | 5378 | const writer = f.object.writer(); |
| 5362 | const operand = try f.resolveInst(ty_op.operand); | 5379 | const operand = try f.resolveInst(ty_op.operand); |
| 5363 | try reap(f, inst, &.{ty_op.operand}); | 5380 | try reap(f, inst, &.{ty_op.operand}); |
| 5364 | const ptr_ty = f.typeOf(ty_op.operand); | 5381 | const ptr_ty = f.typeOf(ty_op.operand); |
| 5365 | const opt_ty = ptr_ty.childType(mod); | 5382 | const opt_ty = ptr_ty.childType(zcu); |
| 5366 | const inst_ty = f.typeOfIndex(inst); | 5383 | const inst_ty = f.typeOfIndex(inst); |
| 5367 | 5384 | ||
| 5368 | if (!inst_ty.childType(mod).hasRuntimeBitsIgnoreComptime(mod)) { | 5385 | if (!inst_ty.childType(zcu).hasRuntimeBitsIgnoreComptime(zcu)) { |
| 5369 | return .{ .undef = inst_ty }; | 5386 | return .{ .undef = inst_ty }; |
| 5370 | } | 5387 | } |
| 5371 | 5388 | ||
| 5372 | const local = try f.allocLocal(inst, inst_ty); | 5389 | const local = try f.allocLocal(inst, inst_ty); |
| 5373 | try f.writeCValue(writer, local, .Other); | 5390 | try f.writeCValue(writer, local, .Other); |
| 5374 | 5391 | ||
| 5375 | if (opt_ty.optionalReprIsPayload(mod)) { | 5392 | if (opt_ty.optionalReprIsPayload(zcu)) { |
| 5376 | // the operand is just a regular pointer, no need to do anything special. | 5393 | // the operand is just a regular pointer, no need to do anything special. |
| 5377 | // *?*T -> **T and ?*T -> *T are **T -> **T and *T -> *T in C | 5394 | // *?*T -> **T and ?*T -> *T are **T -> **T and *T -> *T in C |
| 5378 | try writer.writeAll(" = "); | 5395 | try writer.writeAll(" = "); |
| ... | @@ -5386,18 +5403,18 @@ fn airOptionalPayloadPtr(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -5386,18 +5403,18 @@ fn airOptionalPayloadPtr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5386 | } | 5403 | } |
| 5387 | 5404 | ||
| 5388 | fn airOptionalPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue { | 5405 | fn airOptionalPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5389 | const mod = f.object.dg.module; | 5406 | const zcu = f.object.dg.zcu; |
| 5390 | const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; | 5407 | const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 5391 | const writer = f.object.writer(); | 5408 | const writer = f.object.writer(); |
| 5392 | const operand = try f.resolveInst(ty_op.operand); | 5409 | const operand = try f.resolveInst(ty_op.operand); |
| 5393 | try reap(f, inst, &.{ty_op.operand}); | 5410 | try reap(f, inst, &.{ty_op.operand}); |
| 5394 | const operand_ty = f.typeOf(ty_op.operand); | 5411 | const operand_ty = f.typeOf(ty_op.operand); |
| 5395 | 5412 | ||
| 5396 | const opt_ty = operand_ty.childType(mod); | 5413 | const opt_ty = operand_ty.childType(zcu); |
| 5397 | 5414 | ||
| 5398 | const inst_ty = f.typeOfIndex(inst); | 5415 | const inst_ty = f.typeOfIndex(inst); |
| 5399 | 5416 | ||
| 5400 | if (opt_ty.optionalReprIsPayload(mod)) { | 5417 | if (opt_ty.optionalReprIsPayload(zcu)) { |
| 5401 | if (f.liveness.isUnused(inst)) { | 5418 | if (f.liveness.isUnused(inst)) { |
| 5402 | return .none; | 5419 | return .none; |
| 5403 | } | 5420 | } |
| ... | @@ -5412,7 +5429,7 @@ fn airOptionalPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -5412,7 +5429,7 @@ fn airOptionalPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5412 | } else { | 5429 | } else { |
| 5413 | try f.writeCValueDeref(writer, operand); | 5430 | try f.writeCValueDeref(writer, operand); |
| 5414 | try writer.writeAll(".is_null = "); | 5431 | try writer.writeAll(".is_null = "); |
| 5415 | try f.object.dg.renderValue(writer, Type.bool, Value.false, .Initializer); | 5432 | try f.object.dg.renderValue(writer, Value.false, .Initializer); |
| 5416 | try writer.writeAll(";\n"); | 5433 | try writer.writeAll(";\n"); |
| 5417 | 5434 | ||
| 5418 | if (f.liveness.isUnused(inst)) { | 5435 | if (f.liveness.isUnused(inst)) { |
| ... | @@ -5432,67 +5449,82 @@ fn fieldLocation( | ... | @@ -5432,67 +5449,82 @@ fn fieldLocation( |
| 5432 | container_ptr_ty: Type, | 5449 | container_ptr_ty: Type, |
| 5433 | field_ptr_ty: Type, | 5450 | field_ptr_ty: Type, |
| 5434 | field_index: u32, | 5451 | field_index: u32, |
| 5435 | mod: *Module, | 5452 | zcu: *Zcu, |
| 5436 | ) union(enum) { | 5453 | ) union(enum) { |
| 5437 | begin: void, | 5454 | begin: void, |
| 5438 | field: CValue, | 5455 | field: CValue, |
| 5439 | byte_offset: u32, | 5456 | byte_offset: u32, |
| 5440 | end: void, | 5457 | end: void, |
| 5441 | } { | 5458 | } { |
| 5442 | const ip = &mod.intern_pool; | 5459 | const ip = &zcu.intern_pool; |
| 5443 | const container_ty = container_ptr_ty.childType(mod); | 5460 | const container_ty = Type.fromInterned(ip.indexToKey(container_ptr_ty.toIntern()).ptr_type.child); |
| 5444 | return switch (container_ty.zigTypeTag(mod)) { | 5461 | switch (ip.indexToKey(container_ty.toIntern())) { |
| 5445 | .Struct => blk: { | 5462 | .struct_type => { |
| 5446 | if (mod.typeToPackedStruct(container_ty)) |struct_type| { | 5463 | const loaded_struct = ip.loadStructType(container_ty.toIntern()); |
| 5447 | if (field_ptr_ty.ptrInfo(mod).packed_offset.host_size == 0) | 5464 | switch (loaded_struct.layout) { |
| 5448 | break :blk .{ .byte_offset = @divExact(mod.structPackedFieldBitOffset(struct_type, field_index) + container_ptr_ty.ptrInfo(mod).packed_offset.bit_offset, 8) } | 5465 | .auto, .@"extern" => { |
| 5466 | var field_it = loaded_struct.iterateRuntimeOrder(ip); | ||
| 5467 | var before = true; | ||
| 5468 | while (field_it.next()) |next_field_index| { | ||
| 5469 | if (next_field_index == field_index) before = false; | ||
| 5470 | if (before) continue; | ||
| 5471 | const field_type = Type.fromInterned(loaded_struct.field_types.get(ip)[next_field_index]); | ||
| 5472 | if (!field_type.hasRuntimeBitsIgnoreComptime(zcu)) continue; | ||
| 5473 | return .{ .field = if (loaded_struct.fieldName(ip, next_field_index).unwrap()) |field_name| | ||
| 5474 | .{ .identifier = ip.stringToSlice(field_name) } | ||
| 5475 | else | ||
| 5476 | .{ .field = next_field_index } }; | ||
| 5477 | } | ||
| 5478 | return if (container_ty.hasRuntimeBitsIgnoreComptime(zcu)) .end else .begin; | ||
| 5479 | }, | ||
| 5480 | .@"packed" => return if (field_ptr_ty.ptrInfo(zcu).packed_offset.host_size == 0) | ||
| 5481 | .{ .byte_offset = @divExact(zcu.structPackedFieldBitOffset(loaded_struct, field_index) + | ||
| 5482 | container_ptr_ty.ptrInfo(zcu).packed_offset.bit_offset, 8) } | ||
| 5449 | else | 5483 | else |
| 5450 | break :blk .begin; | 5484 | .begin, |
| 5451 | } | 5485 | } |
| 5452 | 5486 | }, | |
| 5453 | for (field_index..container_ty.structFieldCount(mod)) |next_field_index_usize| { | 5487 | .anon_struct_type => |anon_struct_info| { |
| 5454 | const next_field_index: u32 = @intCast(next_field_index_usize); | 5488 | for (field_index..anon_struct_info.types.len) |next_field_index| { |
| 5455 | if (container_ty.structFieldIsComptime(next_field_index, mod)) continue; | 5489 | if (anon_struct_info.values.get(ip)[next_field_index] != .none) continue; |
| 5456 | const field_ty = container_ty.structFieldType(next_field_index, mod); | 5490 | const field_type = Type.fromInterned(anon_struct_info.types.get(ip)[next_field_index]); |
| 5457 | if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; | 5491 | if (!field_type.hasRuntimeBitsIgnoreComptime(zcu)) continue; |
| 5458 | 5492 | return .{ .field = if (anon_struct_info.fieldName(ip, next_field_index).unwrap()) |field_name| | |
| 5459 | break :blk .{ .field = if (container_ty.isSimpleTuple(mod)) | 5493 | .{ .identifier = ip.stringToSlice(field_name) } |
| 5460 | .{ .field = next_field_index } | ||
| 5461 | else | 5494 | else |
| 5462 | .{ .identifier = ip.stringToSlice(container_ty.legacyStructFieldName(next_field_index, mod)) } }; | 5495 | .{ .field = next_field_index } }; |
| 5463 | } | 5496 | } |
| 5464 | break :blk if (container_ty.hasRuntimeBitsIgnoreComptime(mod)) .end else .begin; | 5497 | return if (container_ty.hasRuntimeBitsIgnoreComptime(zcu)) .end else .begin; |
| 5465 | }, | 5498 | }, |
| 5466 | .Union => { | 5499 | .union_type => { |
| 5467 | const union_obj = mod.typeToUnion(container_ty).?; | 5500 | const loaded_union = ip.loadUnionType(container_ty.toIntern()); |
| 5468 | return switch (union_obj.getLayout(ip)) { | 5501 | switch (loaded_union.getLayout(ip)) { |
| 5469 | .auto, .@"extern" => { | 5502 | .auto, .@"extern" => { |
| 5470 | const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[field_index]); | 5503 | const field_ty = Type.fromInterned(loaded_union.field_types.get(ip)[field_index]); |
| 5471 | if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) | 5504 | if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) |
| 5472 | return if (container_ty.unionTagTypeSafety(mod) != null and | 5505 | return if (loaded_union.hasTag(ip) and !container_ty.unionHasAllZeroBitFieldTypes(zcu)) |
| 5473 | !container_ty.unionHasAllZeroBitFieldTypes(mod)) | ||
| 5474 | .{ .field = .{ .identifier = "payload" } } | 5506 | .{ .field = .{ .identifier = "payload" } } |
| 5475 | else | 5507 | else |
| 5476 | .begin; | 5508 | .begin; |
| 5477 | const field_name = union_obj.loadTagType(ip).names.get(ip)[field_index]; | 5509 | const field_name = loaded_union.loadTagType(ip).names.get(ip)[field_index]; |
| 5478 | return .{ .field = if (container_ty.unionTagTypeSafety(mod)) |_| | 5510 | return .{ .field = if (loaded_union.hasTag(ip)) |
| 5479 | .{ .payload_identifier = ip.stringToSlice(field_name) } | 5511 | .{ .payload_identifier = ip.stringToSlice(field_name) } |
| 5480 | else | 5512 | else |
| 5481 | .{ .identifier = ip.stringToSlice(field_name) } }; | 5513 | .{ .identifier = ip.stringToSlice(field_name) } }; |
| 5482 | }, | 5514 | }, |
| 5483 | .@"packed" => .begin, | 5515 | .@"packed" => return .begin, |
| 5484 | }; | 5516 | } |
| 5485 | }, | 5517 | }, |
| 5486 | .Pointer => switch (container_ty.ptrSize(mod)) { | 5518 | .ptr_type => |ptr_info| switch (ptr_info.flags.size) { |
| 5519 | .One, .Many, .C => unreachable, | ||
| 5487 | .Slice => switch (field_index) { | 5520 | .Slice => switch (field_index) { |
| 5488 | 0 => .{ .field = .{ .identifier = "ptr" } }, | 5521 | 0 => return .{ .field = .{ .identifier = "ptr" } }, |
| 5489 | 1 => .{ .field = .{ .identifier = "len" } }, | 5522 | 1 => return .{ .field = .{ .identifier = "len" } }, |
| 5490 | else => unreachable, | 5523 | else => unreachable, |
| 5491 | }, | 5524 | }, |
| 5492 | .One, .Many, .C => unreachable, | ||
| 5493 | }, | 5525 | }, |
| 5494 | else => unreachable, | 5526 | else => unreachable, |
| 5495 | }; | 5527 | } |
| 5496 | } | 5528 | } |
| 5497 | 5529 | ||
| 5498 | fn airStructFieldPtr(f: *Function, inst: Air.Inst.Index) !CValue { | 5530 | fn airStructFieldPtr(f: *Function, inst: Air.Inst.Index) !CValue { |
| ... | @@ -5515,12 +5547,12 @@ fn airStructFieldPtrIndex(f: *Function, inst: Air.Inst.Index, index: u8) !CValue | ... | @@ -5515,12 +5547,12 @@ fn airStructFieldPtrIndex(f: *Function, inst: Air.Inst.Index, index: u8) !CValue |
| 5515 | } | 5547 | } |
| 5516 | 5548 | ||
| 5517 | fn airFieldParentPtr(f: *Function, inst: Air.Inst.Index) !CValue { | 5549 | fn airFieldParentPtr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5518 | const mod = f.object.dg.module; | 5550 | const zcu = f.object.dg.zcu; |
| 5519 | const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; | 5551 | const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| 5520 | const extra = f.air.extraData(Air.FieldParentPtr, ty_pl.payload).data; | 5552 | const extra = f.air.extraData(Air.FieldParentPtr, ty_pl.payload).data; |
| 5521 | 5553 | ||
| 5522 | const container_ptr_ty = f.typeOfIndex(inst); | 5554 | const container_ptr_ty = f.typeOfIndex(inst); |
| 5523 | const container_ty = container_ptr_ty.childType(mod); | 5555 | const container_ty = container_ptr_ty.childType(zcu); |
| 5524 | 5556 | ||
| 5525 | const field_ptr_ty = f.typeOf(extra.field_ptr); | 5557 | const field_ptr_ty = f.typeOf(extra.field_ptr); |
| 5526 | const field_ptr_val = try f.resolveInst(extra.field_ptr); | 5558 | const field_ptr_val = try f.resolveInst(extra.field_ptr); |
| ... | @@ -5533,10 +5565,10 @@ fn airFieldParentPtr(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -5533,10 +5565,10 @@ fn airFieldParentPtr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5533 | try f.renderType(writer, container_ptr_ty); | 5565 | try f.renderType(writer, container_ptr_ty); |
| 5534 | try writer.writeByte(')'); | 5566 | try writer.writeByte(')'); |
| 5535 | 5567 | ||
| 5536 | switch (fieldLocation(container_ptr_ty, field_ptr_ty, extra.field_index, mod)) { | 5568 | switch (fieldLocation(container_ptr_ty, field_ptr_ty, extra.field_index, zcu)) { |
| 5537 | .begin => try f.writeCValue(writer, field_ptr_val, .Initializer), | 5569 | .begin => try f.writeCValue(writer, field_ptr_val, .Initializer), |
| 5538 | .field => |field| { | 5570 | .field => |field| { |
| 5539 | const u8_ptr_ty = try mod.adjustPtrTypeChild(field_ptr_ty, Type.u8); | 5571 | const u8_ptr_ty = try zcu.adjustPtrTypeChild(field_ptr_ty, Type.u8); |
| 5540 | 5572 | ||
| 5541 | try writer.writeAll("(("); | 5573 | try writer.writeAll("(("); |
| 5542 | try f.renderType(writer, u8_ptr_ty); | 5574 | try f.renderType(writer, u8_ptr_ty); |
| ... | @@ -5549,19 +5581,19 @@ fn airFieldParentPtr(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -5549,19 +5581,19 @@ fn airFieldParentPtr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5549 | try writer.writeAll("))"); | 5581 | try writer.writeAll("))"); |
| 5550 | }, | 5582 | }, |
| 5551 | .byte_offset => |byte_offset| { | 5583 | .byte_offset => |byte_offset| { |
| 5552 | const u8_ptr_ty = try mod.adjustPtrTypeChild(field_ptr_ty, Type.u8); | 5584 | const u8_ptr_ty = try zcu.adjustPtrTypeChild(field_ptr_ty, Type.u8); |
| 5553 | |||
| 5554 | const byte_offset_val = try mod.intValue(Type.usize, byte_offset); | ||
| 5555 | 5585 | ||
| 5556 | try writer.writeAll("(("); | 5586 | try writer.writeAll("(("); |
| 5557 | try f.renderType(writer, u8_ptr_ty); | 5587 | try f.renderType(writer, u8_ptr_ty); |
| 5558 | try writer.writeByte(')'); | 5588 | try writer.writeByte(')'); |
| 5559 | try f.writeCValue(writer, field_ptr_val, .Other); | 5589 | try f.writeCValue(writer, field_ptr_val, .Other); |
| 5560 | try writer.print(" - {})", .{try f.fmtIntLiteral(Type.usize, byte_offset_val)}); | 5590 | try writer.print(" - {})", .{ |
| 5591 | try f.fmtIntLiteral(try zcu.intValue(Type.usize, byte_offset)), | ||
| 5592 | }); | ||
| 5561 | }, | 5593 | }, |
| 5562 | .end => { | 5594 | .end => { |
| 5563 | try f.writeCValue(writer, field_ptr_val, .Other); | 5595 | try f.writeCValue(writer, field_ptr_val, .Other); |
| 5564 | try writer.print(" - {}", .{try f.fmtIntLiteral(Type.usize, try mod.intValue(Type.usize, 1))}); | 5596 | try writer.print(" - {}", .{try f.fmtIntLiteral(try zcu.intValue(Type.usize, 1))}); |
| 5565 | }, | 5597 | }, |
| 5566 | } | 5598 | } |
| 5567 | 5599 | ||
| ... | @@ -5576,12 +5608,12 @@ fn fieldPtr( | ... | @@ -5576,12 +5608,12 @@ fn fieldPtr( |
| 5576 | container_ptr_val: CValue, | 5608 | container_ptr_val: CValue, |
| 5577 | field_index: u32, | 5609 | field_index: u32, |
| 5578 | ) !CValue { | 5610 | ) !CValue { |
| 5579 | const mod = f.object.dg.module; | 5611 | const zcu = f.object.dg.zcu; |
| 5580 | const container_ty = container_ptr_ty.childType(mod); | 5612 | const container_ty = container_ptr_ty.childType(zcu); |
| 5581 | const field_ptr_ty = f.typeOfIndex(inst); | 5613 | const field_ptr_ty = f.typeOfIndex(inst); |
| 5582 | 5614 | ||
| 5583 | // Ensure complete type definition is visible before accessing fields. | 5615 | // Ensure complete type definition is visible before accessing fields. |
| 5584 | _ = try f.typeToIndex(container_ty, .complete); | 5616 | _ = try f.ctypeFromType(container_ty, .complete); |
| 5585 | 5617 | ||
| 5586 | const writer = f.object.writer(); | 5618 | const writer = f.object.writer(); |
| 5587 | const local = try f.allocLocal(inst, field_ptr_ty); | 5619 | const local = try f.allocLocal(inst, field_ptr_ty); |
| ... | @@ -5590,27 +5622,27 @@ fn fieldPtr( | ... | @@ -5590,27 +5622,27 @@ fn fieldPtr( |
| 5590 | try f.renderType(writer, field_ptr_ty); | 5622 | try f.renderType(writer, field_ptr_ty); |
| 5591 | try writer.writeByte(')'); | 5623 | try writer.writeByte(')'); |
| 5592 | 5624 | ||
| 5593 | switch (fieldLocation(container_ptr_ty, field_ptr_ty, field_index, mod)) { | 5625 | switch (fieldLocation(container_ptr_ty, field_ptr_ty, field_index, zcu)) { |
| 5594 | .begin => try f.writeCValue(writer, container_ptr_val, .Initializer), | 5626 | .begin => try f.writeCValue(writer, container_ptr_val, .Initializer), |
| 5595 | .field => |field| { | 5627 | .field => |field| { |
| 5596 | try writer.writeByte('&'); | 5628 | try writer.writeByte('&'); |
| 5597 | try f.writeCValueDerefMember(writer, container_ptr_val, field); | 5629 | try f.writeCValueDerefMember(writer, container_ptr_val, field); |
| 5598 | }, | 5630 | }, |
| 5599 | .byte_offset => |byte_offset| { | 5631 | .byte_offset => |byte_offset| { |
| 5600 | const u8_ptr_ty = try mod.adjustPtrTypeChild(field_ptr_ty, Type.u8); | 5632 | const u8_ptr_ty = try zcu.adjustPtrTypeChild(field_ptr_ty, Type.u8); |
| 5601 | |||
| 5602 | const byte_offset_val = try mod.intValue(Type.usize, byte_offset); | ||
| 5603 | 5633 | ||
| 5604 | try writer.writeAll("(("); | 5634 | try writer.writeAll("(("); |
| 5605 | try f.renderType(writer, u8_ptr_ty); | 5635 | try f.renderType(writer, u8_ptr_ty); |
| 5606 | try writer.writeByte(')'); | 5636 | try writer.writeByte(')'); |
| 5607 | try f.writeCValue(writer, container_ptr_val, .Other); | 5637 | try f.writeCValue(writer, container_ptr_val, .Other); |
| 5608 | try writer.print(" + {})", .{try f.fmtIntLiteral(Type.usize, byte_offset_val)}); | 5638 | try writer.print(" + {})", .{ |
| 5639 | try f.fmtIntLiteral(try zcu.intValue(Type.usize, byte_offset)), | ||
| 5640 | }); | ||
| 5609 | }, | 5641 | }, |
| 5610 | .end => { | 5642 | .end => { |
| 5611 | try writer.writeByte('('); | 5643 | try writer.writeByte('('); |
| 5612 | try f.writeCValue(writer, container_ptr_val, .Other); | 5644 | try f.writeCValue(writer, container_ptr_val, .Other); |
| 5613 | try writer.print(" + {})", .{try f.fmtIntLiteral(Type.usize, try mod.intValue(Type.usize, 1))}); | 5645 | try writer.print(" + {})", .{try f.fmtIntLiteral(try zcu.intValue(Type.usize, 1))}); |
| 5614 | }, | 5646 | }, |
| 5615 | } | 5647 | } |
| 5616 | 5648 | ||
| ... | @@ -5619,13 +5651,13 @@ fn fieldPtr( | ... | @@ -5619,13 +5651,13 @@ fn fieldPtr( |
| 5619 | } | 5651 | } |
| 5620 | 5652 | ||
| 5621 | fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue { | 5653 | fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5622 | const mod = f.object.dg.module; | 5654 | const zcu = f.object.dg.zcu; |
| 5623 | const ip = &mod.intern_pool; | 5655 | const ip = &zcu.intern_pool; |
| 5624 | const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; | 5656 | const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| 5625 | const extra = f.air.extraData(Air.StructField, ty_pl.payload).data; | 5657 | const extra = f.air.extraData(Air.StructField, ty_pl.payload).data; |
| 5626 | 5658 | ||
| 5627 | const inst_ty = f.typeOfIndex(inst); | 5659 | const inst_ty = f.typeOfIndex(inst); |
| 5628 | if (!inst_ty.hasRuntimeBitsIgnoreComptime(mod)) { | 5660 | if (!inst_ty.hasRuntimeBitsIgnoreComptime(zcu)) { |
| 5629 | try reap(f, inst, &.{extra.struct_operand}); | 5661 | try reap(f, inst, &.{extra.struct_operand}); |
| 5630 | return .none; | 5662 | return .none; |
| 5631 | } | 5663 | } |
| ... | @@ -5636,110 +5668,109 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -5636,110 +5668,109 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5636 | const writer = f.object.writer(); | 5668 | const writer = f.object.writer(); |
| 5637 | 5669 | ||
| 5638 | // Ensure complete type definition is visible before accessing fields. | 5670 | // Ensure complete type definition is visible before accessing fields. |
| 5639 | _ = try f.typeToIndex(struct_ty, .complete); | 5671 | _ = try f.ctypeFromType(struct_ty, .complete); |
| 5672 | |||
| 5673 | const field_name: CValue = switch (ip.indexToKey(struct_ty.toIntern())) { | ||
| 5674 | .struct_type => field_name: { | ||
| 5675 | const loaded_struct = ip.loadStructType(struct_ty.toIntern()); | ||
| 5676 | switch (loaded_struct.layout) { | ||
| 5677 | .auto, .@"extern" => break :field_name if (loaded_struct.fieldName(ip, extra.field_index).unwrap()) |field_name| | ||
| 5678 | .{ .identifier = ip.stringToSlice(field_name) } | ||
| 5679 | else | ||
| 5680 | .{ .field = extra.field_index }, | ||
| 5681 | .@"packed" => { | ||
| 5682 | const int_info = struct_ty.intInfo(zcu); | ||
| 5640 | 5683 | ||
| 5641 | const field_name: CValue = switch (mod.intern_pool.indexToKey(struct_ty.ip_index)) { | 5684 | const bit_offset_ty = try zcu.intType(.unsigned, Type.smallestUnsignedBits(int_info.bits - 1)); |
| 5642 | .struct_type => switch (struct_ty.containerLayout(mod)) { | ||
| 5643 | .auto, .@"extern" => if (struct_ty.isSimpleTuple(mod)) | ||
| 5644 | .{ .field = extra.field_index } | ||
| 5645 | else | ||
| 5646 | .{ .identifier = ip.stringToSlice(struct_ty.legacyStructFieldName(extra.field_index, mod)) }, | ||
| 5647 | .@"packed" => { | ||
| 5648 | const struct_type = mod.typeToStruct(struct_ty).?; | ||
| 5649 | const int_info = struct_ty.intInfo(mod); | ||
| 5650 | 5685 | ||
| 5651 | const bit_offset_ty = try mod.intType(.unsigned, Type.smallestUnsignedBits(int_info.bits - 1)); | 5686 | const bit_offset = zcu.structPackedFieldBitOffset(loaded_struct, extra.field_index); |
| 5652 | 5687 | ||
| 5653 | const bit_offset = mod.structPackedFieldBitOffset(struct_type, extra.field_index); | 5688 | const field_int_signedness = if (inst_ty.isAbiInt(zcu)) |
| 5654 | const bit_offset_val = try mod.intValue(bit_offset_ty, bit_offset); | 5689 | inst_ty.intInfo(zcu).signedness |
| 5690 | else | ||
| 5691 | .unsigned; | ||
| 5692 | const field_int_ty = try zcu.intType(field_int_signedness, @as(u16, @intCast(inst_ty.bitSize(zcu)))); | ||
| 5655 | 5693 | ||
| 5656 | const field_int_signedness = if (inst_ty.isAbiInt(mod)) | 5694 | const temp_local = try f.allocLocal(inst, field_int_ty); |
| 5657 | inst_ty.intInfo(mod).signedness | 5695 | try f.writeCValue(writer, temp_local, .Other); |
| 5658 | else | 5696 | try writer.writeAll(" = zig_wrap_"); |
| 5659 | .unsigned; | 5697 | try f.object.dg.renderTypeForBuiltinFnName(writer, field_int_ty); |
| 5660 | const field_int_ty = try mod.intType(field_int_signedness, @as(u16, @intCast(inst_ty.bitSize(mod)))); | 5698 | try writer.writeAll("(("); |
| 5661 | 5699 | try f.renderType(writer, field_int_ty); | |
| 5662 | const temp_local = try f.allocLocal(inst, field_int_ty); | ||
| 5663 | try f.writeCValue(writer, temp_local, .Other); | ||
| 5664 | try writer.writeAll(" = zig_wrap_"); | ||
| 5665 | try f.object.dg.renderTypeForBuiltinFnName(writer, field_int_ty); | ||
| 5666 | try writer.writeAll("(("); | ||
| 5667 | try f.renderType(writer, field_int_ty); | ||
| 5668 | try writer.writeByte(')'); | ||
| 5669 | const cant_cast = int_info.bits > 64; | ||
| 5670 | if (cant_cast) { | ||
| 5671 | if (field_int_ty.bitSize(mod) > 64) return f.fail("TODO: C backend: implement casting between types > 64 bits", .{}); | ||
| 5672 | try writer.writeAll("zig_lo_"); | ||
| 5673 | try f.object.dg.renderTypeForBuiltinFnName(writer, struct_ty); | ||
| 5674 | try writer.writeByte('('); | ||
| 5675 | } | ||
| 5676 | if (bit_offset > 0) { | ||
| 5677 | try writer.writeAll("zig_shr_"); | ||
| 5678 | try f.object.dg.renderTypeForBuiltinFnName(writer, struct_ty); | ||
| 5679 | try writer.writeByte('('); | ||
| 5680 | } | ||
| 5681 | try f.writeCValue(writer, struct_byval, .Other); | ||
| 5682 | if (bit_offset > 0) { | ||
| 5683 | try writer.writeAll(", "); | ||
| 5684 | try f.object.dg.renderValue(writer, bit_offset_ty, bit_offset_val, .FunctionArgument); | ||
| 5685 | try writer.writeByte(')'); | 5700 | try writer.writeByte(')'); |
| 5686 | } | 5701 | const cant_cast = int_info.bits > 64; |
| 5687 | if (cant_cast) try writer.writeByte(')'); | 5702 | if (cant_cast) { |
| 5688 | try f.object.dg.renderBuiltinInfo(writer, field_int_ty, .bits); | 5703 | if (field_int_ty.bitSize(zcu) > 64) return f.fail("TODO: C backend: implement casting between types > 64 bits", .{}); |
| 5689 | try writer.writeAll(");\n"); | 5704 | try writer.writeAll("zig_lo_"); |
| 5690 | if (inst_ty.eql(field_int_ty, f.object.dg.module)) return temp_local; | 5705 | try f.object.dg.renderTypeForBuiltinFnName(writer, struct_ty); |
| 5691 | 5706 | try writer.writeByte('('); | |
| 5692 | const local = try f.allocLocal(inst, inst_ty); | 5707 | } |
| 5693 | try writer.writeAll("memcpy("); | 5708 | if (bit_offset > 0) { |
| 5694 | try f.writeCValue(writer, .{ .local_ref = local.new_local }, .FunctionArgument); | 5709 | try writer.writeAll("zig_shr_"); |
| 5695 | try writer.writeAll(", "); | 5710 | try f.object.dg.renderTypeForBuiltinFnName(writer, struct_ty); |
| 5696 | try f.writeCValue(writer, .{ .local_ref = temp_local.new_local }, .FunctionArgument); | 5711 | try writer.writeByte('('); |
| 5697 | try writer.writeAll(", sizeof("); | 5712 | } |
| 5698 | try f.renderType(writer, inst_ty); | 5713 | try f.writeCValue(writer, struct_byval, .Other); |
| 5699 | try writer.writeAll("));\n"); | 5714 | if (bit_offset > 0) try writer.print(", {})", .{ |
| 5700 | try freeLocal(f, inst, temp_local.new_local, null); | 5715 | try f.fmtIntLiteral(try zcu.intValue(bit_offset_ty, bit_offset)), |
| 5701 | return local; | 5716 | }); |
| 5702 | }, | 5717 | if (cant_cast) try writer.writeByte(')'); |
| 5703 | }, | 5718 | try f.object.dg.renderBuiltinInfo(writer, field_int_ty, .bits); |
| 5719 | try writer.writeAll(");\n"); | ||
| 5720 | if (inst_ty.eql(field_int_ty, f.object.dg.zcu)) return temp_local; | ||
| 5704 | 5721 | ||
| 5705 | .anon_struct_type => |anon_struct_type| if (anon_struct_type.names.len == 0) | 5722 | const local = try f.allocLocal(inst, inst_ty); |
| 5706 | .{ .field = extra.field_index } | 5723 | try writer.writeAll("memcpy("); |
| 5724 | try f.writeCValue(writer, .{ .local_ref = local.new_local }, .FunctionArgument); | ||
| 5725 | try writer.writeAll(", "); | ||
| 5726 | try f.writeCValue(writer, .{ .local_ref = temp_local.new_local }, .FunctionArgument); | ||
| 5727 | try writer.writeAll(", sizeof("); | ||
| 5728 | try f.renderType(writer, inst_ty); | ||
| 5729 | try writer.writeAll("));\n"); | ||
| 5730 | try freeLocal(f, inst, temp_local.new_local, null); | ||
| 5731 | return local; | ||
| 5732 | }, | ||
| 5733 | } | ||
| 5734 | }, | ||
| 5735 | .anon_struct_type => |anon_struct_info| if (anon_struct_info.fieldName(ip, extra.field_index).unwrap()) |field_name| | ||
| 5736 | .{ .identifier = ip.stringToSlice(field_name) } | ||
| 5707 | else | 5737 | else |
| 5708 | .{ .identifier = ip.stringToSlice(struct_ty.legacyStructFieldName(extra.field_index, mod)) }, | 5738 | .{ .field = extra.field_index }, |
| 5709 | |||
| 5710 | .union_type => field_name: { | 5739 | .union_type => field_name: { |
| 5711 | const union_obj = ip.loadUnionType(struct_ty.toIntern()); | 5740 | const loaded_union = ip.loadUnionType(struct_ty.toIntern()); |
| 5712 | if (union_obj.flagsPtr(ip).layout == .@"packed") { | 5741 | switch (loaded_union.getLayout(ip)) { |
| 5713 | const operand_lval = if (struct_byval == .constant) blk: { | 5742 | .auto, .@"extern" => { |
| 5714 | const operand_local = try f.allocLocal(inst, struct_ty); | 5743 | const name = loaded_union.loadTagType(ip).names.get(ip)[extra.field_index]; |
| 5715 | try f.writeCValue(writer, operand_local, .Other); | 5744 | break :field_name if (loaded_union.hasTag(ip)) |
| 5716 | try writer.writeAll(" = "); | 5745 | .{ .payload_identifier = ip.stringToSlice(name) } |
| 5717 | try f.writeCValue(writer, struct_byval, .Initializer); | 5746 | else |
| 5718 | try writer.writeAll(";\n"); | 5747 | .{ .identifier = ip.stringToSlice(name) }; |
| 5719 | break :blk operand_local; | 5748 | }, |
| 5720 | } else struct_byval; | 5749 | .@"packed" => { |
| 5721 | 5750 | const operand_lval = if (struct_byval == .constant) blk: { | |
| 5722 | const local = try f.allocLocal(inst, inst_ty); | 5751 | const operand_local = try f.allocLocal(inst, struct_ty); |
| 5723 | try writer.writeAll("memcpy(&"); | 5752 | try f.writeCValue(writer, operand_local, .Other); |
| 5724 | try f.writeCValue(writer, local, .Other); | 5753 | try writer.writeAll(" = "); |
| 5725 | try writer.writeAll(", &"); | 5754 | try f.writeCValue(writer, struct_byval, .Initializer); |
| 5726 | try f.writeCValue(writer, operand_lval, .Other); | 5755 | try writer.writeAll(";\n"); |
| 5727 | try writer.writeAll(", sizeof("); | 5756 | break :blk operand_local; |
| 5728 | try f.renderType(writer, inst_ty); | 5757 | } else struct_byval; |
| 5729 | try writer.writeAll("));\n"); | 5758 | |
| 5730 | 5759 | const local = try f.allocLocal(inst, inst_ty); | |
| 5731 | if (struct_byval == .constant) { | 5760 | try writer.writeAll("memcpy(&"); |
| 5732 | try freeLocal(f, inst, operand_lval.new_local, null); | 5761 | try f.writeCValue(writer, local, .Other); |
| 5733 | } | 5762 | try writer.writeAll(", &"); |
| 5763 | try f.writeCValue(writer, operand_lval, .Other); | ||
| 5764 | try writer.writeAll(", sizeof("); | ||
| 5765 | try f.renderType(writer, inst_ty); | ||
| 5766 | try writer.writeAll("));\n"); | ||
| 5767 | |||
| 5768 | if (struct_byval == .constant) { | ||
| 5769 | try freeLocal(f, inst, operand_lval.new_local, null); | ||
| 5770 | } | ||
| 5734 | 5771 | ||
| 5735 | return local; | 5772 | return local; |
| 5736 | } else { | 5773 | }, |
| 5737 | const name = union_obj.loadTagType(ip).names.get(ip)[extra.field_index]; | ||
| 5738 | break :field_name if (union_obj.hasTag(ip)) .{ | ||
| 5739 | .payload_identifier = ip.stringToSlice(name), | ||
| 5740 | } else .{ | ||
| 5741 | .identifier = ip.stringToSlice(name), | ||
| 5742 | }; | ||
| 5743 | } | 5774 | } |
| 5744 | }, | 5775 | }, |
| 5745 | else => unreachable, | 5776 | else => unreachable, |
| ... | @@ -5757,7 +5788,7 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -5757,7 +5788,7 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5757 | /// *(E!T) -> E | 5788 | /// *(E!T) -> E |
| 5758 | /// Note that the result is never a pointer. | 5789 | /// Note that the result is never a pointer. |
| 5759 | fn airUnwrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue { | 5790 | fn airUnwrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5760 | const mod = f.object.dg.module; | 5791 | const zcu = f.object.dg.zcu; |
| 5761 | const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; | 5792 | const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 5762 | 5793 | ||
| 5763 | const inst_ty = f.typeOfIndex(inst); | 5794 | const inst_ty = f.typeOfIndex(inst); |
| ... | @@ -5765,13 +5796,13 @@ fn airUnwrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -5765,13 +5796,13 @@ fn airUnwrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5765 | const operand_ty = f.typeOf(ty_op.operand); | 5796 | const operand_ty = f.typeOf(ty_op.operand); |
| 5766 | try reap(f, inst, &.{ty_op.operand}); | 5797 | try reap(f, inst, &.{ty_op.operand}); |
| 5767 | 5798 | ||
| 5768 | const operand_is_ptr = operand_ty.zigTypeTag(mod) == .Pointer; | 5799 | const operand_is_ptr = operand_ty.zigTypeTag(zcu) == .Pointer; |
| 5769 | const error_union_ty = if (operand_is_ptr) operand_ty.childType(mod) else operand_ty; | 5800 | const error_union_ty = if (operand_is_ptr) operand_ty.childType(zcu) else operand_ty; |
| 5770 | const error_ty = error_union_ty.errorUnionSet(mod); | 5801 | const error_ty = error_union_ty.errorUnionSet(zcu); |
| 5771 | const payload_ty = error_union_ty.errorUnionPayload(mod); | 5802 | const payload_ty = error_union_ty.errorUnionPayload(zcu); |
| 5772 | const local = try f.allocLocal(inst, inst_ty); | 5803 | const local = try f.allocLocal(inst, inst_ty); |
| 5773 | 5804 | ||
| 5774 | if (!payload_ty.hasRuntimeBits(mod) and operand == .local and operand.local == local.new_local) { | 5805 | if (!payload_ty.hasRuntimeBits(zcu) and operand == .local and operand.local == local.new_local) { |
| 5775 | // The store will be 'x = x'; elide it. | 5806 | // The store will be 'x = x'; elide it. |
| 5776 | return local; | 5807 | return local; |
| 5777 | } | 5808 | } |
| ... | @@ -5780,35 +5811,32 @@ fn airUnwrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -5780,35 +5811,32 @@ fn airUnwrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5780 | try f.writeCValue(writer, local, .Other); | 5811 | try f.writeCValue(writer, local, .Other); |
| 5781 | try writer.writeAll(" = "); | 5812 | try writer.writeAll(" = "); |
| 5782 | 5813 | ||
| 5783 | if (!payload_ty.hasRuntimeBits(mod)) { | 5814 | if (!payload_ty.hasRuntimeBits(zcu)) |
| 5784 | try f.writeCValue(writer, operand, .Other); | 5815 | try f.writeCValue(writer, operand, .Other) |
| 5785 | } else { | 5816 | else if (error_ty.errorSetIsEmpty(zcu)) |
| 5786 | if (!error_ty.errorSetIsEmpty(mod)) | 5817 | try writer.print("{}", .{ |
| 5787 | if (operand_is_ptr) | 5818 | try f.fmtIntLiteral(try zcu.intValue(try zcu.errorIntType(), 0)), |
| 5788 | try f.writeCValueDerefMember(writer, operand, .{ .identifier = "error" }) | 5819 | }) |
| 5789 | else | 5820 | else if (operand_is_ptr) |
| 5790 | try f.writeCValueMember(writer, operand, .{ .identifier = "error" }) | 5821 | try f.writeCValueDerefMember(writer, operand, .{ .identifier = "error" }) |
| 5791 | else { | 5822 | else |
| 5792 | const err_int_ty = try mod.errorIntType(); | 5823 | try f.writeCValueMember(writer, operand, .{ .identifier = "error" }); |
| 5793 | try f.object.dg.renderValue(writer, err_int_ty, try mod.intValue(err_int_ty, 0), .Initializer); | ||
| 5794 | } | ||
| 5795 | } | ||
| 5796 | try writer.writeAll(";\n"); | 5824 | try writer.writeAll(";\n"); |
| 5797 | return local; | 5825 | return local; |
| 5798 | } | 5826 | } |
| 5799 | 5827 | ||
| 5800 | fn airUnwrapErrUnionPay(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValue { | 5828 | fn airUnwrapErrUnionPay(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValue { |
| 5801 | const mod = f.object.dg.module; | 5829 | const zcu = f.object.dg.zcu; |
| 5802 | const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; | 5830 | const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 5803 | 5831 | ||
| 5804 | const inst_ty = f.typeOfIndex(inst); | 5832 | const inst_ty = f.typeOfIndex(inst); |
| 5805 | const operand = try f.resolveInst(ty_op.operand); | 5833 | const operand = try f.resolveInst(ty_op.operand); |
| 5806 | try reap(f, inst, &.{ty_op.operand}); | 5834 | try reap(f, inst, &.{ty_op.operand}); |
| 5807 | const operand_ty = f.typeOf(ty_op.operand); | 5835 | const operand_ty = f.typeOf(ty_op.operand); |
| 5808 | const error_union_ty = if (is_ptr) operand_ty.childType(mod) else operand_ty; | 5836 | const error_union_ty = if (is_ptr) operand_ty.childType(zcu) else operand_ty; |
| 5809 | 5837 | ||
| 5810 | const writer = f.object.writer(); | 5838 | const writer = f.object.writer(); |
| 5811 | if (!error_union_ty.errorUnionPayload(mod).hasRuntimeBits(mod)) { | 5839 | if (!error_union_ty.errorUnionPayload(zcu).hasRuntimeBits(zcu)) { |
| 5812 | if (!is_ptr) return .none; | 5840 | if (!is_ptr) return .none; |
| 5813 | 5841 | ||
| 5814 | const local = try f.allocLocal(inst, inst_ty); | 5842 | const local = try f.allocLocal(inst, inst_ty); |
| ... | @@ -5834,11 +5862,11 @@ fn airUnwrapErrUnionPay(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValu | ... | @@ -5834,11 +5862,11 @@ fn airUnwrapErrUnionPay(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValu |
| 5834 | } | 5862 | } |
| 5835 | 5863 | ||
| 5836 | fn airWrapOptional(f: *Function, inst: Air.Inst.Index) !CValue { | 5864 | fn airWrapOptional(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5837 | const mod = f.object.dg.module; | 5865 | const zcu = f.object.dg.zcu; |
| 5838 | const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; | 5866 | const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 5839 | 5867 | ||
| 5840 | const inst_ty = f.typeOfIndex(inst); | 5868 | const inst_ty = f.typeOfIndex(inst); |
| 5841 | const repr_is_payload = inst_ty.optionalReprIsPayload(mod); | 5869 | const repr_is_payload = inst_ty.optionalReprIsPayload(zcu); |
| 5842 | const payload_ty = f.typeOf(ty_op.operand); | 5870 | const payload_ty = f.typeOf(ty_op.operand); |
| 5843 | const payload = try f.resolveInst(ty_op.operand); | 5871 | const payload = try f.resolveInst(ty_op.operand); |
| 5844 | try reap(f, inst, &.{ty_op.operand}); | 5872 | try reap(f, inst, &.{ty_op.operand}); |
| ... | @@ -5859,20 +5887,20 @@ fn airWrapOptional(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -5859,20 +5887,20 @@ fn airWrapOptional(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5859 | const a = try Assignment.start(f, writer, Type.bool); | 5887 | const a = try Assignment.start(f, writer, Type.bool); |
| 5860 | try f.writeCValueMember(writer, local, .{ .identifier = "is_null" }); | 5888 | try f.writeCValueMember(writer, local, .{ .identifier = "is_null" }); |
| 5861 | try a.assign(f, writer); | 5889 | try a.assign(f, writer); |
| 5862 | try f.object.dg.renderValue(writer, Type.bool, Value.false, .Other); | 5890 | try f.object.dg.renderValue(writer, Value.false, .Other); |
| 5863 | try a.end(f, writer); | 5891 | try a.end(f, writer); |
| 5864 | } | 5892 | } |
| 5865 | return local; | 5893 | return local; |
| 5866 | } | 5894 | } |
| 5867 | 5895 | ||
| 5868 | fn airWrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue { | 5896 | fn airWrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5869 | const mod = f.object.dg.module; | 5897 | const zcu = f.object.dg.zcu; |
| 5870 | const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; | 5898 | const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 5871 | 5899 | ||
| 5872 | const inst_ty = f.typeOfIndex(inst); | 5900 | const inst_ty = f.typeOfIndex(inst); |
| 5873 | const payload_ty = inst_ty.errorUnionPayload(mod); | 5901 | const payload_ty = inst_ty.errorUnionPayload(zcu); |
| 5874 | const repr_is_err = !payload_ty.hasRuntimeBitsIgnoreComptime(mod); | 5902 | const repr_is_err = !payload_ty.hasRuntimeBitsIgnoreComptime(zcu); |
| 5875 | const err_ty = inst_ty.errorUnionSet(mod); | 5903 | const err_ty = inst_ty.errorUnionSet(zcu); |
| 5876 | const err = try f.resolveInst(ty_op.operand); | 5904 | const err = try f.resolveInst(ty_op.operand); |
| 5877 | try reap(f, inst, &.{ty_op.operand}); | 5905 | try reap(f, inst, &.{ty_op.operand}); |
| 5878 | 5906 | ||
| ... | @@ -5888,7 +5916,7 @@ fn airWrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -5888,7 +5916,7 @@ fn airWrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5888 | const a = try Assignment.start(f, writer, payload_ty); | 5916 | const a = try Assignment.start(f, writer, payload_ty); |
| 5889 | try f.writeCValueMember(writer, local, .{ .identifier = "payload" }); | 5917 | try f.writeCValueMember(writer, local, .{ .identifier = "payload" }); |
| 5890 | try a.assign(f, writer); | 5918 | try a.assign(f, writer); |
| 5891 | try f.object.dg.renderValue(writer, payload_ty, Value.undef, .Other); | 5919 | try f.object.dg.renderUndefValue(writer, payload_ty, .Other); |
| 5892 | try a.end(f, writer); | 5920 | try a.end(f, writer); |
| 5893 | } | 5921 | } |
| 5894 | { | 5922 | { |
| ... | @@ -5905,29 +5933,25 @@ fn airWrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -5905,29 +5933,25 @@ fn airWrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5905 | } | 5933 | } |
| 5906 | 5934 | ||
| 5907 | fn airErrUnionPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue { | 5935 | fn airErrUnionPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5908 | const mod = f.object.dg.module; | 5936 | const zcu = f.object.dg.zcu; |
| 5909 | const writer = f.object.writer(); | 5937 | const writer = f.object.writer(); |
| 5910 | const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; | 5938 | const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 5911 | const operand = try f.resolveInst(ty_op.operand); | 5939 | const operand = try f.resolveInst(ty_op.operand); |
| 5912 | const error_union_ty = f.typeOf(ty_op.operand).childType(mod); | 5940 | const error_union_ty = f.typeOf(ty_op.operand).childType(zcu); |
| 5913 | 5941 | ||
| 5914 | const payload_ty = error_union_ty.errorUnionPayload(mod); | 5942 | const payload_ty = error_union_ty.errorUnionPayload(zcu); |
| 5915 | const err_int_ty = try mod.errorIntType(); | 5943 | const err_int_ty = try zcu.errorIntType(); |
| 5944 | const no_err = try zcu.intValue(err_int_ty, 0); | ||
| 5916 | 5945 | ||
| 5917 | // First, set the non-error value. | 5946 | // First, set the non-error value. |
| 5918 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) { | 5947 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { |
| 5919 | try f.writeCValueDeref(writer, operand); | 5948 | try f.writeCValueDeref(writer, operand); |
| 5920 | try writer.writeAll(" = "); | 5949 | try writer.print(" = {};\n", .{try f.fmtIntLiteral(no_err)}); |
| 5921 | try f.object.dg.renderValue(writer, err_int_ty, try mod.intValue(err_int_ty, 0), .Other); | ||
| 5922 | try writer.writeAll(";\n "); | ||
| 5923 | |||
| 5924 | return operand; | 5950 | return operand; |
| 5925 | } | 5951 | } |
| 5926 | try reap(f, inst, &.{ty_op.operand}); | 5952 | try reap(f, inst, &.{ty_op.operand}); |
| 5927 | try f.writeCValueDeref(writer, operand); | 5953 | try f.writeCValueDeref(writer, operand); |
| 5928 | try writer.writeAll(".error = "); | 5954 | try writer.print(".error = {};\n", .{try f.fmtIntLiteral(no_err)}); |
| 5929 | try f.object.dg.renderValue(writer, err_int_ty, try mod.intValue(err_int_ty, 0), .Other); | ||
| 5930 | try writer.writeAll(";\n"); | ||
| 5931 | 5955 | ||
| 5932 | // Then return the payload pointer (only if it is used) | 5956 | // Then return the payload pointer (only if it is used) |
| 5933 | if (f.liveness.isUnused(inst)) return .none; | 5957 | if (f.liveness.isUnused(inst)) return .none; |
| ... | @@ -5956,14 +5980,14 @@ fn airSaveErrReturnTraceIndex(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -5956,14 +5980,14 @@ fn airSaveErrReturnTraceIndex(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5956 | } | 5980 | } |
| 5957 | 5981 | ||
| 5958 | fn airWrapErrUnionPay(f: *Function, inst: Air.Inst.Index) !CValue { | 5982 | fn airWrapErrUnionPay(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5959 | const mod = f.object.dg.module; | 5983 | const zcu = f.object.dg.zcu; |
| 5960 | const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; | 5984 | const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 5961 | 5985 | ||
| 5962 | const inst_ty = f.typeOfIndex(inst); | 5986 | const inst_ty = f.typeOfIndex(inst); |
| 5963 | const payload_ty = inst_ty.errorUnionPayload(mod); | 5987 | const payload_ty = inst_ty.errorUnionPayload(zcu); |
| 5964 | const payload = try f.resolveInst(ty_op.operand); | 5988 | const payload = try f.resolveInst(ty_op.operand); |
| 5965 | const repr_is_err = !payload_ty.hasRuntimeBitsIgnoreComptime(mod); | 5989 | const repr_is_err = !payload_ty.hasRuntimeBitsIgnoreComptime(zcu); |
| 5966 | const err_ty = inst_ty.errorUnionSet(mod); | 5990 | const err_ty = inst_ty.errorUnionSet(zcu); |
| 5967 | try reap(f, inst, &.{ty_op.operand}); | 5991 | try reap(f, inst, &.{ty_op.operand}); |
| 5968 | 5992 | ||
| 5969 | const writer = f.object.writer(); | 5993 | const writer = f.object.writer(); |
| ... | @@ -5982,15 +6006,14 @@ fn airWrapErrUnionPay(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -5982,15 +6006,14 @@ fn airWrapErrUnionPay(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5982 | else | 6006 | else |
| 5983 | try f.writeCValueMember(writer, local, .{ .identifier = "error" }); | 6007 | try f.writeCValueMember(writer, local, .{ .identifier = "error" }); |
| 5984 | try a.assign(f, writer); | 6008 | try a.assign(f, writer); |
| 5985 | const err_int_ty = try mod.errorIntType(); | 6009 | try f.object.dg.renderValue(writer, try zcu.intValue(try zcu.errorIntType(), 0), .Other); |
| 5986 | try f.object.dg.renderValue(writer, err_int_ty, try mod.intValue(err_int_ty, 0), .Other); | ||
| 5987 | try a.end(f, writer); | 6010 | try a.end(f, writer); |
| 5988 | } | 6011 | } |
| 5989 | return local; | 6012 | return local; |
| 5990 | } | 6013 | } |
| 5991 | 6014 | ||
| 5992 | fn airIsErr(f: *Function, inst: Air.Inst.Index, is_ptr: bool, operator: []const u8) !CValue { | 6015 | fn airIsErr(f: *Function, inst: Air.Inst.Index, is_ptr: bool, operator: []const u8) !CValue { |
| 5993 | const mod = f.object.dg.module; | 6016 | const zcu = f.object.dg.zcu; |
| 5994 | const un_op = f.air.instructions.items(.data)[@intFromEnum(inst)].un_op; | 6017 | const un_op = f.air.instructions.items(.data)[@intFromEnum(inst)].un_op; |
| 5995 | 6018 | ||
| 5996 | const writer = f.object.writer(); | 6019 | const writer = f.object.writer(); |
| ... | @@ -5998,16 +6021,16 @@ fn airIsErr(f: *Function, inst: Air.Inst.Index, is_ptr: bool, operator: []const | ... | @@ -5998,16 +6021,16 @@ fn airIsErr(f: *Function, inst: Air.Inst.Index, is_ptr: bool, operator: []const |
| 5998 | try reap(f, inst, &.{un_op}); | 6021 | try reap(f, inst, &.{un_op}); |
| 5999 | const operand_ty = f.typeOf(un_op); | 6022 | const operand_ty = f.typeOf(un_op); |
| 6000 | const local = try f.allocLocal(inst, Type.bool); | 6023 | const local = try f.allocLocal(inst, Type.bool); |
| 6001 | const err_union_ty = if (is_ptr) operand_ty.childType(mod) else operand_ty; | 6024 | const err_union_ty = if (is_ptr) operand_ty.childType(zcu) else operand_ty; |
| 6002 | const payload_ty = err_union_ty.errorUnionPayload(mod); | 6025 | const payload_ty = err_union_ty.errorUnionPayload(zcu); |
| 6003 | const error_ty = err_union_ty.errorUnionSet(mod); | 6026 | const error_ty = err_union_ty.errorUnionSet(zcu); |
| 6004 | 6027 | ||
| 6028 | const a = try Assignment.start(f, writer, Type.bool); | ||
| 6005 | try f.writeCValue(writer, local, .Other); | 6029 | try f.writeCValue(writer, local, .Other); |
| 6006 | try writer.writeAll(" = "); | 6030 | try a.assign(f, writer); |
| 6007 | 6031 | const err_int_ty = try zcu.errorIntType(); | |
| 6008 | const err_int_ty = try mod.errorIntType(); | 6032 | if (!error_ty.errorSetIsEmpty(zcu)) |
| 6009 | if (!error_ty.errorSetIsEmpty(mod)) | 6033 | if (payload_ty.hasRuntimeBits(zcu)) |
| 6010 | if (payload_ty.hasRuntimeBits(mod)) | ||
| 6011 | if (is_ptr) | 6034 | if (is_ptr) |
| 6012 | try f.writeCValueDerefMember(writer, operand, .{ .identifier = "error" }) | 6035 | try f.writeCValueDerefMember(writer, operand, .{ .identifier = "error" }) |
| 6013 | else | 6036 | else |
| ... | @@ -6015,63 +6038,85 @@ fn airIsErr(f: *Function, inst: Air.Inst.Index, is_ptr: bool, operator: []const | ... | @@ -6015,63 +6038,85 @@ fn airIsErr(f: *Function, inst: Air.Inst.Index, is_ptr: bool, operator: []const |
| 6015 | else | 6038 | else |
| 6016 | try f.writeCValue(writer, operand, .Other) | 6039 | try f.writeCValue(writer, operand, .Other) |
| 6017 | else | 6040 | else |
| 6018 | try f.object.dg.renderValue(writer, err_int_ty, try mod.intValue(err_int_ty, 0), .Other); | 6041 | try f.object.dg.renderValue(writer, try zcu.intValue(err_int_ty, 0), .Other); |
| 6019 | try writer.writeByte(' '); | 6042 | try writer.writeByte(' '); |
| 6020 | try writer.writeAll(operator); | 6043 | try writer.writeAll(operator); |
| 6021 | try writer.writeByte(' '); | 6044 | try writer.writeByte(' '); |
| 6022 | try f.object.dg.renderValue(writer, err_int_ty, try mod.intValue(err_int_ty, 0), .Other); | 6045 | try f.object.dg.renderValue(writer, try zcu.intValue(err_int_ty, 0), .Other); |
| 6023 | try writer.writeAll(";\n"); | 6046 | try a.end(f, writer); |
| 6024 | return local; | 6047 | return local; |
| 6025 | } | 6048 | } |
| 6026 | 6049 | ||
| 6027 | fn airArrayToSlice(f: *Function, inst: Air.Inst.Index) !CValue { | 6050 | fn airArrayToSlice(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6028 | const mod = f.object.dg.module; | 6051 | const zcu = f.object.dg.zcu; |
| 6052 | const ctype_pool = &f.object.dg.ctype_pool; | ||
| 6029 | const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; | 6053 | const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 6030 | 6054 | ||
| 6031 | const operand = try f.resolveInst(ty_op.operand); | 6055 | const operand = try f.resolveInst(ty_op.operand); |
| 6032 | try reap(f, inst, &.{ty_op.operand}); | 6056 | try reap(f, inst, &.{ty_op.operand}); |
| 6033 | const inst_ty = f.typeOfIndex(inst); | 6057 | const inst_ty = f.typeOfIndex(inst); |
| 6058 | const ptr_ty = inst_ty.slicePtrFieldType(zcu); | ||
| 6034 | const writer = f.object.writer(); | 6059 | const writer = f.object.writer(); |
| 6035 | const local = try f.allocLocal(inst, inst_ty); | 6060 | const local = try f.allocLocal(inst, inst_ty); |
| 6036 | const array_ty = f.typeOf(ty_op.operand).childType(mod); | 6061 | const operand_ty = f.typeOf(ty_op.operand); |
| 6037 | 6062 | const array_ty = operand_ty.childType(zcu); | |
| 6038 | try f.writeCValueMember(writer, local, .{ .identifier = "ptr" }); | ||
| 6039 | try writer.writeAll(" = "); | ||
| 6040 | // Unfortunately, C does not support any equivalent to | ||
| 6041 | // &(*(void *)p)[0], although LLVM does via GetElementPtr | ||
| 6042 | if (operand == .undef) { | ||
| 6043 | try f.writeCValue(writer, .{ .undef = inst_ty.slicePtrFieldType(mod) }, .Initializer); | ||
| 6044 | } else if (array_ty.hasRuntimeBitsIgnoreComptime(mod)) { | ||
| 6045 | try writer.writeAll("&("); | ||
| 6046 | try f.writeCValueDeref(writer, operand); | ||
| 6047 | try writer.print(")[{}]", .{try f.fmtIntLiteral(Type.usize, try mod.intValue(Type.usize, 0))}); | ||
| 6048 | } else try f.writeCValue(writer, operand, .Initializer); | ||
| 6049 | try writer.writeAll("; "); | ||
| 6050 | 6063 | ||
| 6051 | const len_val = try mod.intValue(Type.usize, array_ty.arrayLen(mod)); | 6064 | { |
| 6052 | try f.writeCValueMember(writer, local, .{ .identifier = "len" }); | 6065 | const a = try Assignment.start(f, writer, ptr_ty); |
| 6053 | try writer.print(" = {};\n", .{try f.fmtIntLiteral(Type.usize, len_val)}); | 6066 | try f.writeCValueMember(writer, local, .{ .identifier = "ptr" }); |
| 6067 | try a.assign(f, writer); | ||
| 6068 | if (operand == .undef) { | ||
| 6069 | try f.writeCValue(writer, .{ .undef = inst_ty.slicePtrFieldType(zcu) }, .Initializer); | ||
| 6070 | } else { | ||
| 6071 | const ptr_ctype = try f.ctypeFromType(ptr_ty, .complete); | ||
| 6072 | const ptr_child_ctype = ptr_ctype.info(ctype_pool).pointer.elem_ctype; | ||
| 6073 | const elem_ty = array_ty.childType(zcu); | ||
| 6074 | const elem_ctype = try f.ctypeFromType(elem_ty, .complete); | ||
| 6075 | if (!ptr_child_ctype.eql(elem_ctype)) { | ||
| 6076 | try writer.writeByte('('); | ||
| 6077 | try f.renderCType(writer, ptr_ctype); | ||
| 6078 | try writer.writeByte(')'); | ||
| 6079 | } | ||
| 6080 | const operand_ctype = try f.ctypeFromType(operand_ty, .complete); | ||
| 6081 | const operand_child_ctype = operand_ctype.info(ctype_pool).pointer.elem_ctype; | ||
| 6082 | if (operand_child_ctype.info(ctype_pool) == .array) { | ||
| 6083 | try writer.writeByte('&'); | ||
| 6084 | try f.writeCValueDeref(writer, operand); | ||
| 6085 | try writer.print("[{}]", .{try f.fmtIntLiteral(try zcu.intValue(Type.usize, 0))}); | ||
| 6086 | } else try f.writeCValue(writer, operand, .Initializer); | ||
| 6087 | } | ||
| 6088 | try a.end(f, writer); | ||
| 6089 | } | ||
| 6090 | { | ||
| 6091 | const a = try Assignment.start(f, writer, Type.usize); | ||
| 6092 | try f.writeCValueMember(writer, local, .{ .identifier = "len" }); | ||
| 6093 | try a.assign(f, writer); | ||
| 6094 | try writer.print("{}", .{ | ||
| 6095 | try f.fmtIntLiteral(try zcu.intValue(Type.usize, array_ty.arrayLen(zcu))), | ||
| 6096 | }); | ||
| 6097 | try a.end(f, writer); | ||
| 6098 | } | ||
| 6054 | 6099 | ||
| 6055 | return local; | 6100 | return local; |
| 6056 | } | 6101 | } |
| 6057 | 6102 | ||
| 6058 | fn airFloatCast(f: *Function, inst: Air.Inst.Index) !CValue { | 6103 | fn airFloatCast(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6059 | const mod = f.object.dg.module; | 6104 | const zcu = f.object.dg.zcu; |
| 6060 | const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; | 6105 | const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 6061 | 6106 | ||
| 6062 | const inst_ty = f.typeOfIndex(inst); | 6107 | const inst_ty = f.typeOfIndex(inst); |
| 6063 | const inst_scalar_ty = inst_ty.scalarType(mod); | 6108 | const inst_scalar_ty = inst_ty.scalarType(zcu); |
| 6064 | const operand = try f.resolveInst(ty_op.operand); | 6109 | const operand = try f.resolveInst(ty_op.operand); |
| 6065 | try reap(f, inst, &.{ty_op.operand}); | 6110 | try reap(f, inst, &.{ty_op.operand}); |
| 6066 | const operand_ty = f.typeOf(ty_op.operand); | 6111 | const operand_ty = f.typeOf(ty_op.operand); |
| 6067 | const scalar_ty = operand_ty.scalarType(mod); | 6112 | const scalar_ty = operand_ty.scalarType(zcu); |
| 6068 | const target = f.object.dg.module.getTarget(); | 6113 | const target = &f.object.dg.mod.resolved_target.result; |
| 6069 | const operation = if (inst_scalar_ty.isRuntimeFloat() and scalar_ty.isRuntimeFloat()) | 6114 | const operation = if (inst_scalar_ty.isRuntimeFloat() and scalar_ty.isRuntimeFloat()) |
| 6070 | if (inst_scalar_ty.floatBits(target) < scalar_ty.floatBits(target)) "trunc" else "extend" | 6115 | if (inst_scalar_ty.floatBits(target.*) < scalar_ty.floatBits(target.*)) "trunc" else "extend" |
| 6071 | else if (inst_scalar_ty.isInt(mod) and scalar_ty.isRuntimeFloat()) | 6116 | else if (inst_scalar_ty.isInt(zcu) and scalar_ty.isRuntimeFloat()) |
| 6072 | if (inst_scalar_ty.isSignedInt(mod)) "fix" else "fixuns" | 6117 | if (inst_scalar_ty.isSignedInt(zcu)) "fix" else "fixuns" |
| 6073 | else if (inst_scalar_ty.isRuntimeFloat() and scalar_ty.isInt(mod)) | 6118 | else if (inst_scalar_ty.isRuntimeFloat() and scalar_ty.isInt(zcu)) |
| 6074 | if (scalar_ty.isSignedInt(mod)) "float" else "floatun" | 6119 | if (scalar_ty.isSignedInt(zcu)) "float" else "floatun" |
| 6075 | else | 6120 | else |
| 6076 | unreachable; | 6121 | unreachable; |
| 6077 | 6122 | ||
| ... | @@ -6082,20 +6127,20 @@ fn airFloatCast(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -6082,20 +6127,20 @@ fn airFloatCast(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6082 | try f.writeCValue(writer, local, .Other); | 6127 | try f.writeCValue(writer, local, .Other); |
| 6083 | try v.elem(f, writer); | 6128 | try v.elem(f, writer); |
| 6084 | try a.assign(f, writer); | 6129 | try a.assign(f, writer); |
| 6085 | if (inst_scalar_ty.isInt(mod) and scalar_ty.isRuntimeFloat()) { | 6130 | if (inst_scalar_ty.isInt(zcu) and scalar_ty.isRuntimeFloat()) { |
| 6086 | try writer.writeAll("zig_wrap_"); | 6131 | try writer.writeAll("zig_wrap_"); |
| 6087 | try f.object.dg.renderTypeForBuiltinFnName(writer, inst_scalar_ty); | 6132 | try f.object.dg.renderTypeForBuiltinFnName(writer, inst_scalar_ty); |
| 6088 | try writer.writeByte('('); | 6133 | try writer.writeByte('('); |
| 6089 | } | 6134 | } |
| 6090 | try writer.writeAll("zig_"); | 6135 | try writer.writeAll("zig_"); |
| 6091 | try writer.writeAll(operation); | 6136 | try writer.writeAll(operation); |
| 6092 | try writer.writeAll(compilerRtAbbrev(scalar_ty, mod)); | 6137 | try writer.writeAll(compilerRtAbbrev(scalar_ty, zcu, target.*)); |
| 6093 | try writer.writeAll(compilerRtAbbrev(inst_scalar_ty, mod)); | 6138 | try writer.writeAll(compilerRtAbbrev(inst_scalar_ty, zcu, target.*)); |
| 6094 | try writer.writeByte('('); | 6139 | try writer.writeByte('('); |
| 6095 | try f.writeCValue(writer, operand, .FunctionArgument); | 6140 | try f.writeCValue(writer, operand, .FunctionArgument); |
| 6096 | try v.elem(f, writer); | 6141 | try v.elem(f, writer); |
| 6097 | try writer.writeByte(')'); | 6142 | try writer.writeByte(')'); |
| 6098 | if (inst_scalar_ty.isInt(mod) and scalar_ty.isRuntimeFloat()) { | 6143 | if (inst_scalar_ty.isInt(zcu) and scalar_ty.isRuntimeFloat()) { |
| 6099 | try f.object.dg.renderBuiltinInfo(writer, inst_scalar_ty, .bits); | 6144 | try f.object.dg.renderBuiltinInfo(writer, inst_scalar_ty, .bits); |
| 6100 | try writer.writeByte(')'); | 6145 | try writer.writeByte(')'); |
| 6101 | } | 6146 | } |
| ... | @@ -6106,7 +6151,7 @@ fn airFloatCast(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -6106,7 +6151,7 @@ fn airFloatCast(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6106 | } | 6151 | } |
| 6107 | 6152 | ||
| 6108 | fn airIntFromPtr(f: *Function, inst: Air.Inst.Index) !CValue { | 6153 | fn airIntFromPtr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6109 | const mod = f.object.dg.module; | 6154 | const zcu = f.object.dg.zcu; |
| 6110 | const un_op = f.air.instructions.items(.data)[@intFromEnum(inst)].un_op; | 6155 | const un_op = f.air.instructions.items(.data)[@intFromEnum(inst)].un_op; |
| 6111 | 6156 | ||
| 6112 | const operand = try f.resolveInst(un_op); | 6157 | const operand = try f.resolveInst(un_op); |
| ... | @@ -6120,7 +6165,7 @@ fn airIntFromPtr(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -6120,7 +6165,7 @@ fn airIntFromPtr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6120 | try writer.writeAll(" = ("); | 6165 | try writer.writeAll(" = ("); |
| 6121 | try f.renderType(writer, inst_ty); | 6166 | try f.renderType(writer, inst_ty); |
| 6122 | try writer.writeByte(')'); | 6167 | try writer.writeByte(')'); |
| 6123 | if (operand_ty.isSlice(mod)) { | 6168 | if (operand_ty.isSlice(zcu)) { |
| 6124 | try f.writeCValueMember(writer, operand, .{ .identifier = "ptr" }); | 6169 | try f.writeCValueMember(writer, operand, .{ .identifier = "ptr" }); |
| 6125 | } else { | 6170 | } else { |
| 6126 | try f.writeCValue(writer, operand, .Other); | 6171 | try f.writeCValue(writer, operand, .Other); |
| ... | @@ -6135,18 +6180,18 @@ fn airUnBuiltinCall( | ... | @@ -6135,18 +6180,18 @@ fn airUnBuiltinCall( |
| 6135 | operation: []const u8, | 6180 | operation: []const u8, |
| 6136 | info: BuiltinInfo, | 6181 | info: BuiltinInfo, |
| 6137 | ) !CValue { | 6182 | ) !CValue { |
| 6138 | const mod = f.object.dg.module; | 6183 | const zcu = f.object.dg.zcu; |
| 6139 | const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; | 6184 | const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 6140 | 6185 | ||
| 6141 | const operand = try f.resolveInst(ty_op.operand); | 6186 | const operand = try f.resolveInst(ty_op.operand); |
| 6142 | try reap(f, inst, &.{ty_op.operand}); | 6187 | try reap(f, inst, &.{ty_op.operand}); |
| 6143 | const inst_ty = f.typeOfIndex(inst); | 6188 | const inst_ty = f.typeOfIndex(inst); |
| 6144 | const inst_scalar_ty = inst_ty.scalarType(mod); | 6189 | const inst_scalar_ty = inst_ty.scalarType(zcu); |
| 6145 | const operand_ty = f.typeOf(ty_op.operand); | 6190 | const operand_ty = f.typeOf(ty_op.operand); |
| 6146 | const scalar_ty = operand_ty.scalarType(mod); | 6191 | const scalar_ty = operand_ty.scalarType(zcu); |
| 6147 | 6192 | ||
| 6148 | const inst_scalar_cty = try f.typeToCType(inst_scalar_ty, .complete); | 6193 | const inst_scalar_ctype = try f.ctypeFromType(inst_scalar_ty, .complete); |
| 6149 | const ref_ret = inst_scalar_cty.tag() == .array; | 6194 | const ref_ret = inst_scalar_ctype.info(&f.object.dg.ctype_pool) == .array; |
| 6150 | 6195 | ||
| 6151 | const writer = f.object.writer(); | 6196 | const writer = f.object.writer(); |
| 6152 | const local = try f.allocLocal(inst, inst_ty); | 6197 | const local = try f.allocLocal(inst, inst_ty); |
| ... | @@ -6179,23 +6224,23 @@ fn airBinBuiltinCall( | ... | @@ -6179,23 +6224,23 @@ fn airBinBuiltinCall( |
| 6179 | operation: []const u8, | 6224 | operation: []const u8, |
| 6180 | info: BuiltinInfo, | 6225 | info: BuiltinInfo, |
| 6181 | ) !CValue { | 6226 | ) !CValue { |
| 6182 | const mod = f.object.dg.module; | 6227 | const zcu = f.object.dg.zcu; |
| 6183 | const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; | 6228 | const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| 6184 | 6229 | ||
| 6185 | const operand_ty = f.typeOf(bin_op.lhs); | 6230 | const operand_ty = f.typeOf(bin_op.lhs); |
| 6186 | const operand_cty = try f.typeToCType(operand_ty, .complete); | 6231 | const operand_ctype = try f.ctypeFromType(operand_ty, .complete); |
| 6187 | const is_big = operand_cty.tag() == .array; | 6232 | const is_big = operand_ctype.info(&f.object.dg.ctype_pool) == .array; |
| 6188 | 6233 | ||
| 6189 | const lhs = try f.resolveInst(bin_op.lhs); | 6234 | const lhs = try f.resolveInst(bin_op.lhs); |
| 6190 | const rhs = try f.resolveInst(bin_op.rhs); | 6235 | const rhs = try f.resolveInst(bin_op.rhs); |
| 6191 | if (!is_big) try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); | 6236 | if (!is_big) try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); |
| 6192 | 6237 | ||
| 6193 | const inst_ty = f.typeOfIndex(inst); | 6238 | const inst_ty = f.typeOfIndex(inst); |
| 6194 | const inst_scalar_ty = inst_ty.scalarType(mod); | 6239 | const inst_scalar_ty = inst_ty.scalarType(zcu); |
| 6195 | const scalar_ty = operand_ty.scalarType(mod); | 6240 | const scalar_ty = operand_ty.scalarType(zcu); |
| 6196 | 6241 | ||
| 6197 | const inst_scalar_cty = try f.typeToCType(inst_scalar_ty, .complete); | 6242 | const inst_scalar_ctype = try f.ctypeFromType(inst_scalar_ty, .complete); |
| 6198 | const ref_ret = inst_scalar_cty.tag() == .array; | 6243 | const ref_ret = inst_scalar_ctype.info(&f.object.dg.ctype_pool) == .array; |
| 6199 | 6244 | ||
| 6200 | const writer = f.object.writer(); | 6245 | const writer = f.object.writer(); |
| 6201 | const local = try f.allocLocal(inst, inst_ty); | 6246 | const local = try f.allocLocal(inst, inst_ty); |
| ... | @@ -6234,18 +6279,18 @@ fn airCmpBuiltinCall( | ... | @@ -6234,18 +6279,18 @@ fn airCmpBuiltinCall( |
| 6234 | operation: enum { cmp, operator }, | 6279 | operation: enum { cmp, operator }, |
| 6235 | info: BuiltinInfo, | 6280 | info: BuiltinInfo, |
| 6236 | ) !CValue { | 6281 | ) !CValue { |
| 6237 | const mod = f.object.dg.module; | 6282 | const zcu = f.object.dg.zcu; |
| 6238 | const lhs = try f.resolveInst(data.lhs); | 6283 | const lhs = try f.resolveInst(data.lhs); |
| 6239 | const rhs = try f.resolveInst(data.rhs); | 6284 | const rhs = try f.resolveInst(data.rhs); |
| 6240 | try reap(f, inst, &.{ data.lhs, data.rhs }); | 6285 | try reap(f, inst, &.{ data.lhs, data.rhs }); |
| 6241 | 6286 | ||
| 6242 | const inst_ty = f.typeOfIndex(inst); | 6287 | const inst_ty = f.typeOfIndex(inst); |
| 6243 | const inst_scalar_ty = inst_ty.scalarType(mod); | 6288 | const inst_scalar_ty = inst_ty.scalarType(zcu); |
| 6244 | const operand_ty = f.typeOf(data.lhs); | 6289 | const operand_ty = f.typeOf(data.lhs); |
| 6245 | const scalar_ty = operand_ty.scalarType(mod); | 6290 | const scalar_ty = operand_ty.scalarType(zcu); |
| 6246 | 6291 | ||
| 6247 | const inst_scalar_cty = try f.typeToCType(inst_scalar_ty, .complete); | 6292 | const inst_scalar_ctype = try f.ctypeFromType(inst_scalar_ty, .complete); |
| 6248 | const ref_ret = inst_scalar_cty.tag() == .array; | 6293 | const ref_ret = inst_scalar_ctype.info(&f.object.dg.ctype_pool) == .array; |
| 6249 | 6294 | ||
| 6250 | const writer = f.object.writer(); | 6295 | const writer = f.object.writer(); |
| 6251 | const local = try f.allocLocal(inst, inst_ty); | 6296 | const local = try f.allocLocal(inst, inst_ty); |
| ... | @@ -6275,7 +6320,7 @@ fn airCmpBuiltinCall( | ... | @@ -6275,7 +6320,7 @@ fn airCmpBuiltinCall( |
| 6275 | try writer.writeByte(')'); | 6320 | try writer.writeByte(')'); |
| 6276 | if (!ref_ret) try writer.print("{s}{}", .{ | 6321 | if (!ref_ret) try writer.print("{s}{}", .{ |
| 6277 | compareOperatorC(operator), | 6322 | compareOperatorC(operator), |
| 6278 | try f.fmtIntLiteral(Type.i32, try mod.intValue(Type.i32, 0)), | 6323 | try f.fmtIntLiteral(try zcu.intValue(Type.i32, 0)), |
| 6279 | }); | 6324 | }); |
| 6280 | try writer.writeAll(";\n"); | 6325 | try writer.writeAll(";\n"); |
| 6281 | try v.end(f, inst, writer); | 6326 | try v.end(f, inst, writer); |
| ... | @@ -6284,7 +6329,7 @@ fn airCmpBuiltinCall( | ... | @@ -6284,7 +6329,7 @@ fn airCmpBuiltinCall( |
| 6284 | } | 6329 | } |
| 6285 | 6330 | ||
| 6286 | fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue { | 6331 | fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue { |
| 6287 | const mod = f.object.dg.module; | 6332 | const zcu = f.object.dg.zcu; |
| 6288 | const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; | 6333 | const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| 6289 | const extra = f.air.extraData(Air.Cmpxchg, ty_pl.payload).data; | 6334 | const extra = f.air.extraData(Air.Cmpxchg, ty_pl.payload).data; |
| 6290 | const inst_ty = f.typeOfIndex(inst); | 6335 | const inst_ty = f.typeOfIndex(inst); |
| ... | @@ -6292,19 +6337,19 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue | ... | @@ -6292,19 +6337,19 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue |
| 6292 | const expected_value = try f.resolveInst(extra.expected_value); | 6337 | const expected_value = try f.resolveInst(extra.expected_value); |
| 6293 | const new_value = try f.resolveInst(extra.new_value); | 6338 | const new_value = try f.resolveInst(extra.new_value); |
| 6294 | const ptr_ty = f.typeOf(extra.ptr); | 6339 | const ptr_ty = f.typeOf(extra.ptr); |
| 6295 | const ty = ptr_ty.childType(mod); | 6340 | const ty = ptr_ty.childType(zcu); |
| 6296 | 6341 | ||
| 6297 | const writer = f.object.writer(); | 6342 | const writer = f.object.writer(); |
| 6298 | const new_value_mat = try Materialize.start(f, inst, writer, ty, new_value); | 6343 | const new_value_mat = try Materialize.start(f, inst, writer, ty, new_value); |
| 6299 | try reap(f, inst, &.{ extra.ptr, extra.expected_value, extra.new_value }); | 6344 | try reap(f, inst, &.{ extra.ptr, extra.expected_value, extra.new_value }); |
| 6300 | 6345 | ||
| 6301 | const repr_ty = if (ty.isRuntimeFloat()) | 6346 | const repr_ty = if (ty.isRuntimeFloat()) |
| 6302 | mod.intType(.unsigned, @as(u16, @intCast(ty.abiSize(mod) * 8))) catch unreachable | 6347 | zcu.intType(.unsigned, @as(u16, @intCast(ty.abiSize(zcu) * 8))) catch unreachable |
| 6303 | else | 6348 | else |
| 6304 | ty; | 6349 | ty; |
| 6305 | 6350 | ||
| 6306 | const local = try f.allocLocal(inst, inst_ty); | 6351 | const local = try f.allocLocal(inst, inst_ty); |
| 6307 | if (inst_ty.isPtrLikeOptional(mod)) { | 6352 | if (inst_ty.isPtrLikeOptional(zcu)) { |
| 6308 | { | 6353 | { |
| 6309 | const a = try Assignment.start(f, writer, ty); | 6354 | const a = try Assignment.start(f, writer, ty); |
| 6310 | try f.writeCValue(writer, local, .Other); | 6355 | try f.writeCValue(writer, local, .Other); |
| ... | @@ -6317,7 +6362,7 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue | ... | @@ -6317,7 +6362,7 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue |
| 6317 | try writer.print("zig_cmpxchg_{s}((zig_atomic(", .{flavor}); | 6362 | try writer.print("zig_cmpxchg_{s}((zig_atomic(", .{flavor}); |
| 6318 | try f.renderType(writer, ty); | 6363 | try f.renderType(writer, ty); |
| 6319 | try writer.writeByte(')'); | 6364 | try writer.writeByte(')'); |
| 6320 | if (ptr_ty.isVolatilePtr(mod)) try writer.writeAll(" volatile"); | 6365 | if (ptr_ty.isVolatilePtr(zcu)) try writer.writeAll(" volatile"); |
| 6321 | try writer.writeAll(" *)"); | 6366 | try writer.writeAll(" *)"); |
| 6322 | try f.writeCValue(writer, ptr, .Other); | 6367 | try f.writeCValue(writer, ptr, .Other); |
| 6323 | try writer.writeAll(", "); | 6368 | try writer.writeAll(", "); |
| ... | @@ -6331,7 +6376,7 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue | ... | @@ -6331,7 +6376,7 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue |
| 6331 | try writer.writeAll(", "); | 6376 | try writer.writeAll(", "); |
| 6332 | try f.object.dg.renderTypeForBuiltinFnName(writer, ty); | 6377 | try f.object.dg.renderTypeForBuiltinFnName(writer, ty); |
| 6333 | try writer.writeAll(", "); | 6378 | try writer.writeAll(", "); |
| 6334 | try f.object.dg.renderType(writer, repr_ty); | 6379 | try f.renderType(writer, repr_ty); |
| 6335 | try writer.writeByte(')'); | 6380 | try writer.writeByte(')'); |
| 6336 | try writer.writeAll(") {\n"); | 6381 | try writer.writeAll(") {\n"); |
| 6337 | f.object.indent_writer.pushIndent(); | 6382 | f.object.indent_writer.pushIndent(); |
| ... | @@ -6359,7 +6404,7 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue | ... | @@ -6359,7 +6404,7 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue |
| 6359 | try writer.print("zig_cmpxchg_{s}((zig_atomic(", .{flavor}); | 6404 | try writer.print("zig_cmpxchg_{s}((zig_atomic(", .{flavor}); |
| 6360 | try f.renderType(writer, ty); | 6405 | try f.renderType(writer, ty); |
| 6361 | try writer.writeByte(')'); | 6406 | try writer.writeByte(')'); |
| 6362 | if (ptr_ty.isVolatilePtr(mod)) try writer.writeAll(" volatile"); | 6407 | if (ptr_ty.isVolatilePtr(zcu)) try writer.writeAll(" volatile"); |
| 6363 | try writer.writeAll(" *)"); | 6408 | try writer.writeAll(" *)"); |
| 6364 | try f.writeCValue(writer, ptr, .Other); | 6409 | try f.writeCValue(writer, ptr, .Other); |
| 6365 | try writer.writeAll(", "); | 6410 | try writer.writeAll(", "); |
| ... | @@ -6373,7 +6418,7 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue | ... | @@ -6373,7 +6418,7 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue |
| 6373 | try writer.writeAll(", "); | 6418 | try writer.writeAll(", "); |
| 6374 | try f.object.dg.renderTypeForBuiltinFnName(writer, ty); | 6419 | try f.object.dg.renderTypeForBuiltinFnName(writer, ty); |
| 6375 | try writer.writeAll(", "); | 6420 | try writer.writeAll(", "); |
| 6376 | try f.object.dg.renderType(writer, repr_ty); | 6421 | try f.renderType(writer, repr_ty); |
| 6377 | try writer.writeByte(')'); | 6422 | try writer.writeByte(')'); |
| 6378 | try a.end(f, writer); | 6423 | try a.end(f, writer); |
| 6379 | } | 6424 | } |
| ... | @@ -6389,12 +6434,12 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue | ... | @@ -6389,12 +6434,12 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue |
| 6389 | } | 6434 | } |
| 6390 | 6435 | ||
| 6391 | fn airAtomicRmw(f: *Function, inst: Air.Inst.Index) !CValue { | 6436 | fn airAtomicRmw(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6392 | const mod = f.object.dg.module; | 6437 | const zcu = f.object.dg.zcu; |
| 6393 | const pl_op = f.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; | 6438 | const pl_op = f.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; |
| 6394 | const extra = f.air.extraData(Air.AtomicRmw, pl_op.payload).data; | 6439 | const extra = f.air.extraData(Air.AtomicRmw, pl_op.payload).data; |
| 6395 | const inst_ty = f.typeOfIndex(inst); | 6440 | const inst_ty = f.typeOfIndex(inst); |
| 6396 | const ptr_ty = f.typeOf(pl_op.operand); | 6441 | const ptr_ty = f.typeOf(pl_op.operand); |
| 6397 | const ty = ptr_ty.childType(mod); | 6442 | const ty = ptr_ty.childType(zcu); |
| 6398 | const ptr = try f.resolveInst(pl_op.operand); | 6443 | const ptr = try f.resolveInst(pl_op.operand); |
| 6399 | const operand = try f.resolveInst(extra.operand); | 6444 | const operand = try f.resolveInst(extra.operand); |
| 6400 | 6445 | ||
| ... | @@ -6402,10 +6447,10 @@ fn airAtomicRmw(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -6402,10 +6447,10 @@ fn airAtomicRmw(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6402 | const operand_mat = try Materialize.start(f, inst, writer, ty, operand); | 6447 | const operand_mat = try Materialize.start(f, inst, writer, ty, operand); |
| 6403 | try reap(f, inst, &.{ pl_op.operand, extra.operand }); | 6448 | try reap(f, inst, &.{ pl_op.operand, extra.operand }); |
| 6404 | 6449 | ||
| 6405 | const repr_bits = @as(u16, @intCast(ty.abiSize(mod) * 8)); | 6450 | const repr_bits = @as(u16, @intCast(ty.abiSize(zcu) * 8)); |
| 6406 | const is_float = ty.isRuntimeFloat(); | 6451 | const is_float = ty.isRuntimeFloat(); |
| 6407 | const is_128 = repr_bits == 128; | 6452 | const is_128 = repr_bits == 128; |
| 6408 | const repr_ty = if (is_float) mod.intType(.unsigned, repr_bits) catch unreachable else ty; | 6453 | const repr_ty = if (is_float) zcu.intType(.unsigned, repr_bits) catch unreachable else ty; |
| 6409 | 6454 | ||
| 6410 | const local = try f.allocLocal(inst, inst_ty); | 6455 | const local = try f.allocLocal(inst, inst_ty); |
| 6411 | try writer.print("zig_atomicrmw_{s}", .{toAtomicRmwSuffix(extra.op())}); | 6456 | try writer.print("zig_atomicrmw_{s}", .{toAtomicRmwSuffix(extra.op())}); |
| ... | @@ -6421,7 +6466,7 @@ fn airAtomicRmw(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -6421,7 +6466,7 @@ fn airAtomicRmw(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6421 | if (use_atomic) try writer.writeAll("zig_atomic("); | 6466 | if (use_atomic) try writer.writeAll("zig_atomic("); |
| 6422 | try f.renderType(writer, ty); | 6467 | try f.renderType(writer, ty); |
| 6423 | if (use_atomic) try writer.writeByte(')'); | 6468 | if (use_atomic) try writer.writeByte(')'); |
| 6424 | if (ptr_ty.isVolatilePtr(mod)) try writer.writeAll(" volatile"); | 6469 | if (ptr_ty.isVolatilePtr(zcu)) try writer.writeAll(" volatile"); |
| 6425 | try writer.writeAll(" *)"); | 6470 | try writer.writeAll(" *)"); |
| 6426 | try f.writeCValue(writer, ptr, .Other); | 6471 | try f.writeCValue(writer, ptr, .Other); |
| 6427 | try writer.writeAll(", "); | 6472 | try writer.writeAll(", "); |
| ... | @@ -6431,7 +6476,7 @@ fn airAtomicRmw(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -6431,7 +6476,7 @@ fn airAtomicRmw(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6431 | try writer.writeAll(", "); | 6476 | try writer.writeAll(", "); |
| 6432 | try f.object.dg.renderTypeForBuiltinFnName(writer, ty); | 6477 | try f.object.dg.renderTypeForBuiltinFnName(writer, ty); |
| 6433 | try writer.writeAll(", "); | 6478 | try writer.writeAll(", "); |
| 6434 | try f.object.dg.renderType(writer, repr_ty); | 6479 | try f.renderType(writer, repr_ty); |
| 6435 | try writer.writeAll(");\n"); | 6480 | try writer.writeAll(");\n"); |
| 6436 | try operand_mat.end(f, inst); | 6481 | try operand_mat.end(f, inst); |
| 6437 | 6482 | ||
| ... | @@ -6444,15 +6489,15 @@ fn airAtomicRmw(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -6444,15 +6489,15 @@ fn airAtomicRmw(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6444 | } | 6489 | } |
| 6445 | 6490 | ||
| 6446 | fn airAtomicLoad(f: *Function, inst: Air.Inst.Index) !CValue { | 6491 | fn airAtomicLoad(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6447 | const mod = f.object.dg.module; | 6492 | const zcu = f.object.dg.zcu; |
| 6448 | const atomic_load = f.air.instructions.items(.data)[@intFromEnum(inst)].atomic_load; | 6493 | const atomic_load = f.air.instructions.items(.data)[@intFromEnum(inst)].atomic_load; |
| 6449 | const ptr = try f.resolveInst(atomic_load.ptr); | 6494 | const ptr = try f.resolveInst(atomic_load.ptr); |
| 6450 | try reap(f, inst, &.{atomic_load.ptr}); | 6495 | try reap(f, inst, &.{atomic_load.ptr}); |
| 6451 | const ptr_ty = f.typeOf(atomic_load.ptr); | 6496 | const ptr_ty = f.typeOf(atomic_load.ptr); |
| 6452 | const ty = ptr_ty.childType(mod); | 6497 | const ty = ptr_ty.childType(zcu); |
| 6453 | 6498 | ||
| 6454 | const repr_ty = if (ty.isRuntimeFloat()) | 6499 | const repr_ty = if (ty.isRuntimeFloat()) |
| 6455 | mod.intType(.unsigned, @as(u16, @intCast(ty.abiSize(mod) * 8))) catch unreachable | 6500 | zcu.intType(.unsigned, @as(u16, @intCast(ty.abiSize(zcu) * 8))) catch unreachable |
| 6456 | else | 6501 | else |
| 6457 | ty; | 6502 | ty; |
| 6458 | 6503 | ||
| ... | @@ -6465,7 +6510,7 @@ fn airAtomicLoad(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -6465,7 +6510,7 @@ fn airAtomicLoad(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6465 | try writer.writeAll(", (zig_atomic("); | 6510 | try writer.writeAll(", (zig_atomic("); |
| 6466 | try f.renderType(writer, ty); | 6511 | try f.renderType(writer, ty); |
| 6467 | try writer.writeByte(')'); | 6512 | try writer.writeByte(')'); |
| 6468 | if (ptr_ty.isVolatilePtr(mod)) try writer.writeAll(" volatile"); | 6513 | if (ptr_ty.isVolatilePtr(zcu)) try writer.writeAll(" volatile"); |
| 6469 | try writer.writeAll(" *)"); | 6514 | try writer.writeAll(" *)"); |
| 6470 | try f.writeCValue(writer, ptr, .Other); | 6515 | try f.writeCValue(writer, ptr, .Other); |
| 6471 | try writer.writeAll(", "); | 6516 | try writer.writeAll(", "); |
| ... | @@ -6473,17 +6518,17 @@ fn airAtomicLoad(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -6473,17 +6518,17 @@ fn airAtomicLoad(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6473 | try writer.writeAll(", "); | 6518 | try writer.writeAll(", "); |
| 6474 | try f.object.dg.renderTypeForBuiltinFnName(writer, ty); | 6519 | try f.object.dg.renderTypeForBuiltinFnName(writer, ty); |
| 6475 | try writer.writeAll(", "); | 6520 | try writer.writeAll(", "); |
| 6476 | try f.object.dg.renderType(writer, repr_ty); | 6521 | try f.renderType(writer, repr_ty); |
| 6477 | try writer.writeAll(");\n"); | 6522 | try writer.writeAll(");\n"); |
| 6478 | 6523 | ||
| 6479 | return local; | 6524 | return local; |
| 6480 | } | 6525 | } |
| 6481 | 6526 | ||
| 6482 | fn airAtomicStore(f: *Function, inst: Air.Inst.Index, order: [*:0]const u8) !CValue { | 6527 | fn airAtomicStore(f: *Function, inst: Air.Inst.Index, order: [*:0]const u8) !CValue { |
| 6483 | const mod = f.object.dg.module; | 6528 | const zcu = f.object.dg.zcu; |
| 6484 | const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; | 6529 | const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| 6485 | const ptr_ty = f.typeOf(bin_op.lhs); | 6530 | const ptr_ty = f.typeOf(bin_op.lhs); |
| 6486 | const ty = ptr_ty.childType(mod); | 6531 | const ty = ptr_ty.childType(zcu); |
| 6487 | const ptr = try f.resolveInst(bin_op.lhs); | 6532 | const ptr = try f.resolveInst(bin_op.lhs); |
| 6488 | const element = try f.resolveInst(bin_op.rhs); | 6533 | const element = try f.resolveInst(bin_op.rhs); |
| 6489 | 6534 | ||
| ... | @@ -6492,14 +6537,14 @@ fn airAtomicStore(f: *Function, inst: Air.Inst.Index, order: [*:0]const u8) !CVa | ... | @@ -6492,14 +6537,14 @@ fn airAtomicStore(f: *Function, inst: Air.Inst.Index, order: [*:0]const u8) !CVa |
| 6492 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); | 6537 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); |
| 6493 | 6538 | ||
| 6494 | const repr_ty = if (ty.isRuntimeFloat()) | 6539 | const repr_ty = if (ty.isRuntimeFloat()) |
| 6495 | mod.intType(.unsigned, @as(u16, @intCast(ty.abiSize(mod) * 8))) catch unreachable | 6540 | zcu.intType(.unsigned, @as(u16, @intCast(ty.abiSize(zcu) * 8))) catch unreachable |
| 6496 | else | 6541 | else |
| 6497 | ty; | 6542 | ty; |
| 6498 | 6543 | ||
| 6499 | try writer.writeAll("zig_atomic_store((zig_atomic("); | 6544 | try writer.writeAll("zig_atomic_store((zig_atomic("); |
| 6500 | try f.renderType(writer, ty); | 6545 | try f.renderType(writer, ty); |
| 6501 | try writer.writeByte(')'); | 6546 | try writer.writeByte(')'); |
| 6502 | if (ptr_ty.isVolatilePtr(mod)) try writer.writeAll(" volatile"); | 6547 | if (ptr_ty.isVolatilePtr(zcu)) try writer.writeAll(" volatile"); |
| 6503 | try writer.writeAll(" *)"); | 6548 | try writer.writeAll(" *)"); |
| 6504 | try f.writeCValue(writer, ptr, .Other); | 6549 | try f.writeCValue(writer, ptr, .Other); |
| 6505 | try writer.writeAll(", "); | 6550 | try writer.writeAll(", "); |
| ... | @@ -6507,7 +6552,7 @@ fn airAtomicStore(f: *Function, inst: Air.Inst.Index, order: [*:0]const u8) !CVa | ... | @@ -6507,7 +6552,7 @@ fn airAtomicStore(f: *Function, inst: Air.Inst.Index, order: [*:0]const u8) !CVa |
| 6507 | try writer.print(", {s}, ", .{order}); | 6552 | try writer.print(", {s}, ", .{order}); |
| 6508 | try f.object.dg.renderTypeForBuiltinFnName(writer, ty); | 6553 | try f.object.dg.renderTypeForBuiltinFnName(writer, ty); |
| 6509 | try writer.writeAll(", "); | 6554 | try writer.writeAll(", "); |
| 6510 | try f.object.dg.renderType(writer, repr_ty); | 6555 | try f.renderType(writer, repr_ty); |
| 6511 | try writer.writeAll(");\n"); | 6556 | try writer.writeAll(");\n"); |
| 6512 | try element_mat.end(f, inst); | 6557 | try element_mat.end(f, inst); |
| 6513 | 6558 | ||
| ... | @@ -6515,8 +6560,8 @@ fn airAtomicStore(f: *Function, inst: Air.Inst.Index, order: [*:0]const u8) !CVa | ... | @@ -6515,8 +6560,8 @@ fn airAtomicStore(f: *Function, inst: Air.Inst.Index, order: [*:0]const u8) !CVa |
| 6515 | } | 6560 | } |
| 6516 | 6561 | ||
| 6517 | fn writeSliceOrPtr(f: *Function, writer: anytype, ptr: CValue, ptr_ty: Type) !void { | 6562 | fn writeSliceOrPtr(f: *Function, writer: anytype, ptr: CValue, ptr_ty: Type) !void { |
| 6518 | const mod = f.object.dg.module; | 6563 | const zcu = f.object.dg.zcu; |
| 6519 | if (ptr_ty.isSlice(mod)) { | 6564 | if (ptr_ty.isSlice(zcu)) { |
| 6520 | try f.writeCValueMember(writer, ptr, .{ .identifier = "ptr" }); | 6565 | try f.writeCValueMember(writer, ptr, .{ .identifier = "ptr" }); |
| 6521 | } else { | 6566 | } else { |
| 6522 | try f.writeCValue(writer, ptr, .FunctionArgument); | 6567 | try f.writeCValue(writer, ptr, .FunctionArgument); |
| ... | @@ -6524,14 +6569,14 @@ fn writeSliceOrPtr(f: *Function, writer: anytype, ptr: CValue, ptr_ty: Type) !vo | ... | @@ -6524,14 +6569,14 @@ fn writeSliceOrPtr(f: *Function, writer: anytype, ptr: CValue, ptr_ty: Type) !vo |
| 6524 | } | 6569 | } |
| 6525 | 6570 | ||
| 6526 | fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { | 6571 | fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { |
| 6527 | const mod = f.object.dg.module; | 6572 | const zcu = f.object.dg.zcu; |
| 6528 | const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; | 6573 | const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| 6529 | const dest_ty = f.typeOf(bin_op.lhs); | 6574 | const dest_ty = f.typeOf(bin_op.lhs); |
| 6530 | const dest_slice = try f.resolveInst(bin_op.lhs); | 6575 | const dest_slice = try f.resolveInst(bin_op.lhs); |
| 6531 | const value = try f.resolveInst(bin_op.rhs); | 6576 | const value = try f.resolveInst(bin_op.rhs); |
| 6532 | const elem_ty = f.typeOf(bin_op.rhs); | 6577 | const elem_ty = f.typeOf(bin_op.rhs); |
| 6533 | const elem_abi_size = elem_ty.abiSize(mod); | 6578 | const elem_abi_size = elem_ty.abiSize(zcu); |
| 6534 | const val_is_undef = if (try f.air.value(bin_op.rhs, mod)) |val| val.isUndefDeep(mod) else false; | 6579 | const val_is_undef = if (try f.air.value(bin_op.rhs, zcu)) |val| val.isUndefDeep(zcu) else false; |
| 6535 | const writer = f.object.writer(); | 6580 | const writer = f.object.writer(); |
| 6536 | 6581 | ||
| 6537 | if (val_is_undef) { | 6582 | if (val_is_undef) { |
| ... | @@ -6541,7 +6586,7 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { | ... | @@ -6541,7 +6586,7 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { |
| 6541 | } | 6586 | } |
| 6542 | 6587 | ||
| 6543 | try writer.writeAll("memset("); | 6588 | try writer.writeAll("memset("); |
| 6544 | switch (dest_ty.ptrSize(mod)) { | 6589 | switch (dest_ty.ptrSize(zcu)) { |
| 6545 | .Slice => { | 6590 | .Slice => { |
| 6546 | try f.writeCValueMember(writer, dest_slice, .{ .identifier = "ptr" }); | 6591 | try f.writeCValueMember(writer, dest_slice, .{ .identifier = "ptr" }); |
| 6547 | try writer.writeAll(", 0xaa, "); | 6592 | try writer.writeAll(", 0xaa, "); |
| ... | @@ -6553,8 +6598,8 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { | ... | @@ -6553,8 +6598,8 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { |
| 6553 | } | 6598 | } |
| 6554 | }, | 6599 | }, |
| 6555 | .One => { | 6600 | .One => { |
| 6556 | const array_ty = dest_ty.childType(mod); | 6601 | const array_ty = dest_ty.childType(zcu); |
| 6557 | const len = array_ty.arrayLen(mod) * elem_abi_size; | 6602 | const len = array_ty.arrayLen(zcu) * elem_abi_size; |
| 6558 | 6603 | ||
| 6559 | try f.writeCValue(writer, dest_slice, .FunctionArgument); | 6604 | try f.writeCValue(writer, dest_slice, .FunctionArgument); |
| 6560 | try writer.print(", 0xaa, {d});\n", .{len}); | 6605 | try writer.print(", 0xaa, {d});\n", .{len}); |
| ... | @@ -6565,12 +6610,12 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { | ... | @@ -6565,12 +6610,12 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { |
| 6565 | return .none; | 6610 | return .none; |
| 6566 | } | 6611 | } |
| 6567 | 6612 | ||
| 6568 | if (elem_abi_size > 1 or dest_ty.isVolatilePtr(mod)) { | 6613 | if (elem_abi_size > 1 or dest_ty.isVolatilePtr(zcu)) { |
| 6569 | // For the assignment in this loop, the array pointer needs to get | 6614 | // For the assignment in this loop, the array pointer needs to get |
| 6570 | // casted to a regular pointer, otherwise an error like this occurs: | 6615 | // casted to a regular pointer, otherwise an error like this occurs: |
| 6571 | // error: array type 'uint32_t[20]' (aka 'unsigned int[20]') is not assignable | 6616 | // error: array type 'uint32_t[20]' (aka 'unsigned int[20]') is not assignable |
| 6572 | const elem_ptr_ty = try mod.ptrType(.{ | 6617 | const elem_ptr_ty = try zcu.ptrType(.{ |
| 6573 | .child = elem_ty.ip_index, | 6618 | .child = elem_ty.toIntern(), |
| 6574 | .flags = .{ | 6619 | .flags = .{ |
| 6575 | .size = .C, | 6620 | .size = .C, |
| 6576 | }, | 6621 | }, |
| ... | @@ -6581,17 +6626,17 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { | ... | @@ -6581,17 +6626,17 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { |
| 6581 | try writer.writeAll("for ("); | 6626 | try writer.writeAll("for ("); |
| 6582 | try f.writeCValue(writer, index, .Other); | 6627 | try f.writeCValue(writer, index, .Other); |
| 6583 | try writer.writeAll(" = "); | 6628 | try writer.writeAll(" = "); |
| 6584 | try f.object.dg.renderValue(writer, Type.usize, try mod.intValue(Type.usize, 0), .Initializer); | 6629 | try f.object.dg.renderValue(writer, try zcu.intValue(Type.usize, 0), .Initializer); |
| 6585 | try writer.writeAll("; "); | 6630 | try writer.writeAll("; "); |
| 6586 | try f.writeCValue(writer, index, .Other); | 6631 | try f.writeCValue(writer, index, .Other); |
| 6587 | try writer.writeAll(" != "); | 6632 | try writer.writeAll(" != "); |
| 6588 | switch (dest_ty.ptrSize(mod)) { | 6633 | switch (dest_ty.ptrSize(zcu)) { |
| 6589 | .Slice => { | 6634 | .Slice => { |
| 6590 | try f.writeCValueMember(writer, dest_slice, .{ .identifier = "len" }); | 6635 | try f.writeCValueMember(writer, dest_slice, .{ .identifier = "len" }); |
| 6591 | }, | 6636 | }, |
| 6592 | .One => { | 6637 | .One => { |
| 6593 | const array_ty = dest_ty.childType(mod); | 6638 | const array_ty = dest_ty.childType(zcu); |
| 6594 | try writer.print("{d}", .{array_ty.arrayLen(mod)}); | 6639 | try writer.print("{d}", .{array_ty.arrayLen(zcu)}); |
| 6595 | }, | 6640 | }, |
| 6596 | .Many, .C => unreachable, | 6641 | .Many, .C => unreachable, |
| 6597 | } | 6642 | } |
| ... | @@ -6620,7 +6665,7 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { | ... | @@ -6620,7 +6665,7 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { |
| 6620 | const bitcasted = try bitcast(f, Type.u8, value, elem_ty); | 6665 | const bitcasted = try bitcast(f, Type.u8, value, elem_ty); |
| 6621 | 6666 | ||
| 6622 | try writer.writeAll("memset("); | 6667 | try writer.writeAll("memset("); |
| 6623 | switch (dest_ty.ptrSize(mod)) { | 6668 | switch (dest_ty.ptrSize(zcu)) { |
| 6624 | .Slice => { | 6669 | .Slice => { |
| 6625 | try f.writeCValueMember(writer, dest_slice, .{ .identifier = "ptr" }); | 6670 | try f.writeCValueMember(writer, dest_slice, .{ .identifier = "ptr" }); |
| 6626 | try writer.writeAll(", "); | 6671 | try writer.writeAll(", "); |
| ... | @@ -6630,8 +6675,8 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { | ... | @@ -6630,8 +6675,8 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { |
| 6630 | try writer.writeAll(");\n"); | 6675 | try writer.writeAll(");\n"); |
| 6631 | }, | 6676 | }, |
| 6632 | .One => { | 6677 | .One => { |
| 6633 | const array_ty = dest_ty.childType(mod); | 6678 | const array_ty = dest_ty.childType(zcu); |
| 6634 | const len = array_ty.arrayLen(mod) * elem_abi_size; | 6679 | const len = array_ty.arrayLen(zcu) * elem_abi_size; |
| 6635 | 6680 | ||
| 6636 | try f.writeCValue(writer, dest_slice, .FunctionArgument); | 6681 | try f.writeCValue(writer, dest_slice, .FunctionArgument); |
| 6637 | try writer.writeAll(", "); | 6682 | try writer.writeAll(", "); |
| ... | @@ -6646,7 +6691,7 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { | ... | @@ -6646,7 +6691,7 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { |
| 6646 | } | 6691 | } |
| 6647 | 6692 | ||
| 6648 | fn airMemcpy(f: *Function, inst: Air.Inst.Index) !CValue { | 6693 | fn airMemcpy(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6649 | const mod = f.object.dg.module; | 6694 | const zcu = f.object.dg.zcu; |
| 6650 | const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; | 6695 | const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| 6651 | const dest_ptr = try f.resolveInst(bin_op.lhs); | 6696 | const dest_ptr = try f.resolveInst(bin_op.lhs); |
| 6652 | const src_ptr = try f.resolveInst(bin_op.rhs); | 6697 | const src_ptr = try f.resolveInst(bin_op.rhs); |
| ... | @@ -6659,42 +6704,32 @@ fn airMemcpy(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -6659,42 +6704,32 @@ fn airMemcpy(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6659 | try writer.writeAll(", "); | 6704 | try writer.writeAll(", "); |
| 6660 | try writeSliceOrPtr(f, writer, src_ptr, src_ty); | 6705 | try writeSliceOrPtr(f, writer, src_ptr, src_ty); |
| 6661 | try writer.writeAll(", "); | 6706 | try writer.writeAll(", "); |
| 6662 | switch (dest_ty.ptrSize(mod)) { | 6707 | switch (dest_ty.ptrSize(zcu)) { |
| 6663 | .Slice => { | 6708 | .One => try writer.print("{}", .{ |
| 6664 | const elem_ty = dest_ty.childType(mod); | 6709 | try f.fmtIntLiteral(try zcu.intValue(Type.usize, dest_ty.childType(zcu).arrayLen(zcu))), |
| 6665 | const elem_abi_size = elem_ty.abiSize(mod); | 6710 | }), |
| 6666 | try f.writeCValueMember(writer, dest_ptr, .{ .identifier = "len" }); | ||
| 6667 | if (elem_abi_size > 1) { | ||
| 6668 | try writer.print(" * {d});\n", .{elem_abi_size}); | ||
| 6669 | } else { | ||
| 6670 | try writer.writeAll(");\n"); | ||
| 6671 | } | ||
| 6672 | }, | ||
| 6673 | .One => { | ||
| 6674 | const array_ty = dest_ty.childType(mod); | ||
| 6675 | const elem_ty = array_ty.childType(mod); | ||
| 6676 | const elem_abi_size = elem_ty.abiSize(mod); | ||
| 6677 | const len = array_ty.arrayLen(mod) * elem_abi_size; | ||
| 6678 | try writer.print("{d});\n", .{len}); | ||
| 6679 | }, | ||
| 6680 | .Many, .C => unreachable, | 6711 | .Many, .C => unreachable, |
| 6712 | .Slice => try f.writeCValueMember(writer, dest_ptr, .{ .identifier = "len" }), | ||
| 6681 | } | 6713 | } |
| 6714 | try writer.writeAll(" * sizeof("); | ||
| 6715 | try f.renderType(writer, dest_ty.elemType2(zcu)); | ||
| 6716 | try writer.writeAll("));\n"); | ||
| 6682 | 6717 | ||
| 6683 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); | 6718 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); |
| 6684 | return .none; | 6719 | return .none; |
| 6685 | } | 6720 | } |
| 6686 | 6721 | ||
| 6687 | fn airSetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue { | 6722 | fn airSetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6688 | const mod = f.object.dg.module; | 6723 | const zcu = f.object.dg.zcu; |
| 6689 | const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; | 6724 | const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| 6690 | const union_ptr = try f.resolveInst(bin_op.lhs); | 6725 | const union_ptr = try f.resolveInst(bin_op.lhs); |
| 6691 | const new_tag = try f.resolveInst(bin_op.rhs); | 6726 | const new_tag = try f.resolveInst(bin_op.rhs); |
| 6692 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); | 6727 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); |
| 6693 | 6728 | ||
| 6694 | const union_ty = f.typeOf(bin_op.lhs).childType(mod); | 6729 | const union_ty = f.typeOf(bin_op.lhs).childType(zcu); |
| 6695 | const layout = union_ty.unionGetLayout(mod); | 6730 | const layout = union_ty.unionGetLayout(zcu); |
| 6696 | if (layout.tag_size == 0) return .none; | 6731 | if (layout.tag_size == 0) return .none; |
| 6697 | const tag_ty = union_ty.unionTagTypeSafety(mod).?; | 6732 | const tag_ty = union_ty.unionTagTypeSafety(zcu).?; |
| 6698 | 6733 | ||
| 6699 | const writer = f.object.writer(); | 6734 | const writer = f.object.writer(); |
| 6700 | const a = try Assignment.start(f, writer, tag_ty); | 6735 | const a = try Assignment.start(f, writer, tag_ty); |
| ... | @@ -6706,14 +6741,14 @@ fn airSetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -6706,14 +6741,14 @@ fn airSetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6706 | } | 6741 | } |
| 6707 | 6742 | ||
| 6708 | fn airGetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue { | 6743 | fn airGetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6709 | const mod = f.object.dg.module; | 6744 | const zcu = f.object.dg.zcu; |
| 6710 | const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; | 6745 | const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 6711 | 6746 | ||
| 6712 | const operand = try f.resolveInst(ty_op.operand); | 6747 | const operand = try f.resolveInst(ty_op.operand); |
| 6713 | try reap(f, inst, &.{ty_op.operand}); | 6748 | try reap(f, inst, &.{ty_op.operand}); |
| 6714 | 6749 | ||
| 6715 | const union_ty = f.typeOf(ty_op.operand); | 6750 | const union_ty = f.typeOf(ty_op.operand); |
| 6716 | const layout = union_ty.unionGetLayout(mod); | 6751 | const layout = union_ty.unionGetLayout(zcu); |
| 6717 | if (layout.tag_size == 0) return .none; | 6752 | if (layout.tag_size == 0) return .none; |
| 6718 | 6753 | ||
| 6719 | const inst_ty = f.typeOfIndex(inst); | 6754 | const inst_ty = f.typeOfIndex(inst); |
| ... | @@ -6728,7 +6763,7 @@ fn airGetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -6728,7 +6763,7 @@ fn airGetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6728 | } | 6763 | } |
| 6729 | 6764 | ||
| 6730 | fn airTagName(f: *Function, inst: Air.Inst.Index) !CValue { | 6765 | fn airTagName(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6731 | const mod = f.object.dg.module; | 6766 | const zcu = f.object.dg.zcu; |
| 6732 | const un_op = f.air.instructions.items(.data)[@intFromEnum(inst)].un_op; | 6767 | const un_op = f.air.instructions.items(.data)[@intFromEnum(inst)].un_op; |
| 6733 | 6768 | ||
| 6734 | const inst_ty = f.typeOfIndex(inst); | 6769 | const inst_ty = f.typeOfIndex(inst); |
| ... | @@ -6740,7 +6775,7 @@ fn airTagName(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -6740,7 +6775,7 @@ fn airTagName(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6740 | const local = try f.allocLocal(inst, inst_ty); | 6775 | const local = try f.allocLocal(inst, inst_ty); |
| 6741 | try f.writeCValue(writer, local, .Other); | 6776 | try f.writeCValue(writer, local, .Other); |
| 6742 | try writer.print(" = {s}(", .{ | 6777 | try writer.print(" = {s}(", .{ |
| 6743 | try f.getLazyFnName(.{ .tag_name = enum_ty.getOwnerDecl(mod) }, .{ .tag_name = enum_ty }), | 6778 | try f.getLazyFnName(.{ .tag_name = enum_ty.getOwnerDecl(zcu) }, .{ .tag_name = enum_ty }), |
| 6744 | }); | 6779 | }); |
| 6745 | try f.writeCValue(writer, operand, .Other); | 6780 | try f.writeCValue(writer, operand, .Other); |
| 6746 | try writer.writeAll(");\n"); | 6781 | try writer.writeAll(");\n"); |
| ... | @@ -6765,14 +6800,14 @@ fn airErrorName(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -6765,14 +6800,14 @@ fn airErrorName(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6765 | } | 6800 | } |
| 6766 | 6801 | ||
| 6767 | fn airSplat(f: *Function, inst: Air.Inst.Index) !CValue { | 6802 | fn airSplat(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6768 | const mod = f.object.dg.module; | 6803 | const zcu = f.object.dg.zcu; |
| 6769 | const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; | 6804 | const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 6770 | 6805 | ||
| 6771 | const operand = try f.resolveInst(ty_op.operand); | 6806 | const operand = try f.resolveInst(ty_op.operand); |
| 6772 | try reap(f, inst, &.{ty_op.operand}); | 6807 | try reap(f, inst, &.{ty_op.operand}); |
| 6773 | 6808 | ||
| 6774 | const inst_ty = f.typeOfIndex(inst); | 6809 | const inst_ty = f.typeOfIndex(inst); |
| 6775 | const inst_scalar_ty = inst_ty.scalarType(mod); | 6810 | const inst_scalar_ty = inst_ty.scalarType(zcu); |
| 6776 | 6811 | ||
| 6777 | const writer = f.object.writer(); | 6812 | const writer = f.object.writer(); |
| 6778 | const local = try f.allocLocal(inst, inst_ty); | 6813 | const local = try f.allocLocal(inst, inst_ty); |
| ... | @@ -6820,7 +6855,7 @@ fn airSelect(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -6820,7 +6855,7 @@ fn airSelect(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6820 | } | 6855 | } |
| 6821 | 6856 | ||
| 6822 | fn airShuffle(f: *Function, inst: Air.Inst.Index) !CValue { | 6857 | fn airShuffle(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6823 | const mod = f.object.dg.module; | 6858 | const zcu = f.object.dg.zcu; |
| 6824 | const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; | 6859 | const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| 6825 | const extra = f.air.extraData(Air.Shuffle, ty_pl.payload).data; | 6860 | const extra = f.air.extraData(Air.Shuffle, ty_pl.payload).data; |
| 6826 | 6861 | ||
| ... | @@ -6836,15 +6871,15 @@ fn airShuffle(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -6836,15 +6871,15 @@ fn airShuffle(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6836 | for (0..extra.mask_len) |index| { | 6871 | for (0..extra.mask_len) |index| { |
| 6837 | try f.writeCValue(writer, local, .Other); | 6872 | try f.writeCValue(writer, local, .Other); |
| 6838 | try writer.writeByte('['); | 6873 | try writer.writeByte('['); |
| 6839 | try f.object.dg.renderValue(writer, Type.usize, try mod.intValue(Type.usize, index), .Other); | 6874 | try f.object.dg.renderValue(writer, try zcu.intValue(Type.usize, index), .Other); |
| 6840 | try writer.writeAll("] = "); | 6875 | try writer.writeAll("] = "); |
| 6841 | 6876 | ||
| 6842 | const mask_elem = (try mask.elemValue(mod, index)).toSignedInt(mod); | 6877 | const mask_elem = (try mask.elemValue(zcu, index)).toSignedInt(zcu); |
| 6843 | const src_val = try mod.intValue(Type.usize, @as(u64, @intCast(mask_elem ^ mask_elem >> 63))); | 6878 | const src_val = try zcu.intValue(Type.usize, @as(u64, @intCast(mask_elem ^ mask_elem >> 63))); |
| 6844 | 6879 | ||
| 6845 | try f.writeCValue(writer, if (mask_elem >= 0) lhs else rhs, .Other); | 6880 | try f.writeCValue(writer, if (mask_elem >= 0) lhs else rhs, .Other); |
| 6846 | try writer.writeByte('['); | 6881 | try writer.writeByte('['); |
| 6847 | try f.object.dg.renderValue(writer, Type.usize, src_val, .Other); | 6882 | try f.object.dg.renderValue(writer, src_val, .Other); |
| 6848 | try writer.writeAll("];\n"); | 6883 | try writer.writeAll("];\n"); |
| 6849 | } | 6884 | } |
| 6850 | 6885 | ||
| ... | @@ -6852,7 +6887,7 @@ fn airShuffle(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -6852,7 +6887,7 @@ fn airShuffle(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6852 | } | 6887 | } |
| 6853 | 6888 | ||
| 6854 | fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue { | 6889 | fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6855 | const mod = f.object.dg.module; | 6890 | const zcu = f.object.dg.zcu; |
| 6856 | const reduce = f.air.instructions.items(.data)[@intFromEnum(inst)].reduce; | 6891 | const reduce = f.air.instructions.items(.data)[@intFromEnum(inst)].reduce; |
| 6857 | 6892 | ||
| 6858 | const scalar_ty = f.typeOfIndex(inst); | 6893 | const scalar_ty = f.typeOfIndex(inst); |
| ... | @@ -6861,7 +6896,7 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -6861,7 +6896,7 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6861 | const operand_ty = f.typeOf(reduce.operand); | 6896 | const operand_ty = f.typeOf(reduce.operand); |
| 6862 | const writer = f.object.writer(); | 6897 | const writer = f.object.writer(); |
| 6863 | 6898 | ||
| 6864 | const use_operator = scalar_ty.bitSize(mod) <= 64; | 6899 | const use_operator = scalar_ty.bitSize(zcu) <= 64; |
| 6865 | const op: union(enum) { | 6900 | const op: union(enum) { |
| 6866 | const Func = struct { operation: []const u8, info: BuiltinInfo = .none }; | 6901 | const Func = struct { operation: []const u8, info: BuiltinInfo = .none }; |
| 6867 | float_op: Func, | 6902 | float_op: Func, |
| ... | @@ -6872,28 +6907,28 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -6872,28 +6907,28 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6872 | .And => if (use_operator) .{ .infix = " &= " } else .{ .builtin = .{ .operation = "and" } }, | 6907 | .And => if (use_operator) .{ .infix = " &= " } else .{ .builtin = .{ .operation = "and" } }, |
| 6873 | .Or => if (use_operator) .{ .infix = " |= " } else .{ .builtin = .{ .operation = "or" } }, | 6908 | .Or => if (use_operator) .{ .infix = " |= " } else .{ .builtin = .{ .operation = "or" } }, |
| 6874 | .Xor => if (use_operator) .{ .infix = " ^= " } else .{ .builtin = .{ .operation = "xor" } }, | 6909 | .Xor => if (use_operator) .{ .infix = " ^= " } else .{ .builtin = .{ .operation = "xor" } }, |
| 6875 | .Min => switch (scalar_ty.zigTypeTag(mod)) { | 6910 | .Min => switch (scalar_ty.zigTypeTag(zcu)) { |
| 6876 | .Int => if (use_operator) .{ .ternary = " < " } else .{ | 6911 | .Int => if (use_operator) .{ .ternary = " < " } else .{ |
| 6877 | .builtin = .{ .operation = "min" }, | 6912 | .builtin = .{ .operation = "min" }, |
| 6878 | }, | 6913 | }, |
| 6879 | .Float => .{ .float_op = .{ .operation = "fmin" } }, | 6914 | .Float => .{ .float_op = .{ .operation = "fmin" } }, |
| 6880 | else => unreachable, | 6915 | else => unreachable, |
| 6881 | }, | 6916 | }, |
| 6882 | .Max => switch (scalar_ty.zigTypeTag(mod)) { | 6917 | .Max => switch (scalar_ty.zigTypeTag(zcu)) { |
| 6883 | .Int => if (use_operator) .{ .ternary = " > " } else .{ | 6918 | .Int => if (use_operator) .{ .ternary = " > " } else .{ |
| 6884 | .builtin = .{ .operation = "max" }, | 6919 | .builtin = .{ .operation = "max" }, |
| 6885 | }, | 6920 | }, |
| 6886 | .Float => .{ .float_op = .{ .operation = "fmax" } }, | 6921 | .Float => .{ .float_op = .{ .operation = "fmax" } }, |
| 6887 | else => unreachable, | 6922 | else => unreachable, |
| 6888 | }, | 6923 | }, |
| 6889 | .Add => switch (scalar_ty.zigTypeTag(mod)) { | 6924 | .Add => switch (scalar_ty.zigTypeTag(zcu)) { |
| 6890 | .Int => if (use_operator) .{ .infix = " += " } else .{ | 6925 | .Int => if (use_operator) .{ .infix = " += " } else .{ |
| 6891 | .builtin = .{ .operation = "addw", .info = .bits }, | 6926 | .builtin = .{ .operation = "addw", .info = .bits }, |
| 6892 | }, | 6927 | }, |
| 6893 | .Float => .{ .builtin = .{ .operation = "add" } }, | 6928 | .Float => .{ .builtin = .{ .operation = "add" } }, |
| 6894 | else => unreachable, | 6929 | else => unreachable, |
| 6895 | }, | 6930 | }, |
| 6896 | .Mul => switch (scalar_ty.zigTypeTag(mod)) { | 6931 | .Mul => switch (scalar_ty.zigTypeTag(zcu)) { |
| 6897 | .Int => if (use_operator) .{ .infix = " *= " } else .{ | 6932 | .Int => if (use_operator) .{ .infix = " *= " } else .{ |
| 6898 | .builtin = .{ .operation = "mulw", .info = .bits }, | 6933 | .builtin = .{ .operation = "mulw", .info = .bits }, |
| 6899 | }, | 6934 | }, |
| ... | @@ -6908,7 +6943,7 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -6908,7 +6943,7 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6908 | // Equivalent to: | 6943 | // Equivalent to: |
| 6909 | // reduce: { | 6944 | // reduce: { |
| 6910 | // var accum: T = init; | 6945 | // var accum: T = init; |
| 6911 | // for (vec) : (elem) { | 6946 | // for (vec) |elem| { |
| 6912 | // accum = func(accum, elem); | 6947 | // accum = func(accum, elem); |
| 6913 | // } | 6948 | // } |
| 6914 | // break :reduce accum; | 6949 | // break :reduce accum; |
| ... | @@ -6918,40 +6953,40 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -6918,40 +6953,40 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6918 | try f.writeCValue(writer, accum, .Other); | 6953 | try f.writeCValue(writer, accum, .Other); |
| 6919 | try writer.writeAll(" = "); | 6954 | try writer.writeAll(" = "); |
| 6920 | 6955 | ||
| 6921 | try f.object.dg.renderValue(writer, scalar_ty, switch (reduce.operation) { | 6956 | try f.object.dg.renderValue(writer, switch (reduce.operation) { |
| 6922 | .Or, .Xor => switch (scalar_ty.zigTypeTag(mod)) { | 6957 | .Or, .Xor => switch (scalar_ty.zigTypeTag(zcu)) { |
| 6923 | .Bool => Value.false, | 6958 | .Bool => Value.false, |
| 6924 | .Int => try mod.intValue(scalar_ty, 0), | 6959 | .Int => try zcu.intValue(scalar_ty, 0), |
| 6925 | else => unreachable, | 6960 | else => unreachable, |
| 6926 | }, | 6961 | }, |
| 6927 | .And => switch (scalar_ty.zigTypeTag(mod)) { | 6962 | .And => switch (scalar_ty.zigTypeTag(zcu)) { |
| 6928 | .Bool => Value.true, | 6963 | .Bool => Value.true, |
| 6929 | .Int => switch (scalar_ty.intInfo(mod).signedness) { | 6964 | .Int => switch (scalar_ty.intInfo(zcu).signedness) { |
| 6930 | .unsigned => try scalar_ty.maxIntScalar(mod, scalar_ty), | 6965 | .unsigned => try scalar_ty.maxIntScalar(zcu, scalar_ty), |
| 6931 | .signed => try mod.intValue(scalar_ty, -1), | 6966 | .signed => try zcu.intValue(scalar_ty, -1), |
| 6932 | }, | 6967 | }, |
| 6933 | else => unreachable, | 6968 | else => unreachable, |
| 6934 | }, | 6969 | }, |
| 6935 | .Add => switch (scalar_ty.zigTypeTag(mod)) { | 6970 | .Add => switch (scalar_ty.zigTypeTag(zcu)) { |
| 6936 | .Int => try mod.intValue(scalar_ty, 0), | 6971 | .Int => try zcu.intValue(scalar_ty, 0), |
| 6937 | .Float => try mod.floatValue(scalar_ty, 0.0), | 6972 | .Float => try zcu.floatValue(scalar_ty, 0.0), |
| 6938 | else => unreachable, | 6973 | else => unreachable, |
| 6939 | }, | 6974 | }, |
| 6940 | .Mul => switch (scalar_ty.zigTypeTag(mod)) { | 6975 | .Mul => switch (scalar_ty.zigTypeTag(zcu)) { |
| 6941 | .Int => try mod.intValue(scalar_ty, 1), | 6976 | .Int => try zcu.intValue(scalar_ty, 1), |
| 6942 | .Float => try mod.floatValue(scalar_ty, 1.0), | 6977 | .Float => try zcu.floatValue(scalar_ty, 1.0), |
| 6943 | else => unreachable, | 6978 | else => unreachable, |
| 6944 | }, | 6979 | }, |
| 6945 | .Min => switch (scalar_ty.zigTypeTag(mod)) { | 6980 | .Min => switch (scalar_ty.zigTypeTag(zcu)) { |
| 6946 | .Bool => Value.true, | 6981 | .Bool => Value.true, |
| 6947 | .Int => try scalar_ty.maxIntScalar(mod, scalar_ty), | 6982 | .Int => try scalar_ty.maxIntScalar(zcu, scalar_ty), |
| 6948 | .Float => try mod.floatValue(scalar_ty, std.math.nan(f128)), | 6983 | .Float => try zcu.floatValue(scalar_ty, std.math.nan(f128)), |
| 6949 | else => unreachable, | 6984 | else => unreachable, |
| 6950 | }, | 6985 | }, |
| 6951 | .Max => switch (scalar_ty.zigTypeTag(mod)) { | 6986 | .Max => switch (scalar_ty.zigTypeTag(zcu)) { |
| 6952 | .Bool => Value.false, | 6987 | .Bool => Value.false, |
| 6953 | .Int => try scalar_ty.minIntScalar(mod, scalar_ty), | 6988 | .Int => try scalar_ty.minIntScalar(zcu, scalar_ty), |
| 6954 | .Float => try mod.floatValue(scalar_ty, std.math.nan(f128)), | 6989 | .Float => try zcu.floatValue(scalar_ty, std.math.nan(f128)), |
| 6955 | else => unreachable, | 6990 | else => unreachable, |
| 6956 | }, | 6991 | }, |
| 6957 | }, .Initializer); | 6992 | }, .Initializer); |
| ... | @@ -7007,11 +7042,11 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -7007,11 +7042,11 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7007 | } | 7042 | } |
| 7008 | 7043 | ||
| 7009 | fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { | 7044 | fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7010 | const mod = f.object.dg.module; | 7045 | const zcu = f.object.dg.zcu; |
| 7011 | const ip = &mod.intern_pool; | 7046 | const ip = &zcu.intern_pool; |
| 7012 | const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; | 7047 | const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| 7013 | const inst_ty = f.typeOfIndex(inst); | 7048 | const inst_ty = f.typeOfIndex(inst); |
| 7014 | const len = @as(usize, @intCast(inst_ty.arrayLen(mod))); | 7049 | const len = @as(usize, @intCast(inst_ty.arrayLen(zcu))); |
| 7015 | const elements = @as([]const Air.Inst.Ref, @ptrCast(f.air.extra[ty_pl.payload..][0..len])); | 7050 | const elements = @as([]const Air.Inst.Ref, @ptrCast(f.air.extra[ty_pl.payload..][0..len])); |
| 7016 | const gpa = f.object.dg.gpa; | 7051 | const gpa = f.object.dg.gpa; |
| 7017 | const resolved_elements = try gpa.alloc(CValue, elements.len); | 7052 | const resolved_elements = try gpa.alloc(CValue, elements.len); |
| ... | @@ -7028,10 +7063,9 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -7028,10 +7063,9 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7028 | 7063 | ||
| 7029 | const writer = f.object.writer(); | 7064 | const writer = f.object.writer(); |
| 7030 | const local = try f.allocLocal(inst, inst_ty); | 7065 | const local = try f.allocLocal(inst, inst_ty); |
| 7031 | switch (inst_ty.zigTypeTag(mod)) { | 7066 | switch (ip.indexToKey(inst_ty.toIntern())) { |
| 7032 | .Array, .Vector => { | 7067 | inline .array_type, .vector_type => |info, tag| { |
| 7033 | const elem_ty = inst_ty.childType(mod); | 7068 | const a = try Assignment.init(f, Type.fromInterned(info.child)); |
| 7034 | const a = try Assignment.init(f, elem_ty); | ||
| 7035 | for (resolved_elements, 0..) |element, i| { | 7069 | for (resolved_elements, 0..) |element, i| { |
| 7036 | try a.restart(f, writer); | 7070 | try a.restart(f, writer); |
| 7037 | try f.writeCValue(writer, local, .Other); | 7071 | try f.writeCValue(writer, local, .Other); |
| ... | @@ -7040,94 +7074,112 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -7040,94 +7074,112 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7040 | try f.writeCValue(writer, element, .Other); | 7074 | try f.writeCValue(writer, element, .Other); |
| 7041 | try a.end(f, writer); | 7075 | try a.end(f, writer); |
| 7042 | } | 7076 | } |
| 7043 | if (inst_ty.sentinel(mod)) |sentinel| { | 7077 | if (tag == .array_type and info.sentinel != .none) { |
| 7044 | try a.restart(f, writer); | 7078 | try a.restart(f, writer); |
| 7045 | try f.writeCValue(writer, local, .Other); | 7079 | try f.writeCValue(writer, local, .Other); |
| 7046 | try writer.print("[{d}]", .{resolved_elements.len}); | 7080 | try writer.print("[{d}]", .{info.len}); |
| 7047 | try a.assign(f, writer); | 7081 | try a.assign(f, writer); |
| 7048 | try f.object.dg.renderValue(writer, elem_ty, sentinel, .Other); | 7082 | try f.object.dg.renderValue(writer, Value.fromInterned(info.sentinel), .Other); |
| 7049 | try a.end(f, writer); | 7083 | try a.end(f, writer); |
| 7050 | } | 7084 | } |
| 7051 | }, | 7085 | }, |
| 7052 | .Struct => switch (inst_ty.containerLayout(mod)) { | 7086 | .struct_type => { |
| 7053 | .auto, .@"extern" => for (resolved_elements, 0..) |element, field_index| { | 7087 | const loaded_struct = ip.loadStructType(inst_ty.toIntern()); |
| 7054 | if (inst_ty.structFieldIsComptime(field_index, mod)) continue; | 7088 | switch (loaded_struct.layout) { |
| 7055 | const field_ty = inst_ty.structFieldType(field_index, mod); | 7089 | .auto, .@"extern" => { |
| 7056 | if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; | 7090 | var field_it = loaded_struct.iterateRuntimeOrder(ip); |
| 7057 | 7091 | while (field_it.next()) |field_index| { | |
| 7058 | const a = try Assignment.start(f, writer, field_ty); | 7092 | const field_ty = Type.fromInterned(loaded_struct.field_types.get(ip)[field_index]); |
| 7059 | try f.writeCValueMember(writer, local, if (inst_ty.isSimpleTuple(mod)) | 7093 | if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; |
| 7060 | .{ .field = field_index } | 7094 | |
| 7061 | else | 7095 | const a = try Assignment.start(f, writer, field_ty); |
| 7062 | .{ .identifier = ip.stringToSlice(inst_ty.legacyStructFieldName(@intCast(field_index), mod)) }); | 7096 | try f.writeCValueMember(writer, local, if (loaded_struct.fieldName(ip, field_index).unwrap()) |field_name| |
| 7063 | try a.assign(f, writer); | 7097 | .{ .identifier = ip.stringToSlice(field_name) } |
| 7064 | try f.writeCValue(writer, element, .Other); | 7098 | else |
| 7065 | try a.end(f, writer); | 7099 | .{ .field = field_index }); |
| 7066 | }, | 7100 | try a.assign(f, writer); |
| 7067 | .@"packed" => { | 7101 | try f.writeCValue(writer, resolved_elements[field_index], .Other); |
| 7068 | try f.writeCValue(writer, local, .Other); | 7102 | try a.end(f, writer); |
| 7069 | try writer.writeAll(" = "); | 7103 | } |
| 7070 | const int_info = inst_ty.intInfo(mod); | 7104 | }, |
| 7071 | 7105 | .@"packed" => { | |
| 7072 | const bit_offset_ty = try mod.intType(.unsigned, Type.smallestUnsignedBits(int_info.bits - 1)); | 7106 | try f.writeCValue(writer, local, .Other); |
| 7107 | try writer.writeAll(" = "); | ||
| 7108 | const int_info = inst_ty.intInfo(zcu); | ||
| 7073 | 7109 | ||
| 7074 | var bit_offset: u64 = 0; | 7110 | const bit_offset_ty = try zcu.intType(.unsigned, Type.smallestUnsignedBits(int_info.bits - 1)); |
| 7075 | 7111 | ||
| 7076 | var empty = true; | 7112 | var bit_offset: u64 = 0; |
| 7077 | for (0..elements.len) |field_index| { | ||
| 7078 | if (inst_ty.structFieldIsComptime(field_index, mod)) continue; | ||
| 7079 | const field_ty = inst_ty.structFieldType(field_index, mod); | ||
| 7080 | if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; | ||
| 7081 | 7113 | ||
| 7082 | if (!empty) { | 7114 | var empty = true; |
| 7083 | try writer.writeAll("zig_or_"); | 7115 | for (0..elements.len) |field_index| { |
| 7116 | if (inst_ty.structFieldIsComptime(field_index, zcu)) continue; | ||
| 7117 | const field_ty = inst_ty.structFieldType(field_index, zcu); | ||
| 7118 | if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; | ||
| 7119 | |||
| 7120 | if (!empty) { | ||
| 7121 | try writer.writeAll("zig_or_"); | ||
| 7122 | try f.object.dg.renderTypeForBuiltinFnName(writer, inst_ty); | ||
| 7123 | try writer.writeByte('('); | ||
| 7124 | } | ||
| 7125 | empty = false; | ||
| 7126 | } | ||
| 7127 | empty = true; | ||
| 7128 | for (resolved_elements, 0..) |element, field_index| { | ||
| 7129 | if (inst_ty.structFieldIsComptime(field_index, zcu)) continue; | ||
| 7130 | const field_ty = inst_ty.structFieldType(field_index, zcu); | ||
| 7131 | if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; | ||
| 7132 | |||
| 7133 | if (!empty) try writer.writeAll(", "); | ||
| 7134 | // TODO: Skip this entire shift if val is 0? | ||
| 7135 | try writer.writeAll("zig_shlw_"); | ||
| 7084 | try f.object.dg.renderTypeForBuiltinFnName(writer, inst_ty); | 7136 | try f.object.dg.renderTypeForBuiltinFnName(writer, inst_ty); |
| 7085 | try writer.writeByte('('); | 7137 | try writer.writeByte('('); |
| 7086 | } | ||
| 7087 | empty = false; | ||
| 7088 | } | ||
| 7089 | empty = true; | ||
| 7090 | for (resolved_elements, 0..) |element, field_index| { | ||
| 7091 | if (inst_ty.structFieldIsComptime(field_index, mod)) continue; | ||
| 7092 | const field_ty = inst_ty.structFieldType(field_index, mod); | ||
| 7093 | if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; | ||
| 7094 | |||
| 7095 | if (!empty) try writer.writeAll(", "); | ||
| 7096 | // TODO: Skip this entire shift if val is 0? | ||
| 7097 | try writer.writeAll("zig_shlw_"); | ||
| 7098 | try f.object.dg.renderTypeForBuiltinFnName(writer, inst_ty); | ||
| 7099 | try writer.writeByte('('); | ||
| 7100 | 7138 | ||
| 7101 | if (inst_ty.isAbiInt(mod) and (field_ty.isAbiInt(mod) or field_ty.isPtrAtRuntime(mod))) { | 7139 | if (inst_ty.isAbiInt(zcu) and (field_ty.isAbiInt(zcu) or field_ty.isPtrAtRuntime(zcu))) { |
| 7102 | try f.renderIntCast(writer, inst_ty, element, .{}, field_ty, .FunctionArgument); | 7140 | try f.renderIntCast(writer, inst_ty, element, .{}, field_ty, .FunctionArgument); |
| 7103 | } else { | 7141 | } else { |
| 7104 | try writer.writeByte('('); | ||
| 7105 | try f.renderType(writer, inst_ty); | ||
| 7106 | try writer.writeByte(')'); | ||
| 7107 | if (field_ty.isPtrAtRuntime(mod)) { | ||
| 7108 | try writer.writeByte('('); | 7142 | try writer.writeByte('('); |
| 7109 | try f.renderType(writer, switch (int_info.signedness) { | 7143 | try f.renderType(writer, inst_ty); |
| 7110 | .unsigned => Type.usize, | ||
| 7111 | .signed => Type.isize, | ||
| 7112 | }); | ||
| 7113 | try writer.writeByte(')'); | 7144 | try writer.writeByte(')'); |
| 7145 | if (field_ty.isPtrAtRuntime(zcu)) { | ||
| 7146 | try writer.writeByte('('); | ||
| 7147 | try f.renderType(writer, switch (int_info.signedness) { | ||
| 7148 | .unsigned => Type.usize, | ||
| 7149 | .signed => Type.isize, | ||
| 7150 | }); | ||
| 7151 | try writer.writeByte(')'); | ||
| 7152 | } | ||
| 7153 | try f.writeCValue(writer, element, .Other); | ||
| 7114 | } | 7154 | } |
| 7115 | try f.writeCValue(writer, element, .Other); | ||
| 7116 | } | ||
| 7117 | |||
| 7118 | try writer.writeAll(", "); | ||
| 7119 | const bit_offset_val = try mod.intValue(bit_offset_ty, bit_offset); | ||
| 7120 | try f.object.dg.renderValue(writer, bit_offset_ty, bit_offset_val, .FunctionArgument); | ||
| 7121 | try f.object.dg.renderBuiltinInfo(writer, inst_ty, .bits); | ||
| 7122 | try writer.writeByte(')'); | ||
| 7123 | if (!empty) try writer.writeByte(')'); | ||
| 7124 | 7155 | ||
| 7125 | bit_offset += field_ty.bitSize(mod); | 7156 | try writer.print(", {}", .{ |
| 7126 | empty = false; | 7157 | try f.fmtIntLiteral(try zcu.intValue(bit_offset_ty, bit_offset)), |
| 7127 | } | 7158 | }); |
| 7159 | try f.object.dg.renderBuiltinInfo(writer, inst_ty, .bits); | ||
| 7160 | try writer.writeByte(')'); | ||
| 7161 | if (!empty) try writer.writeByte(')'); | ||
| 7128 | 7162 | ||
| 7129 | try writer.writeAll(";\n"); | 7163 | bit_offset += field_ty.bitSize(zcu); |
| 7130 | }, | 7164 | empty = false; |
| 7165 | } | ||
| 7166 | try writer.writeAll(";\n"); | ||
| 7167 | }, | ||
| 7168 | } | ||
| 7169 | }, | ||
| 7170 | .anon_struct_type => |anon_struct_info| for (0..anon_struct_info.types.len) |field_index| { | ||
| 7171 | if (anon_struct_info.values.get(ip)[field_index] != .none) continue; | ||
| 7172 | const field_ty = Type.fromInterned(anon_struct_info.types.get(ip)[field_index]); | ||
| 7173 | if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; | ||
| 7174 | |||
| 7175 | const a = try Assignment.start(f, writer, field_ty); | ||
| 7176 | try f.writeCValueMember(writer, local, if (anon_struct_info.fieldName(ip, field_index).unwrap()) |field_name| | ||
| 7177 | .{ .identifier = ip.stringToSlice(field_name) } | ||
| 7178 | else | ||
| 7179 | .{ .field = field_index }); | ||
| 7180 | try a.assign(f, writer); | ||
| 7181 | try f.writeCValue(writer, resolved_elements[field_index], .Other); | ||
| 7182 | try a.end(f, writer); | ||
| 7131 | }, | 7183 | }, |
| 7132 | else => unreachable, | 7184 | else => unreachable, |
| 7133 | } | 7185 | } |
| ... | @@ -7136,21 +7188,21 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -7136,21 +7188,21 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7136 | } | 7188 | } |
| 7137 | 7189 | ||
| 7138 | fn airUnionInit(f: *Function, inst: Air.Inst.Index) !CValue { | 7190 | fn airUnionInit(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7139 | const mod = f.object.dg.module; | 7191 | const zcu = f.object.dg.zcu; |
| 7140 | const ip = &mod.intern_pool; | 7192 | const ip = &zcu.intern_pool; |
| 7141 | const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; | 7193 | const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| 7142 | const extra = f.air.extraData(Air.UnionInit, ty_pl.payload).data; | 7194 | const extra = f.air.extraData(Air.UnionInit, ty_pl.payload).data; |
| 7143 | 7195 | ||
| 7144 | const union_ty = f.typeOfIndex(inst); | 7196 | const union_ty = f.typeOfIndex(inst); |
| 7145 | const union_obj = mod.typeToUnion(union_ty).?; | 7197 | const loaded_union = ip.loadUnionType(union_ty.toIntern()); |
| 7146 | const field_name = union_obj.loadTagType(ip).names.get(ip)[extra.field_index]; | 7198 | const field_name = loaded_union.loadTagType(ip).names.get(ip)[extra.field_index]; |
| 7147 | const payload_ty = f.typeOf(extra.init); | 7199 | const payload_ty = f.typeOf(extra.init); |
| 7148 | const payload = try f.resolveInst(extra.init); | 7200 | const payload = try f.resolveInst(extra.init); |
| 7149 | try reap(f, inst, &.{extra.init}); | 7201 | try reap(f, inst, &.{extra.init}); |
| 7150 | 7202 | ||
| 7151 | const writer = f.object.writer(); | 7203 | const writer = f.object.writer(); |
| 7152 | const local = try f.allocLocal(inst, union_ty); | 7204 | const local = try f.allocLocal(inst, union_ty); |
| 7153 | if (union_obj.getLayout(ip) == .@"packed") { | 7205 | if (loaded_union.getLayout(ip) == .@"packed") { |
| 7154 | try f.writeCValue(writer, local, .Other); | 7206 | try f.writeCValue(writer, local, .Other); |
| 7155 | try writer.writeAll(" = "); | 7207 | try writer.writeAll(" = "); |
| 7156 | try f.writeCValue(writer, payload, .Initializer); | 7208 | try f.writeCValue(writer, payload, .Initializer); |
| ... | @@ -7158,19 +7210,16 @@ fn airUnionInit(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -7158,19 +7210,16 @@ fn airUnionInit(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7158 | return local; | 7210 | return local; |
| 7159 | } | 7211 | } |
| 7160 | 7212 | ||
| 7161 | const field: CValue = if (union_ty.unionTagTypeSafety(mod)) |tag_ty| field: { | 7213 | const field: CValue = if (union_ty.unionTagTypeSafety(zcu)) |tag_ty| field: { |
| 7162 | const layout = union_ty.unionGetLayout(mod); | 7214 | const layout = union_ty.unionGetLayout(zcu); |
| 7163 | if (layout.tag_size != 0) { | 7215 | if (layout.tag_size != 0) { |
| 7164 | const field_index = tag_ty.enumFieldIndex(field_name, mod).?; | 7216 | const field_index = tag_ty.enumFieldIndex(field_name, zcu).?; |
| 7165 | 7217 | const tag_val = try zcu.enumValueFieldIndex(tag_ty, field_index); | |
| 7166 | const tag_val = try mod.enumValueFieldIndex(tag_ty, field_index); | ||
| 7167 | |||
| 7168 | const int_val = try tag_val.intFromEnum(tag_ty, mod); | ||
| 7169 | 7218 | ||
| 7170 | const a = try Assignment.start(f, writer, tag_ty); | 7219 | const a = try Assignment.start(f, writer, tag_ty); |
| 7171 | try f.writeCValueMember(writer, local, .{ .identifier = "tag" }); | 7220 | try f.writeCValueMember(writer, local, .{ .identifier = "tag" }); |
| 7172 | try a.assign(f, writer); | 7221 | try a.assign(f, writer); |
| 7173 | try writer.print("{}", .{try f.fmtIntLiteral(tag_ty, int_val)}); | 7222 | try writer.print("{}", .{try f.fmtIntLiteral(try tag_val.intFromEnum(tag_ty, zcu))}); |
| 7174 | try a.end(f, writer); | 7223 | try a.end(f, writer); |
| 7175 | } | 7224 | } |
| 7176 | break :field .{ .payload_identifier = ip.stringToSlice(field_name) }; | 7225 | break :field .{ .payload_identifier = ip.stringToSlice(field_name) }; |
| ... | @@ -7185,7 +7234,7 @@ fn airUnionInit(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -7185,7 +7234,7 @@ fn airUnionInit(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7185 | } | 7234 | } |
| 7186 | 7235 | ||
| 7187 | fn airPrefetch(f: *Function, inst: Air.Inst.Index) !CValue { | 7236 | fn airPrefetch(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7188 | const mod = f.object.dg.module; | 7237 | const zcu = f.object.dg.zcu; |
| 7189 | const prefetch = f.air.instructions.items(.data)[@intFromEnum(inst)].prefetch; | 7238 | const prefetch = f.air.instructions.items(.data)[@intFromEnum(inst)].prefetch; |
| 7190 | 7239 | ||
| 7191 | const ptr_ty = f.typeOf(prefetch.ptr); | 7240 | const ptr_ty = f.typeOf(prefetch.ptr); |
| ... | @@ -7196,7 +7245,7 @@ fn airPrefetch(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -7196,7 +7245,7 @@ fn airPrefetch(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7196 | switch (prefetch.cache) { | 7245 | switch (prefetch.cache) { |
| 7197 | .data => { | 7246 | .data => { |
| 7198 | try writer.writeAll("zig_prefetch("); | 7247 | try writer.writeAll("zig_prefetch("); |
| 7199 | if (ptr_ty.isSlice(mod)) | 7248 | if (ptr_ty.isSlice(zcu)) |
| 7200 | try f.writeCValueMember(writer, ptr, .{ .identifier = "ptr" }) | 7249 | try f.writeCValueMember(writer, ptr, .{ .identifier = "ptr" }) |
| 7201 | else | 7250 | else |
| 7202 | try f.writeCValue(writer, ptr, .FunctionArgument); | 7251 | try f.writeCValue(writer, ptr, .FunctionArgument); |
| ... | @@ -7242,14 +7291,14 @@ fn airWasmMemoryGrow(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -7242,14 +7291,14 @@ fn airWasmMemoryGrow(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7242 | } | 7291 | } |
| 7243 | 7292 | ||
| 7244 | fn airFloatNeg(f: *Function, inst: Air.Inst.Index) !CValue { | 7293 | fn airFloatNeg(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7245 | const mod = f.object.dg.module; | 7294 | const zcu = f.object.dg.zcu; |
| 7246 | const un_op = f.air.instructions.items(.data)[@intFromEnum(inst)].un_op; | 7295 | const un_op = f.air.instructions.items(.data)[@intFromEnum(inst)].un_op; |
| 7247 | 7296 | ||
| 7248 | const operand = try f.resolveInst(un_op); | 7297 | const operand = try f.resolveInst(un_op); |
| 7249 | try reap(f, inst, &.{un_op}); | 7298 | try reap(f, inst, &.{un_op}); |
| 7250 | 7299 | ||
| 7251 | const operand_ty = f.typeOf(un_op); | 7300 | const operand_ty = f.typeOf(un_op); |
| 7252 | const scalar_ty = operand_ty.scalarType(mod); | 7301 | const scalar_ty = operand_ty.scalarType(zcu); |
| 7253 | 7302 | ||
| 7254 | const writer = f.object.writer(); | 7303 | const writer = f.object.writer(); |
| 7255 | const local = try f.allocLocal(inst, operand_ty); | 7304 | const local = try f.allocLocal(inst, operand_ty); |
| ... | @@ -7268,15 +7317,15 @@ fn airFloatNeg(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -7268,15 +7317,15 @@ fn airFloatNeg(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7268 | } | 7317 | } |
| 7269 | 7318 | ||
| 7270 | fn airAbs(f: *Function, inst: Air.Inst.Index) !CValue { | 7319 | fn airAbs(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7271 | const mod = f.object.dg.module; | 7320 | const zcu = f.object.dg.zcu; |
| 7272 | const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; | 7321 | const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 7273 | const operand = try f.resolveInst(ty_op.operand); | 7322 | const operand = try f.resolveInst(ty_op.operand); |
| 7274 | const ty = f.typeOf(ty_op.operand); | 7323 | const ty = f.typeOf(ty_op.operand); |
| 7275 | const scalar_ty = ty.scalarType(mod); | 7324 | const scalar_ty = ty.scalarType(zcu); |
| 7276 | 7325 | ||
| 7277 | switch (scalar_ty.zigTypeTag(mod)) { | 7326 | switch (scalar_ty.zigTypeTag(zcu)) { |
| 7278 | .Int => if (ty.zigTypeTag(mod) == .Vector) { | 7327 | .Int => if (ty.zigTypeTag(zcu) == .Vector) { |
| 7279 | return f.fail("TODO implement airAbs for '{}'", .{ty.fmt(mod)}); | 7328 | return f.fail("TODO implement airAbs for '{}'", .{ty.fmt(zcu)}); |
| 7280 | } else { | 7329 | } else { |
| 7281 | return airUnBuiltinCall(f, inst, "abs", .none); | 7330 | return airUnBuiltinCall(f, inst, "abs", .none); |
| 7282 | }, | 7331 | }, |
| ... | @@ -7286,8 +7335,8 @@ fn airAbs(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -7286,8 +7335,8 @@ fn airAbs(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7286 | } | 7335 | } |
| 7287 | 7336 | ||
| 7288 | fn unFloatOp(f: *Function, inst: Air.Inst.Index, operand: CValue, ty: Type, operation: []const u8) !CValue { | 7337 | fn unFloatOp(f: *Function, inst: Air.Inst.Index, operand: CValue, ty: Type, operation: []const u8) !CValue { |
| 7289 | const mod = f.object.dg.module; | 7338 | const zcu = f.object.dg.zcu; |
| 7290 | const scalar_ty = ty.scalarType(mod); | 7339 | const scalar_ty = ty.scalarType(zcu); |
| 7291 | 7340 | ||
| 7292 | const writer = f.object.writer(); | 7341 | const writer = f.object.writer(); |
| 7293 | const local = try f.allocLocal(inst, ty); | 7342 | const local = try f.allocLocal(inst, ty); |
| ... | @@ -7316,7 +7365,7 @@ fn airUnFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CVal | ... | @@ -7316,7 +7365,7 @@ fn airUnFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CVal |
| 7316 | } | 7365 | } |
| 7317 | 7366 | ||
| 7318 | fn airBinFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CValue { | 7367 | fn airBinFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CValue { |
| 7319 | const mod = f.object.dg.module; | 7368 | const zcu = f.object.dg.zcu; |
| 7320 | const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; | 7369 | const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| 7321 | 7370 | ||
| 7322 | const lhs = try f.resolveInst(bin_op.lhs); | 7371 | const lhs = try f.resolveInst(bin_op.lhs); |
| ... | @@ -7324,7 +7373,7 @@ fn airBinFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CVa | ... | @@ -7324,7 +7373,7 @@ fn airBinFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CVa |
| 7324 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); | 7373 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); |
| 7325 | 7374 | ||
| 7326 | const inst_ty = f.typeOfIndex(inst); | 7375 | const inst_ty = f.typeOfIndex(inst); |
| 7327 | const inst_scalar_ty = inst_ty.scalarType(mod); | 7376 | const inst_scalar_ty = inst_ty.scalarType(zcu); |
| 7328 | 7377 | ||
| 7329 | const writer = f.object.writer(); | 7378 | const writer = f.object.writer(); |
| 7330 | const local = try f.allocLocal(inst, inst_ty); | 7379 | const local = try f.allocLocal(inst, inst_ty); |
| ... | @@ -7346,7 +7395,7 @@ fn airBinFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CVa | ... | @@ -7346,7 +7395,7 @@ fn airBinFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CVa |
| 7346 | } | 7395 | } |
| 7347 | 7396 | ||
| 7348 | fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue { | 7397 | fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7349 | const mod = f.object.dg.module; | 7398 | const zcu = f.object.dg.zcu; |
| 7350 | const pl_op = f.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; | 7399 | const pl_op = f.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; |
| 7351 | const bin_op = f.air.extraData(Air.Bin, pl_op.payload).data; | 7400 | const bin_op = f.air.extraData(Air.Bin, pl_op.payload).data; |
| 7352 | 7401 | ||
| ... | @@ -7356,7 +7405,7 @@ fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -7356,7 +7405,7 @@ fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7356 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs, pl_op.operand }); | 7405 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs, pl_op.operand }); |
| 7357 | 7406 | ||
| 7358 | const inst_ty = f.typeOfIndex(inst); | 7407 | const inst_ty = f.typeOfIndex(inst); |
| 7359 | const inst_scalar_ty = inst_ty.scalarType(mod); | 7408 | const inst_scalar_ty = inst_ty.scalarType(zcu); |
| 7360 | 7409 | ||
| 7361 | const writer = f.object.writer(); | 7410 | const writer = f.object.writer(); |
| 7362 | const local = try f.allocLocal(inst, inst_ty); | 7411 | const local = try f.allocLocal(inst, inst_ty); |
| ... | @@ -7381,20 +7430,20 @@ fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -7381,20 +7430,20 @@ fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7381 | } | 7430 | } |
| 7382 | 7431 | ||
| 7383 | fn airCVaStart(f: *Function, inst: Air.Inst.Index) !CValue { | 7432 | fn airCVaStart(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7384 | const mod = f.object.dg.module; | 7433 | const zcu = f.object.dg.zcu; |
| 7385 | const inst_ty = f.typeOfIndex(inst); | 7434 | const inst_ty = f.typeOfIndex(inst); |
| 7386 | const decl_index = f.object.dg.pass.decl; | 7435 | const decl_index = f.object.dg.pass.decl; |
| 7387 | const decl = mod.declPtr(decl_index); | 7436 | const decl = zcu.declPtr(decl_index); |
| 7388 | const fn_cty = try f.typeToCType(decl.typeOf(mod), .complete); | 7437 | const function_ctype = try f.ctypeFromType(decl.typeOf(zcu), .complete); |
| 7389 | const param_len = fn_cty.castTag(.varargs_function).?.data.param_types.len; | 7438 | const params_len = function_ctype.info(&f.object.dg.ctype_pool).function.param_ctypes.len; |
| 7390 | 7439 | ||
| 7391 | const writer = f.object.writer(); | 7440 | const writer = f.object.writer(); |
| 7392 | const local = try f.allocLocal(inst, inst_ty); | 7441 | const local = try f.allocLocal(inst, inst_ty); |
| 7393 | try writer.writeAll("va_start(*(va_list *)&"); | 7442 | try writer.writeAll("va_start(*(va_list *)&"); |
| 7394 | try f.writeCValue(writer, local, .Other); | 7443 | try f.writeCValue(writer, local, .Other); |
| 7395 | if (param_len > 0) { | 7444 | if (params_len > 0) { |
| 7396 | try writer.writeAll(", "); | 7445 | try writer.writeAll(", "); |
| 7397 | try f.writeCValue(writer, .{ .arg = param_len - 1 }, .FunctionArgument); | 7446 | try f.writeCValue(writer, .{ .arg = params_len - 1 }, .FunctionArgument); |
| 7398 | } | 7447 | } |
| 7399 | try writer.writeAll(");\n"); | 7448 | try writer.writeAll(");\n"); |
| 7400 | return local; | 7449 | return local; |
| ... | @@ -7589,9 +7638,8 @@ fn signAbbrev(signedness: std.builtin.Signedness) u8 { | ... | @@ -7589,9 +7638,8 @@ fn signAbbrev(signedness: std.builtin.Signedness) u8 { |
| 7589 | }; | 7638 | }; |
| 7590 | } | 7639 | } |
| 7591 | 7640 | ||
| 7592 | fn compilerRtAbbrev(ty: Type, mod: *Module) []const u8 { | 7641 | fn compilerRtAbbrev(ty: Type, zcu: *Zcu, target: std.Target) []const u8 { |
| 7593 | const target = mod.getTarget(); | 7642 | return if (ty.isInt(zcu)) switch (ty.intInfo(zcu).bits) { |
| 7594 | return if (ty.isInt(mod)) switch (ty.intInfo(mod).bits) { | ||
| 7595 | 1...32 => "si", | 7643 | 1...32 => "si", |
| 7596 | 33...64 => "di", | 7644 | 33...64 => "di", |
| 7597 | 65...128 => "ti", | 7645 | 65...128 => "ti", |
| ... | @@ -7744,7 +7792,7 @@ const FormatIntLiteralContext = struct { | ... | @@ -7744,7 +7792,7 @@ const FormatIntLiteralContext = struct { |
| 7744 | dg: *DeclGen, | 7792 | dg: *DeclGen, |
| 7745 | int_info: InternPool.Key.IntType, | 7793 | int_info: InternPool.Key.IntType, |
| 7746 | kind: CType.Kind, | 7794 | kind: CType.Kind, |
| 7747 | cty: CType, | 7795 | ctype: CType, |
| 7748 | val: Value, | 7796 | val: Value, |
| 7749 | }; | 7797 | }; |
| 7750 | fn formatIntLiteral( | 7798 | fn formatIntLiteral( |
| ... | @@ -7753,8 +7801,9 @@ fn formatIntLiteral( | ... | @@ -7753,8 +7801,9 @@ fn formatIntLiteral( |
| 7753 | options: std.fmt.FormatOptions, | 7801 | options: std.fmt.FormatOptions, |
| 7754 | writer: anytype, | 7802 | writer: anytype, |
| 7755 | ) @TypeOf(writer).Error!void { | 7803 | ) @TypeOf(writer).Error!void { |
| 7756 | const mod = data.dg.module; | 7804 | const zcu = data.dg.zcu; |
| 7757 | const target = mod.getTarget(); | 7805 | const target = &data.dg.mod.resolved_target.result; |
| 7806 | const ctype_pool = &data.dg.ctype_pool; | ||
| 7758 | 7807 | ||
| 7759 | const ExpectedContents = struct { | 7808 | const ExpectedContents = struct { |
| 7760 | const base = 10; | 7809 | const base = 10; |
| ... | @@ -7774,7 +7823,7 @@ fn formatIntLiteral( | ... | @@ -7774,7 +7823,7 @@ fn formatIntLiteral( |
| 7774 | defer allocator.free(undef_limbs); | 7823 | defer allocator.free(undef_limbs); |
| 7775 | 7824 | ||
| 7776 | var int_buf: Value.BigIntSpace = undefined; | 7825 | var int_buf: Value.BigIntSpace = undefined; |
| 7777 | const int = if (data.val.isUndefDeep(mod)) blk: { | 7826 | const int = if (data.val.isUndefDeep(zcu)) blk: { |
| 7778 | undef_limbs = try allocator.alloc(BigIntLimb, BigInt.calcTwosCompLimbCount(data.int_info.bits)); | 7827 | undef_limbs = try allocator.alloc(BigIntLimb, BigInt.calcTwosCompLimbCount(data.int_info.bits)); |
| 7779 | @memset(undef_limbs, undefPattern(BigIntLimb)); | 7828 | @memset(undef_limbs, undefPattern(BigIntLimb)); |
| 7780 | 7829 | ||
| ... | @@ -7785,10 +7834,10 @@ fn formatIntLiteral( | ... | @@ -7785,10 +7834,10 @@ fn formatIntLiteral( |
| 7785 | }; | 7834 | }; |
| 7786 | undef_int.truncate(undef_int.toConst(), data.int_info.signedness, data.int_info.bits); | 7835 | undef_int.truncate(undef_int.toConst(), data.int_info.signedness, data.int_info.bits); |
| 7787 | break :blk undef_int.toConst(); | 7836 | break :blk undef_int.toConst(); |
| 7788 | } else data.val.toBigInt(&int_buf, mod); | 7837 | } else data.val.toBigInt(&int_buf, zcu); |
| 7789 | assert(int.fitsInTwosComp(data.int_info.signedness, data.int_info.bits)); | 7838 | assert(int.fitsInTwosComp(data.int_info.signedness, data.int_info.bits)); |
| 7790 | 7839 | ||
| 7791 | const c_bits: usize = @intCast(data.cty.byteSize(data.dg.ctypes.set, target) * 8); | 7840 | const c_bits: usize = @intCast(data.ctype.byteSize(ctype_pool, data.dg.mod) * 8); |
| 7792 | var one_limbs: [BigInt.calcLimbLen(1)]BigIntLimb = undefined; | 7841 | var one_limbs: [BigInt.calcLimbLen(1)]BigIntLimb = undefined; |
| 7793 | const one = BigInt.Mutable.init(&one_limbs, 1).toConst(); | 7842 | const one = BigInt.Mutable.init(&one_limbs, 1).toConst(); |
| 7794 | 7843 | ||
| ... | @@ -7800,45 +7849,45 @@ fn formatIntLiteral( | ... | @@ -7800,45 +7849,45 @@ fn formatIntLiteral( |
| 7800 | defer allocator.free(wrap.limbs); | 7849 | defer allocator.free(wrap.limbs); |
| 7801 | 7850 | ||
| 7802 | const c_limb_info: struct { | 7851 | const c_limb_info: struct { |
| 7803 | cty: CType, | 7852 | ctype: CType, |
| 7804 | count: usize, | 7853 | count: usize, |
| 7805 | endian: std.builtin.Endian, | 7854 | endian: std.builtin.Endian, |
| 7806 | homogeneous: bool, | 7855 | homogeneous: bool, |
| 7807 | } = switch (data.cty.tag()) { | 7856 | } = switch (data.ctype.info(ctype_pool)) { |
| 7808 | else => .{ | 7857 | .basic => |basic_info| switch (basic_info) { |
| 7809 | .cty = CType.initTag(.void), | 7858 | else => .{ |
| 7810 | .count = 1, | 7859 | .ctype = .{ .index = .void }, |
| 7811 | .endian = .little, | 7860 | .count = 1, |
| 7812 | .homogeneous = true, | 7861 | .endian = .little, |
| 7813 | }, | ||
| 7814 | .zig_u128, .zig_i128 => .{ | ||
| 7815 | .cty = CType.initTag(.uint64_t), | ||
| 7816 | .count = 2, | ||
| 7817 | .endian = .big, | ||
| 7818 | .homogeneous = false, | ||
| 7819 | }, | ||
| 7820 | .array => info: { | ||
| 7821 | const array_data = data.cty.castTag(.array).?.data; | ||
| 7822 | break :info .{ | ||
| 7823 | .cty = data.dg.indexToCType(array_data.elem_type), | ||
| 7824 | .count = @as(usize, @intCast(array_data.len)), | ||
| 7825 | .endian = target.cpu.arch.endian(), | ||
| 7826 | .homogeneous = true, | 7862 | .homogeneous = true, |
| 7827 | }; | 7863 | }, |
| 7864 | .zig_u128, .zig_i128 => .{ | ||
| 7865 | .ctype = .{ .index = .uint64_t }, | ||
| 7866 | .count = 2, | ||
| 7867 | .endian = .big, | ||
| 7868 | .homogeneous = false, | ||
| 7869 | }, | ||
| 7828 | }, | 7870 | }, |
| 7871 | .array => |array_info| .{ | ||
| 7872 | .ctype = array_info.elem_ctype, | ||
| 7873 | .count = @intCast(array_info.len), | ||
| 7874 | .endian = target.cpu.arch.endian(), | ||
| 7875 | .homogeneous = true, | ||
| 7876 | }, | ||
| 7877 | else => unreachable, | ||
| 7829 | }; | 7878 | }; |
| 7830 | if (c_limb_info.count == 1) { | 7879 | if (c_limb_info.count == 1) { |
| 7831 | if (wrap.addWrap(int, one, data.int_info.signedness, c_bits) or | 7880 | if (wrap.addWrap(int, one, data.int_info.signedness, c_bits) or |
| 7832 | data.int_info.signedness == .signed and wrap.subWrap(int, one, data.int_info.signedness, c_bits)) | 7881 | data.int_info.signedness == .signed and wrap.subWrap(int, one, data.int_info.signedness, c_bits)) |
| 7833 | return writer.print("{s}_{s}", .{ | 7882 | return writer.print("{s}_{s}", .{ |
| 7834 | data.cty.getStandardDefineAbbrev() orelse return writer.print("zig_{s}Int_{c}{d}", .{ | 7883 | data.ctype.getStandardDefineAbbrev() orelse return writer.print("zig_{s}Int_{c}{d}", .{ |
| 7835 | if (int.positive) "max" else "min", signAbbrev(data.int_info.signedness), c_bits, | 7884 | if (int.positive) "max" else "min", signAbbrev(data.int_info.signedness), c_bits, |
| 7836 | }), | 7885 | }), |
| 7837 | if (int.positive) "MAX" else "MIN", | 7886 | if (int.positive) "MAX" else "MIN", |
| 7838 | }); | 7887 | }); |
| 7839 | 7888 | ||
| 7840 | if (!int.positive) try writer.writeByte('-'); | 7889 | if (!int.positive) try writer.writeByte('-'); |
| 7841 | try data.cty.renderLiteralPrefix(writer, data.kind); | 7890 | try data.ctype.renderLiteralPrefix(writer, data.kind, ctype_pool); |
| 7842 | 7891 | ||
| 7843 | const style: struct { base: u8, case: std.fmt.Case = undefined } = switch (fmt.len) { | 7892 | const style: struct { base: u8, case: std.fmt.Case = undefined } = switch (fmt.len) { |
| 7844 | 0 => .{ .base = 10 }, | 7893 | 0 => .{ .base = 10 }, |
| ... | @@ -7869,7 +7918,7 @@ fn formatIntLiteral( | ... | @@ -7869,7 +7918,7 @@ fn formatIntLiteral( |
| 7869 | defer allocator.free(string); | 7918 | defer allocator.free(string); |
| 7870 | try writer.writeAll(string); | 7919 | try writer.writeAll(string); |
| 7871 | } else { | 7920 | } else { |
| 7872 | try data.cty.renderLiteralPrefix(writer, data.kind); | 7921 | try data.ctype.renderLiteralPrefix(writer, data.kind, ctype_pool); |
| 7873 | wrap.convertToTwosComplement(int, data.int_info.signedness, c_bits); | 7922 | wrap.convertToTwosComplement(int, data.int_info.signedness, c_bits); |
| 7874 | @memset(wrap.limbs[wrap.len..], 0); | 7923 | @memset(wrap.limbs[wrap.len..], 0); |
| 7875 | wrap.len = wrap.limbs.len; | 7924 | wrap.len = wrap.limbs.len; |
| ... | @@ -7879,7 +7928,7 @@ fn formatIntLiteral( | ... | @@ -7879,7 +7928,7 @@ fn formatIntLiteral( |
| 7879 | .signedness = undefined, | 7928 | .signedness = undefined, |
| 7880 | .bits = @as(u16, @intCast(@divExact(c_bits, c_limb_info.count))), | 7929 | .bits = @as(u16, @intCast(@divExact(c_bits, c_limb_info.count))), |
| 7881 | }; | 7930 | }; |
| 7882 | var c_limb_cty: CType = undefined; | 7931 | var c_limb_ctype: CType = undefined; |
| 7883 | 7932 | ||
| 7884 | var limb_offset: usize = 0; | 7933 | var limb_offset: usize = 0; |
| 7885 | const most_significant_limb_i = wrap.len - limbs_per_c_limb; | 7934 | const most_significant_limb_i = wrap.len - limbs_per_c_limb; |
| ... | @@ -7900,7 +7949,7 @@ fn formatIntLiteral( | ... | @@ -7900,7 +7949,7 @@ fn formatIntLiteral( |
| 7900 | { | 7949 | { |
| 7901 | // most significant limb is actually signed | 7950 | // most significant limb is actually signed |
| 7902 | c_limb_int_info.signedness = .signed; | 7951 | c_limb_int_info.signedness = .signed; |
| 7903 | c_limb_cty = c_limb_info.cty.toSigned(); | 7952 | c_limb_ctype = c_limb_info.ctype.toSigned(); |
| 7904 | 7953 | ||
| 7905 | c_limb_mut.positive = wrap.positive; | 7954 | c_limb_mut.positive = wrap.positive; |
| 7906 | c_limb_mut.truncate( | 7955 | c_limb_mut.truncate( |
| ... | @@ -7910,7 +7959,7 @@ fn formatIntLiteral( | ... | @@ -7910,7 +7959,7 @@ fn formatIntLiteral( |
| 7910 | ); | 7959 | ); |
| 7911 | } else { | 7960 | } else { |
| 7912 | c_limb_int_info.signedness = .unsigned; | 7961 | c_limb_int_info.signedness = .unsigned; |
| 7913 | c_limb_cty = c_limb_info.cty; | 7962 | c_limb_ctype = c_limb_info.ctype; |
| 7914 | } | 7963 | } |
| 7915 | 7964 | ||
| 7916 | if (limb_offset > 0) try writer.writeAll(", "); | 7965 | if (limb_offset > 0) try writer.writeAll(", "); |
| ... | @@ -7918,12 +7967,12 @@ fn formatIntLiteral( | ... | @@ -7918,12 +7967,12 @@ fn formatIntLiteral( |
| 7918 | .dg = data.dg, | 7967 | .dg = data.dg, |
| 7919 | .int_info = c_limb_int_info, | 7968 | .int_info = c_limb_int_info, |
| 7920 | .kind = data.kind, | 7969 | .kind = data.kind, |
| 7921 | .cty = c_limb_cty, | 7970 | .ctype = c_limb_ctype, |
| 7922 | .val = try mod.intValue_big(Type.comptime_int, c_limb_mut.toConst()), | 7971 | .val = try zcu.intValue_big(Type.comptime_int, c_limb_mut.toConst()), |
| 7923 | }, fmt, options, writer); | 7972 | }, fmt, options, writer); |
| 7924 | } | 7973 | } |
| 7925 | } | 7974 | } |
| 7926 | try data.cty.renderLiteralSuffix(writer); | 7975 | try data.ctype.renderLiteralSuffix(writer, ctype_pool); |
| 7927 | } | 7976 | } |
| 7928 | 7977 | ||
| 7929 | const Materialize = struct { | 7978 | const Materialize = struct { |
| ... | @@ -7966,10 +8015,10 @@ const Materialize = struct { | ... | @@ -7966,10 +8015,10 @@ const Materialize = struct { |
| 7966 | }; | 8015 | }; |
| 7967 | 8016 | ||
| 7968 | const Assignment = struct { | 8017 | const Assignment = struct { |
| 7969 | cty: CType.Index, | 8018 | ctype: CType, |
| 7970 | 8019 | ||
| 7971 | pub fn init(f: *Function, ty: Type) !Assignment { | 8020 | pub fn init(f: *Function, ty: Type) !Assignment { |
| 7972 | return .{ .cty = try f.typeToIndex(ty, .complete) }; | 8021 | return .{ .ctype = try f.ctypeFromType(ty, .complete) }; |
| 7973 | } | 8022 | } |
| 7974 | 8023 | ||
| 7975 | pub fn start(f: *Function, writer: anytype, ty: Type) !Assignment { | 8024 | pub fn start(f: *Function, writer: anytype, ty: Type) !Assignment { |
| ... | @@ -7997,7 +8046,7 @@ const Assignment = struct { | ... | @@ -7997,7 +8046,7 @@ const Assignment = struct { |
| 7997 | .assign => {}, | 8046 | .assign => {}, |
| 7998 | .memcpy => { | 8047 | .memcpy => { |
| 7999 | try writer.writeAll(", sizeof("); | 8048 | try writer.writeAll(", sizeof("); |
| 8000 | try f.renderCType(writer, self.cty); | 8049 | try f.renderCType(writer, self.ctype); |
| 8001 | try writer.writeAll("))"); | 8050 | try writer.writeAll("))"); |
| 8002 | }, | 8051 | }, |
| 8003 | } | 8052 | } |
| ... | @@ -8005,7 +8054,7 @@ const Assignment = struct { | ... | @@ -8005,7 +8054,7 @@ const Assignment = struct { |
| 8005 | } | 8054 | } |
| 8006 | 8055 | ||
| 8007 | fn strategy(self: Assignment, f: *Function) enum { assign, memcpy } { | 8056 | fn strategy(self: Assignment, f: *Function) enum { assign, memcpy } { |
| 8008 | return switch (f.indexToCType(self.cty).tag()) { | 8057 | return switch (self.ctype.info(&f.object.dg.ctype_pool)) { |
| 8009 | else => .assign, | 8058 | else => .assign, |
| 8010 | .array, .vector => .memcpy, | 8059 | .array, .vector => .memcpy, |
| 8011 | }; | 8060 | }; |
| ... | @@ -8016,21 +8065,17 @@ const Vectorize = struct { | ... | @@ -8016,21 +8065,17 @@ const Vectorize = struct { |
| 8016 | index: CValue = .none, | 8065 | index: CValue = .none, |
| 8017 | 8066 | ||
| 8018 | pub fn start(f: *Function, inst: Air.Inst.Index, writer: anytype, ty: Type) !Vectorize { | 8067 | pub fn start(f: *Function, inst: Air.Inst.Index, writer: anytype, ty: Type) !Vectorize { |
| 8019 | const mod = f.object.dg.module; | 8068 | const zcu = f.object.dg.zcu; |
| 8020 | return if (ty.zigTypeTag(mod) == .Vector) index: { | 8069 | return if (ty.zigTypeTag(zcu) == .Vector) index: { |
| 8021 | const len_val = try mod.intValue(Type.usize, ty.vectorLen(mod)); | ||
| 8022 | |||
| 8023 | const local = try f.allocLocal(inst, Type.usize); | 8070 | const local = try f.allocLocal(inst, Type.usize); |
| 8024 | 8071 | ||
| 8025 | try writer.writeAll("for ("); | 8072 | try writer.writeAll("for ("); |
| 8026 | try f.writeCValue(writer, local, .Other); | 8073 | try f.writeCValue(writer, local, .Other); |
| 8027 | try writer.print(" = {d}; ", .{try f.fmtIntLiteral(Type.usize, try mod.intValue(Type.usize, 0))}); | 8074 | try writer.print(" = {d}; ", .{try f.fmtIntLiteral(try zcu.intValue(Type.usize, 0))}); |
| 8028 | try f.writeCValue(writer, local, .Other); | 8075 | try f.writeCValue(writer, local, .Other); |
| 8029 | try writer.print(" < {d}; ", .{ | 8076 | try writer.print(" < {d}; ", .{try f.fmtIntLiteral(try zcu.intValue(Type.usize, ty.vectorLen(zcu)))}); |
| 8030 | try f.fmtIntLiteral(Type.usize, len_val), | ||
| 8031 | }); | ||
| 8032 | try f.writeCValue(writer, local, .Other); | 8077 | try f.writeCValue(writer, local, .Other); |
| 8033 | try writer.print(" += {d}) {{\n", .{try f.fmtIntLiteral(Type.usize, try mod.intValue(Type.usize, 1))}); | 8078 | try writer.print(" += {d}) {{\n", .{try f.fmtIntLiteral(try zcu.intValue(Type.usize, 1))}); |
| 8034 | f.object.indent_writer.pushIndent(); | 8079 | f.object.indent_writer.pushIndent(); |
| 8035 | 8080 | ||
| 8036 | break :index .{ .index = local }; | 8081 | break :index .{ .index = local }; |
| ... | @@ -8054,32 +8099,10 @@ const Vectorize = struct { | ... | @@ -8054,32 +8099,10 @@ const Vectorize = struct { |
| 8054 | } | 8099 | } |
| 8055 | }; | 8100 | }; |
| 8056 | 8101 | ||
| 8057 | fn lowerFnRetTy(ret_ty: Type, mod: *Module) !Type { | 8102 | fn lowersToArray(ty: Type, zcu: *Zcu) bool { |
| 8058 | if (ret_ty.ip_index == .noreturn_type) return Type.noreturn; | 8103 | return switch (ty.zigTypeTag(zcu)) { |
| 8059 | |||
| 8060 | if (lowersToArray(ret_ty, mod)) { | ||
| 8061 | const gpa = mod.gpa; | ||
| 8062 | const ip = &mod.intern_pool; | ||
| 8063 | const names = [1]InternPool.NullTerminatedString{ | ||
| 8064 | try ip.getOrPutString(gpa, "array"), | ||
| 8065 | }; | ||
| 8066 | const types = [1]InternPool.Index{ret_ty.ip_index}; | ||
| 8067 | const values = [1]InternPool.Index{.none}; | ||
| 8068 | const interned = try ip.getAnonStructType(gpa, .{ | ||
| 8069 | .names = &names, | ||
| 8070 | .types = &types, | ||
| 8071 | .values = &values, | ||
| 8072 | }); | ||
| 8073 | return Type.fromInterned(interned); | ||
| 8074 | } | ||
| 8075 | |||
| 8076 | return if (ret_ty.hasRuntimeBitsIgnoreComptime(mod)) ret_ty else Type.void; | ||
| 8077 | } | ||
| 8078 | |||
| 8079 | fn lowersToArray(ty: Type, mod: *Module) bool { | ||
| 8080 | return switch (ty.zigTypeTag(mod)) { | ||
| 8081 | .Array, .Vector => return true, | 8104 | .Array, .Vector => return true, |
| 8082 | else => return ty.isAbiInt(mod) and toCIntBits(@as(u32, @intCast(ty.bitSize(mod)))) == null, | 8105 | else => return ty.isAbiInt(zcu) and toCIntBits(@as(u32, @intCast(ty.bitSize(zcu)))) == null, |
| 8083 | }; | 8106 | }; |
| 8084 | } | 8107 | } |
| 8085 | 8108 | ||
| ... | @@ -8098,7 +8121,7 @@ fn die(f: *Function, inst: Air.Inst.Index, ref: Air.Inst.Ref) !void { | ... | @@ -8098,7 +8121,7 @@ fn die(f: *Function, inst: Air.Inst.Index, ref: Air.Inst.Ref) !void { |
| 8098 | const ref_inst = ref.toIndex() orelse return; | 8121 | const ref_inst = ref.toIndex() orelse return; |
| 8099 | const c_value = (f.value_map.fetchRemove(ref) orelse return).value; | 8122 | const c_value = (f.value_map.fetchRemove(ref) orelse return).value; |
| 8100 | const local_index = switch (c_value) { | 8123 | const local_index = switch (c_value) { |
| 8101 | .local, .new_local => |l| l, | 8124 | .new_local, .local => |l| l, |
| 8102 | else => return, | 8125 | else => return, |
| 8103 | }; | 8126 | }; |
| 8104 | try freeLocal(f, inst, local_index, ref_inst); | 8127 | try freeLocal(f, inst, local_index, ref_inst); |
src/codegen/c/Type.zig created+2491| ... | @@ -0,0 +1,2491 @@ | ||
| 1 | index: CType.Index, | ||
| 2 | |||
| 3 | pub fn fromPoolIndex(pool_index: usize) CType { | ||
| 4 | return .{ .index = @enumFromInt(CType.Index.first_pool_index + pool_index) }; | ||
| 5 | } | ||
| 6 | |||
| 7 | pub fn toPoolIndex(ctype: CType) ?u32 { | ||
| 8 | const pool_index, const is_basic = | ||
| 9 | @subWithOverflow(@intFromEnum(ctype.index), CType.Index.first_pool_index); | ||
| 10 | return switch (is_basic) { | ||
| 11 | 0 => pool_index, | ||
| 12 | 1 => null, | ||
| 13 | }; | ||
| 14 | } | ||
| 15 | |||
| 16 | pub fn eql(lhs: CType, rhs: CType) bool { | ||
| 17 | return lhs.index == rhs.index; | ||
| 18 | } | ||
| 19 | |||
| 20 | pub fn isBool(ctype: CType) bool { | ||
| 21 | return switch (ctype.index) { | ||
| 22 | ._Bool, .bool => true, | ||
| 23 | else => false, | ||
| 24 | }; | ||
| 25 | } | ||
| 26 | |||
| 27 | pub fn isInteger(ctype: CType) bool { | ||
| 28 | return switch (ctype.index) { | ||
| 29 | .char, | ||
| 30 | .@"signed char", | ||
| 31 | .short, | ||
| 32 | .int, | ||
| 33 | .long, | ||
| 34 | .@"long long", | ||
| 35 | .@"unsigned char", | ||
| 36 | .@"unsigned short", | ||
| 37 | .@"unsigned int", | ||
| 38 | .@"unsigned long", | ||
| 39 | .@"unsigned long long", | ||
| 40 | .size_t, | ||
| 41 | .ptrdiff_t, | ||
| 42 | .uint8_t, | ||
| 43 | .int8_t, | ||
| 44 | .uint16_t, | ||
| 45 | .int16_t, | ||
| 46 | .uint32_t, | ||
| 47 | .int32_t, | ||
| 48 | .uint64_t, | ||
| 49 | .int64_t, | ||
| 50 | .uintptr_t, | ||
| 51 | .intptr_t, | ||
| 52 | .zig_u128, | ||
| 53 | .zig_i128, | ||
| 54 | => true, | ||
| 55 | else => false, | ||
| 56 | }; | ||
| 57 | } | ||
| 58 | |||
| 59 | pub fn signedness(ctype: CType, mod: *Module) std.builtin.Signedness { | ||
| 60 | return switch (ctype.index) { | ||
| 61 | .char => mod.resolved_target.result.charSignedness(), | ||
| 62 | .@"signed char", | ||
| 63 | .short, | ||
| 64 | .int, | ||
| 65 | .long, | ||
| 66 | .@"long long", | ||
| 67 | .ptrdiff_t, | ||
| 68 | .int8_t, | ||
| 69 | .int16_t, | ||
| 70 | .int32_t, | ||
| 71 | .int64_t, | ||
| 72 | .intptr_t, | ||
| 73 | .zig_i128, | ||
| 74 | => .signed, | ||
| 75 | .@"unsigned char", | ||
| 76 | .@"unsigned short", | ||
| 77 | .@"unsigned int", | ||
| 78 | .@"unsigned long", | ||
| 79 | .@"unsigned long long", | ||
| 80 | .size_t, | ||
| 81 | .uint8_t, | ||
| 82 | .uint16_t, | ||
| 83 | .uint32_t, | ||
| 84 | .uint64_t, | ||
| 85 | .uintptr_t, | ||
| 86 | .zig_u128, | ||
| 87 | => .unsigned, | ||
| 88 | else => unreachable, | ||
| 89 | }; | ||
| 90 | } | ||
| 91 | |||
| 92 | pub fn isFloat(ctype: CType) bool { | ||
| 93 | return switch (ctype.index) { | ||
| 94 | .float, | ||
| 95 | .double, | ||
| 96 | .@"long double", | ||
| 97 | .zig_f16, | ||
| 98 | .zig_f32, | ||
| 99 | .zig_f64, | ||
| 100 | .zig_f80, | ||
| 101 | .zig_f128, | ||
| 102 | .zig_c_longdouble, | ||
| 103 | => true, | ||
| 104 | else => false, | ||
| 105 | }; | ||
| 106 | } | ||
| 107 | |||
| 108 | pub fn toSigned(ctype: CType) CType { | ||
| 109 | return switch (ctype.index) { | ||
| 110 | .char, .@"signed char", .@"unsigned char" => .{ .index = .@"signed char" }, | ||
| 111 | .short, .@"unsigned short" => .{ .index = .short }, | ||
| 112 | .int, .@"unsigned int" => .{ .index = .int }, | ||
| 113 | .long, .@"unsigned long" => .{ .index = .long }, | ||
| 114 | .@"long long", .@"unsigned long long" => .{ .index = .@"long long" }, | ||
| 115 | .size_t, .ptrdiff_t => .{ .index = .ptrdiff_t }, | ||
| 116 | .uint8_t, .int8_t => .{ .index = .int8_t }, | ||
| 117 | .uint16_t, .int16_t => .{ .index = .int16_t }, | ||
| 118 | .uint32_t, .int32_t => .{ .index = .int32_t }, | ||
| 119 | .uint64_t, .int64_t => .{ .index = .int64_t }, | ||
| 120 | .uintptr_t, .intptr_t => .{ .index = .intptr_t }, | ||
| 121 | .zig_u128, .zig_i128 => .{ .index = .zig_i128 }, | ||
| 122 | .float, | ||
| 123 | .double, | ||
| 124 | .@"long double", | ||
| 125 | .zig_f16, | ||
| 126 | .zig_f32, | ||
| 127 | .zig_f80, | ||
| 128 | .zig_f128, | ||
| 129 | .zig_c_longdouble, | ||
| 130 | => ctype, | ||
| 131 | else => unreachable, | ||
| 132 | }; | ||
| 133 | } | ||
| 134 | |||
| 135 | pub fn toUnsigned(ctype: CType) CType { | ||
| 136 | return switch (ctype.index) { | ||
| 137 | .char, .@"signed char", .@"unsigned char" => .{ .index = .@"unsigned char" }, | ||
| 138 | .short, .@"unsigned short" => .{ .index = .@"unsigned short" }, | ||
| 139 | .int, .@"unsigned int" => .{ .index = .@"unsigned int" }, | ||
| 140 | .long, .@"unsigned long" => .{ .index = .@"unsigned long" }, | ||
| 141 | .@"long long", .@"unsigned long long" => .{ .index = .@"unsigned long long" }, | ||
| 142 | .size_t, .ptrdiff_t => .{ .index = .size_t }, | ||
| 143 | .uint8_t, .int8_t => .{ .index = .uint8_t }, | ||
| 144 | .uint16_t, .int16_t => .{ .index = .uint16_t }, | ||
| 145 | .uint32_t, .int32_t => .{ .index = .uint32_t }, | ||
| 146 | .uint64_t, .int64_t => .{ .index = .uint64_t }, | ||
| 147 | .uintptr_t, .intptr_t => .{ .index = .uintptr_t }, | ||
| 148 | .zig_u128, .zig_i128 => .{ .index = .zig_u128 }, | ||
| 149 | else => unreachable, | ||
| 150 | }; | ||
| 151 | } | ||
| 152 | |||
| 153 | pub fn toSignedness(ctype: CType, s: std.builtin.Signedness) CType { | ||
| 154 | return switch (s) { | ||
| 155 | .unsigned => ctype.toUnsigned(), | ||
| 156 | .signed => ctype.toSigned(), | ||
| 157 | }; | ||
| 158 | } | ||
| 159 | |||
| 160 | pub fn getStandardDefineAbbrev(ctype: CType) ?[]const u8 { | ||
| 161 | return switch (ctype.index) { | ||
| 162 | .char => "CHAR", | ||
| 163 | .@"signed char" => "SCHAR", | ||
| 164 | .short => "SHRT", | ||
| 165 | .int => "INT", | ||
| 166 | .long => "LONG", | ||
| 167 | .@"long long" => "LLONG", | ||
| 168 | .@"unsigned char" => "UCHAR", | ||
| 169 | .@"unsigned short" => "USHRT", | ||
| 170 | .@"unsigned int" => "UINT", | ||
| 171 | .@"unsigned long" => "ULONG", | ||
| 172 | .@"unsigned long long" => "ULLONG", | ||
| 173 | .float => "FLT", | ||
| 174 | .double => "DBL", | ||
| 175 | .@"long double" => "LDBL", | ||
| 176 | .size_t => "SIZE", | ||
| 177 | .ptrdiff_t => "PTRDIFF", | ||
| 178 | .uint8_t => "UINT8", | ||
| 179 | .int8_t => "INT8", | ||
| 180 | .uint16_t => "UINT16", | ||
| 181 | .int16_t => "INT16", | ||
| 182 | .uint32_t => "UINT32", | ||
| 183 | .int32_t => "INT32", | ||
| 184 | .uint64_t => "UINT64", | ||
| 185 | .int64_t => "INT64", | ||
| 186 | .uintptr_t => "UINTPTR", | ||
| 187 | .intptr_t => "INTPTR", | ||
| 188 | else => null, | ||
| 189 | }; | ||
| 190 | } | ||
| 191 | |||
| 192 | pub fn renderLiteralPrefix(ctype: CType, writer: anytype, kind: Kind, pool: *const Pool) @TypeOf(writer).Error!void { | ||
| 193 | switch (ctype.info(pool)) { | ||
| 194 | .basic => |basic_info| switch (basic_info) { | ||
| 195 | .void => unreachable, | ||
| 196 | ._Bool, | ||
| 197 | .char, | ||
| 198 | .@"signed char", | ||
| 199 | .short, | ||
| 200 | .@"unsigned short", | ||
| 201 | .bool, | ||
| 202 | .size_t, | ||
| 203 | .ptrdiff_t, | ||
| 204 | .uintptr_t, | ||
| 205 | .intptr_t, | ||
| 206 | => switch (kind) { | ||
| 207 | else => try writer.print("({s})", .{@tagName(basic_info)}), | ||
| 208 | .global => {}, | ||
| 209 | }, | ||
| 210 | .int, | ||
| 211 | .long, | ||
| 212 | .@"long long", | ||
| 213 | .@"unsigned char", | ||
| 214 | .@"unsigned int", | ||
| 215 | .@"unsigned long", | ||
| 216 | .@"unsigned long long", | ||
| 217 | .float, | ||
| 218 | .double, | ||
| 219 | .@"long double", | ||
| 220 | => {}, | ||
| 221 | .uint8_t, | ||
| 222 | .int8_t, | ||
| 223 | .uint16_t, | ||
| 224 | .int16_t, | ||
| 225 | .uint32_t, | ||
| 226 | .int32_t, | ||
| 227 | .uint64_t, | ||
| 228 | .int64_t, | ||
| 229 | => try writer.print("{s}_C(", .{ctype.getStandardDefineAbbrev().?}), | ||
| 230 | .zig_u128, | ||
| 231 | .zig_i128, | ||
| 232 | .zig_f16, | ||
| 233 | .zig_f32, | ||
| 234 | .zig_f64, | ||
| 235 | .zig_f80, | ||
| 236 | .zig_f128, | ||
| 237 | .zig_c_longdouble, | ||
| 238 | => try writer.print("zig_{s}_{s}(", .{ | ||
| 239 | switch (kind) { | ||
| 240 | else => "make", | ||
| 241 | .global => "init", | ||
| 242 | }, | ||
| 243 | @tagName(basic_info)["zig_".len..], | ||
| 244 | }), | ||
| 245 | .va_list => unreachable, | ||
| 246 | _ => unreachable, | ||
| 247 | }, | ||
| 248 | .array, .vector => try writer.writeByte('{'), | ||
| 249 | else => unreachable, | ||
| 250 | } | ||
| 251 | } | ||
| 252 | |||
| 253 | pub fn renderLiteralSuffix(ctype: CType, writer: anytype, pool: *const Pool) @TypeOf(writer).Error!void { | ||
| 254 | switch (ctype.info(pool)) { | ||
| 255 | .basic => |basic_info| switch (basic_info) { | ||
| 256 | .void => unreachable, | ||
| 257 | ._Bool => {}, | ||
| 258 | .char, | ||
| 259 | .@"signed char", | ||
| 260 | .short, | ||
| 261 | .int, | ||
| 262 | => {}, | ||
| 263 | .long => try writer.writeByte('l'), | ||
| 264 | .@"long long" => try writer.writeAll("ll"), | ||
| 265 | .@"unsigned char", | ||
| 266 | .@"unsigned short", | ||
| 267 | .@"unsigned int", | ||
| 268 | => try writer.writeByte('u'), | ||
| 269 | .@"unsigned long", | ||
| 270 | .size_t, | ||
| 271 | .uintptr_t, | ||
| 272 | => try writer.writeAll("ul"), | ||
| 273 | .@"unsigned long long" => try writer.writeAll("ull"), | ||
| 274 | .float => try writer.writeByte('f'), | ||
| 275 | .double => {}, | ||
| 276 | .@"long double" => try writer.writeByte('l'), | ||
| 277 | .bool, | ||
| 278 | .ptrdiff_t, | ||
| 279 | .intptr_t, | ||
| 280 | => {}, | ||
| 281 | .uint8_t, | ||
| 282 | .int8_t, | ||
| 283 | .uint16_t, | ||
| 284 | .int16_t, | ||
| 285 | .uint32_t, | ||
| 286 | .int32_t, | ||
| 287 | .uint64_t, | ||
| 288 | .int64_t, | ||
| 289 | .zig_u128, | ||
| 290 | .zig_i128, | ||
| 291 | .zig_f16, | ||
| 292 | .zig_f32, | ||
| 293 | .zig_f64, | ||
| 294 | .zig_f80, | ||
| 295 | .zig_f128, | ||
| 296 | .zig_c_longdouble, | ||
| 297 | => try writer.writeByte(')'), | ||
| 298 | .va_list => unreachable, | ||
| 299 | _ => unreachable, | ||
| 300 | }, | ||
| 301 | .array, .vector => try writer.writeByte('}'), | ||
| 302 | else => unreachable, | ||
| 303 | } | ||
| 304 | } | ||
| 305 | |||
| 306 | pub fn floatActiveBits(ctype: CType, mod: *Module) u16 { | ||
| 307 | const target = &mod.resolved_target.result; | ||
| 308 | return switch (ctype.index) { | ||
| 309 | .float => target.c_type_bit_size(.float), | ||
| 310 | .double => target.c_type_bit_size(.double), | ||
| 311 | .@"long double", .zig_c_longdouble => target.c_type_bit_size(.longdouble), | ||
| 312 | .zig_f16 => 16, | ||
| 313 | .zig_f32 => 32, | ||
| 314 | .zig_f64 => 64, | ||
| 315 | .zig_f80 => 80, | ||
| 316 | .zig_f128 => 128, | ||
| 317 | else => unreachable, | ||
| 318 | }; | ||
| 319 | } | ||
| 320 | |||
| 321 | pub fn byteSize(ctype: CType, pool: *const Pool, mod: *Module) u64 { | ||
| 322 | const target = &mod.resolved_target.result; | ||
| 323 | return switch (ctype.info(pool)) { | ||
| 324 | .basic => |basic_info| switch (basic_info) { | ||
| 325 | .void => 0, | ||
| 326 | .char, .@"signed char", ._Bool, .@"unsigned char", .bool, .uint8_t, .int8_t => 1, | ||
| 327 | .short => target.c_type_byte_size(.short), | ||
| 328 | .int => target.c_type_byte_size(.int), | ||
| 329 | .long => target.c_type_byte_size(.long), | ||
| 330 | .@"long long" => target.c_type_byte_size(.longlong), | ||
| 331 | .@"unsigned short" => target.c_type_byte_size(.ushort), | ||
| 332 | .@"unsigned int" => target.c_type_byte_size(.uint), | ||
| 333 | .@"unsigned long" => target.c_type_byte_size(.ulong), | ||
| 334 | .@"unsigned long long" => target.c_type_byte_size(.ulonglong), | ||
| 335 | .float => target.c_type_byte_size(.float), | ||
| 336 | .double => target.c_type_byte_size(.double), | ||
| 337 | .@"long double" => target.c_type_byte_size(.longdouble), | ||
| 338 | .size_t, | ||
| 339 | .ptrdiff_t, | ||
| 340 | .uintptr_t, | ||
| 341 | .intptr_t, | ||
| 342 | => @divExact(target.ptrBitWidth(), 8), | ||
| 343 | .uint16_t, .int16_t, .zig_f16 => 2, | ||
| 344 | .uint32_t, .int32_t, .zig_f32 => 4, | ||
| 345 | .uint64_t, .int64_t, .zig_f64 => 8, | ||
| 346 | .zig_u128, .zig_i128, .zig_f128 => 16, | ||
| 347 | .zig_f80 => if (target.c_type_bit_size(.longdouble) == 80) | ||
| 348 | target.c_type_byte_size(.longdouble) | ||
| 349 | else | ||
| 350 | 16, | ||
| 351 | .zig_c_longdouble => target.c_type_byte_size(.longdouble), | ||
| 352 | .va_list => unreachable, | ||
| 353 | _ => unreachable, | ||
| 354 | }, | ||
| 355 | .pointer => @divExact(target.ptrBitWidth(), 8), | ||
| 356 | .array, .vector => |sequence_info| sequence_info.elem_ctype.byteSize(pool, mod) * sequence_info.len, | ||
| 357 | else => unreachable, | ||
| 358 | }; | ||
| 359 | } | ||
| 360 | |||
| 361 | pub fn info(ctype: CType, pool: *const Pool) Info { | ||
| 362 | const pool_index = ctype.toPoolIndex() orelse return .{ .basic = ctype.index }; | ||
| 363 | const item = pool.items.get(pool_index); | ||
| 364 | switch (item.tag) { | ||
| 365 | .basic => unreachable, | ||
| 366 | .pointer => return .{ .pointer = .{ | ||
| 367 | .elem_ctype = .{ .index = @enumFromInt(item.data) }, | ||
| 368 | } }, | ||
| 369 | .pointer_const => return .{ .pointer = .{ | ||
| 370 | .elem_ctype = .{ .index = @enumFromInt(item.data) }, | ||
| 371 | .@"const" = true, | ||
| 372 | } }, | ||
| 373 | .pointer_volatile => return .{ .pointer = .{ | ||
| 374 | .elem_ctype = .{ .index = @enumFromInt(item.data) }, | ||
| 375 | .@"volatile" = true, | ||
| 376 | } }, | ||
| 377 | .pointer_const_volatile => return .{ .pointer = .{ | ||
| 378 | .elem_ctype = .{ .index = @enumFromInt(item.data) }, | ||
| 379 | .@"const" = true, | ||
| 380 | .@"volatile" = true, | ||
| 381 | } }, | ||
| 382 | .aligned => { | ||
| 383 | const extra = pool.getExtra(Pool.Aligned, item.data); | ||
| 384 | return .{ .aligned = .{ | ||
| 385 | .ctype = .{ .index = extra.ctype }, | ||
| 386 | .alignas = extra.flags.alignas, | ||
| 387 | } }; | ||
| 388 | }, | ||
| 389 | .array_small => { | ||
| 390 | const extra = pool.getExtra(Pool.SequenceSmall, item.data); | ||
| 391 | return .{ .array = .{ | ||
| 392 | .elem_ctype = .{ .index = extra.elem_ctype }, | ||
| 393 | .len = extra.len, | ||
| 394 | } }; | ||
| 395 | }, | ||
| 396 | .array_large => { | ||
| 397 | const extra = pool.getExtra(Pool.SequenceLarge, item.data); | ||
| 398 | return .{ .array = .{ | ||
| 399 | .elem_ctype = .{ .index = extra.elem_ctype }, | ||
| 400 | .len = extra.len(), | ||
| 401 | } }; | ||
| 402 | }, | ||
| 403 | .vector => { | ||
| 404 | const extra = pool.getExtra(Pool.SequenceSmall, item.data); | ||
| 405 | return .{ .vector = .{ | ||
| 406 | .elem_ctype = .{ .index = extra.elem_ctype }, | ||
| 407 | .len = extra.len, | ||
| 408 | } }; | ||
| 409 | }, | ||
| 410 | .fwd_decl_struct_anon => { | ||
| 411 | const extra_trail = pool.getExtraTrail(Pool.FwdDeclAnon, item.data); | ||
| 412 | return .{ .fwd_decl = .{ | ||
| 413 | .tag = .@"struct", | ||
| 414 | .name = .{ .anon = .{ | ||
| 415 | .extra_index = extra_trail.trail.extra_index, | ||
| 416 | .len = extra_trail.extra.fields_len, | ||
| 417 | } }, | ||
| 418 | } }; | ||
| 419 | }, | ||
| 420 | .fwd_decl_union_anon => { | ||
| 421 | const extra_trail = pool.getExtraTrail(Pool.FwdDeclAnon, item.data); | ||
| 422 | return .{ .fwd_decl = .{ | ||
| 423 | .tag = .@"union", | ||
| 424 | .name = .{ .anon = .{ | ||
| 425 | .extra_index = extra_trail.trail.extra_index, | ||
| 426 | .len = extra_trail.extra.fields_len, | ||
| 427 | } }, | ||
| 428 | } }; | ||
| 429 | }, | ||
| 430 | .fwd_decl_struct => return .{ .fwd_decl = .{ | ||
| 431 | .tag = .@"struct", | ||
| 432 | .name = .{ .owner_decl = @enumFromInt(item.data) }, | ||
| 433 | } }, | ||
| 434 | .fwd_decl_union => return .{ .fwd_decl = .{ | ||
| 435 | .tag = .@"union", | ||
| 436 | .name = .{ .owner_decl = @enumFromInt(item.data) }, | ||
| 437 | } }, | ||
| 438 | .aggregate_struct_anon => { | ||
| 439 | const extra_trail = pool.getExtraTrail(Pool.AggregateAnon, item.data); | ||
| 440 | return .{ .aggregate = .{ | ||
| 441 | .tag = .@"struct", | ||
| 442 | .name = .{ .anon = .{ | ||
| 443 | .owner_decl = extra_trail.extra.owner_decl, | ||
| 444 | .id = extra_trail.extra.id, | ||
| 445 | } }, | ||
| 446 | .fields = .{ | ||
| 447 | .extra_index = extra_trail.trail.extra_index, | ||
| 448 | .len = extra_trail.extra.fields_len, | ||
| 449 | }, | ||
| 450 | } }; | ||
| 451 | }, | ||
| 452 | .aggregate_union_anon => { | ||
| 453 | const extra_trail = pool.getExtraTrail(Pool.AggregateAnon, item.data); | ||
| 454 | return .{ .aggregate = .{ | ||
| 455 | .tag = .@"union", | ||
| 456 | .name = .{ .anon = .{ | ||
| 457 | .owner_decl = extra_trail.extra.owner_decl, | ||
| 458 | .id = extra_trail.extra.id, | ||
| 459 | } }, | ||
| 460 | .fields = .{ | ||
| 461 | .extra_index = extra_trail.trail.extra_index, | ||
| 462 | .len = extra_trail.extra.fields_len, | ||
| 463 | }, | ||
| 464 | } }; | ||
| 465 | }, | ||
| 466 | .aggregate_struct_packed_anon => { | ||
| 467 | const extra_trail = pool.getExtraTrail(Pool.AggregateAnon, item.data); | ||
| 468 | return .{ .aggregate = .{ | ||
| 469 | .tag = .@"struct", | ||
| 470 | .@"packed" = true, | ||
| 471 | .name = .{ .anon = .{ | ||
| 472 | .owner_decl = extra_trail.extra.owner_decl, | ||
| 473 | .id = extra_trail.extra.id, | ||
| 474 | } }, | ||
| 475 | .fields = .{ | ||
| 476 | .extra_index = extra_trail.trail.extra_index, | ||
| 477 | .len = extra_trail.extra.fields_len, | ||
| 478 | }, | ||
| 479 | } }; | ||
| 480 | }, | ||
| 481 | .aggregate_union_packed_anon => { | ||
| 482 | const extra_trail = pool.getExtraTrail(Pool.AggregateAnon, item.data); | ||
| 483 | return .{ .aggregate = .{ | ||
| 484 | .tag = .@"union", | ||
| 485 | .@"packed" = true, | ||
| 486 | .name = .{ .anon = .{ | ||
| 487 | .owner_decl = extra_trail.extra.owner_decl, | ||
| 488 | .id = extra_trail.extra.id, | ||
| 489 | } }, | ||
| 490 | .fields = .{ | ||
| 491 | .extra_index = extra_trail.trail.extra_index, | ||
| 492 | .len = extra_trail.extra.fields_len, | ||
| 493 | }, | ||
| 494 | } }; | ||
| 495 | }, | ||
| 496 | .aggregate_struct => { | ||
| 497 | const extra_trail = pool.getExtraTrail(Pool.Aggregate, item.data); | ||
| 498 | return .{ .aggregate = .{ | ||
| 499 | .tag = .@"struct", | ||
| 500 | .name = .{ .fwd_decl = .{ .index = extra_trail.extra.fwd_decl } }, | ||
| 501 | .fields = .{ | ||
| 502 | .extra_index = extra_trail.trail.extra_index, | ||
| 503 | .len = extra_trail.extra.fields_len, | ||
| 504 | }, | ||
| 505 | } }; | ||
| 506 | }, | ||
| 507 | .aggregate_union => { | ||
| 508 | const extra_trail = pool.getExtraTrail(Pool.Aggregate, item.data); | ||
| 509 | return .{ .aggregate = .{ | ||
| 510 | .tag = .@"union", | ||
| 511 | .name = .{ .fwd_decl = .{ .index = extra_trail.extra.fwd_decl } }, | ||
| 512 | .fields = .{ | ||
| 513 | .extra_index = extra_trail.trail.extra_index, | ||
| 514 | .len = extra_trail.extra.fields_len, | ||
| 515 | }, | ||
| 516 | } }; | ||
| 517 | }, | ||
| 518 | .aggregate_struct_packed => { | ||
| 519 | const extra_trail = pool.getExtraTrail(Pool.Aggregate, item.data); | ||
| 520 | return .{ .aggregate = .{ | ||
| 521 | .tag = .@"struct", | ||
| 522 | .@"packed" = true, | ||
| 523 | .name = .{ .fwd_decl = .{ .index = extra_trail.extra.fwd_decl } }, | ||
| 524 | .fields = .{ | ||
| 525 | .extra_index = extra_trail.trail.extra_index, | ||
| 526 | .len = extra_trail.extra.fields_len, | ||
| 527 | }, | ||
| 528 | } }; | ||
| 529 | }, | ||
| 530 | .aggregate_union_packed => { | ||
| 531 | const extra_trail = pool.getExtraTrail(Pool.Aggregate, item.data); | ||
| 532 | return .{ .aggregate = .{ | ||
| 533 | .tag = .@"union", | ||
| 534 | .@"packed" = true, | ||
| 535 | .name = .{ .fwd_decl = .{ .index = extra_trail.extra.fwd_decl } }, | ||
| 536 | .fields = .{ | ||
| 537 | .extra_index = extra_trail.trail.extra_index, | ||
| 538 | .len = extra_trail.extra.fields_len, | ||
| 539 | }, | ||
| 540 | } }; | ||
| 541 | }, | ||
| 542 | .function => { | ||
| 543 | const extra_trail = pool.getExtraTrail(Pool.Function, item.data); | ||
| 544 | return .{ .function = .{ | ||
| 545 | .return_ctype = .{ .index = extra_trail.extra.return_ctype }, | ||
| 546 | .param_ctypes = .{ | ||
| 547 | .extra_index = extra_trail.trail.extra_index, | ||
| 548 | .len = extra_trail.extra.param_ctypes_len, | ||
| 549 | }, | ||
| 550 | .varargs = false, | ||
| 551 | } }; | ||
| 552 | }, | ||
| 553 | .function_varargs => { | ||
| 554 | const extra_trail = pool.getExtraTrail(Pool.Function, item.data); | ||
| 555 | return .{ .function = .{ | ||
| 556 | .return_ctype = .{ .index = extra_trail.extra.return_ctype }, | ||
| 557 | .param_ctypes = .{ | ||
| 558 | .extra_index = extra_trail.trail.extra_index, | ||
| 559 | .len = extra_trail.extra.param_ctypes_len, | ||
| 560 | }, | ||
| 561 | .varargs = true, | ||
| 562 | } }; | ||
| 563 | }, | ||
| 564 | } | ||
| 565 | } | ||
| 566 | |||
| 567 | pub fn hash(ctype: CType, pool: *const Pool) Pool.Map.Hash { | ||
| 568 | return if (ctype.toPoolIndex()) |pool_index| | ||
| 569 | pool.map.entries.items(.hash)[pool_index] | ||
| 570 | else | ||
| 571 | CType.Index.basic_hashes[@intFromEnum(ctype.index)]; | ||
| 572 | } | ||
| 573 | |||
| 574 | fn toForward(ctype: CType, pool: *Pool, allocator: std.mem.Allocator) !CType { | ||
| 575 | return switch (ctype.info(pool)) { | ||
| 576 | .basic, .pointer, .fwd_decl => ctype, | ||
| 577 | .aligned => |aligned_info| pool.getAligned(allocator, .{ | ||
| 578 | .ctype = try aligned_info.ctype.toForward(pool, allocator), | ||
| 579 | .alignas = aligned_info.alignas, | ||
| 580 | }), | ||
| 581 | .array => |array_info| pool.getArray(allocator, .{ | ||
| 582 | .elem_ctype = try array_info.elem_ctype.toForward(pool, allocator), | ||
| 583 | .len = array_info.len, | ||
| 584 | }), | ||
| 585 | .vector => |vector_info| pool.getVector(allocator, .{ | ||
| 586 | .elem_ctype = try vector_info.elem_ctype.toForward(pool, allocator), | ||
| 587 | .len = vector_info.len, | ||
| 588 | }), | ||
| 589 | .aggregate => |aggregate_info| switch (aggregate_info.name) { | ||
| 590 | .anon => ctype, | ||
| 591 | .fwd_decl => |fwd_decl| fwd_decl, | ||
| 592 | }, | ||
| 593 | .function => unreachable, | ||
| 594 | }; | ||
| 595 | } | ||
| 596 | |||
| 597 | const Index = enum(u32) { | ||
| 598 | void, | ||
| 599 | |||
| 600 | // C basic types | ||
| 601 | char, | ||
| 602 | |||
| 603 | @"signed char", | ||
| 604 | short, | ||
| 605 | int, | ||
| 606 | long, | ||
| 607 | @"long long", | ||
| 608 | |||
| 609 | _Bool, | ||
| 610 | @"unsigned char", | ||
| 611 | @"unsigned short", | ||
| 612 | @"unsigned int", | ||
| 613 | @"unsigned long", | ||
| 614 | @"unsigned long long", | ||
| 615 | |||
| 616 | float, | ||
| 617 | double, | ||
| 618 | @"long double", | ||
| 619 | |||
| 620 | // C header types | ||
| 621 | // - stdbool.h | ||
| 622 | bool, | ||
| 623 | // - stddef.h | ||
| 624 | size_t, | ||
| 625 | ptrdiff_t, | ||
| 626 | // - stdint.h | ||
| 627 | uint8_t, | ||
| 628 | int8_t, | ||
| 629 | uint16_t, | ||
| 630 | int16_t, | ||
| 631 | uint32_t, | ||
| 632 | int32_t, | ||
| 633 | uint64_t, | ||
| 634 | int64_t, | ||
| 635 | uintptr_t, | ||
| 636 | intptr_t, | ||
| 637 | // - stdarg.h | ||
| 638 | va_list, | ||
| 639 | |||
| 640 | // zig.h types | ||
| 641 | zig_u128, | ||
| 642 | zig_i128, | ||
| 643 | zig_f16, | ||
| 644 | zig_f32, | ||
| 645 | zig_f64, | ||
| 646 | zig_f80, | ||
| 647 | zig_f128, | ||
| 648 | zig_c_longdouble, | ||
| 649 | |||
| 650 | _, | ||
| 651 | |||
| 652 | const first_pool_index: u32 = @typeInfo(CType.Index).Enum.fields.len; | ||
| 653 | const basic_hashes = init: { | ||
| 654 | @setEvalBranchQuota(1_600); | ||
| 655 | var basic_hashes_init: [first_pool_index]Pool.Map.Hash = undefined; | ||
| 656 | for (&basic_hashes_init, 0..) |*basic_hash, index| { | ||
| 657 | const ctype_index: CType.Index = @enumFromInt(index); | ||
| 658 | var hasher = Pool.Hasher.init; | ||
| 659 | hasher.update(@intFromEnum(ctype_index)); | ||
| 660 | basic_hash.* = hasher.final(.basic); | ||
| 661 | } | ||
| 662 | break :init basic_hashes_init; | ||
| 663 | }; | ||
| 664 | }; | ||
| 665 | |||
| 666 | const Slice = struct { | ||
| 667 | extra_index: Pool.ExtraIndex, | ||
| 668 | len: u32, | ||
| 669 | |||
| 670 | pub fn at(slice: CType.Slice, index: usize, pool: *const Pool) CType { | ||
| 671 | var extra: Pool.ExtraTrail = .{ .extra_index = slice.extra_index }; | ||
| 672 | return .{ .index = extra.next(slice.len, CType.Index, pool)[index] }; | ||
| 673 | } | ||
| 674 | }; | ||
| 675 | |||
| 676 | pub const Kind = enum { | ||
| 677 | forward, | ||
| 678 | forward_parameter, | ||
| 679 | complete, | ||
| 680 | global, | ||
| 681 | parameter, | ||
| 682 | |||
| 683 | pub fn isForward(kind: Kind) bool { | ||
| 684 | return switch (kind) { | ||
| 685 | .forward, .forward_parameter => true, | ||
| 686 | .complete, .global, .parameter => false, | ||
| 687 | }; | ||
| 688 | } | ||
| 689 | |||
| 690 | pub fn isParameter(kind: Kind) bool { | ||
| 691 | return switch (kind) { | ||
| 692 | .forward_parameter, .parameter => true, | ||
| 693 | .forward, .complete, .global => false, | ||
| 694 | }; | ||
| 695 | } | ||
| 696 | |||
| 697 | pub fn asParameter(kind: Kind) Kind { | ||
| 698 | return switch (kind) { | ||
| 699 | .forward, .forward_parameter => .forward_parameter, | ||
| 700 | .complete, .parameter, .global => .parameter, | ||
| 701 | }; | ||
| 702 | } | ||
| 703 | |||
| 704 | pub fn noParameter(kind: Kind) Kind { | ||
| 705 | return switch (kind) { | ||
| 706 | .forward, .forward_parameter => .forward, | ||
| 707 | .complete, .parameter => .complete, | ||
| 708 | .global => .global, | ||
| 709 | }; | ||
| 710 | } | ||
| 711 | }; | ||
| 712 | |||
| 713 | pub const String = struct { | ||
| 714 | index: String.Index, | ||
| 715 | |||
| 716 | const Index = enum(u32) { | ||
| 717 | _, | ||
| 718 | }; | ||
| 719 | |||
| 720 | pub fn slice(string: String, pool: *const Pool) []const u8 { | ||
| 721 | const start = pool.string_indices.items[@intFromEnum(string.index)]; | ||
| 722 | const end = pool.string_indices.items[@intFromEnum(string.index) + 1]; | ||
| 723 | return pool.string_bytes.items[start..end]; | ||
| 724 | } | ||
| 725 | }; | ||
| 726 | |||
| 727 | pub const Info = union(enum) { | ||
| 728 | basic: CType.Index, | ||
| 729 | pointer: Pointer, | ||
| 730 | aligned: Aligned, | ||
| 731 | array: Sequence, | ||
| 732 | vector: Sequence, | ||
| 733 | fwd_decl: FwdDecl, | ||
| 734 | aggregate: Aggregate, | ||
| 735 | function: Function, | ||
| 736 | |||
| 737 | const Tag = @typeInfo(Info).Union.tag_type.?; | ||
| 738 | |||
| 739 | pub const Pointer = struct { | ||
| 740 | elem_ctype: CType, | ||
| 741 | @"const": bool = false, | ||
| 742 | @"volatile": bool = false, | ||
| 743 | |||
| 744 | fn tag(pointer_info: Pointer) Pool.Tag { | ||
| 745 | return @enumFromInt(@intFromEnum(Pool.Tag.pointer) + | ||
| 746 | @as(u2, @bitCast(packed struct(u2) { | ||
| 747 | @"const": bool, | ||
| 748 | @"volatile": bool, | ||
| 749 | }{ | ||
| 750 | .@"const" = pointer_info.@"const", | ||
| 751 | .@"volatile" = pointer_info.@"volatile", | ||
| 752 | }))); | ||
| 753 | } | ||
| 754 | }; | ||
| 755 | |||
| 756 | pub const Aligned = struct { | ||
| 757 | ctype: CType, | ||
| 758 | alignas: AlignAs, | ||
| 759 | }; | ||
| 760 | |||
| 761 | pub const Sequence = struct { | ||
| 762 | elem_ctype: CType, | ||
| 763 | len: u64, | ||
| 764 | }; | ||
| 765 | |||
| 766 | pub const AggregateTag = enum { @"enum", @"struct", @"union" }; | ||
| 767 | |||
| 768 | pub const Field = struct { | ||
| 769 | name: String, | ||
| 770 | ctype: CType, | ||
| 771 | alignas: AlignAs, | ||
| 772 | |||
| 773 | pub const Slice = struct { | ||
| 774 | extra_index: Pool.ExtraIndex, | ||
| 775 | len: u32, | ||
| 776 | |||
| 777 | pub fn at(slice: Field.Slice, index: usize, pool: *const Pool) Field { | ||
| 778 | assert(index < slice.len); | ||
| 779 | const extra = pool.getExtra(Pool.Field, @intCast(slice.extra_index + | ||
| 780 | index * @typeInfo(Pool.Field).Struct.fields.len)); | ||
| 781 | return .{ | ||
| 782 | .name = .{ .index = extra.name }, | ||
| 783 | .ctype = .{ .index = extra.ctype }, | ||
| 784 | .alignas = extra.flags.alignas, | ||
| 785 | }; | ||
| 786 | } | ||
| 787 | |||
| 788 | fn eqlAdapted( | ||
| 789 | lhs_slice: Field.Slice, | ||
| 790 | lhs_pool: *const Pool, | ||
| 791 | rhs_slice: Field.Slice, | ||
| 792 | rhs_pool: *const Pool, | ||
| 793 | pool_adapter: anytype, | ||
| 794 | ) bool { | ||
| 795 | if (lhs_slice.len != rhs_slice.len) return false; | ||
| 796 | for (0..lhs_slice.len) |index| { | ||
| 797 | if (!lhs_slice.at(index, lhs_pool).eqlAdapted( | ||
| 798 | lhs_pool, | ||
| 799 | rhs_slice.at(index, rhs_pool), | ||
| 800 | rhs_pool, | ||
| 801 | pool_adapter, | ||
| 802 | )) return false; | ||
| 803 | } | ||
| 804 | return true; | ||
| 805 | } | ||
| 806 | }; | ||
| 807 | |||
| 808 | fn eqlAdapted( | ||
| 809 | lhs_field: Field, | ||
| 810 | lhs_pool: *const Pool, | ||
| 811 | rhs_field: Field, | ||
| 812 | rhs_pool: *const Pool, | ||
| 813 | pool_adapter: anytype, | ||
| 814 | ) bool { | ||
| 815 | return std.meta.eql(lhs_field.alignas, rhs_field.alignas) and | ||
| 816 | pool_adapter.eql(lhs_field.ctype, rhs_field.ctype) and std.mem.eql( | ||
| 817 | u8, | ||
| 818 | lhs_field.name.slice(lhs_pool), | ||
| 819 | rhs_field.name.slice(rhs_pool), | ||
| 820 | ); | ||
| 821 | } | ||
| 822 | }; | ||
| 823 | |||
| 824 | pub const FwdDecl = struct { | ||
| 825 | tag: AggregateTag, | ||
| 826 | name: union(enum) { | ||
| 827 | anon: Field.Slice, | ||
| 828 | owner_decl: DeclIndex, | ||
| 829 | }, | ||
| 830 | }; | ||
| 831 | |||
| 832 | pub const Aggregate = struct { | ||
| 833 | tag: AggregateTag, | ||
| 834 | @"packed": bool = false, | ||
| 835 | name: union(enum) { | ||
| 836 | anon: struct { | ||
| 837 | owner_decl: DeclIndex, | ||
| 838 | id: u32, | ||
| 839 | }, | ||
| 840 | fwd_decl: CType, | ||
| 841 | }, | ||
| 842 | fields: Field.Slice, | ||
| 843 | }; | ||
| 844 | |||
| 845 | pub const Function = struct { | ||
| 846 | return_ctype: CType, | ||
| 847 | param_ctypes: CType.Slice, | ||
| 848 | varargs: bool = false, | ||
| 849 | }; | ||
| 850 | |||
| 851 | pub fn eqlAdapted( | ||
| 852 | lhs_info: Info, | ||
| 853 | lhs_pool: *const Pool, | ||
| 854 | rhs_ctype: CType, | ||
| 855 | rhs_pool: *const Pool, | ||
| 856 | pool_adapter: anytype, | ||
| 857 | ) bool { | ||
| 858 | const rhs_info = rhs_ctype.info(rhs_pool); | ||
| 859 | if (@as(Info.Tag, lhs_info) != @as(Info.Tag, rhs_info)) return false; | ||
| 860 | return switch (lhs_info) { | ||
| 861 | .basic => |lhs_basic_info| lhs_basic_info == rhs_info.basic, | ||
| 862 | .pointer => |lhs_pointer_info| lhs_pointer_info.@"const" == rhs_info.pointer.@"const" and | ||
| 863 | lhs_pointer_info.@"volatile" == rhs_info.pointer.@"volatile" and | ||
| 864 | pool_adapter.eql(lhs_pointer_info.elem_ctype, rhs_info.pointer.elem_ctype), | ||
| 865 | .aligned => |lhs_aligned_info| std.meta.eql(lhs_aligned_info.alignas, rhs_info.aligned.alignas) and | ||
| 866 | pool_adapter.eql(lhs_aligned_info.ctype, rhs_info.aligned.ctype), | ||
| 867 | .array => |lhs_array_info| lhs_array_info.len == rhs_info.array.len and | ||
| 868 | pool_adapter.eql(lhs_array_info.elem_ctype, rhs_info.array.elem_ctype), | ||
| 869 | .vector => |lhs_vector_info| lhs_vector_info.len == rhs_info.vector.len and | ||
| 870 | pool_adapter.eql(lhs_vector_info.elem_ctype, rhs_info.vector.elem_ctype), | ||
| 871 | .fwd_decl => |lhs_fwd_decl_info| lhs_fwd_decl_info.tag == rhs_info.fwd_decl.tag and | ||
| 872 | switch (lhs_fwd_decl_info.name) { | ||
| 873 | .anon => |lhs_anon| rhs_info.fwd_decl.name == .anon and lhs_anon.eqlAdapted( | ||
| 874 | lhs_pool, | ||
| 875 | rhs_info.fwd_decl.name.anon, | ||
| 876 | rhs_pool, | ||
| 877 | pool_adapter, | ||
| 878 | ), | ||
| 879 | .owner_decl => |lhs_owner_decl| rhs_info.fwd_decl.name == .owner_decl and | ||
| 880 | lhs_owner_decl == rhs_info.fwd_decl.name.owner_decl, | ||
| 881 | }, | ||
| 882 | .aggregate => |lhs_aggregate_info| lhs_aggregate_info.tag == rhs_info.aggregate.tag and | ||
| 883 | lhs_aggregate_info.@"packed" == rhs_info.aggregate.@"packed" and | ||
| 884 | switch (lhs_aggregate_info.name) { | ||
| 885 | .anon => |lhs_anon| rhs_info.aggregate.name == .anon and | ||
| 886 | lhs_anon.owner_decl == rhs_info.aggregate.name.anon.owner_decl and | ||
| 887 | lhs_anon.id == rhs_info.aggregate.name.anon.id, | ||
| 888 | .fwd_decl => |lhs_fwd_decl| rhs_info.aggregate.name == .fwd_decl and | ||
| 889 | pool_adapter.eql(lhs_fwd_decl, rhs_info.aggregate.name.fwd_decl), | ||
| 890 | } and lhs_aggregate_info.fields.eqlAdapted( | ||
| 891 | lhs_pool, | ||
| 892 | rhs_info.aggregate.fields, | ||
| 893 | rhs_pool, | ||
| 894 | pool_adapter, | ||
| 895 | ), | ||
| 896 | .function => |lhs_function_info| lhs_function_info.param_ctypes.len == | ||
| 897 | rhs_info.function.param_ctypes.len and | ||
| 898 | pool_adapter.eql(lhs_function_info.return_ctype, rhs_info.function.return_ctype) and | ||
| 899 | for (0..lhs_function_info.param_ctypes.len) |param_index| | ||
| 900 | { | ||
| 901 | if (!pool_adapter.eql( | ||
| 902 | lhs_function_info.param_ctypes.at(param_index, lhs_pool), | ||
| 903 | rhs_info.function.param_ctypes.at(param_index, rhs_pool), | ||
| 904 | )) break false; | ||
| 905 | } else true, | ||
| 906 | }; | ||
| 907 | } | ||
| 908 | }; | ||
| 909 | |||
| 910 | pub const Pool = struct { | ||
| 911 | map: Map, | ||
| 912 | items: std.MultiArrayList(Item), | ||
| 913 | extra: std.ArrayListUnmanaged(u32), | ||
| 914 | |||
| 915 | string_map: Map, | ||
| 916 | string_indices: std.ArrayListUnmanaged(u32), | ||
| 917 | string_bytes: std.ArrayListUnmanaged(u8), | ||
| 918 | |||
| 919 | const Map = std.AutoArrayHashMapUnmanaged(void, void); | ||
| 920 | |||
| 921 | pub const empty: Pool = .{ | ||
| 922 | .map = .{}, | ||
| 923 | .items = .{}, | ||
| 924 | .extra = .{}, | ||
| 925 | |||
| 926 | .string_map = .{}, | ||
| 927 | .string_indices = .{}, | ||
| 928 | .string_bytes = .{}, | ||
| 929 | }; | ||
| 930 | |||
| 931 | pub fn init(pool: *Pool, allocator: std.mem.Allocator) !void { | ||
| 932 | if (pool.string_indices.items.len == 0) | ||
| 933 | try pool.string_indices.append(allocator, 0); | ||
| 934 | } | ||
| 935 | |||
| 936 | pub fn deinit(pool: *Pool, allocator: std.mem.Allocator) void { | ||
| 937 | pool.map.deinit(allocator); | ||
| 938 | pool.items.deinit(allocator); | ||
| 939 | pool.extra.deinit(allocator); | ||
| 940 | |||
| 941 | pool.string_map.deinit(allocator); | ||
| 942 | pool.string_indices.deinit(allocator); | ||
| 943 | pool.string_bytes.deinit(allocator); | ||
| 944 | |||
| 945 | pool.* = undefined; | ||
| 946 | } | ||
| 947 | |||
| 948 | pub fn move(pool: *Pool) Pool { | ||
| 949 | defer pool.* = empty; | ||
| 950 | return pool.*; | ||
| 951 | } | ||
| 952 | |||
| 953 | pub fn clearRetainingCapacity(pool: *Pool) void { | ||
| 954 | pool.map.clearRetainingCapacity(); | ||
| 955 | pool.items.shrinkRetainingCapacity(0); | ||
| 956 | pool.extra.clearRetainingCapacity(); | ||
| 957 | |||
| 958 | pool.string_map.clearRetainingCapacity(); | ||
| 959 | pool.string_indices.shrinkRetainingCapacity(1); | ||
| 960 | pool.string_bytes.clearRetainingCapacity(); | ||
| 961 | } | ||
| 962 | |||
| 963 | pub fn freeUnusedCapacity(pool: *Pool, allocator: std.mem.Allocator) void { | ||
| 964 | pool.map.shrinkAndFree(allocator, pool.map.count()); | ||
| 965 | pool.items.shrinkAndFree(allocator, pool.items.len); | ||
| 966 | pool.extra.shrinkAndFree(allocator, pool.extra.items.len); | ||
| 967 | |||
| 968 | pool.string_map.shrinkAndFree(allocator, pool.string_map.count()); | ||
| 969 | pool.string_indices.shrinkAndFree(allocator, pool.string_indices.items.len); | ||
| 970 | pool.string_bytes.shrinkAndFree(allocator, pool.string_bytes.items.len); | ||
| 971 | } | ||
| 972 | |||
| 973 | pub fn getPointer(pool: *Pool, allocator: std.mem.Allocator, pointer_info: Info.Pointer) !CType { | ||
| 974 | var hasher = Hasher.init; | ||
| 975 | hasher.update(pointer_info.elem_ctype.hash(pool)); | ||
| 976 | return pool.tagData( | ||
| 977 | allocator, | ||
| 978 | hasher, | ||
| 979 | pointer_info.tag(), | ||
| 980 | @intFromEnum(pointer_info.elem_ctype.index), | ||
| 981 | ); | ||
| 982 | } | ||
| 983 | |||
| 984 | pub fn getAligned(pool: *Pool, allocator: std.mem.Allocator, aligned_info: Info.Aligned) !CType { | ||
| 985 | return pool.tagExtra(allocator, .aligned, Aligned, .{ | ||
| 986 | .ctype = aligned_info.ctype.index, | ||
| 987 | .flags = .{ .alignas = aligned_info.alignas }, | ||
| 988 | }); | ||
| 989 | } | ||
| 990 | |||
| 991 | pub fn getArray(pool: *Pool, allocator: std.mem.Allocator, array_info: Info.Sequence) !CType { | ||
| 992 | return if (std.math.cast(u32, array_info.len)) |small_len| | ||
| 993 | pool.tagExtra(allocator, .array_small, SequenceSmall, .{ | ||
| 994 | .elem_ctype = array_info.elem_ctype.index, | ||
| 995 | .len = small_len, | ||
| 996 | }) | ||
| 997 | else | ||
| 998 | pool.tagExtra(allocator, .array_large, SequenceLarge, .{ | ||
| 999 | .elem_ctype = array_info.elem_ctype.index, | ||
| 1000 | .len_lo = @truncate(array_info.len >> 0), | ||
| 1001 | .len_hi = @truncate(array_info.len >> 32), | ||
| 1002 | }); | ||
| 1003 | } | ||
| 1004 | |||
| 1005 | pub fn getVector(pool: *Pool, allocator: std.mem.Allocator, vector_info: Info.Sequence) !CType { | ||
| 1006 | return pool.tagExtra(allocator, .vector, SequenceSmall, .{ | ||
| 1007 | .elem_ctype = vector_info.elem_ctype.index, | ||
| 1008 | .len = @intCast(vector_info.len), | ||
| 1009 | }); | ||
| 1010 | } | ||
| 1011 | |||
| 1012 | pub fn getFwdDecl( | ||
| 1013 | pool: *Pool, | ||
| 1014 | allocator: std.mem.Allocator, | ||
| 1015 | fwd_decl_info: struct { | ||
| 1016 | tag: Info.AggregateTag, | ||
| 1017 | name: union(enum) { | ||
| 1018 | anon: []const Info.Field, | ||
| 1019 | owner_decl: DeclIndex, | ||
| 1020 | }, | ||
| 1021 | }, | ||
| 1022 | ) !CType { | ||
| 1023 | var hasher = Hasher.init; | ||
| 1024 | switch (fwd_decl_info.name) { | ||
| 1025 | .anon => |fields| { | ||
| 1026 | const ExpectedContents = [32]CType; | ||
| 1027 | var stack align(@max( | ||
| 1028 | @alignOf(std.heap.StackFallbackAllocator(0)), | ||
| 1029 | @alignOf(ExpectedContents), | ||
| 1030 | )) = std.heap.stackFallback(@sizeOf(ExpectedContents), allocator); | ||
| 1031 | const stack_allocator = stack.get(); | ||
| 1032 | const field_ctypes = try stack_allocator.alloc(CType, fields.len); | ||
| 1033 | defer stack_allocator.free(field_ctypes); | ||
| 1034 | for (field_ctypes, fields) |*field_ctype, field| | ||
| 1035 | field_ctype.* = try field.ctype.toForward(pool, allocator); | ||
| 1036 | const extra: FwdDeclAnon = .{ .fields_len = @intCast(fields.len) }; | ||
| 1037 | const extra_index = try pool.addExtra( | ||
| 1038 | allocator, | ||
| 1039 | FwdDeclAnon, | ||
| 1040 | extra, | ||
| 1041 | fields.len * @typeInfo(Field).Struct.fields.len, | ||
| 1042 | ); | ||
| 1043 | for (fields, field_ctypes) |field, field_ctype| pool.addHashedExtraAssumeCapacity( | ||
| 1044 | &hasher, | ||
| 1045 | Field, | ||
| 1046 | .{ | ||
| 1047 | .name = field.name.index, | ||
| 1048 | .ctype = field_ctype.index, | ||
| 1049 | .flags = .{ .alignas = field.alignas }, | ||
| 1050 | }, | ||
| 1051 | ); | ||
| 1052 | hasher.updateExtra(FwdDeclAnon, extra, pool); | ||
| 1053 | return pool.tagTrailingExtra(allocator, hasher, switch (fwd_decl_info.tag) { | ||
| 1054 | .@"struct" => .fwd_decl_struct_anon, | ||
| 1055 | .@"union" => .fwd_decl_union_anon, | ||
| 1056 | .@"enum" => unreachable, | ||
| 1057 | }, extra_index); | ||
| 1058 | }, | ||
| 1059 | .owner_decl => |owner_decl| { | ||
| 1060 | hasher.update(owner_decl); | ||
| 1061 | return pool.tagData(allocator, hasher, switch (fwd_decl_info.tag) { | ||
| 1062 | .@"struct" => .fwd_decl_struct, | ||
| 1063 | .@"union" => .fwd_decl_union, | ||
| 1064 | .@"enum" => unreachable, | ||
| 1065 | }, @intFromEnum(owner_decl)); | ||
| 1066 | }, | ||
| 1067 | } | ||
| 1068 | } | ||
| 1069 | |||
| 1070 | pub fn getAggregate( | ||
| 1071 | pool: *Pool, | ||
| 1072 | allocator: std.mem.Allocator, | ||
| 1073 | aggregate_info: struct { | ||
| 1074 | tag: Info.AggregateTag, | ||
| 1075 | @"packed": bool = false, | ||
| 1076 | name: union(enum) { | ||
| 1077 | anon: struct { | ||
| 1078 | owner_decl: DeclIndex, | ||
| 1079 | id: u32, | ||
| 1080 | }, | ||
| 1081 | fwd_decl: CType, | ||
| 1082 | }, | ||
| 1083 | fields: []const Info.Field, | ||
| 1084 | }, | ||
| 1085 | ) !CType { | ||
| 1086 | var hasher = Hasher.init; | ||
| 1087 | switch (aggregate_info.name) { | ||
| 1088 | .anon => |anon| { | ||
| 1089 | const extra: AggregateAnon = .{ | ||
| 1090 | .owner_decl = anon.owner_decl, | ||
| 1091 | .id = anon.id, | ||
| 1092 | .fields_len = @intCast(aggregate_info.fields.len), | ||
| 1093 | }; | ||
| 1094 | const extra_index = try pool.addExtra( | ||
| 1095 | allocator, | ||
| 1096 | AggregateAnon, | ||
| 1097 | extra, | ||
| 1098 | aggregate_info.fields.len * @typeInfo(Field).Struct.fields.len, | ||
| 1099 | ); | ||
| 1100 | for (aggregate_info.fields) |field| pool.addHashedExtraAssumeCapacity(&hasher, Field, .{ | ||
| 1101 | .name = field.name.index, | ||
| 1102 | .ctype = field.ctype.index, | ||
| 1103 | .flags = .{ .alignas = field.alignas }, | ||
| 1104 | }); | ||
| 1105 | hasher.updateExtra(AggregateAnon, extra, pool); | ||
| 1106 | return pool.tagTrailingExtra(allocator, hasher, switch (aggregate_info.tag) { | ||
| 1107 | .@"struct" => switch (aggregate_info.@"packed") { | ||
| 1108 | false => .aggregate_struct_anon, | ||
| 1109 | true => .aggregate_struct_packed_anon, | ||
| 1110 | }, | ||
| 1111 | .@"union" => switch (aggregate_info.@"packed") { | ||
| 1112 | false => .aggregate_union_anon, | ||
| 1113 | true => .aggregate_union_packed_anon, | ||
| 1114 | }, | ||
| 1115 | .@"enum" => unreachable, | ||
| 1116 | }, extra_index); | ||
| 1117 | }, | ||
| 1118 | .fwd_decl => |fwd_decl| { | ||
| 1119 | const extra: Aggregate = .{ | ||
| 1120 | .fwd_decl = fwd_decl.index, | ||
| 1121 | .fields_len = @intCast(aggregate_info.fields.len), | ||
| 1122 | }; | ||
| 1123 | const extra_index = try pool.addExtra( | ||
| 1124 | allocator, | ||
| 1125 | Aggregate, | ||
| 1126 | extra, | ||
| 1127 | aggregate_info.fields.len * @typeInfo(Field).Struct.fields.len, | ||
| 1128 | ); | ||
| 1129 | for (aggregate_info.fields) |field| pool.addHashedExtraAssumeCapacity(&hasher, Field, .{ | ||
| 1130 | .name = field.name.index, | ||
| 1131 | .ctype = field.ctype.index, | ||
| 1132 | .flags = .{ .alignas = field.alignas }, | ||
| 1133 | }); | ||
| 1134 | hasher.updateExtra(Aggregate, extra, pool); | ||
| 1135 | return pool.tagTrailingExtra(allocator, hasher, switch (aggregate_info.tag) { | ||
| 1136 | .@"struct" => switch (aggregate_info.@"packed") { | ||
| 1137 | false => .aggregate_struct, | ||
| 1138 | true => .aggregate_struct_packed, | ||
| 1139 | }, | ||
| 1140 | .@"union" => switch (aggregate_info.@"packed") { | ||
| 1141 | false => .aggregate_union, | ||
| 1142 | true => .aggregate_union_packed, | ||
| 1143 | }, | ||
| 1144 | .@"enum" => unreachable, | ||
| 1145 | }, extra_index); | ||
| 1146 | }, | ||
| 1147 | } | ||
| 1148 | } | ||
| 1149 | |||
| 1150 | pub fn getFunction( | ||
| 1151 | pool: *Pool, | ||
| 1152 | allocator: std.mem.Allocator, | ||
| 1153 | function_info: struct { | ||
| 1154 | return_ctype: CType, | ||
| 1155 | param_ctypes: []const CType, | ||
| 1156 | varargs: bool = false, | ||
| 1157 | }, | ||
| 1158 | ) !CType { | ||
| 1159 | var hasher = Hasher.init; | ||
| 1160 | const extra: Function = .{ | ||
| 1161 | .return_ctype = function_info.return_ctype.index, | ||
| 1162 | .param_ctypes_len = @intCast(function_info.param_ctypes.len), | ||
| 1163 | }; | ||
| 1164 | const extra_index = try pool.addExtra(allocator, Function, extra, function_info.param_ctypes.len); | ||
| 1165 | for (function_info.param_ctypes) |param_ctype| { | ||
| 1166 | hasher.update(param_ctype.hash(pool)); | ||
| 1167 | pool.extra.appendAssumeCapacity(@intFromEnum(param_ctype.index)); | ||
| 1168 | } | ||
| 1169 | hasher.updateExtra(Function, extra, pool); | ||
| 1170 | return pool.tagTrailingExtra(allocator, hasher, switch (function_info.varargs) { | ||
| 1171 | false => .function, | ||
| 1172 | true => .function_varargs, | ||
| 1173 | }, extra_index); | ||
| 1174 | } | ||
| 1175 | |||
| 1176 | pub fn fromFields( | ||
| 1177 | pool: *Pool, | ||
| 1178 | allocator: std.mem.Allocator, | ||
| 1179 | tag: Info.AggregateTag, | ||
| 1180 | fields: []Info.Field, | ||
| 1181 | kind: Kind, | ||
| 1182 | ) !CType { | ||
| 1183 | sortFields(fields); | ||
| 1184 | const fwd_decl = try pool.getFwdDecl(allocator, .{ | ||
| 1185 | .tag = tag, | ||
| 1186 | .name = .{ .anon = fields }, | ||
| 1187 | }); | ||
| 1188 | return if (kind.isForward()) fwd_decl else pool.getAggregate(allocator, .{ | ||
| 1189 | .tag = tag, | ||
| 1190 | .name = .{ .fwd_decl = fwd_decl }, | ||
| 1191 | .fields = fields, | ||
| 1192 | }); | ||
| 1193 | } | ||
| 1194 | |||
| 1195 | pub fn fromIntInfo( | ||
| 1196 | pool: *Pool, | ||
| 1197 | allocator: std.mem.Allocator, | ||
| 1198 | int_info: std.builtin.Type.Int, | ||
| 1199 | mod: *Module, | ||
| 1200 | kind: Kind, | ||
| 1201 | ) !CType { | ||
| 1202 | switch (int_info.bits) { | ||
| 1203 | 0 => return .{ .index = .void }, | ||
| 1204 | 1...8 => switch (int_info.signedness) { | ||
| 1205 | .unsigned => return .{ .index = .uint8_t }, | ||
| 1206 | .signed => return .{ .index = .int8_t }, | ||
| 1207 | }, | ||
| 1208 | 9...16 => switch (int_info.signedness) { | ||
| 1209 | .unsigned => return .{ .index = .uint16_t }, | ||
| 1210 | .signed => return .{ .index = .int16_t }, | ||
| 1211 | }, | ||
| 1212 | 17...32 => switch (int_info.signedness) { | ||
| 1213 | .unsigned => return .{ .index = .uint32_t }, | ||
| 1214 | .signed => return .{ .index = .int32_t }, | ||
| 1215 | }, | ||
| 1216 | 33...64 => switch (int_info.signedness) { | ||
| 1217 | .unsigned => return .{ .index = .uint64_t }, | ||
| 1218 | .signed => return .{ .index = .int64_t }, | ||
| 1219 | }, | ||
| 1220 | 65...128 => switch (int_info.signedness) { | ||
| 1221 | .unsigned => return .{ .index = .zig_u128 }, | ||
| 1222 | .signed => return .{ .index = .zig_i128 }, | ||
| 1223 | }, | ||
| 1224 | else => { | ||
| 1225 | const target = &mod.resolved_target.result; | ||
| 1226 | const abi_align = Type.intAbiAlignment(int_info.bits, target.*); | ||
| 1227 | const abi_align_bytes = abi_align.toByteUnits().?; | ||
| 1228 | const array_ctype = try pool.getArray(allocator, .{ | ||
| 1229 | .len = @divExact(Type.intAbiSize(int_info.bits, target.*), abi_align_bytes), | ||
| 1230 | .elem_ctype = try pool.fromIntInfo(allocator, .{ | ||
| 1231 | .signedness = .unsigned, | ||
| 1232 | .bits = @intCast(abi_align_bytes * 8), | ||
| 1233 | }, mod, kind.noParameter()), | ||
| 1234 | }); | ||
| 1235 | if (!kind.isParameter()) return array_ctype; | ||
| 1236 | var fields = [_]Info.Field{ | ||
| 1237 | .{ | ||
| 1238 | .name = try pool.string(allocator, "array"), | ||
| 1239 | .ctype = array_ctype, | ||
| 1240 | .alignas = AlignAs.fromAbiAlignment(abi_align), | ||
| 1241 | }, | ||
| 1242 | }; | ||
| 1243 | return pool.fromFields(allocator, .@"struct", &fields, kind); | ||
| 1244 | }, | ||
| 1245 | } | ||
| 1246 | } | ||
| 1247 | |||
| 1248 | pub fn fromType( | ||
| 1249 | pool: *Pool, | ||
| 1250 | allocator: std.mem.Allocator, | ||
| 1251 | scratch: *std.ArrayListUnmanaged(u32), | ||
| 1252 | ty: Type, | ||
| 1253 | zcu: *Zcu, | ||
| 1254 | mod: *Module, | ||
| 1255 | kind: Kind, | ||
| 1256 | ) !CType { | ||
| 1257 | const ip = &zcu.intern_pool; | ||
| 1258 | switch (ty.toIntern()) { | ||
| 1259 | .u0_type, | ||
| 1260 | .i0_type, | ||
| 1261 | .anyopaque_type, | ||
| 1262 | .void_type, | ||
| 1263 | .empty_struct_type, | ||
| 1264 | .type_type, | ||
| 1265 | .comptime_int_type, | ||
| 1266 | .comptime_float_type, | ||
| 1267 | .null_type, | ||
| 1268 | .undefined_type, | ||
| 1269 | .enum_literal_type, | ||
| 1270 | => return .{ .index = .void }, | ||
| 1271 | .u1_type, .u8_type => return .{ .index = .uint8_t }, | ||
| 1272 | .i8_type => return .{ .index = .int8_t }, | ||
| 1273 | .u16_type => return .{ .index = .uint16_t }, | ||
| 1274 | .i16_type => return .{ .index = .int16_t }, | ||
| 1275 | .u29_type, .u32_type => return .{ .index = .uint32_t }, | ||
| 1276 | .i32_type => return .{ .index = .int32_t }, | ||
| 1277 | .u64_type => return .{ .index = .uint64_t }, | ||
| 1278 | .i64_type => return .{ .index = .int64_t }, | ||
| 1279 | .u80_type, .u128_type => return .{ .index = .zig_u128 }, | ||
| 1280 | .i128_type => return .{ .index = .zig_i128 }, | ||
| 1281 | .usize_type => return .{ .index = .uintptr_t }, | ||
| 1282 | .isize_type => return .{ .index = .intptr_t }, | ||
| 1283 | .c_char_type => return .{ .index = .char }, | ||
| 1284 | .c_short_type => return .{ .index = .short }, | ||
| 1285 | .c_ushort_type => return .{ .index = .@"unsigned short" }, | ||
| 1286 | .c_int_type => return .{ .index = .int }, | ||
| 1287 | .c_uint_type => return .{ .index = .@"unsigned int" }, | ||
| 1288 | .c_long_type => return .{ .index = .long }, | ||
| 1289 | .c_ulong_type => return .{ .index = .@"unsigned long" }, | ||
| 1290 | .c_longlong_type => return .{ .index = .@"long long" }, | ||
| 1291 | .c_ulonglong_type => return .{ .index = .@"unsigned long long" }, | ||
| 1292 | .c_longdouble_type => return .{ .index = .@"long double" }, | ||
| 1293 | .f16_type => return .{ .index = .zig_f16 }, | ||
| 1294 | .f32_type => return .{ .index = .zig_f32 }, | ||
| 1295 | .f64_type => return .{ .index = .zig_f64 }, | ||
| 1296 | .f80_type => return .{ .index = .zig_f80 }, | ||
| 1297 | .f128_type => return .{ .index = .zig_f128 }, | ||
| 1298 | .bool_type, .optional_noreturn_type => return .{ .index = .bool }, | ||
| 1299 | .noreturn_type, | ||
| 1300 | .anyframe_type, | ||
| 1301 | .generic_poison_type, | ||
| 1302 | => unreachable, | ||
| 1303 | .atomic_order_type, | ||
| 1304 | .atomic_rmw_op_type, | ||
| 1305 | .calling_convention_type, | ||
| 1306 | .address_space_type, | ||
| 1307 | .float_mode_type, | ||
| 1308 | .reduce_op_type, | ||
| 1309 | .call_modifier_type, | ||
| 1310 | => |ip_index| return pool.fromType( | ||
| 1311 | allocator, | ||
| 1312 | scratch, | ||
| 1313 | Type.fromInterned(ip.loadEnumType(ip_index).tag_ty), | ||
| 1314 | zcu, | ||
| 1315 | mod, | ||
| 1316 | kind, | ||
| 1317 | ), | ||
| 1318 | .anyerror_type, | ||
| 1319 | .anyerror_void_error_union_type, | ||
| 1320 | .adhoc_inferred_error_set_type, | ||
| 1321 | => return pool.fromIntInfo(allocator, .{ | ||
| 1322 | .signedness = .unsigned, | ||
| 1323 | .bits = zcu.errorSetBits(), | ||
| 1324 | }, mod, kind), | ||
| 1325 | .manyptr_u8_type, | ||
| 1326 | => return pool.getPointer(allocator, .{ | ||
| 1327 | .elem_ctype = .{ .index = .uint8_t }, | ||
| 1328 | }), | ||
| 1329 | .manyptr_const_u8_type, | ||
| 1330 | .manyptr_const_u8_sentinel_0_type, | ||
| 1331 | => return pool.getPointer(allocator, .{ | ||
| 1332 | .elem_ctype = .{ .index = .uint8_t }, | ||
| 1333 | .@"const" = true, | ||
| 1334 | }), | ||
| 1335 | .single_const_pointer_to_comptime_int_type, | ||
| 1336 | => return pool.getPointer(allocator, .{ | ||
| 1337 | .elem_ctype = .{ .index = .void }, | ||
| 1338 | .@"const" = true, | ||
| 1339 | }), | ||
| 1340 | .slice_const_u8_type, | ||
| 1341 | .slice_const_u8_sentinel_0_type, | ||
| 1342 | => { | ||
| 1343 | const target = &mod.resolved_target.result; | ||
| 1344 | var fields = [_]Info.Field{ | ||
| 1345 | .{ | ||
| 1346 | .name = try pool.string(allocator, "ptr"), | ||
| 1347 | .ctype = try pool.getPointer(allocator, .{ | ||
| 1348 | .elem_ctype = .{ .index = .uint8_t }, | ||
| 1349 | .@"const" = true, | ||
| 1350 | }), | ||
| 1351 | .alignas = AlignAs.fromAbiAlignment(Type.ptrAbiAlignment(target.*)), | ||
| 1352 | }, | ||
| 1353 | .{ | ||
| 1354 | .name = try pool.string(allocator, "len"), | ||
| 1355 | .ctype = .{ .index = .uintptr_t }, | ||
| 1356 | .alignas = AlignAs.fromAbiAlignment( | ||
| 1357 | Type.intAbiAlignment(target.ptrBitWidth(), target.*), | ||
| 1358 | ), | ||
| 1359 | }, | ||
| 1360 | }; | ||
| 1361 | return pool.fromFields(allocator, .@"struct", &fields, kind); | ||
| 1362 | }, | ||
| 1363 | |||
| 1364 | .undef, | ||
| 1365 | .zero, | ||
| 1366 | .zero_usize, | ||
| 1367 | .zero_u8, | ||
| 1368 | .one, | ||
| 1369 | .one_usize, | ||
| 1370 | .one_u8, | ||
| 1371 | .four_u8, | ||
| 1372 | .negative_one, | ||
| 1373 | .calling_convention_c, | ||
| 1374 | .calling_convention_inline, | ||
| 1375 | .void_value, | ||
| 1376 | .unreachable_value, | ||
| 1377 | .null_value, | ||
| 1378 | .bool_true, | ||
| 1379 | .bool_false, | ||
| 1380 | .empty_struct, | ||
| 1381 | .generic_poison, | ||
| 1382 | .var_args_param_type, | ||
| 1383 | .none, | ||
| 1384 | => unreachable, | ||
| 1385 | |||
| 1386 | //.prefetch_options_type, | ||
| 1387 | //.export_options_type, | ||
| 1388 | //.extern_options_type, | ||
| 1389 | //.type_info_type, | ||
| 1390 | //_, | ||
| 1391 | else => |ip_index| switch (ip.indexToKey(ip_index)) { | ||
| 1392 | .int_type => |int_info| return pool.fromIntInfo(allocator, int_info, mod, kind), | ||
| 1393 | .ptr_type => |ptr_info| switch (ptr_info.flags.size) { | ||
| 1394 | .One, .Many, .C => { | ||
| 1395 | const elem_ctype = elem_ctype: { | ||
| 1396 | if (ptr_info.packed_offset.host_size > 0 and | ||
| 1397 | ptr_info.flags.vector_index == .none) | ||
| 1398 | break :elem_ctype try pool.fromIntInfo(allocator, .{ | ||
| 1399 | .signedness = .unsigned, | ||
| 1400 | .bits = ptr_info.packed_offset.host_size * 8, | ||
| 1401 | }, mod, .forward); | ||
| 1402 | const elem: Info.Aligned = .{ | ||
| 1403 | .ctype = try pool.fromType( | ||
| 1404 | allocator, | ||
| 1405 | scratch, | ||
| 1406 | Type.fromInterned(ptr_info.child), | ||
| 1407 | zcu, | ||
| 1408 | mod, | ||
| 1409 | .forward, | ||
| 1410 | ), | ||
| 1411 | .alignas = AlignAs.fromAlignment(.{ | ||
| 1412 | .@"align" = ptr_info.flags.alignment, | ||
| 1413 | .abi = Type.fromInterned(ptr_info.child).abiAlignment(zcu), | ||
| 1414 | }), | ||
| 1415 | }; | ||
| 1416 | break :elem_ctype if (elem.alignas.abiOrder().compare(.gte)) | ||
| 1417 | elem.ctype | ||
| 1418 | else | ||
| 1419 | try pool.getAligned(allocator, elem); | ||
| 1420 | }; | ||
| 1421 | const elem_tag: Info.Tag = switch (elem_ctype.info(pool)) { | ||
| 1422 | .aligned => |aligned_info| aligned_info.ctype.info(pool), | ||
| 1423 | else => |elem_tag| elem_tag, | ||
| 1424 | }; | ||
| 1425 | return pool.getPointer(allocator, .{ | ||
| 1426 | .elem_ctype = elem_ctype, | ||
| 1427 | .@"const" = switch (elem_tag) { | ||
| 1428 | .basic, | ||
| 1429 | .pointer, | ||
| 1430 | .aligned, | ||
| 1431 | .array, | ||
| 1432 | .vector, | ||
| 1433 | .fwd_decl, | ||
| 1434 | .aggregate, | ||
| 1435 | => ptr_info.flags.is_const, | ||
| 1436 | .function => false, | ||
| 1437 | }, | ||
| 1438 | .@"volatile" = ptr_info.flags.is_volatile, | ||
| 1439 | }); | ||
| 1440 | }, | ||
| 1441 | .Slice => { | ||
| 1442 | const target = &mod.resolved_target.result; | ||
| 1443 | var fields = [_]Info.Field{ | ||
| 1444 | .{ | ||
| 1445 | .name = try pool.string(allocator, "ptr"), | ||
| 1446 | .ctype = try pool.fromType( | ||
| 1447 | allocator, | ||
| 1448 | scratch, | ||
| 1449 | Type.fromInterned(ip.slicePtrType(ip_index)), | ||
| 1450 | zcu, | ||
| 1451 | mod, | ||
| 1452 | kind, | ||
| 1453 | ), | ||
| 1454 | .alignas = AlignAs.fromAbiAlignment(Type.ptrAbiAlignment(target.*)), | ||
| 1455 | }, | ||
| 1456 | .{ | ||
| 1457 | .name = try pool.string(allocator, "len"), | ||
| 1458 | .ctype = .{ .index = .uintptr_t }, | ||
| 1459 | .alignas = AlignAs.fromAbiAlignment( | ||
| 1460 | Type.intAbiAlignment(target.ptrBitWidth(), target.*), | ||
| 1461 | ), | ||
| 1462 | }, | ||
| 1463 | }; | ||
| 1464 | return pool.fromFields(allocator, .@"struct", &fields, kind); | ||
| 1465 | }, | ||
| 1466 | }, | ||
| 1467 | .array_type => |array_info| { | ||
| 1468 | const len = array_info.len + @intFromBool(array_info.sentinel != .none); | ||
| 1469 | if (len == 0) return .{ .index = .void }; | ||
| 1470 | const elem_type = Type.fromInterned(array_info.child); | ||
| 1471 | const elem_ctype = try pool.fromType( | ||
| 1472 | allocator, | ||
| 1473 | scratch, | ||
| 1474 | elem_type, | ||
| 1475 | zcu, | ||
| 1476 | mod, | ||
| 1477 | kind.noParameter(), | ||
| 1478 | ); | ||
| 1479 | if (elem_ctype.index == .void) return .{ .index = .void }; | ||
| 1480 | const array_ctype = try pool.getArray(allocator, .{ | ||
| 1481 | .elem_ctype = elem_ctype, | ||
| 1482 | .len = array_info.len + @intFromBool(array_info.sentinel != .none), | ||
| 1483 | }); | ||
| 1484 | if (!kind.isParameter()) return array_ctype; | ||
| 1485 | var fields = [_]Info.Field{ | ||
| 1486 | .{ | ||
| 1487 | .name = try pool.string(allocator, "array"), | ||
| 1488 | .ctype = array_ctype, | ||
| 1489 | .alignas = AlignAs.fromAbiAlignment(elem_type.abiAlignment(zcu)), | ||
| 1490 | }, | ||
| 1491 | }; | ||
| 1492 | return pool.fromFields(allocator, .@"struct", &fields, kind); | ||
| 1493 | }, | ||
| 1494 | .vector_type => |vector_info| { | ||
| 1495 | if (vector_info.len == 0) return .{ .index = .void }; | ||
| 1496 | const elem_type = Type.fromInterned(vector_info.child); | ||
| 1497 | const elem_ctype = try pool.fromType( | ||
| 1498 | allocator, | ||
| 1499 | scratch, | ||
| 1500 | elem_type, | ||
| 1501 | zcu, | ||
| 1502 | mod, | ||
| 1503 | kind.noParameter(), | ||
| 1504 | ); | ||
| 1505 | if (elem_ctype.index == .void) return .{ .index = .void }; | ||
| 1506 | const vector_ctype = try pool.getVector(allocator, .{ | ||
| 1507 | .elem_ctype = elem_ctype, | ||
| 1508 | .len = vector_info.len, | ||
| 1509 | }); | ||
| 1510 | if (!kind.isParameter()) return vector_ctype; | ||
| 1511 | var fields = [_]Info.Field{ | ||
| 1512 | .{ | ||
| 1513 | .name = try pool.string(allocator, "array"), | ||
| 1514 | .ctype = vector_ctype, | ||
| 1515 | .alignas = AlignAs.fromAbiAlignment(elem_type.abiAlignment(zcu)), | ||
| 1516 | }, | ||
| 1517 | }; | ||
| 1518 | return pool.fromFields(allocator, .@"struct", &fields, kind); | ||
| 1519 | }, | ||
| 1520 | .opt_type => |payload_type| { | ||
| 1521 | if (ip.isNoReturn(payload_type)) return .{ .index = .void }; | ||
| 1522 | const payload_ctype = try pool.fromType( | ||
| 1523 | allocator, | ||
| 1524 | scratch, | ||
| 1525 | Type.fromInterned(payload_type), | ||
| 1526 | zcu, | ||
| 1527 | mod, | ||
| 1528 | kind.noParameter(), | ||
| 1529 | ); | ||
| 1530 | if (payload_ctype.index == .void) return .{ .index = .bool }; | ||
| 1531 | switch (payload_type) { | ||
| 1532 | .anyerror_type => return payload_ctype, | ||
| 1533 | else => switch (ip.indexToKey(payload_type)) { | ||
| 1534 | .ptr_type => |payload_ptr_info| if (payload_ptr_info.flags.size != .C and | ||
| 1535 | !payload_ptr_info.flags.is_allowzero) return payload_ctype, | ||
| 1536 | .error_set_type, .inferred_error_set_type => return payload_ctype, | ||
| 1537 | else => {}, | ||
| 1538 | }, | ||
| 1539 | } | ||
| 1540 | var fields = [_]Info.Field{ | ||
| 1541 | .{ | ||
| 1542 | .name = try pool.string(allocator, "is_null"), | ||
| 1543 | .ctype = .{ .index = .bool }, | ||
| 1544 | .alignas = AlignAs.fromAbiAlignment(.@"1"), | ||
| 1545 | }, | ||
| 1546 | .{ | ||
| 1547 | .name = try pool.string(allocator, "payload"), | ||
| 1548 | .ctype = payload_ctype, | ||
| 1549 | .alignas = AlignAs.fromAbiAlignment( | ||
| 1550 | Type.fromInterned(payload_type).abiAlignment(zcu), | ||
| 1551 | ), | ||
| 1552 | }, | ||
| 1553 | }; | ||
| 1554 | return pool.fromFields(allocator, .@"struct", &fields, kind); | ||
| 1555 | }, | ||
| 1556 | .anyframe_type => unreachable, | ||
| 1557 | .error_union_type => |error_union_info| { | ||
| 1558 | const error_set_bits = zcu.errorSetBits(); | ||
| 1559 | const error_set_ctype = try pool.fromIntInfo(allocator, .{ | ||
| 1560 | .signedness = .unsigned, | ||
| 1561 | .bits = error_set_bits, | ||
| 1562 | }, mod, kind); | ||
| 1563 | if (ip.isNoReturn(error_union_info.payload_type)) return error_set_ctype; | ||
| 1564 | const payload_type = Type.fromInterned(error_union_info.payload_type); | ||
| 1565 | const payload_ctype = try pool.fromType( | ||
| 1566 | allocator, | ||
| 1567 | scratch, | ||
| 1568 | payload_type, | ||
| 1569 | zcu, | ||
| 1570 | mod, | ||
| 1571 | kind.noParameter(), | ||
| 1572 | ); | ||
| 1573 | if (payload_ctype.index == .void) return error_set_ctype; | ||
| 1574 | const target = &mod.resolved_target.result; | ||
| 1575 | var fields = [_]Info.Field{ | ||
| 1576 | .{ | ||
| 1577 | .name = try pool.string(allocator, "error"), | ||
| 1578 | .ctype = error_set_ctype, | ||
| 1579 | .alignas = AlignAs.fromAbiAlignment( | ||
| 1580 | Type.intAbiAlignment(error_set_bits, target.*), | ||
| 1581 | ), | ||
| 1582 | }, | ||
| 1583 | .{ | ||
| 1584 | .name = try pool.string(allocator, "payload"), | ||
| 1585 | .ctype = payload_ctype, | ||
| 1586 | .alignas = AlignAs.fromAbiAlignment(payload_type.abiAlignment(zcu)), | ||
| 1587 | }, | ||
| 1588 | }; | ||
| 1589 | return pool.fromFields(allocator, .@"struct", &fields, kind); | ||
| 1590 | }, | ||
| 1591 | .simple_type => unreachable, | ||
| 1592 | .struct_type => { | ||
| 1593 | const loaded_struct = ip.loadStructType(ip_index); | ||
| 1594 | switch (loaded_struct.layout) { | ||
| 1595 | .auto, .@"extern" => { | ||
| 1596 | const fwd_decl = try pool.getFwdDecl(allocator, .{ | ||
| 1597 | .tag = .@"struct", | ||
| 1598 | .name = .{ .owner_decl = loaded_struct.decl.unwrap().? }, | ||
| 1599 | }); | ||
| 1600 | if (kind.isForward()) return if (ty.hasRuntimeBitsIgnoreComptime(zcu)) | ||
| 1601 | fwd_decl | ||
| 1602 | else | ||
| 1603 | .{ .index = .void }; | ||
| 1604 | const scratch_top = scratch.items.len; | ||
| 1605 | defer scratch.shrinkRetainingCapacity(scratch_top); | ||
| 1606 | try scratch.ensureUnusedCapacity( | ||
| 1607 | allocator, | ||
| 1608 | loaded_struct.field_types.len * @typeInfo(Field).Struct.fields.len, | ||
| 1609 | ); | ||
| 1610 | var hasher = Hasher.init; | ||
| 1611 | var tag: Pool.Tag = .aggregate_struct; | ||
| 1612 | var field_it = loaded_struct.iterateRuntimeOrder(ip); | ||
| 1613 | while (field_it.next()) |field_index| { | ||
| 1614 | const field_type = Type.fromInterned( | ||
| 1615 | loaded_struct.field_types.get(ip)[field_index], | ||
| 1616 | ); | ||
| 1617 | const field_ctype = try pool.fromType( | ||
| 1618 | allocator, | ||
| 1619 | scratch, | ||
| 1620 | field_type, | ||
| 1621 | zcu, | ||
| 1622 | mod, | ||
| 1623 | kind.noParameter(), | ||
| 1624 | ); | ||
| 1625 | if (field_ctype.index == .void) continue; | ||
| 1626 | const field_name = if (loaded_struct.fieldName(ip, field_index) | ||
| 1627 | .unwrap()) |field_name| | ||
| 1628 | try pool.string(allocator, ip.stringToSlice(field_name)) | ||
| 1629 | else | ||
| 1630 | try pool.fmt(allocator, "f{d}", .{field_index}); | ||
| 1631 | const field_alignas = AlignAs.fromAlignment(.{ | ||
| 1632 | .@"align" = loaded_struct.fieldAlign(ip, field_index), | ||
| 1633 | .abi = field_type.abiAlignment(zcu), | ||
| 1634 | }); | ||
| 1635 | pool.addHashedExtraAssumeCapacityTo(scratch, &hasher, Field, .{ | ||
| 1636 | .name = field_name.index, | ||
| 1637 | .ctype = field_ctype.index, | ||
| 1638 | .flags = .{ .alignas = field_alignas }, | ||
| 1639 | }); | ||
| 1640 | if (field_alignas.abiOrder().compare(.lt)) | ||
| 1641 | tag = .aggregate_struct_packed; | ||
| 1642 | } | ||
| 1643 | const fields_len: u32 = @intCast(@divExact( | ||
| 1644 | scratch.items.len - scratch_top, | ||
| 1645 | @typeInfo(Field).Struct.fields.len, | ||
| 1646 | )); | ||
| 1647 | if (fields_len == 0) return .{ .index = .void }; | ||
| 1648 | try pool.ensureUnusedCapacity(allocator, 1); | ||
| 1649 | const extra_index = try pool.addHashedExtra(allocator, &hasher, Aggregate, .{ | ||
| 1650 | .fwd_decl = fwd_decl.index, | ||
| 1651 | .fields_len = fields_len, | ||
| 1652 | }, fields_len * @typeInfo(Field).Struct.fields.len); | ||
| 1653 | pool.extra.appendSliceAssumeCapacity(scratch.items[scratch_top..]); | ||
| 1654 | return pool.tagTrailingExtraAssumeCapacity(hasher, tag, extra_index); | ||
| 1655 | }, | ||
| 1656 | .@"packed" => return pool.fromType( | ||
| 1657 | allocator, | ||
| 1658 | scratch, | ||
| 1659 | Type.fromInterned(loaded_struct.backingIntType(ip).*), | ||
| 1660 | zcu, | ||
| 1661 | mod, | ||
| 1662 | kind, | ||
| 1663 | ), | ||
| 1664 | } | ||
| 1665 | }, | ||
| 1666 | .anon_struct_type => |anon_struct_info| { | ||
| 1667 | const scratch_top = scratch.items.len; | ||
| 1668 | defer scratch.shrinkRetainingCapacity(scratch_top); | ||
| 1669 | try scratch.ensureUnusedCapacity(allocator, anon_struct_info.types.len * | ||
| 1670 | @typeInfo(Field).Struct.fields.len); | ||
| 1671 | var hasher = Hasher.init; | ||
| 1672 | for (0..anon_struct_info.types.len) |field_index| { | ||
| 1673 | if (anon_struct_info.values.get(ip)[field_index] != .none) continue; | ||
| 1674 | const field_type = Type.fromInterned( | ||
| 1675 | anon_struct_info.types.get(ip)[field_index], | ||
| 1676 | ); | ||
| 1677 | const field_ctype = try pool.fromType( | ||
| 1678 | allocator, | ||
| 1679 | scratch, | ||
| 1680 | field_type, | ||
| 1681 | zcu, | ||
| 1682 | mod, | ||
| 1683 | kind.noParameter(), | ||
| 1684 | ); | ||
| 1685 | if (field_ctype.index == .void) continue; | ||
| 1686 | const field_name = if (anon_struct_info.fieldName(ip, @intCast(field_index)) | ||
| 1687 | .unwrap()) |field_name| | ||
| 1688 | try pool.string(allocator, ip.stringToSlice(field_name)) | ||
| 1689 | else | ||
| 1690 | try pool.fmt(allocator, "f{d}", .{field_index}); | ||
| 1691 | pool.addHashedExtraAssumeCapacityTo(scratch, &hasher, Field, .{ | ||
| 1692 | .name = field_name.index, | ||
| 1693 | .ctype = field_ctype.index, | ||
| 1694 | .flags = .{ .alignas = AlignAs.fromAbiAlignment( | ||
| 1695 | field_type.abiAlignment(zcu), | ||
| 1696 | ) }, | ||
| 1697 | }); | ||
| 1698 | } | ||
| 1699 | const fields_len: u32 = @intCast(@divExact( | ||
| 1700 | scratch.items.len - scratch_top, | ||
| 1701 | @typeInfo(Field).Struct.fields.len, | ||
| 1702 | )); | ||
| 1703 | if (fields_len == 0) return .{ .index = .void }; | ||
| 1704 | if (kind.isForward()) { | ||
| 1705 | try pool.ensureUnusedCapacity(allocator, 1); | ||
| 1706 | const extra_index = try pool.addHashedExtra( | ||
| 1707 | allocator, | ||
| 1708 | &hasher, | ||
| 1709 | FwdDeclAnon, | ||
| 1710 | .{ .fields_len = fields_len }, | ||
| 1711 | fields_len * @typeInfo(Field).Struct.fields.len, | ||
| 1712 | ); | ||
| 1713 | pool.extra.appendSliceAssumeCapacity(scratch.items[scratch_top..]); | ||
| 1714 | return pool.tagTrailingExtra( | ||
| 1715 | allocator, | ||
| 1716 | hasher, | ||
| 1717 | .fwd_decl_struct_anon, | ||
| 1718 | extra_index, | ||
| 1719 | ); | ||
| 1720 | } | ||
| 1721 | const fwd_decl = try pool.fromType(allocator, scratch, ty, zcu, mod, .forward); | ||
| 1722 | try pool.ensureUnusedCapacity(allocator, 1); | ||
| 1723 | const extra_index = try pool.addHashedExtra(allocator, &hasher, Aggregate, .{ | ||
| 1724 | .fwd_decl = fwd_decl.index, | ||
| 1725 | .fields_len = fields_len, | ||
| 1726 | }, fields_len * @typeInfo(Field).Struct.fields.len); | ||
| 1727 | pool.extra.appendSliceAssumeCapacity(scratch.items[scratch_top..]); | ||
| 1728 | return pool.tagTrailingExtraAssumeCapacity(hasher, .aggregate_struct, extra_index); | ||
| 1729 | }, | ||
| 1730 | .union_type => { | ||
| 1731 | const loaded_union = ip.loadUnionType(ip_index); | ||
| 1732 | switch (loaded_union.getLayout(ip)) { | ||
| 1733 | .auto, .@"extern" => { | ||
| 1734 | const has_tag = loaded_union.hasTag(ip); | ||
| 1735 | const fwd_decl = try pool.getFwdDecl(allocator, .{ | ||
| 1736 | .tag = if (has_tag) .@"struct" else .@"union", | ||
| 1737 | .name = .{ .owner_decl = loaded_union.decl }, | ||
| 1738 | }); | ||
| 1739 | if (kind.isForward()) return if (ty.hasRuntimeBitsIgnoreComptime(zcu)) | ||
| 1740 | fwd_decl | ||
| 1741 | else | ||
| 1742 | .{ .index = .void }; | ||
| 1743 | const loaded_tag = loaded_union.loadTagType(ip); | ||
| 1744 | const scratch_top = scratch.items.len; | ||
| 1745 | defer scratch.shrinkRetainingCapacity(scratch_top); | ||
| 1746 | try scratch.ensureUnusedCapacity( | ||
| 1747 | allocator, | ||
| 1748 | loaded_union.field_types.len * @typeInfo(Field).Struct.fields.len, | ||
| 1749 | ); | ||
| 1750 | var hasher = Hasher.init; | ||
| 1751 | var tag: Pool.Tag = .aggregate_union; | ||
| 1752 | var payload_align: Alignment = .@"1"; | ||
| 1753 | for (0..loaded_union.field_types.len) |field_index| { | ||
| 1754 | const field_type = Type.fromInterned( | ||
| 1755 | loaded_union.field_types.get(ip)[field_index], | ||
| 1756 | ); | ||
| 1757 | if (ip.isNoReturn(field_type.toIntern())) continue; | ||
| 1758 | const field_ctype = try pool.fromType( | ||
| 1759 | allocator, | ||
| 1760 | scratch, | ||
| 1761 | field_type, | ||
| 1762 | zcu, | ||
| 1763 | mod, | ||
| 1764 | kind.noParameter(), | ||
| 1765 | ); | ||
| 1766 | if (field_ctype.index == .void) continue; | ||
| 1767 | const field_name = try pool.string( | ||
| 1768 | allocator, | ||
| 1769 | ip.stringToSlice(loaded_tag.names.get(ip)[field_index]), | ||
| 1770 | ); | ||
| 1771 | const field_alignas = AlignAs.fromAlignment(.{ | ||
| 1772 | .@"align" = loaded_union.fieldAlign(ip, @intCast(field_index)), | ||
| 1773 | .abi = field_type.abiAlignment(zcu), | ||
| 1774 | }); | ||
| 1775 | pool.addHashedExtraAssumeCapacityTo(scratch, &hasher, Field, .{ | ||
| 1776 | .name = field_name.index, | ||
| 1777 | .ctype = field_ctype.index, | ||
| 1778 | .flags = .{ .alignas = field_alignas }, | ||
| 1779 | }); | ||
| 1780 | if (field_alignas.abiOrder().compare(.lt)) | ||
| 1781 | tag = .aggregate_union_packed; | ||
| 1782 | payload_align = payload_align.maxStrict(field_alignas.@"align"); | ||
| 1783 | } | ||
| 1784 | const fields_len: u32 = @intCast(@divExact( | ||
| 1785 | scratch.items.len - scratch_top, | ||
| 1786 | @typeInfo(Field).Struct.fields.len, | ||
| 1787 | )); | ||
| 1788 | if (!has_tag) { | ||
| 1789 | if (fields_len == 0) return .{ .index = .void }; | ||
| 1790 | try pool.ensureUnusedCapacity(allocator, 1); | ||
| 1791 | const extra_index = try pool.addHashedExtra( | ||
| 1792 | allocator, | ||
| 1793 | &hasher, | ||
| 1794 | Aggregate, | ||
| 1795 | .{ .fwd_decl = fwd_decl.index, .fields_len = fields_len }, | ||
| 1796 | fields_len * @typeInfo(Field).Struct.fields.len, | ||
| 1797 | ); | ||
| 1798 | pool.extra.appendSliceAssumeCapacity(scratch.items[scratch_top..]); | ||
| 1799 | return pool.tagTrailingExtraAssumeCapacity(hasher, tag, extra_index); | ||
| 1800 | } | ||
| 1801 | try pool.ensureUnusedCapacity(allocator, 2); | ||
| 1802 | var struct_fields: [2]Info.Field = undefined; | ||
| 1803 | var struct_fields_len: usize = 0; | ||
| 1804 | if (loaded_tag.tag_ty != .comptime_int_type) { | ||
| 1805 | const tag_type = Type.fromInterned(loaded_tag.tag_ty); | ||
| 1806 | const tag_ctype: CType = try pool.fromType( | ||
| 1807 | allocator, | ||
| 1808 | scratch, | ||
| 1809 | tag_type, | ||
| 1810 | zcu, | ||
| 1811 | mod, | ||
| 1812 | kind.noParameter(), | ||
| 1813 | ); | ||
| 1814 | if (tag_ctype.index != .void) { | ||
| 1815 | struct_fields[struct_fields_len] = .{ | ||
| 1816 | .name = try pool.string(allocator, "tag"), | ||
| 1817 | .ctype = tag_ctype, | ||
| 1818 | .alignas = AlignAs.fromAbiAlignment(tag_type.abiAlignment(zcu)), | ||
| 1819 | }; | ||
| 1820 | struct_fields_len += 1; | ||
| 1821 | } | ||
| 1822 | } | ||
| 1823 | if (fields_len > 0) { | ||
| 1824 | const payload_ctype = payload_ctype: { | ||
| 1825 | const extra_index = try pool.addHashedExtra( | ||
| 1826 | allocator, | ||
| 1827 | &hasher, | ||
| 1828 | AggregateAnon, | ||
| 1829 | .{ | ||
| 1830 | .owner_decl = loaded_union.decl, | ||
| 1831 | .id = 0, | ||
| 1832 | .fields_len = fields_len, | ||
| 1833 | }, | ||
| 1834 | fields_len * @typeInfo(Field).Struct.fields.len, | ||
| 1835 | ); | ||
| 1836 | pool.extra.appendSliceAssumeCapacity(scratch.items[scratch_top..]); | ||
| 1837 | break :payload_ctype pool.tagTrailingExtraAssumeCapacity( | ||
| 1838 | hasher, | ||
| 1839 | switch (tag) { | ||
| 1840 | .aggregate_union => .aggregate_union_anon, | ||
| 1841 | .aggregate_union_packed => .aggregate_union_packed_anon, | ||
| 1842 | else => unreachable, | ||
| 1843 | }, | ||
| 1844 | extra_index, | ||
| 1845 | ); | ||
| 1846 | }; | ||
| 1847 | if (payload_ctype.index != .void) { | ||
| 1848 | struct_fields[struct_fields_len] = .{ | ||
| 1849 | .name = try pool.string(allocator, "payload"), | ||
| 1850 | .ctype = payload_ctype, | ||
| 1851 | .alignas = AlignAs.fromAbiAlignment(payload_align), | ||
| 1852 | }; | ||
| 1853 | struct_fields_len += 1; | ||
| 1854 | } | ||
| 1855 | } | ||
| 1856 | if (struct_fields_len == 0) return .{ .index = .void }; | ||
| 1857 | sortFields(struct_fields[0..struct_fields_len]); | ||
| 1858 | return pool.getAggregate(allocator, .{ | ||
| 1859 | .tag = .@"struct", | ||
| 1860 | .name = .{ .fwd_decl = fwd_decl }, | ||
| 1861 | .fields = struct_fields[0..struct_fields_len], | ||
| 1862 | }); | ||
| 1863 | }, | ||
| 1864 | .@"packed" => return pool.fromIntInfo(allocator, .{ | ||
| 1865 | .signedness = .unsigned, | ||
| 1866 | .bits = @intCast(ty.bitSize(zcu)), | ||
| 1867 | }, mod, kind), | ||
| 1868 | } | ||
| 1869 | }, | ||
| 1870 | .opaque_type => return .{ .index = .void }, | ||
| 1871 | .enum_type => return pool.fromType( | ||
| 1872 | allocator, | ||
| 1873 | scratch, | ||
| 1874 | Type.fromInterned(ip.loadEnumType(ip_index).tag_ty), | ||
| 1875 | zcu, | ||
| 1876 | mod, | ||
| 1877 | kind, | ||
| 1878 | ), | ||
| 1879 | .func_type => |func_info| if (func_info.is_generic) return .{ .index = .void } else { | ||
| 1880 | const scratch_top = scratch.items.len; | ||
| 1881 | defer scratch.shrinkRetainingCapacity(scratch_top); | ||
| 1882 | try scratch.ensureUnusedCapacity(allocator, func_info.param_types.len); | ||
| 1883 | var hasher = Hasher.init; | ||
| 1884 | const return_type = Type.fromInterned(func_info.return_type); | ||
| 1885 | const return_ctype: CType = | ||
| 1886 | if (!ip.isNoReturn(func_info.return_type)) try pool.fromType( | ||
| 1887 | allocator, | ||
| 1888 | scratch, | ||
| 1889 | return_type, | ||
| 1890 | zcu, | ||
| 1891 | mod, | ||
| 1892 | kind.asParameter(), | ||
| 1893 | ) else .{ .index = .void }; | ||
| 1894 | for (0..func_info.param_types.len) |param_index| { | ||
| 1895 | const param_type = Type.fromInterned( | ||
| 1896 | func_info.param_types.get(ip)[param_index], | ||
| 1897 | ); | ||
| 1898 | const param_ctype = try pool.fromType( | ||
| 1899 | allocator, | ||
| 1900 | scratch, | ||
| 1901 | param_type, | ||
| 1902 | zcu, | ||
| 1903 | mod, | ||
| 1904 | kind.asParameter(), | ||
| 1905 | ); | ||
| 1906 | if (param_ctype.index == .void) continue; | ||
| 1907 | hasher.update(param_ctype.hash(pool)); | ||
| 1908 | scratch.appendAssumeCapacity(@intFromEnum(param_ctype.index)); | ||
| 1909 | } | ||
| 1910 | const param_ctypes_len: u32 = @intCast(scratch.items.len - scratch_top); | ||
| 1911 | try pool.ensureUnusedCapacity(allocator, 1); | ||
| 1912 | const extra_index = try pool.addHashedExtra(allocator, &hasher, Function, .{ | ||
| 1913 | .return_ctype = return_ctype.index, | ||
| 1914 | .param_ctypes_len = param_ctypes_len, | ||
| 1915 | }, param_ctypes_len); | ||
| 1916 | pool.extra.appendSliceAssumeCapacity(scratch.items[scratch_top..]); | ||
| 1917 | return pool.tagTrailingExtraAssumeCapacity(hasher, switch (func_info.is_var_args) { | ||
| 1918 | false => .function, | ||
| 1919 | true => .function_varargs, | ||
| 1920 | }, extra_index); | ||
| 1921 | }, | ||
| 1922 | .error_set_type, | ||
| 1923 | .inferred_error_set_type, | ||
| 1924 | => return pool.fromIntInfo(allocator, .{ | ||
| 1925 | .signedness = .unsigned, | ||
| 1926 | .bits = zcu.errorSetBits(), | ||
| 1927 | }, mod, kind), | ||
| 1928 | |||
| 1929 | .undef, | ||
| 1930 | .simple_value, | ||
| 1931 | .variable, | ||
| 1932 | .extern_func, | ||
| 1933 | .func, | ||
| 1934 | .int, | ||
| 1935 | .err, | ||
| 1936 | .error_union, | ||
| 1937 | .enum_literal, | ||
| 1938 | .enum_tag, | ||
| 1939 | .empty_enum_value, | ||
| 1940 | .float, | ||
| 1941 | .ptr, | ||
| 1942 | .slice, | ||
| 1943 | .opt, | ||
| 1944 | .aggregate, | ||
| 1945 | .un, | ||
| 1946 | .memoized_call, | ||
| 1947 | => unreachable, | ||
| 1948 | }, | ||
| 1949 | } | ||
| 1950 | } | ||
| 1951 | |||
| 1952 | pub fn getOrPutAdapted( | ||
| 1953 | pool: *Pool, | ||
| 1954 | allocator: std.mem.Allocator, | ||
| 1955 | source_pool: *const Pool, | ||
| 1956 | source_ctype: CType, | ||
| 1957 | pool_adapter: anytype, | ||
| 1958 | ) !struct { CType, bool } { | ||
| 1959 | const tag = source_pool.items.items(.tag)[ | ||
| 1960 | source_ctype.toPoolIndex() orelse return .{ source_ctype, true } | ||
| 1961 | ]; | ||
| 1962 | try pool.ensureUnusedCapacity(allocator, 1); | ||
| 1963 | const CTypeAdapter = struct { | ||
| 1964 | pool: *const Pool, | ||
| 1965 | source_pool: *const Pool, | ||
| 1966 | source_info: Info, | ||
| 1967 | pool_adapter: @TypeOf(pool_adapter), | ||
| 1968 | pub fn hash(map_adapter: @This(), key_ctype: CType) Map.Hash { | ||
| 1969 | return key_ctype.hash(map_adapter.source_pool); | ||
| 1970 | } | ||
| 1971 | pub fn eql(map_adapter: @This(), _: CType, _: void, pool_index: usize) bool { | ||
| 1972 | return map_adapter.source_info.eqlAdapted( | ||
| 1973 | map_adapter.source_pool, | ||
| 1974 | CType.fromPoolIndex(pool_index), | ||
| 1975 | map_adapter.pool, | ||
| 1976 | map_adapter.pool_adapter, | ||
| 1977 | ); | ||
| 1978 | } | ||
| 1979 | }; | ||
| 1980 | const source_info = source_ctype.info(source_pool); | ||
| 1981 | const gop = pool.map.getOrPutAssumeCapacityAdapted(source_ctype, CTypeAdapter{ | ||
| 1982 | .pool = pool, | ||
| 1983 | .source_pool = source_pool, | ||
| 1984 | .source_info = source_info, | ||
| 1985 | .pool_adapter = pool_adapter, | ||
| 1986 | }); | ||
| 1987 | errdefer _ = pool.map.pop(); | ||
| 1988 | const ctype = CType.fromPoolIndex(gop.index); | ||
| 1989 | if (!gop.found_existing) switch (source_info) { | ||
| 1990 | .basic => unreachable, | ||
| 1991 | .pointer => |pointer_info| pool.items.appendAssumeCapacity(.{ | ||
| 1992 | .tag = tag, | ||
| 1993 | .data = @intFromEnum(pool_adapter.copy(pointer_info.elem_ctype).index), | ||
| 1994 | }), | ||
| 1995 | .aligned => |aligned_info| pool.items.appendAssumeCapacity(.{ | ||
| 1996 | .tag = tag, | ||
| 1997 | .data = try pool.addExtra(allocator, Aligned, .{ | ||
| 1998 | .ctype = pool_adapter.copy(aligned_info.ctype).index, | ||
| 1999 | .flags = .{ .alignas = aligned_info.alignas }, | ||
| 2000 | }, 0), | ||
| 2001 | }), | ||
| 2002 | .array, .vector => |sequence_info| pool.items.appendAssumeCapacity(.{ | ||
| 2003 | .tag = tag, | ||
| 2004 | .data = switch (tag) { | ||
| 2005 | .array_small, .vector => try pool.addExtra(allocator, SequenceSmall, .{ | ||
| 2006 | .elem_ctype = pool_adapter.copy(sequence_info.elem_ctype).index, | ||
| 2007 | .len = @intCast(sequence_info.len), | ||
| 2008 | }, 0), | ||
| 2009 | .array_large => try pool.addExtra(allocator, SequenceLarge, .{ | ||
| 2010 | .elem_ctype = pool_adapter.copy(sequence_info.elem_ctype).index, | ||
| 2011 | .len_lo = @truncate(sequence_info.len >> 0), | ||
| 2012 | .len_hi = @truncate(sequence_info.len >> 32), | ||
| 2013 | }, 0), | ||
| 2014 | else => unreachable, | ||
| 2015 | }, | ||
| 2016 | }), | ||
| 2017 | .fwd_decl => |fwd_decl_info| switch (fwd_decl_info.name) { | ||
| 2018 | .anon => |fields| { | ||
| 2019 | pool.items.appendAssumeCapacity(.{ | ||
| 2020 | .tag = tag, | ||
| 2021 | .data = try pool.addExtra(allocator, FwdDeclAnon, .{ | ||
| 2022 | .fields_len = fields.len, | ||
| 2023 | }, fields.len * @typeInfo(Field).Struct.fields.len), | ||
| 2024 | }); | ||
| 2025 | for (0..fields.len) |field_index| { | ||
| 2026 | const field = fields.at(field_index, source_pool); | ||
| 2027 | const field_name = try pool.string(allocator, field.name.slice(source_pool)); | ||
| 2028 | pool.addExtraAssumeCapacity(Field, .{ | ||
| 2029 | .name = field_name.index, | ||
| 2030 | .ctype = pool_adapter.copy(field.ctype).index, | ||
| 2031 | .flags = .{ .alignas = field.alignas }, | ||
| 2032 | }); | ||
| 2033 | } | ||
| 2034 | }, | ||
| 2035 | .owner_decl => |owner_decl| pool.items.appendAssumeCapacity(.{ | ||
| 2036 | .tag = tag, | ||
| 2037 | .data = @intFromEnum(owner_decl), | ||
| 2038 | }), | ||
| 2039 | }, | ||
| 2040 | .aggregate => |aggregate_info| { | ||
| 2041 | pool.items.appendAssumeCapacity(.{ | ||
| 2042 | .tag = tag, | ||
| 2043 | .data = switch (aggregate_info.name) { | ||
| 2044 | .anon => |anon| try pool.addExtra(allocator, AggregateAnon, .{ | ||
| 2045 | .owner_decl = anon.owner_decl, | ||
| 2046 | .id = anon.id, | ||
| 2047 | .fields_len = aggregate_info.fields.len, | ||
| 2048 | }, aggregate_info.fields.len * @typeInfo(Field).Struct.fields.len), | ||
| 2049 | .fwd_decl => |fwd_decl| try pool.addExtra(allocator, Aggregate, .{ | ||
| 2050 | .fwd_decl = pool_adapter.copy(fwd_decl).index, | ||
| 2051 | .fields_len = aggregate_info.fields.len, | ||
| 2052 | }, aggregate_info.fields.len * @typeInfo(Field).Struct.fields.len), | ||
| 2053 | }, | ||
| 2054 | }); | ||
| 2055 | for (0..aggregate_info.fields.len) |field_index| { | ||
| 2056 | const field = aggregate_info.fields.at(field_index, source_pool); | ||
| 2057 | const field_name = try pool.string(allocator, field.name.slice(source_pool)); | ||
| 2058 | pool.addExtraAssumeCapacity(Field, .{ | ||
| 2059 | .name = field_name.index, | ||
| 2060 | .ctype = pool_adapter.copy(field.ctype).index, | ||
| 2061 | .flags = .{ .alignas = field.alignas }, | ||
| 2062 | }); | ||
| 2063 | } | ||
| 2064 | }, | ||
| 2065 | .function => |function_info| { | ||
| 2066 | pool.items.appendAssumeCapacity(.{ | ||
| 2067 | .tag = tag, | ||
| 2068 | .data = try pool.addExtra(allocator, Function, .{ | ||
| 2069 | .return_ctype = pool_adapter.copy(function_info.return_ctype).index, | ||
| 2070 | .param_ctypes_len = function_info.param_ctypes.len, | ||
| 2071 | }, function_info.param_ctypes.len), | ||
| 2072 | }); | ||
| 2073 | for (0..function_info.param_ctypes.len) |param_index| pool.extra.appendAssumeCapacity( | ||
| 2074 | @intFromEnum(pool_adapter.copy( | ||
| 2075 | function_info.param_ctypes.at(param_index, source_pool), | ||
| 2076 | ).index), | ||
| 2077 | ); | ||
| 2078 | }, | ||
| 2079 | }; | ||
| 2080 | assert(source_info.eqlAdapted(source_pool, ctype, pool, pool_adapter)); | ||
| 2081 | assert(source_ctype.hash(source_pool) == ctype.hash(pool)); | ||
| 2082 | return .{ ctype, gop.found_existing }; | ||
| 2083 | } | ||
| 2084 | |||
| 2085 | pub fn string(pool: *Pool, allocator: std.mem.Allocator, str: []const u8) !String { | ||
| 2086 | try pool.string_bytes.appendSlice(allocator, str); | ||
| 2087 | return pool.trailingString(allocator); | ||
| 2088 | } | ||
| 2089 | |||
| 2090 | pub fn fmt( | ||
| 2091 | pool: *Pool, | ||
| 2092 | allocator: std.mem.Allocator, | ||
| 2093 | comptime fmt_str: []const u8, | ||
| 2094 | fmt_args: anytype, | ||
| 2095 | ) !String { | ||
| 2096 | try pool.string_bytes.writer(allocator).print(fmt_str, fmt_args); | ||
| 2097 | return pool.trailingString(allocator); | ||
| 2098 | } | ||
| 2099 | |||
| 2100 | fn ensureUnusedCapacity(pool: *Pool, allocator: std.mem.Allocator, len: u32) !void { | ||
| 2101 | try pool.map.ensureUnusedCapacity(allocator, len); | ||
| 2102 | try pool.items.ensureUnusedCapacity(allocator, len); | ||
| 2103 | } | ||
| 2104 | |||
| 2105 | const Hasher = struct { | ||
| 2106 | const Impl = std.hash.Wyhash; | ||
| 2107 | impl: Impl, | ||
| 2108 | |||
| 2109 | const init: Hasher = .{ .impl = Impl.init(0) }; | ||
| 2110 | |||
| 2111 | fn updateExtra(hasher: *Hasher, comptime Extra: type, extra: Extra, pool: *const Pool) void { | ||
| 2112 | inline for (@typeInfo(Extra).Struct.fields) |field| { | ||
| 2113 | const value = @field(extra, field.name); | ||
| 2114 | hasher.update(switch (field.type) { | ||
| 2115 | Pool.Tag, String, CType => unreachable, | ||
| 2116 | CType.Index => (CType{ .index = value }).hash(pool), | ||
| 2117 | String.Index => (String{ .index = value }).slice(pool), | ||
| 2118 | else => value, | ||
| 2119 | }); | ||
| 2120 | } | ||
| 2121 | } | ||
| 2122 | fn update(hasher: *Hasher, data: anytype) void { | ||
| 2123 | switch (@TypeOf(data)) { | ||
| 2124 | Pool.Tag => @compileError("pass tag to final"), | ||
| 2125 | CType, CType.Index => @compileError("hash ctype.hash(pool) instead"), | ||
| 2126 | String, String.Index => @compileError("hash string.slice(pool) instead"), | ||
| 2127 | u32, DeclIndex, Aligned.Flags => hasher.impl.update(std.mem.asBytes(&data)), | ||
| 2128 | []const u8 => hasher.impl.update(data), | ||
| 2129 | else => @compileError("unhandled type: " ++ @typeName(@TypeOf(data))), | ||
| 2130 | } | ||
| 2131 | } | ||
| 2132 | |||
| 2133 | fn final(hasher: Hasher, tag: Pool.Tag) Map.Hash { | ||
| 2134 | var impl = hasher.impl; | ||
| 2135 | impl.update(std.mem.asBytes(&tag)); | ||
| 2136 | return @truncate(impl.final()); | ||
| 2137 | } | ||
| 2138 | }; | ||
| 2139 | |||
| 2140 | fn tagData( | ||
| 2141 | pool: *Pool, | ||
| 2142 | allocator: std.mem.Allocator, | ||
| 2143 | hasher: Hasher, | ||
| 2144 | tag: Pool.Tag, | ||
| 2145 | data: u32, | ||
| 2146 | ) !CType { | ||
| 2147 | try pool.ensureUnusedCapacity(allocator, 1); | ||
| 2148 | const Key = struct { hash: Map.Hash, tag: Pool.Tag, data: u32 }; | ||
| 2149 | const CTypeAdapter = struct { | ||
| 2150 | pool: *const Pool, | ||
| 2151 | pub fn hash(_: @This(), key: Key) Map.Hash { | ||
| 2152 | return key.hash; | ||
| 2153 | } | ||
| 2154 | pub fn eql(ctype_adapter: @This(), lhs_key: Key, _: void, rhs_index: usize) bool { | ||
| 2155 | const rhs_item = ctype_adapter.pool.items.get(rhs_index); | ||
| 2156 | return lhs_key.tag == rhs_item.tag and lhs_key.data == rhs_item.data; | ||
| 2157 | } | ||
| 2158 | }; | ||
| 2159 | const gop = pool.map.getOrPutAssumeCapacityAdapted( | ||
| 2160 | Key{ .hash = hasher.final(tag), .tag = tag, .data = data }, | ||
| 2161 | CTypeAdapter{ .pool = pool }, | ||
| 2162 | ); | ||
| 2163 | if (!gop.found_existing) pool.items.appendAssumeCapacity(.{ .tag = tag, .data = data }); | ||
| 2164 | return CType.fromPoolIndex(gop.index); | ||
| 2165 | } | ||
| 2166 | |||
| 2167 | fn tagExtra( | ||
| 2168 | pool: *Pool, | ||
| 2169 | allocator: std.mem.Allocator, | ||
| 2170 | tag: Pool.Tag, | ||
| 2171 | comptime Extra: type, | ||
| 2172 | extra: Extra, | ||
| 2173 | ) !CType { | ||
| 2174 | var hasher = Hasher.init; | ||
| 2175 | hasher.updateExtra(Extra, extra, pool); | ||
| 2176 | return pool.tagTrailingExtra( | ||
| 2177 | allocator, | ||
| 2178 | hasher, | ||
| 2179 | tag, | ||
| 2180 | try pool.addExtra(allocator, Extra, extra, 0), | ||
| 2181 | ); | ||
| 2182 | } | ||
| 2183 | |||
| 2184 | fn tagTrailingExtra( | ||
| 2185 | pool: *Pool, | ||
| 2186 | allocator: std.mem.Allocator, | ||
| 2187 | hasher: Hasher, | ||
| 2188 | tag: Pool.Tag, | ||
| 2189 | extra_index: ExtraIndex, | ||
| 2190 | ) !CType { | ||
| 2191 | try pool.ensureUnusedCapacity(allocator, 1); | ||
| 2192 | return pool.tagTrailingExtraAssumeCapacity(hasher, tag, extra_index); | ||
| 2193 | } | ||
| 2194 | |||
| 2195 | fn tagTrailingExtraAssumeCapacity( | ||
| 2196 | pool: *Pool, | ||
| 2197 | hasher: Hasher, | ||
| 2198 | tag: Pool.Tag, | ||
| 2199 | extra_index: ExtraIndex, | ||
| 2200 | ) CType { | ||
| 2201 | const Key = struct { hash: Map.Hash, tag: Pool.Tag, extra: []const u32 }; | ||
| 2202 | const CTypeAdapter = struct { | ||
| 2203 | pool: *const Pool, | ||
| 2204 | pub fn hash(_: @This(), key: Key) Map.Hash { | ||
| 2205 | return key.hash; | ||
| 2206 | } | ||
| 2207 | pub fn eql(ctype_adapter: @This(), lhs_key: Key, _: void, rhs_index: usize) bool { | ||
| 2208 | const rhs_item = ctype_adapter.pool.items.get(rhs_index); | ||
| 2209 | if (lhs_key.tag != rhs_item.tag) return false; | ||
| 2210 | const rhs_extra = ctype_adapter.pool.extra.items[rhs_item.data..]; | ||
| 2211 | return std.mem.startsWith(u32, rhs_extra, lhs_key.extra); | ||
| 2212 | } | ||
| 2213 | }; | ||
| 2214 | const gop = pool.map.getOrPutAssumeCapacityAdapted( | ||
| 2215 | Key{ .hash = hasher.final(tag), .tag = tag, .extra = pool.extra.items[extra_index..] }, | ||
| 2216 | CTypeAdapter{ .pool = pool }, | ||
| 2217 | ); | ||
| 2218 | if (gop.found_existing) | ||
| 2219 | pool.extra.shrinkRetainingCapacity(extra_index) | ||
| 2220 | else | ||
| 2221 | pool.items.appendAssumeCapacity(.{ .tag = tag, .data = extra_index }); | ||
| 2222 | return CType.fromPoolIndex(gop.index); | ||
| 2223 | } | ||
| 2224 | |||
| 2225 | fn sortFields(fields: []Info.Field) void { | ||
| 2226 | std.mem.sort(Info.Field, fields, {}, struct { | ||
| 2227 | fn before(_: void, lhs_field: Info.Field, rhs_field: Info.Field) bool { | ||
| 2228 | return lhs_field.alignas.order(rhs_field.alignas).compare(.gt); | ||
| 2229 | } | ||
| 2230 | }.before); | ||
| 2231 | } | ||
| 2232 | |||
| 2233 | fn trailingString(pool: *Pool, allocator: std.mem.Allocator) !String { | ||
| 2234 | const StringAdapter = struct { | ||
| 2235 | pool: *const Pool, | ||
| 2236 | pub fn hash(_: @This(), slice: []const u8) Map.Hash { | ||
| 2237 | return @truncate(Hasher.Impl.hash(1, slice)); | ||
| 2238 | } | ||
| 2239 | pub fn eql(string_adapter: @This(), lhs_slice: []const u8, _: void, rhs_index: usize) bool { | ||
| 2240 | const rhs_string: String = .{ .index = @enumFromInt(rhs_index) }; | ||
| 2241 | const rhs_slice = rhs_string.slice(string_adapter.pool); | ||
| 2242 | return std.mem.eql(u8, lhs_slice, rhs_slice); | ||
| 2243 | } | ||
| 2244 | }; | ||
| 2245 | try pool.string_map.ensureUnusedCapacity(allocator, 1); | ||
| 2246 | try pool.string_indices.ensureUnusedCapacity(allocator, 1); | ||
| 2247 | |||
| 2248 | const start = pool.string_indices.getLast(); | ||
| 2249 | const gop = pool.string_map.getOrPutAssumeCapacityAdapted( | ||
| 2250 | @as([]const u8, pool.string_bytes.items[start..]), | ||
| 2251 | StringAdapter{ .pool = pool }, | ||
| 2252 | ); | ||
| 2253 | if (gop.found_existing) | ||
| 2254 | pool.string_bytes.shrinkRetainingCapacity(start) | ||
| 2255 | else | ||
| 2256 | pool.string_indices.appendAssumeCapacity(@intCast(pool.string_bytes.items.len)); | ||
| 2257 | return .{ .index = @enumFromInt(gop.index) }; | ||
| 2258 | } | ||
| 2259 | |||
| 2260 | const Item = struct { | ||
| 2261 | tag: Pool.Tag, | ||
| 2262 | data: u32, | ||
| 2263 | }; | ||
| 2264 | |||
| 2265 | const ExtraIndex = u32; | ||
| 2266 | |||
| 2267 | const Tag = enum(u8) { | ||
| 2268 | basic, | ||
| 2269 | pointer, | ||
| 2270 | pointer_const, | ||
| 2271 | pointer_volatile, | ||
| 2272 | pointer_const_volatile, | ||
| 2273 | aligned, | ||
| 2274 | array_small, | ||
| 2275 | array_large, | ||
| 2276 | vector, | ||
| 2277 | fwd_decl_struct_anon, | ||
| 2278 | fwd_decl_union_anon, | ||
| 2279 | fwd_decl_struct, | ||
| 2280 | fwd_decl_union, | ||
| 2281 | aggregate_struct_anon, | ||
| 2282 | aggregate_struct_packed_anon, | ||
| 2283 | aggregate_union_anon, | ||
| 2284 | aggregate_union_packed_anon, | ||
| 2285 | aggregate_struct, | ||
| 2286 | aggregate_struct_packed, | ||
| 2287 | aggregate_union, | ||
| 2288 | aggregate_union_packed, | ||
| 2289 | function, | ||
| 2290 | function_varargs, | ||
| 2291 | }; | ||
| 2292 | |||
| 2293 | const Aligned = struct { | ||
| 2294 | ctype: CType.Index, | ||
| 2295 | flags: Flags, | ||
| 2296 | |||
| 2297 | const Flags = packed struct(u32) { | ||
| 2298 | alignas: AlignAs, | ||
| 2299 | _: u20 = 0, | ||
| 2300 | }; | ||
| 2301 | }; | ||
| 2302 | |||
| 2303 | const SequenceSmall = struct { | ||
| 2304 | elem_ctype: CType.Index, | ||
| 2305 | len: u32, | ||
| 2306 | }; | ||
| 2307 | |||
| 2308 | const SequenceLarge = struct { | ||
| 2309 | elem_ctype: CType.Index, | ||
| 2310 | len_lo: u32, | ||
| 2311 | len_hi: u32, | ||
| 2312 | |||
| 2313 | fn len(extra: SequenceLarge) u64 { | ||
| 2314 | return @as(u64, extra.len_lo) << 0 | | ||
| 2315 | @as(u64, extra.len_hi) << 32; | ||
| 2316 | } | ||
| 2317 | }; | ||
| 2318 | |||
| 2319 | const Field = struct { | ||
| 2320 | name: String.Index, | ||
| 2321 | ctype: CType.Index, | ||
| 2322 | flags: Flags, | ||
| 2323 | |||
| 2324 | const Flags = Aligned.Flags; | ||
| 2325 | }; | ||
| 2326 | |||
| 2327 | const FwdDeclAnon = struct { | ||
| 2328 | fields_len: u32, | ||
| 2329 | }; | ||
| 2330 | |||
| 2331 | const AggregateAnon = struct { | ||
| 2332 | owner_decl: DeclIndex, | ||
| 2333 | id: u32, | ||
| 2334 | fields_len: u32, | ||
| 2335 | }; | ||
| 2336 | |||
| 2337 | const Aggregate = struct { | ||
| 2338 | fwd_decl: CType.Index, | ||
| 2339 | fields_len: u32, | ||
| 2340 | }; | ||
| 2341 | |||
| 2342 | const Function = struct { | ||
| 2343 | return_ctype: CType.Index, | ||
| 2344 | param_ctypes_len: u32, | ||
| 2345 | }; | ||
| 2346 | |||
| 2347 | fn addExtra( | ||
| 2348 | pool: *Pool, | ||
| 2349 | allocator: std.mem.Allocator, | ||
| 2350 | comptime Extra: type, | ||
| 2351 | extra: Extra, | ||
| 2352 | trailing_len: usize, | ||
| 2353 | ) !ExtraIndex { | ||
| 2354 | try pool.extra.ensureUnusedCapacity( | ||
| 2355 | allocator, | ||
| 2356 | @typeInfo(Extra).Struct.fields.len + trailing_len, | ||
| 2357 | ); | ||
| 2358 | defer pool.addExtraAssumeCapacity(Extra, extra); | ||
| 2359 | return @intCast(pool.extra.items.len); | ||
| 2360 | } | ||
| 2361 | fn addExtraAssumeCapacity(pool: *Pool, comptime Extra: type, extra: Extra) void { | ||
| 2362 | addExtraAssumeCapacityTo(&pool.extra, Extra, extra); | ||
| 2363 | } | ||
| 2364 | fn addExtraAssumeCapacityTo( | ||
| 2365 | array: *std.ArrayListUnmanaged(u32), | ||
| 2366 | comptime Extra: type, | ||
| 2367 | extra: Extra, | ||
| 2368 | ) void { | ||
| 2369 | inline for (@typeInfo(Extra).Struct.fields) |field| { | ||
| 2370 | const value = @field(extra, field.name); | ||
| 2371 | array.appendAssumeCapacity(switch (field.type) { | ||
| 2372 | u32 => value, | ||
| 2373 | CType.Index, String.Index, DeclIndex => @intFromEnum(value), | ||
| 2374 | Aligned.Flags => @bitCast(value), | ||
| 2375 | else => @compileError("bad field type: " ++ field.name ++ ": " ++ | ||
| 2376 | @typeName(field.type)), | ||
| 2377 | }); | ||
| 2378 | } | ||
| 2379 | } | ||
| 2380 | |||
| 2381 | fn addHashedExtra( | ||
| 2382 | pool: *Pool, | ||
| 2383 | allocator: std.mem.Allocator, | ||
| 2384 | hasher: *Hasher, | ||
| 2385 | comptime Extra: type, | ||
| 2386 | extra: Extra, | ||
| 2387 | trailing_len: usize, | ||
| 2388 | ) !ExtraIndex { | ||
| 2389 | hasher.updateExtra(Extra, extra, pool); | ||
| 2390 | return pool.addExtra(allocator, Extra, extra, trailing_len); | ||
| 2391 | } | ||
| 2392 | fn addHashedExtraAssumeCapacity( | ||
| 2393 | pool: *Pool, | ||
| 2394 | hasher: *Hasher, | ||
| 2395 | comptime Extra: type, | ||
| 2396 | extra: Extra, | ||
| 2397 | ) void { | ||
| 2398 | hasher.updateExtra(Extra, extra, pool); | ||
| 2399 | pool.addExtraAssumeCapacity(Extra, extra); | ||
| 2400 | } | ||
| 2401 | fn addHashedExtraAssumeCapacityTo( | ||
| 2402 | pool: *Pool, | ||
| 2403 | array: *std.ArrayListUnmanaged(u32), | ||
| 2404 | hasher: *Hasher, | ||
| 2405 | comptime Extra: type, | ||
| 2406 | extra: Extra, | ||
| 2407 | ) void { | ||
| 2408 | hasher.updateExtra(Extra, extra, pool); | ||
| 2409 | addExtraAssumeCapacityTo(array, Extra, extra); | ||
| 2410 | } | ||
| 2411 | |||
| 2412 | const ExtraTrail = struct { | ||
| 2413 | extra_index: ExtraIndex, | ||
| 2414 | |||
| 2415 | fn next( | ||
| 2416 | extra_trail: *ExtraTrail, | ||
| 2417 | len: u32, | ||
| 2418 | comptime Extra: type, | ||
| 2419 | pool: *const Pool, | ||
| 2420 | ) []const Extra { | ||
| 2421 | defer extra_trail.extra_index += @intCast(len); | ||
| 2422 | return @ptrCast(pool.extra.items[extra_trail.extra_index..][0..len]); | ||
| 2423 | } | ||
| 2424 | }; | ||
| 2425 | |||
| 2426 | fn getExtraTrail( | ||
| 2427 | pool: *const Pool, | ||
| 2428 | comptime Extra: type, | ||
| 2429 | extra_index: ExtraIndex, | ||
| 2430 | ) struct { extra: Extra, trail: ExtraTrail } { | ||
| 2431 | var extra: Extra = undefined; | ||
| 2432 | const fields = @typeInfo(Extra).Struct.fields; | ||
| 2433 | inline for (fields, pool.extra.items[extra_index..][0..fields.len]) |field, value| | ||
| 2434 | @field(extra, field.name) = switch (field.type) { | ||
| 2435 | u32 => value, | ||
| 2436 | CType.Index, String.Index, DeclIndex => @enumFromInt(value), | ||
| 2437 | Aligned.Flags => @bitCast(value), | ||
| 2438 | else => @compileError("bad field type: " ++ field.name ++ ": " ++ @typeName(field.type)), | ||
| 2439 | }; | ||
| 2440 | return .{ | ||
| 2441 | .extra = extra, | ||
| 2442 | .trail = .{ .extra_index = extra_index + @as(ExtraIndex, @intCast(fields.len)) }, | ||
| 2443 | }; | ||
| 2444 | } | ||
| 2445 | |||
| 2446 | fn getExtra(pool: *const Pool, comptime Extra: type, extra_index: ExtraIndex) Extra { | ||
| 2447 | return pool.getExtraTrail(Extra, extra_index).extra; | ||
| 2448 | } | ||
| 2449 | }; | ||
| 2450 | |||
| 2451 | pub const AlignAs = packed struct { | ||
| 2452 | @"align": Alignment, | ||
| 2453 | abi: Alignment, | ||
| 2454 | |||
| 2455 | pub fn fromAlignment(alignas: AlignAs) AlignAs { | ||
| 2456 | assert(alignas.abi != .none); | ||
| 2457 | return .{ | ||
| 2458 | .@"align" = if (alignas.@"align" != .none) alignas.@"align" else alignas.abi, | ||
| 2459 | .abi = alignas.abi, | ||
| 2460 | }; | ||
| 2461 | } | ||
| 2462 | pub fn fromAbiAlignment(abi: Alignment) AlignAs { | ||
| 2463 | assert(abi != .none); | ||
| 2464 | return .{ .@"align" = abi, .abi = abi }; | ||
| 2465 | } | ||
| 2466 | pub fn fromByteUnits(@"align": u64, abi: u64) AlignAs { | ||
| 2467 | return fromAlignment(.{ | ||
| 2468 | .@"align" = Alignment.fromByteUnits(@"align"), | ||
| 2469 | .abi = Alignment.fromNonzeroByteUnits(abi), | ||
| 2470 | }); | ||
| 2471 | } | ||
| 2472 | |||
| 2473 | pub fn order(lhs: AlignAs, rhs: AlignAs) std.math.Order { | ||
| 2474 | return lhs.@"align".order(rhs.@"align"); | ||
| 2475 | } | ||
| 2476 | pub fn abiOrder(alignas: AlignAs) std.math.Order { | ||
| 2477 | return alignas.@"align".order(alignas.abi); | ||
| 2478 | } | ||
| 2479 | pub fn toByteUnits(alignas: AlignAs) u64 { | ||
| 2480 | return alignas.@"align".toByteUnits().?; | ||
| 2481 | } | ||
| 2482 | }; | ||
| 2483 | |||
| 2484 | const Alignment = @import("../../InternPool.zig").Alignment; | ||
| 2485 | const assert = std.debug.assert; | ||
| 2486 | const CType = @This(); | ||
| 2487 | const DeclIndex = std.zig.DeclIndex; | ||
| 2488 | const Module = @import("../../Package/Module.zig"); | ||
| 2489 | const std = @import("std"); | ||
| 2490 | const Type = @import("../../type.zig").Type; | ||
| 2491 | const Zcu = @import("../../Module.zig"); | ||
src/codegen/c/type.zig deleted-2318| ... | @@ -1,2318 +0,0 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const mem = std.mem; | ||
| 3 | const Allocator = mem.Allocator; | ||
| 4 | const assert = std.debug.assert; | ||
| 5 | const autoHash = std.hash.autoHash; | ||
| 6 | const Target = std.Target; | ||
| 7 | |||
| 8 | const Alignment = @import("../../InternPool.zig").Alignment; | ||
| 9 | const Module = @import("../../Module.zig"); | ||
| 10 | const InternPool = @import("../../InternPool.zig"); | ||
| 11 | const Type = @import("../../type.zig").Type; | ||
| 12 | |||
| 13 | pub const CType = extern union { | ||
| 14 | /// If the tag value is less than Tag.no_payload_count, then no pointer | ||
| 15 | /// dereference is needed. | ||
| 16 | tag_if_small_enough: Tag, | ||
| 17 | ptr_otherwise: *const Payload, | ||
| 18 | |||
| 19 | pub fn initTag(small_tag: Tag) CType { | ||
| 20 | assert(!small_tag.hasPayload()); | ||
| 21 | return .{ .tag_if_small_enough = small_tag }; | ||
| 22 | } | ||
| 23 | |||
| 24 | pub fn initPayload(pl: anytype) CType { | ||
| 25 | const T = @typeInfo(@TypeOf(pl)).Pointer.child; | ||
| 26 | return switch (pl.base.tag) { | ||
| 27 | inline else => |t| if (comptime t.hasPayload() and t.Type() == T) .{ | ||
| 28 | .ptr_otherwise = &pl.base, | ||
| 29 | } else unreachable, | ||
| 30 | }; | ||
| 31 | } | ||
| 32 | |||
| 33 | pub fn hasPayload(self: CType) bool { | ||
| 34 | return self.tag_if_small_enough.hasPayload(); | ||
| 35 | } | ||
| 36 | |||
| 37 | pub fn tag(self: CType) Tag { | ||
| 38 | return if (self.hasPayload()) self.ptr_otherwise.tag else self.tag_if_small_enough; | ||
| 39 | } | ||
| 40 | |||
| 41 | pub fn cast(self: CType, comptime T: type) ?*const T { | ||
| 42 | if (!self.hasPayload()) return null; | ||
| 43 | const pl = self.ptr_otherwise; | ||
| 44 | return switch (pl.tag) { | ||
| 45 | inline else => |t| if (comptime t.hasPayload() and t.Type() == T) | ||
| 46 | @fieldParentPtr(T, "base", pl) | ||
| 47 | else | ||
| 48 | null, | ||
| 49 | }; | ||
| 50 | } | ||
| 51 | |||
| 52 | pub fn castTag(self: CType, comptime t: Tag) ?*const t.Type() { | ||
| 53 | return if (self.tag() == t) @fieldParentPtr(t.Type(), "base", self.ptr_otherwise) else null; | ||
| 54 | } | ||
| 55 | |||
| 56 | pub const Tag = enum(usize) { | ||
| 57 | // The first section of this enum are tags that require no payload. | ||
| 58 | void, | ||
| 59 | |||
| 60 | // C basic types | ||
| 61 | char, | ||
| 62 | |||
| 63 | @"signed char", | ||
| 64 | short, | ||
| 65 | int, | ||
| 66 | long, | ||
| 67 | @"long long", | ||
| 68 | |||
| 69 | _Bool, | ||
| 70 | @"unsigned char", | ||
| 71 | @"unsigned short", | ||
| 72 | @"unsigned int", | ||
| 73 | @"unsigned long", | ||
| 74 | @"unsigned long long", | ||
| 75 | |||
| 76 | float, | ||
| 77 | double, | ||
| 78 | @"long double", | ||
| 79 | |||
| 80 | // C header types | ||
| 81 | // - stdbool.h | ||
| 82 | bool, | ||
| 83 | // - stddef.h | ||
| 84 | size_t, | ||
| 85 | ptrdiff_t, | ||
| 86 | // - stdint.h | ||
| 87 | uint8_t, | ||
| 88 | int8_t, | ||
| 89 | uint16_t, | ||
| 90 | int16_t, | ||
| 91 | uint32_t, | ||
| 92 | int32_t, | ||
| 93 | uint64_t, | ||
| 94 | int64_t, | ||
| 95 | uintptr_t, | ||
| 96 | intptr_t, | ||
| 97 | |||
| 98 | // zig.h types | ||
| 99 | zig_u128, | ||
| 100 | zig_i128, | ||
| 101 | zig_f16, | ||
| 102 | zig_f32, | ||
| 103 | zig_f64, | ||
| 104 | zig_f80, | ||
| 105 | zig_f128, | ||
| 106 | zig_c_longdouble, // Keep last_no_payload_tag updated! | ||
| 107 | |||
| 108 | // After this, the tag requires a payload. | ||
| 109 | pointer, | ||
| 110 | pointer_const, | ||
| 111 | pointer_volatile, | ||
| 112 | pointer_const_volatile, | ||
| 113 | array, | ||
| 114 | vector, | ||
| 115 | fwd_anon_struct, | ||
| 116 | fwd_anon_union, | ||
| 117 | fwd_struct, | ||
| 118 | fwd_union, | ||
| 119 | unnamed_struct, | ||
| 120 | unnamed_union, | ||
| 121 | packed_unnamed_struct, | ||
| 122 | packed_unnamed_union, | ||
| 123 | anon_struct, | ||
| 124 | anon_union, | ||
| 125 | @"struct", | ||
| 126 | @"union", | ||
| 127 | packed_struct, | ||
| 128 | packed_union, | ||
| 129 | function, | ||
| 130 | varargs_function, | ||
| 131 | |||
| 132 | pub const last_no_payload_tag = Tag.zig_c_longdouble; | ||
| 133 | pub const no_payload_count = @intFromEnum(last_no_payload_tag) + 1; | ||
| 134 | |||
| 135 | pub fn hasPayload(self: Tag) bool { | ||
| 136 | return @intFromEnum(self) >= no_payload_count; | ||
| 137 | } | ||
| 138 | |||
| 139 | pub fn toIndex(self: Tag) Index { | ||
| 140 | assert(!self.hasPayload()); | ||
| 141 | return @as(Index, @intCast(@intFromEnum(self))); | ||
| 142 | } | ||
| 143 | |||
| 144 | pub fn Type(comptime self: Tag) type { | ||
| 145 | return switch (self) { | ||
| 146 | .void, | ||
| 147 | .char, | ||
| 148 | .@"signed char", | ||
| 149 | .short, | ||
| 150 | .int, | ||
| 151 | .long, | ||
| 152 | .@"long long", | ||
| 153 | ._Bool, | ||
| 154 | .@"unsigned char", | ||
| 155 | .@"unsigned short", | ||
| 156 | .@"unsigned int", | ||
| 157 | .@"unsigned long", | ||
| 158 | .@"unsigned long long", | ||
| 159 | .float, | ||
| 160 | .double, | ||
| 161 | .@"long double", | ||
| 162 | .bool, | ||
| 163 | .size_t, | ||
| 164 | .ptrdiff_t, | ||
| 165 | .uint8_t, | ||
| 166 | .int8_t, | ||
| 167 | .uint16_t, | ||
| 168 | .int16_t, | ||
| 169 | .uint32_t, | ||
| 170 | .int32_t, | ||
| 171 | .uint64_t, | ||
| 172 | .int64_t, | ||
| 173 | .uintptr_t, | ||
| 174 | .intptr_t, | ||
| 175 | .zig_u128, | ||
| 176 | .zig_i128, | ||
| 177 | .zig_f16, | ||
| 178 | .zig_f32, | ||
| 179 | .zig_f64, | ||
| 180 | .zig_f80, | ||
| 181 | .zig_f128, | ||
| 182 | .zig_c_longdouble, | ||
| 183 | => @compileError("Type Tag " ++ @tagName(self) ++ " has no payload"), | ||
| 184 | |||
| 185 | .pointer, | ||
| 186 | .pointer_const, | ||
| 187 | .pointer_volatile, | ||
| 188 | .pointer_const_volatile, | ||
| 189 | => Payload.Child, | ||
| 190 | |||
| 191 | .array, | ||
| 192 | .vector, | ||
| 193 | => Payload.Sequence, | ||
| 194 | |||
| 195 | .fwd_anon_struct, | ||
| 196 | .fwd_anon_union, | ||
| 197 | => Payload.Fields, | ||
| 198 | |||
| 199 | .fwd_struct, | ||
| 200 | .fwd_union, | ||
| 201 | => Payload.FwdDecl, | ||
| 202 | |||
| 203 | .unnamed_struct, | ||
| 204 | .unnamed_union, | ||
| 205 | .packed_unnamed_struct, | ||
| 206 | .packed_unnamed_union, | ||
| 207 | => Payload.Unnamed, | ||
| 208 | |||
| 209 | .anon_struct, | ||
| 210 | .anon_union, | ||
| 211 | .@"struct", | ||
| 212 | .@"union", | ||
| 213 | .packed_struct, | ||
| 214 | .packed_union, | ||
| 215 | => Payload.Aggregate, | ||
| 216 | |||
| 217 | .function, | ||
| 218 | .varargs_function, | ||
| 219 | => Payload.Function, | ||
| 220 | }; | ||
| 221 | } | ||
| 222 | }; | ||
| 223 | |||
| 224 | pub const Payload = struct { | ||
| 225 | tag: Tag, | ||
| 226 | |||
| 227 | pub const Child = struct { | ||
| 228 | base: Payload, | ||
| 229 | data: Index, | ||
| 230 | }; | ||
| 231 | |||
| 232 | pub const Sequence = struct { | ||
| 233 | base: Payload, | ||
| 234 | data: struct { | ||
| 235 | len: u64, | ||
| 236 | elem_type: Index, | ||
| 237 | }, | ||
| 238 | }; | ||
| 239 | |||
| 240 | pub const FwdDecl = struct { | ||
| 241 | base: Payload, | ||
| 242 | data: InternPool.DeclIndex, | ||
| 243 | }; | ||
| 244 | |||
| 245 | pub const Fields = struct { | ||
| 246 | base: Payload, | ||
| 247 | data: Data, | ||
| 248 | |||
| 249 | pub const Data = []const Field; | ||
| 250 | pub const Field = struct { | ||
| 251 | name: [*:0]const u8, | ||
| 252 | type: Index, | ||
| 253 | alignas: AlignAs, | ||
| 254 | }; | ||
| 255 | }; | ||
| 256 | |||
| 257 | pub const Unnamed = struct { | ||
| 258 | base: Payload, | ||
| 259 | data: struct { | ||
| 260 | fields: Fields.Data, | ||
| 261 | owner_decl: InternPool.DeclIndex, | ||
| 262 | id: u32, | ||
| 263 | }, | ||
| 264 | }; | ||
| 265 | |||
| 266 | pub const Aggregate = struct { | ||
| 267 | base: Payload, | ||
| 268 | data: struct { | ||
| 269 | fields: Fields.Data, | ||
| 270 | fwd_decl: Index, | ||
| 271 | }, | ||
| 272 | }; | ||
| 273 | |||
| 274 | pub const Function = struct { | ||
| 275 | base: Payload, | ||
| 276 | data: struct { | ||
| 277 | return_type: Index, | ||
| 278 | param_types: []const Index, | ||
| 279 | }, | ||
| 280 | }; | ||
| 281 | }; | ||
| 282 | |||
| 283 | pub const AlignAs = struct { | ||
| 284 | @"align": Alignment, | ||
| 285 | abi: Alignment, | ||
| 286 | |||
| 287 | pub fn init(@"align": Alignment, abi_align: Alignment) AlignAs { | ||
| 288 | assert(abi_align != .none); | ||
| 289 | return .{ | ||
| 290 | .@"align" = if (@"align" != .none) @"align" else abi_align, | ||
| 291 | .abi = abi_align, | ||
| 292 | }; | ||
| 293 | } | ||
| 294 | |||
| 295 | pub fn initByteUnits(alignment: u64, abi_alignment: u32) AlignAs { | ||
| 296 | return init( | ||
| 297 | Alignment.fromByteUnits(alignment), | ||
| 298 | Alignment.fromNonzeroByteUnits(abi_alignment), | ||
| 299 | ); | ||
| 300 | } | ||
| 301 | pub fn abiAlign(ty: Type, mod: *Module) AlignAs { | ||
| 302 | const abi_align = ty.abiAlignment(mod); | ||
| 303 | return init(abi_align, abi_align); | ||
| 304 | } | ||
| 305 | pub fn fieldAlign(struct_ty: Type, field_i: usize, mod: *Module) AlignAs { | ||
| 306 | return init( | ||
| 307 | struct_ty.structFieldAlign(field_i, mod), | ||
| 308 | struct_ty.structFieldType(field_i, mod).abiAlignment(mod), | ||
| 309 | ); | ||
| 310 | } | ||
| 311 | pub fn unionPayloadAlign(union_ty: Type, mod: *Module) AlignAs { | ||
| 312 | const union_obj = mod.typeToUnion(union_ty).?; | ||
| 313 | const union_payload_align = mod.unionAbiAlignment(union_obj); | ||
| 314 | return init(union_payload_align, union_payload_align); | ||
| 315 | } | ||
| 316 | |||
| 317 | pub fn order(lhs: AlignAs, rhs: AlignAs) std.math.Order { | ||
| 318 | return lhs.@"align".order(rhs.@"align"); | ||
| 319 | } | ||
| 320 | pub fn abiOrder(self: AlignAs) std.math.Order { | ||
| 321 | return self.@"align".order(self.abi); | ||
| 322 | } | ||
| 323 | pub fn toByteUnits(self: AlignAs) u64 { | ||
| 324 | return self.@"align".toByteUnitsOptional().?; | ||
| 325 | } | ||
| 326 | }; | ||
| 327 | |||
| 328 | pub const Index = u32; | ||
| 329 | pub const Store = struct { | ||
| 330 | arena: std.heap.ArenaAllocator.State = .{}, | ||
| 331 | set: Set = .{}, | ||
| 332 | |||
| 333 | pub const Set = struct { | ||
| 334 | pub const Map = std.ArrayHashMapUnmanaged(CType, void, HashContext, true); | ||
| 335 | const HashContext = struct { | ||
| 336 | store: *const Set, | ||
| 337 | |||
| 338 | pub fn hash(self: @This(), cty: CType) Map.Hash { | ||
| 339 | return @as(Map.Hash, @truncate(cty.hash(self.store.*))); | ||
| 340 | } | ||
| 341 | pub fn eql(_: @This(), lhs: CType, rhs: CType, _: usize) bool { | ||
| 342 | return lhs.eql(rhs); | ||
| 343 | } | ||
| 344 | }; | ||
| 345 | |||
| 346 | map: Map = .{}, | ||
| 347 | |||
| 348 | pub fn indexToCType(self: Set, index: Index) CType { | ||
| 349 | if (index < Tag.no_payload_count) return initTag(@as(Tag, @enumFromInt(index))); | ||
| 350 | return self.map.keys()[index - Tag.no_payload_count]; | ||
| 351 | } | ||
| 352 | |||
| 353 | pub fn indexToHash(self: Set, index: Index) Map.Hash { | ||
| 354 | if (index < Tag.no_payload_count) | ||
| 355 | return (HashContext{ .store = &self }).hash(self.indexToCType(index)); | ||
| 356 | return self.map.entries.items(.hash)[index - Tag.no_payload_count]; | ||
| 357 | } | ||
| 358 | |||
| 359 | pub fn typeToIndex(self: Set, ty: Type, mod: *Module, kind: Kind) ?Index { | ||
| 360 | const lookup = Convert.Lookup{ .imm = .{ .set = &self, .mod = mod } }; | ||
| 361 | |||
| 362 | var convert: Convert = undefined; | ||
| 363 | convert.initType(ty, kind, lookup) catch unreachable; | ||
| 364 | |||
| 365 | const t = convert.tag(); | ||
| 366 | if (!t.hasPayload()) return t.toIndex(); | ||
| 367 | |||
| 368 | return if (self.map.getIndexAdapted( | ||
| 369 | ty, | ||
| 370 | TypeAdapter32{ .kind = kind, .lookup = lookup, .convert = &convert }, | ||
| 371 | )) |idx| @as(Index, @intCast(Tag.no_payload_count + idx)) else null; | ||
| 372 | } | ||
| 373 | }; | ||
| 374 | |||
| 375 | pub const Promoted = struct { | ||
| 376 | arena: std.heap.ArenaAllocator, | ||
| 377 | set: Set, | ||
| 378 | |||
| 379 | pub fn gpa(self: *Promoted) Allocator { | ||
| 380 | return self.arena.child_allocator; | ||
| 381 | } | ||
| 382 | |||
| 383 | pub fn cTypeToIndex(self: *Promoted, cty: CType) Allocator.Error!Index { | ||
| 384 | const t = cty.tag(); | ||
| 385 | if (@intFromEnum(t) < Tag.no_payload_count) return @as(Index, @intCast(@intFromEnum(t))); | ||
| 386 | |||
| 387 | const gop = try self.set.map.getOrPutContext(self.gpa(), cty, .{ .store = &self.set }); | ||
| 388 | if (!gop.found_existing) gop.key_ptr.* = cty; | ||
| 389 | if (std.debug.runtime_safety) { | ||
| 390 | const key = &self.set.map.entries.items(.key)[gop.index]; | ||
| 391 | assert(key == gop.key_ptr); | ||
| 392 | assert(cty.eql(key.*)); | ||
| 393 | assert(cty.hash(self.set) == key.hash(self.set)); | ||
| 394 | } | ||
| 395 | return @as(Index, @intCast(Tag.no_payload_count + gop.index)); | ||
| 396 | } | ||
| 397 | |||
| 398 | pub fn typeToIndex( | ||
| 399 | self: *Promoted, | ||
| 400 | ty: Type, | ||
| 401 | mod: *Module, | ||
| 402 | kind: Kind, | ||
| 403 | ) Allocator.Error!Index { | ||
| 404 | const lookup = Convert.Lookup{ .mut = .{ .promoted = self, .mod = mod } }; | ||
| 405 | |||
| 406 | var convert: Convert = undefined; | ||
| 407 | try convert.initType(ty, kind, lookup); | ||
| 408 | |||
| 409 | const t = convert.tag(); | ||
| 410 | if (!t.hasPayload()) return t.toIndex(); | ||
| 411 | |||
| 412 | const gop = try self.set.map.getOrPutContextAdapted( | ||
| 413 | self.gpa(), | ||
| 414 | ty, | ||
| 415 | TypeAdapter32{ .kind = kind, .lookup = lookup.freeze(), .convert = &convert }, | ||
| 416 | .{ .store = &self.set }, | ||
| 417 | ); | ||
| 418 | if (!gop.found_existing) { | ||
| 419 | errdefer _ = self.set.map.pop(); | ||
| 420 | gop.key_ptr.* = try createFromConvert(self, ty, lookup.getModule(), kind, convert); | ||
| 421 | } | ||
| 422 | if (std.debug.runtime_safety) { | ||
| 423 | const adapter = TypeAdapter64{ | ||
| 424 | .kind = kind, | ||
| 425 | .lookup = lookup.freeze(), | ||
| 426 | .convert = &convert, | ||
| 427 | }; | ||
| 428 | const cty = &self.set.map.entries.items(.key)[gop.index]; | ||
| 429 | assert(cty == gop.key_ptr); | ||
| 430 | assert(adapter.eql(ty, cty.*)); | ||
| 431 | assert(adapter.hash(ty) == cty.hash(self.set)); | ||
| 432 | } | ||
| 433 | return @as(Index, @intCast(Tag.no_payload_count + gop.index)); | ||
| 434 | } | ||
| 435 | }; | ||
| 436 | |||
| 437 | pub fn promote(self: Store, gpa: Allocator) Promoted { | ||
| 438 | return .{ .arena = self.arena.promote(gpa), .set = self.set }; | ||
| 439 | } | ||
| 440 | |||
| 441 | pub fn demote(self: *Store, promoted: Promoted) void { | ||
| 442 | self.arena = promoted.arena.state; | ||
| 443 | self.set = promoted.set; | ||
| 444 | } | ||
| 445 | |||
| 446 | pub fn indexToCType(self: Store, index: Index) CType { | ||
| 447 | return self.set.indexToCType(index); | ||
| 448 | } | ||
| 449 | |||
| 450 | pub fn indexToHash(self: Store, index: Index) Set.Map.Hash { | ||
| 451 | return self.set.indexToHash(index); | ||
| 452 | } | ||
| 453 | |||
| 454 | pub fn cTypeToIndex(self: *Store, gpa: Allocator, cty: CType) !Index { | ||
| 455 | var promoted = self.promote(gpa); | ||
| 456 | defer self.demote(promoted); | ||
| 457 | return promoted.cTypeToIndex(cty); | ||
| 458 | } | ||
| 459 | |||
| 460 | pub fn typeToCType(self: *Store, gpa: Allocator, ty: Type, mod: *Module, kind: Kind) !CType { | ||
| 461 | const idx = try self.typeToIndex(gpa, ty, mod, kind); | ||
| 462 | return self.indexToCType(idx); | ||
| 463 | } | ||
| 464 | |||
| 465 | pub fn typeToIndex(self: *Store, gpa: Allocator, ty: Type, mod: *Module, kind: Kind) !Index { | ||
| 466 | var promoted = self.promote(gpa); | ||
| 467 | defer self.demote(promoted); | ||
| 468 | return promoted.typeToIndex(ty, mod, kind); | ||
| 469 | } | ||
| 470 | |||
| 471 | pub fn clearRetainingCapacity(self: *Store, gpa: Allocator) void { | ||
| 472 | var promoted = self.promote(gpa); | ||
| 473 | defer self.demote(promoted); | ||
| 474 | promoted.set.map.clearRetainingCapacity(); | ||
| 475 | _ = promoted.arena.reset(.retain_capacity); | ||
| 476 | } | ||
| 477 | |||
| 478 | pub fn clearAndFree(self: *Store, gpa: Allocator) void { | ||
| 479 | var promoted = self.promote(gpa); | ||
| 480 | defer self.demote(promoted); | ||
| 481 | promoted.set.map.clearAndFree(gpa); | ||
| 482 | _ = promoted.arena.reset(.free_all); | ||
| 483 | } | ||
| 484 | |||
| 485 | pub fn shrinkRetainingCapacity(self: *Store, gpa: Allocator, new_len: usize) void { | ||
| 486 | self.set.map.shrinkRetainingCapacity(gpa, new_len); | ||
| 487 | } | ||
| 488 | |||
| 489 | pub fn shrinkAndFree(self: *Store, gpa: Allocator, new_len: usize) void { | ||
| 490 | self.set.map.shrinkAndFree(gpa, new_len); | ||
| 491 | } | ||
| 492 | |||
| 493 | pub fn count(self: Store) usize { | ||
| 494 | return self.set.map.count(); | ||
| 495 | } | ||
| 496 | |||
| 497 | pub fn move(self: *Store) Store { | ||
| 498 | const moved = self.*; | ||
| 499 | self.* = .{}; | ||
| 500 | return moved; | ||
| 501 | } | ||
| 502 | |||
| 503 | pub fn deinit(self: *Store, gpa: Allocator) void { | ||
| 504 | var promoted = self.promote(gpa); | ||
| 505 | promoted.set.map.deinit(gpa); | ||
| 506 | _ = promoted.arena.deinit(); | ||
| 507 | self.* = undefined; | ||
| 508 | } | ||
| 509 | }; | ||
| 510 | |||
| 511 | pub fn isBool(self: CType) bool { | ||
| 512 | return switch (self.tag()) { | ||
| 513 | ._Bool, | ||
| 514 | .bool, | ||
| 515 | => true, | ||
| 516 | else => false, | ||
| 517 | }; | ||
| 518 | } | ||
| 519 | |||
| 520 | pub fn isInteger(self: CType) bool { | ||
| 521 | return switch (self.tag()) { | ||
| 522 | .char, | ||
| 523 | .@"signed char", | ||
| 524 | .short, | ||
| 525 | .int, | ||
| 526 | .long, | ||
| 527 | .@"long long", | ||
| 528 | .@"unsigned char", | ||
| 529 | .@"unsigned short", | ||
| 530 | .@"unsigned int", | ||
| 531 | .@"unsigned long", | ||
| 532 | .@"unsigned long long", | ||
| 533 | .size_t, | ||
| 534 | .ptrdiff_t, | ||
| 535 | .uint8_t, | ||
| 536 | .int8_t, | ||
| 537 | .uint16_t, | ||
| 538 | .int16_t, | ||
| 539 | .uint32_t, | ||
| 540 | .int32_t, | ||
| 541 | .uint64_t, | ||
| 542 | .int64_t, | ||
| 543 | .uintptr_t, | ||
| 544 | .intptr_t, | ||
| 545 | .zig_u128, | ||
| 546 | .zig_i128, | ||
| 547 | => true, | ||
| 548 | else => false, | ||
| 549 | }; | ||
| 550 | } | ||
| 551 | |||
| 552 | pub fn signedness(self: CType, target: std.Target) std.builtin.Signedness { | ||
| 553 | return switch (self.tag()) { | ||
| 554 | .char => target.charSignedness(), | ||
| 555 | .@"signed char", | ||
| 556 | .short, | ||
| 557 | .int, | ||
| 558 | .long, | ||
| 559 | .@"long long", | ||
| 560 | .ptrdiff_t, | ||
| 561 | .int8_t, | ||
| 562 | .int16_t, | ||
| 563 | .int32_t, | ||
| 564 | .int64_t, | ||
| 565 | .intptr_t, | ||
| 566 | .zig_i128, | ||
| 567 | => .signed, | ||
| 568 | .@"unsigned char", | ||
| 569 | .@"unsigned short", | ||
| 570 | .@"unsigned int", | ||
| 571 | .@"unsigned long", | ||
| 572 | .@"unsigned long long", | ||
| 573 | .size_t, | ||
| 574 | .uint8_t, | ||
| 575 | .uint16_t, | ||
| 576 | .uint32_t, | ||
| 577 | .uint64_t, | ||
| 578 | .uintptr_t, | ||
| 579 | .zig_u128, | ||
| 580 | => .unsigned, | ||
| 581 | else => unreachable, | ||
| 582 | }; | ||
| 583 | } | ||
| 584 | |||
| 585 | pub fn isFloat(self: CType) bool { | ||
| 586 | return switch (self.tag()) { | ||
| 587 | .float, | ||
| 588 | .double, | ||
| 589 | .@"long double", | ||
| 590 | .zig_f16, | ||
| 591 | .zig_f32, | ||
| 592 | .zig_f64, | ||
| 593 | .zig_f80, | ||
| 594 | .zig_f128, | ||
| 595 | .zig_c_longdouble, | ||
| 596 | => true, | ||
| 597 | else => false, | ||
| 598 | }; | ||
| 599 | } | ||
| 600 | |||
| 601 | pub fn isPointer(self: CType) bool { | ||
| 602 | return switch (self.tag()) { | ||
| 603 | .pointer, | ||
| 604 | .pointer_const, | ||
| 605 | .pointer_volatile, | ||
| 606 | .pointer_const_volatile, | ||
| 607 | => true, | ||
| 608 | else => false, | ||
| 609 | }; | ||
| 610 | } | ||
| 611 | |||
| 612 | pub fn isFunction(self: CType) bool { | ||
| 613 | return switch (self.tag()) { | ||
| 614 | .function, | ||
| 615 | .varargs_function, | ||
| 616 | => true, | ||
| 617 | else => false, | ||
| 618 | }; | ||
| 619 | } | ||
| 620 | |||
| 621 | pub fn toSigned(self: CType) CType { | ||
| 622 | return CType.initTag(switch (self.tag()) { | ||
| 623 | .char, .@"signed char", .@"unsigned char" => .@"signed char", | ||
| 624 | .short, .@"unsigned short" => .short, | ||
| 625 | .int, .@"unsigned int" => .int, | ||
| 626 | .long, .@"unsigned long" => .long, | ||
| 627 | .@"long long", .@"unsigned long long" => .@"long long", | ||
| 628 | .size_t, .ptrdiff_t => .ptrdiff_t, | ||
| 629 | .uint8_t, .int8_t => .int8_t, | ||
| 630 | .uint16_t, .int16_t => .int16_t, | ||
| 631 | .uint32_t, .int32_t => .int32_t, | ||
| 632 | .uint64_t, .int64_t => .int64_t, | ||
| 633 | .uintptr_t, .intptr_t => .intptr_t, | ||
| 634 | .zig_u128, .zig_i128 => .zig_i128, | ||
| 635 | .float, | ||
| 636 | .double, | ||
| 637 | .@"long double", | ||
| 638 | .zig_f16, | ||
| 639 | .zig_f32, | ||
| 640 | .zig_f80, | ||
| 641 | .zig_f128, | ||
| 642 | .zig_c_longdouble, | ||
| 643 | => |t| t, | ||
| 644 | else => unreachable, | ||
| 645 | }); | ||
| 646 | } | ||
| 647 | |||
| 648 | pub fn toUnsigned(self: CType) CType { | ||
| 649 | return CType.initTag(switch (self.tag()) { | ||
| 650 | .char, .@"signed char", .@"unsigned char" => .@"unsigned char", | ||
| 651 | .short, .@"unsigned short" => .@"unsigned short", | ||
| 652 | .int, .@"unsigned int" => .@"unsigned int", | ||
| 653 | .long, .@"unsigned long" => .@"unsigned long", | ||
| 654 | .@"long long", .@"unsigned long long" => .@"unsigned long long", | ||
| 655 | .size_t, .ptrdiff_t => .size_t, | ||
| 656 | .uint8_t, .int8_t => .uint8_t, | ||
| 657 | .uint16_t, .int16_t => .uint16_t, | ||
| 658 | .uint32_t, .int32_t => .uint32_t, | ||
| 659 | .uint64_t, .int64_t => .uint64_t, | ||
| 660 | .uintptr_t, .intptr_t => .uintptr_t, | ||
| 661 | .zig_u128, .zig_i128 => .zig_u128, | ||
| 662 | else => unreachable, | ||
| 663 | }); | ||
| 664 | } | ||
| 665 | |||
| 666 | pub fn toSignedness(self: CType, s: std.builtin.Signedness) CType { | ||
| 667 | return switch (s) { | ||
| 668 | .unsigned => self.toUnsigned(), | ||
| 669 | .signed => self.toSigned(), | ||
| 670 | }; | ||
| 671 | } | ||
| 672 | |||
| 673 | pub fn getStandardDefineAbbrev(self: CType) ?[]const u8 { | ||
| 674 | return switch (self.tag()) { | ||
| 675 | .char => "CHAR", | ||
| 676 | .@"signed char" => "SCHAR", | ||
| 677 | .short => "SHRT", | ||
| 678 | .int => "INT", | ||
| 679 | .long => "LONG", | ||
| 680 | .@"long long" => "LLONG", | ||
| 681 | .@"unsigned char" => "UCHAR", | ||
| 682 | .@"unsigned short" => "USHRT", | ||
| 683 | .@"unsigned int" => "UINT", | ||
| 684 | .@"unsigned long" => "ULONG", | ||
| 685 | .@"unsigned long long" => "ULLONG", | ||
| 686 | .float => "FLT", | ||
| 687 | .double => "DBL", | ||
| 688 | .@"long double" => "LDBL", | ||
| 689 | .size_t => "SIZE", | ||
| 690 | .ptrdiff_t => "PTRDIFF", | ||
| 691 | .uint8_t => "UINT8", | ||
| 692 | .int8_t => "INT8", | ||
| 693 | .uint16_t => "UINT16", | ||
| 694 | .int16_t => "INT16", | ||
| 695 | .uint32_t => "UINT32", | ||
| 696 | .int32_t => "INT32", | ||
| 697 | .uint64_t => "UINT64", | ||
| 698 | .int64_t => "INT64", | ||
| 699 | .uintptr_t => "UINTPTR", | ||
| 700 | .intptr_t => "INTPTR", | ||
| 701 | else => null, | ||
| 702 | }; | ||
| 703 | } | ||
| 704 | |||
| 705 | pub fn renderLiteralPrefix(self: CType, writer: anytype, kind: Kind) @TypeOf(writer).Error!void { | ||
| 706 | switch (self.tag()) { | ||
| 707 | .void => unreachable, | ||
| 708 | ._Bool, | ||
| 709 | .char, | ||
| 710 | .@"signed char", | ||
| 711 | .short, | ||
| 712 | .@"unsigned short", | ||
| 713 | .bool, | ||
| 714 | .size_t, | ||
| 715 | .ptrdiff_t, | ||
| 716 | .uintptr_t, | ||
| 717 | .intptr_t, | ||
| 718 | => |t| switch (kind) { | ||
| 719 | else => try writer.print("({s})", .{@tagName(t)}), | ||
| 720 | .global => {}, | ||
| 721 | }, | ||
| 722 | .int, | ||
| 723 | .long, | ||
| 724 | .@"long long", | ||
| 725 | .@"unsigned char", | ||
| 726 | .@"unsigned int", | ||
| 727 | .@"unsigned long", | ||
| 728 | .@"unsigned long long", | ||
| 729 | .float, | ||
| 730 | .double, | ||
| 731 | .@"long double", | ||
| 732 | => {}, | ||
| 733 | .uint8_t, | ||
| 734 | .int8_t, | ||
| 735 | .uint16_t, | ||
| 736 | .int16_t, | ||
| 737 | .uint32_t, | ||
| 738 | .int32_t, | ||
| 739 | .uint64_t, | ||
| 740 | .int64_t, | ||
| 741 | => try writer.print("{s}_C(", .{self.getStandardDefineAbbrev().?}), | ||
| 742 | .zig_u128, | ||
| 743 | .zig_i128, | ||
| 744 | .zig_f16, | ||
| 745 | .zig_f32, | ||
| 746 | .zig_f64, | ||
| 747 | .zig_f80, | ||
| 748 | .zig_f128, | ||
| 749 | .zig_c_longdouble, | ||
| 750 | => |t| try writer.print("zig_{s}_{s}(", .{ | ||
| 751 | switch (kind) { | ||
| 752 | else => "make", | ||
| 753 | .global => "init", | ||
| 754 | }, | ||
| 755 | @tagName(t)["zig_".len..], | ||
| 756 | }), | ||
| 757 | .pointer, | ||
| 758 | .pointer_const, | ||
| 759 | .pointer_volatile, | ||
| 760 | .pointer_const_volatile, | ||
| 761 | => unreachable, | ||
| 762 | .array, | ||
| 763 | .vector, | ||
| 764 | => try writer.writeByte('{'), | ||
| 765 | .fwd_anon_struct, | ||
| 766 | .fwd_anon_union, | ||
| 767 | .fwd_struct, | ||
| 768 | .fwd_union, | ||
| 769 | .unnamed_struct, | ||
| 770 | .unnamed_union, | ||
| 771 | .packed_unnamed_struct, | ||
| 772 | .packed_unnamed_union, | ||
| 773 | .anon_struct, | ||
| 774 | .anon_union, | ||
| 775 | .@"struct", | ||
| 776 | .@"union", | ||
| 777 | .packed_struct, | ||
| 778 | .packed_union, | ||
| 779 | .function, | ||
| 780 | .varargs_function, | ||
| 781 | => unreachable, | ||
| 782 | } | ||
| 783 | } | ||
| 784 | |||
| 785 | pub fn renderLiteralSuffix(self: CType, writer: anytype) @TypeOf(writer).Error!void { | ||
| 786 | switch (self.tag()) { | ||
| 787 | .void => unreachable, | ||
| 788 | ._Bool => {}, | ||
| 789 | .char, | ||
| 790 | .@"signed char", | ||
| 791 | .short, | ||
| 792 | .int, | ||
| 793 | => {}, | ||
| 794 | .long => try writer.writeByte('l'), | ||
| 795 | .@"long long" => try writer.writeAll("ll"), | ||
| 796 | .@"unsigned char", | ||
| 797 | .@"unsigned short", | ||
| 798 | .@"unsigned int", | ||
| 799 | => try writer.writeByte('u'), | ||
| 800 | .@"unsigned long", | ||
| 801 | .size_t, | ||
| 802 | .uintptr_t, | ||
| 803 | => try writer.writeAll("ul"), | ||
| 804 | .@"unsigned long long" => try writer.writeAll("ull"), | ||
| 805 | .float => try writer.writeByte('f'), | ||
| 806 | .double => {}, | ||
| 807 | .@"long double" => try writer.writeByte('l'), | ||
| 808 | .bool, | ||
| 809 | .ptrdiff_t, | ||
| 810 | .intptr_t, | ||
| 811 | => {}, | ||
| 812 | .uint8_t, | ||
| 813 | .int8_t, | ||
| 814 | .uint16_t, | ||
| 815 | .int16_t, | ||
| 816 | .uint32_t, | ||
| 817 | .int32_t, | ||
| 818 | .uint64_t, | ||
| 819 | .int64_t, | ||
| 820 | .zig_u128, | ||
| 821 | .zig_i128, | ||
| 822 | .zig_f16, | ||
| 823 | .zig_f32, | ||
| 824 | .zig_f64, | ||
| 825 | .zig_f80, | ||
| 826 | .zig_f128, | ||
| 827 | .zig_c_longdouble, | ||
| 828 | => try writer.writeByte(')'), | ||
| 829 | .pointer, | ||
| 830 | .pointer_const, | ||
| 831 | .pointer_volatile, | ||
| 832 | .pointer_const_volatile, | ||
| 833 | => unreachable, | ||
| 834 | .array, | ||
| 835 | .vector, | ||
| 836 | => try writer.writeByte('}'), | ||
| 837 | .fwd_anon_struct, | ||
| 838 | .fwd_anon_union, | ||
| 839 | .fwd_struct, | ||
| 840 | .fwd_union, | ||
| 841 | .unnamed_struct, | ||
| 842 | .unnamed_union, | ||
| 843 | .packed_unnamed_struct, | ||
| 844 | .packed_unnamed_union, | ||
| 845 | .anon_struct, | ||
| 846 | .anon_union, | ||
| 847 | .@"struct", | ||
| 848 | .@"union", | ||
| 849 | .packed_struct, | ||
| 850 | .packed_union, | ||
| 851 | .function, | ||
| 852 | .varargs_function, | ||
| 853 | => unreachable, | ||
| 854 | } | ||
| 855 | } | ||
| 856 | |||
| 857 | pub fn floatActiveBits(self: CType, target: Target) u16 { | ||
| 858 | return switch (self.tag()) { | ||
| 859 | .float => target.c_type_bit_size(.float), | ||
| 860 | .double => target.c_type_bit_size(.double), | ||
| 861 | .@"long double", .zig_c_longdouble => target.c_type_bit_size(.longdouble), | ||
| 862 | .zig_f16 => 16, | ||
| 863 | .zig_f32 => 32, | ||
| 864 | .zig_f64 => 64, | ||
| 865 | .zig_f80 => 80, | ||
| 866 | .zig_f128 => 128, | ||
| 867 | else => unreachable, | ||
| 868 | }; | ||
| 869 | } | ||
| 870 | |||
| 871 | pub fn byteSize(self: CType, store: Store.Set, target: Target) u64 { | ||
| 872 | return switch (self.tag()) { | ||
| 873 | .void => 0, | ||
| 874 | .char, .@"signed char", ._Bool, .@"unsigned char", .bool, .uint8_t, .int8_t => 1, | ||
| 875 | .short => target.c_type_byte_size(.short), | ||
| 876 | .int => target.c_type_byte_size(.int), | ||
| 877 | .long => target.c_type_byte_size(.long), | ||
| 878 | .@"long long" => target.c_type_byte_size(.longlong), | ||
| 879 | .@"unsigned short" => target.c_type_byte_size(.ushort), | ||
| 880 | .@"unsigned int" => target.c_type_byte_size(.uint), | ||
| 881 | .@"unsigned long" => target.c_type_byte_size(.ulong), | ||
| 882 | .@"unsigned long long" => target.c_type_byte_size(.ulonglong), | ||
| 883 | .float => target.c_type_byte_size(.float), | ||
| 884 | .double => target.c_type_byte_size(.double), | ||
| 885 | .@"long double" => target.c_type_byte_size(.longdouble), | ||
| 886 | .size_t, | ||
| 887 | .ptrdiff_t, | ||
| 888 | .uintptr_t, | ||
| 889 | .intptr_t, | ||
| 890 | .pointer, | ||
| 891 | .pointer_const, | ||
| 892 | .pointer_volatile, | ||
| 893 | .pointer_const_volatile, | ||
| 894 | => @divExact(target.ptrBitWidth(), 8), | ||
| 895 | .uint16_t, .int16_t, .zig_f16 => 2, | ||
| 896 | .uint32_t, .int32_t, .zig_f32 => 4, | ||
| 897 | .uint64_t, .int64_t, .zig_f64 => 8, | ||
| 898 | .zig_u128, .zig_i128, .zig_f128 => 16, | ||
| 899 | .zig_f80 => if (target.c_type_bit_size(.longdouble) == 80) | ||
| 900 | target.c_type_byte_size(.longdouble) | ||
| 901 | else | ||
| 902 | 16, | ||
| 903 | .zig_c_longdouble => target.c_type_byte_size(.longdouble), | ||
| 904 | |||
| 905 | .array, | ||
| 906 | .vector, | ||
| 907 | => { | ||
| 908 | const data = self.cast(Payload.Sequence).?.data; | ||
| 909 | return data.len * store.indexToCType(data.elem_type).byteSize(store, target); | ||
| 910 | }, | ||
| 911 | |||
| 912 | .fwd_anon_struct, | ||
| 913 | .fwd_anon_union, | ||
| 914 | .fwd_struct, | ||
| 915 | .fwd_union, | ||
| 916 | .unnamed_struct, | ||
| 917 | .unnamed_union, | ||
| 918 | .packed_unnamed_struct, | ||
| 919 | .packed_unnamed_union, | ||
| 920 | .anon_struct, | ||
| 921 | .anon_union, | ||
| 922 | .@"struct", | ||
| 923 | .@"union", | ||
| 924 | .packed_struct, | ||
| 925 | .packed_union, | ||
| 926 | .function, | ||
| 927 | .varargs_function, | ||
| 928 | => unreachable, | ||
| 929 | }; | ||
| 930 | } | ||
| 931 | |||
| 932 | pub fn isPacked(self: CType) bool { | ||
| 933 | return switch (self.tag()) { | ||
| 934 | else => false, | ||
| 935 | .packed_unnamed_struct, | ||
| 936 | .packed_unnamed_union, | ||
| 937 | .packed_struct, | ||
| 938 | .packed_union, | ||
| 939 | => true, | ||
| 940 | }; | ||
| 941 | } | ||
| 942 | |||
| 943 | pub fn fields(self: CType) Payload.Fields.Data { | ||
| 944 | return if (self.cast(Payload.Aggregate)) |pl| | ||
| 945 | pl.data.fields | ||
| 946 | else if (self.cast(Payload.Unnamed)) |pl| | ||
| 947 | pl.data.fields | ||
| 948 | else if (self.cast(Payload.Fields)) |pl| | ||
| 949 | pl.data | ||
| 950 | else | ||
| 951 | unreachable; | ||
| 952 | } | ||
| 953 | |||
| 954 | pub fn eql(lhs: CType, rhs: CType) bool { | ||
| 955 | return lhs.eqlContext(rhs, struct { | ||
| 956 | pub fn eqlIndex(_: @This(), lhs_idx: Index, rhs_idx: Index) bool { | ||
| 957 | return lhs_idx == rhs_idx; | ||
| 958 | } | ||
| 959 | }{}); | ||
| 960 | } | ||
| 961 | |||
| 962 | pub fn eqlContext(lhs: CType, rhs: CType, ctx: anytype) bool { | ||
| 963 | // As a shortcut, if the small tags / addresses match, we're done. | ||
| 964 | if (lhs.tag_if_small_enough == rhs.tag_if_small_enough) return true; | ||
| 965 | |||
| 966 | const lhs_tag = lhs.tag(); | ||
| 967 | const rhs_tag = rhs.tag(); | ||
| 968 | if (lhs_tag != rhs_tag) return false; | ||
| 969 | |||
| 970 | return switch (lhs_tag) { | ||
| 971 | .void, | ||
| 972 | .char, | ||
| 973 | .@"signed char", | ||
| 974 | .short, | ||
| 975 | .int, | ||
| 976 | .long, | ||
| 977 | .@"long long", | ||
| 978 | ._Bool, | ||
| 979 | .@"unsigned char", | ||
| 980 | .@"unsigned short", | ||
| 981 | .@"unsigned int", | ||
| 982 | .@"unsigned long", | ||
| 983 | .@"unsigned long long", | ||
| 984 | .float, | ||
| 985 | .double, | ||
| 986 | .@"long double", | ||
| 987 | .bool, | ||
| 988 | .size_t, | ||
| 989 | .ptrdiff_t, | ||
| 990 | .uint8_t, | ||
| 991 | .int8_t, | ||
| 992 | .uint16_t, | ||
| 993 | .int16_t, | ||
| 994 | .uint32_t, | ||
| 995 | .int32_t, | ||
| 996 | .uint64_t, | ||
| 997 | .int64_t, | ||
| 998 | .uintptr_t, | ||
| 999 | .intptr_t, | ||
| 1000 | .zig_u128, | ||
| 1001 | .zig_i128, | ||
| 1002 | .zig_f16, | ||
| 1003 | .zig_f32, | ||
| 1004 | .zig_f64, | ||
| 1005 | .zig_f80, | ||
| 1006 | .zig_f128, | ||
| 1007 | .zig_c_longdouble, | ||
| 1008 | => false, | ||
| 1009 | |||
| 1010 | .pointer, | ||
| 1011 | .pointer_const, | ||
| 1012 | .pointer_volatile, | ||
| 1013 | .pointer_const_volatile, | ||
| 1014 | => ctx.eqlIndex(lhs.cast(Payload.Child).?.data, rhs.cast(Payload.Child).?.data), | ||
| 1015 | |||
| 1016 | .array, | ||
| 1017 | .vector, | ||
| 1018 | => { | ||
| 1019 | const lhs_data = lhs.cast(Payload.Sequence).?.data; | ||
| 1020 | const rhs_data = rhs.cast(Payload.Sequence).?.data; | ||
| 1021 | return lhs_data.len == rhs_data.len and | ||
| 1022 | ctx.eqlIndex(lhs_data.elem_type, rhs_data.elem_type); | ||
| 1023 | }, | ||
| 1024 | |||
| 1025 | .fwd_anon_struct, | ||
| 1026 | .fwd_anon_union, | ||
| 1027 | => { | ||
| 1028 | const lhs_data = lhs.cast(Payload.Fields).?.data; | ||
| 1029 | const rhs_data = rhs.cast(Payload.Fields).?.data; | ||
| 1030 | if (lhs_data.len != rhs_data.len) return false; | ||
| 1031 | for (lhs_data, rhs_data) |lhs_field, rhs_field| { | ||
| 1032 | if (!ctx.eqlIndex(lhs_field.type, rhs_field.type)) return false; | ||
| 1033 | if (lhs_field.alignas.@"align" != rhs_field.alignas.@"align") return false; | ||
| 1034 | if (std.mem.orderZ(u8, lhs_field.name, rhs_field.name) != .eq) return false; | ||
| 1035 | } | ||
| 1036 | return true; | ||
| 1037 | }, | ||
| 1038 | |||
| 1039 | .fwd_struct, | ||
| 1040 | .fwd_union, | ||
| 1041 | => lhs.cast(Payload.FwdDecl).?.data == rhs.cast(Payload.FwdDecl).?.data, | ||
| 1042 | |||
| 1043 | .unnamed_struct, | ||
| 1044 | .unnamed_union, | ||
| 1045 | .packed_unnamed_struct, | ||
| 1046 | .packed_unnamed_union, | ||
| 1047 | => { | ||
| 1048 | const lhs_data = lhs.cast(Payload.Unnamed).?.data; | ||
| 1049 | const rhs_data = rhs.cast(Payload.Unnamed).?.data; | ||
| 1050 | return lhs_data.owner_decl == rhs_data.owner_decl and lhs_data.id == rhs_data.id; | ||
| 1051 | }, | ||
| 1052 | |||
| 1053 | .anon_struct, | ||
| 1054 | .anon_union, | ||
| 1055 | .@"struct", | ||
| 1056 | .@"union", | ||
| 1057 | .packed_struct, | ||
| 1058 | .packed_union, | ||
| 1059 | => ctx.eqlIndex( | ||
| 1060 | lhs.cast(Payload.Aggregate).?.data.fwd_decl, | ||
| 1061 | rhs.cast(Payload.Aggregate).?.data.fwd_decl, | ||
| 1062 | ), | ||
| 1063 | |||
| 1064 | .function, | ||
| 1065 | .varargs_function, | ||
| 1066 | => { | ||
| 1067 | const lhs_data = lhs.cast(Payload.Function).?.data; | ||
| 1068 | const rhs_data = rhs.cast(Payload.Function).?.data; | ||
| 1069 | if (lhs_data.param_types.len != rhs_data.param_types.len) return false; | ||
| 1070 | if (!ctx.eqlIndex(lhs_data.return_type, rhs_data.return_type)) return false; | ||
| 1071 | for (lhs_data.param_types, rhs_data.param_types) |lhs_param_idx, rhs_param_idx| { | ||
| 1072 | if (!ctx.eqlIndex(lhs_param_idx, rhs_param_idx)) return false; | ||
| 1073 | } | ||
| 1074 | return true; | ||
| 1075 | }, | ||
| 1076 | }; | ||
| 1077 | } | ||
| 1078 | |||
| 1079 | pub fn hash(self: CType, store: Store.Set) u64 { | ||
| 1080 | var hasher = std.hash.Wyhash.init(0); | ||
| 1081 | self.updateHasher(&hasher, store); | ||
| 1082 | return hasher.final(); | ||
| 1083 | } | ||
| 1084 | |||
| 1085 | pub fn updateHasher(self: CType, hasher: anytype, store: Store.Set) void { | ||
| 1086 | const t = self.tag(); | ||
| 1087 | autoHash(hasher, t); | ||
| 1088 | switch (t) { | ||
| 1089 | .void, | ||
| 1090 | .char, | ||
| 1091 | .@"signed char", | ||
| 1092 | .short, | ||
| 1093 | .int, | ||
| 1094 | .long, | ||
| 1095 | .@"long long", | ||
| 1096 | ._Bool, | ||
| 1097 | .@"unsigned char", | ||
| 1098 | .@"unsigned short", | ||
| 1099 | .@"unsigned int", | ||
| 1100 | .@"unsigned long", | ||
| 1101 | .@"unsigned long long", | ||
| 1102 | .float, | ||
| 1103 | .double, | ||
| 1104 | .@"long double", | ||
| 1105 | .bool, | ||
| 1106 | .size_t, | ||
| 1107 | .ptrdiff_t, | ||
| 1108 | .uint8_t, | ||
| 1109 | .int8_t, | ||
| 1110 | .uint16_t, | ||
| 1111 | .int16_t, | ||
| 1112 | .uint32_t, | ||
| 1113 | .int32_t, | ||
| 1114 | .uint64_t, | ||
| 1115 | .int64_t, | ||
| 1116 | .uintptr_t, | ||
| 1117 | .intptr_t, | ||
| 1118 | .zig_u128, | ||
| 1119 | .zig_i128, | ||
| 1120 | .zig_f16, | ||
| 1121 | .zig_f32, | ||
| 1122 | .zig_f64, | ||
| 1123 | .zig_f80, | ||
| 1124 | .zig_f128, | ||
| 1125 | .zig_c_longdouble, | ||
| 1126 | => {}, | ||
| 1127 | |||
| 1128 | .pointer, | ||
| 1129 | .pointer_const, | ||
| 1130 | .pointer_volatile, | ||
| 1131 | .pointer_const_volatile, | ||
| 1132 | => store.indexToCType(self.cast(Payload.Child).?.data).updateHasher(hasher, store), | ||
| 1133 | |||
| 1134 | .array, | ||
| 1135 | .vector, | ||
| 1136 | => { | ||
| 1137 | const data = self.cast(Payload.Sequence).?.data; | ||
| 1138 | autoHash(hasher, data.len); | ||
| 1139 | store.indexToCType(data.elem_type).updateHasher(hasher, store); | ||
| 1140 | }, | ||
| 1141 | |||
| 1142 | .fwd_anon_struct, | ||
| 1143 | .fwd_anon_union, | ||
| 1144 | => for (self.cast(Payload.Fields).?.data) |field| { | ||
| 1145 | store.indexToCType(field.type).updateHasher(hasher, store); | ||
| 1146 | hasher.update(mem.span(field.name)); | ||
| 1147 | autoHash(hasher, field.alignas.@"align"); | ||
| 1148 | }, | ||
| 1149 | |||
| 1150 | .fwd_struct, | ||
| 1151 | .fwd_union, | ||
| 1152 | => autoHash(hasher, self.cast(Payload.FwdDecl).?.data), | ||
| 1153 | |||
| 1154 | .unnamed_struct, | ||
| 1155 | .unnamed_union, | ||
| 1156 | .packed_unnamed_struct, | ||
| 1157 | .packed_unnamed_union, | ||
| 1158 | => { | ||
| 1159 | const data = self.cast(Payload.Unnamed).?.data; | ||
| 1160 | autoHash(hasher, data.owner_decl); | ||
| 1161 | autoHash(hasher, data.id); | ||
| 1162 | }, | ||
| 1163 | |||
| 1164 | .anon_struct, | ||
| 1165 | .anon_union, | ||
| 1166 | .@"struct", | ||
| 1167 | .@"union", | ||
| 1168 | .packed_struct, | ||
| 1169 | .packed_union, | ||
| 1170 | => store.indexToCType(self.cast(Payload.Aggregate).?.data.fwd_decl) | ||
| 1171 | .updateHasher(hasher, store), | ||
| 1172 | |||
| 1173 | .function, | ||
| 1174 | .varargs_function, | ||
| 1175 | => { | ||
| 1176 | const data = self.cast(Payload.Function).?.data; | ||
| 1177 | store.indexToCType(data.return_type).updateHasher(hasher, store); | ||
| 1178 | for (data.param_types) |param_ty| { | ||
| 1179 | store.indexToCType(param_ty).updateHasher(hasher, store); | ||
| 1180 | } | ||
| 1181 | }, | ||
| 1182 | } | ||
| 1183 | } | ||
| 1184 | |||
| 1185 | pub const Kind = enum { forward, forward_parameter, complete, global, parameter, payload }; | ||
| 1186 | |||
| 1187 | const Convert = struct { | ||
| 1188 | storage: union { | ||
| 1189 | none: void, | ||
| 1190 | child: Payload.Child, | ||
| 1191 | seq: Payload.Sequence, | ||
| 1192 | fwd: Payload.FwdDecl, | ||
| 1193 | anon: struct { | ||
| 1194 | fields: [2]Payload.Fields.Field, | ||
| 1195 | pl: union { | ||
| 1196 | forward: Payload.Fields, | ||
| 1197 | complete: Payload.Aggregate, | ||
| 1198 | }, | ||
| 1199 | }, | ||
| 1200 | }, | ||
| 1201 | value: union(enum) { | ||
| 1202 | tag: Tag, | ||
| 1203 | cty: CType, | ||
| 1204 | }, | ||
| 1205 | |||
| 1206 | pub fn init(self: *@This(), t: Tag) void { | ||
| 1207 | self.* = if (t.hasPayload()) .{ | ||
| 1208 | .storage = .{ .none = {} }, | ||
| 1209 | .value = .{ .tag = t }, | ||
| 1210 | } else .{ | ||
| 1211 | .storage = .{ .none = {} }, | ||
| 1212 | .value = .{ .cty = initTag(t) }, | ||
| 1213 | }; | ||
| 1214 | } | ||
| 1215 | |||
| 1216 | pub fn tag(self: @This()) Tag { | ||
| 1217 | return switch (self.value) { | ||
| 1218 | .tag => |t| t, | ||
| 1219 | .cty => |c| c.tag(), | ||
| 1220 | }; | ||
| 1221 | } | ||
| 1222 | |||
| 1223 | fn tagFromIntInfo(int_info: std.builtin.Type.Int) Tag { | ||
| 1224 | return switch (int_info.bits) { | ||
| 1225 | 0 => .void, | ||
| 1226 | 1...8 => switch (int_info.signedness) { | ||
| 1227 | .unsigned => .uint8_t, | ||
| 1228 | .signed => .int8_t, | ||
| 1229 | }, | ||
| 1230 | 9...16 => switch (int_info.signedness) { | ||
| 1231 | .unsigned => .uint16_t, | ||
| 1232 | .signed => .int16_t, | ||
| 1233 | }, | ||
| 1234 | 17...32 => switch (int_info.signedness) { | ||
| 1235 | .unsigned => .uint32_t, | ||
| 1236 | .signed => .int32_t, | ||
| 1237 | }, | ||
| 1238 | 33...64 => switch (int_info.signedness) { | ||
| 1239 | .unsigned => .uint64_t, | ||
| 1240 | .signed => .int64_t, | ||
| 1241 | }, | ||
| 1242 | 65...128 => switch (int_info.signedness) { | ||
| 1243 | .unsigned => .zig_u128, | ||
| 1244 | .signed => .zig_i128, | ||
| 1245 | }, | ||
| 1246 | else => .array, | ||
| 1247 | }; | ||
| 1248 | } | ||
| 1249 | |||
| 1250 | pub const Lookup = union(enum) { | ||
| 1251 | fail: *Module, | ||
| 1252 | imm: struct { | ||
| 1253 | set: *const Store.Set, | ||
| 1254 | mod: *Module, | ||
| 1255 | }, | ||
| 1256 | mut: struct { | ||
| 1257 | promoted: *Store.Promoted, | ||
| 1258 | mod: *Module, | ||
| 1259 | }, | ||
| 1260 | |||
| 1261 | pub fn isMutable(self: @This()) bool { | ||
| 1262 | return switch (self) { | ||
| 1263 | .fail, .imm => false, | ||
| 1264 | .mut => true, | ||
| 1265 | }; | ||
| 1266 | } | ||
| 1267 | |||
| 1268 | pub fn getTarget(self: @This()) Target { | ||
| 1269 | return self.getModule().getTarget(); | ||
| 1270 | } | ||
| 1271 | |||
| 1272 | pub fn getModule(self: @This()) *Module { | ||
| 1273 | return switch (self) { | ||
| 1274 | .fail => |mod| mod, | ||
| 1275 | .imm => |imm| imm.mod, | ||
| 1276 | .mut => |mut| mut.mod, | ||
| 1277 | }; | ||
| 1278 | } | ||
| 1279 | |||
| 1280 | pub fn getSet(self: @This()) ?*const Store.Set { | ||
| 1281 | return switch (self) { | ||
| 1282 | .fail => null, | ||
| 1283 | .imm => |imm| imm.set, | ||
| 1284 | .mut => |mut| &mut.promoted.set, | ||
| 1285 | }; | ||
| 1286 | } | ||
| 1287 | |||
| 1288 | pub fn typeToIndex(self: @This(), ty: Type, kind: Kind) !?Index { | ||
| 1289 | return switch (self) { | ||
| 1290 | .fail => null, | ||
| 1291 | .imm => |imm| imm.set.typeToIndex(ty, imm.mod, kind), | ||
| 1292 | .mut => |mut| try mut.promoted.typeToIndex(ty, mut.mod, kind), | ||
| 1293 | }; | ||
| 1294 | } | ||
| 1295 | |||
| 1296 | pub fn indexToCType(self: @This(), index: Index) ?CType { | ||
| 1297 | return if (self.getSet()) |set| set.indexToCType(index) else null; | ||
| 1298 | } | ||
| 1299 | |||
| 1300 | pub fn freeze(self: @This()) @This() { | ||
| 1301 | return switch (self) { | ||
| 1302 | .fail, .imm => self, | ||
| 1303 | .mut => |mut| .{ .imm = .{ .set = &mut.promoted.set, .mod = mut.mod } }, | ||
| 1304 | }; | ||
| 1305 | } | ||
| 1306 | }; | ||
| 1307 | |||
| 1308 | fn sortFields(self: *@This(), fields_len: usize) []Payload.Fields.Field { | ||
| 1309 | const Field = Payload.Fields.Field; | ||
| 1310 | const slice = self.storage.anon.fields[0..fields_len]; | ||
| 1311 | mem.sort(Field, slice, {}, struct { | ||
| 1312 | fn before(_: void, lhs: Field, rhs: Field) bool { | ||
| 1313 | return lhs.alignas.order(rhs.alignas).compare(.gt); | ||
| 1314 | } | ||
| 1315 | }.before); | ||
| 1316 | return slice; | ||
| 1317 | } | ||
| 1318 | |||
| 1319 | fn initAnon(self: *@This(), kind: Kind, fwd_idx: Index, fields_len: usize) void { | ||
| 1320 | switch (kind) { | ||
| 1321 | .forward, .forward_parameter => { | ||
| 1322 | self.storage.anon.pl = .{ .forward = .{ | ||
| 1323 | .base = .{ .tag = .fwd_anon_struct }, | ||
| 1324 | .data = self.sortFields(fields_len), | ||
| 1325 | } }; | ||
| 1326 | self.value = .{ .cty = initPayload(&self.storage.anon.pl.forward) }; | ||
| 1327 | }, | ||
| 1328 | .complete, .parameter, .global => { | ||
| 1329 | self.storage.anon.pl = .{ .complete = .{ | ||
| 1330 | .base = .{ .tag = .anon_struct }, | ||
| 1331 | .data = .{ | ||
| 1332 | .fields = self.sortFields(fields_len), | ||
| 1333 | .fwd_decl = fwd_idx, | ||
| 1334 | }, | ||
| 1335 | } }; | ||
| 1336 | self.value = .{ .cty = initPayload(&self.storage.anon.pl.complete) }; | ||
| 1337 | }, | ||
| 1338 | .payload => unreachable, | ||
| 1339 | } | ||
| 1340 | } | ||
| 1341 | |||
| 1342 | fn initArrayParameter(self: *@This(), ty: Type, kind: Kind, lookup: Lookup) !void { | ||
| 1343 | if (switch (kind) { | ||
| 1344 | .forward_parameter => @as(Index, undefined), | ||
| 1345 | .parameter => try lookup.typeToIndex(ty, .forward_parameter), | ||
| 1346 | .forward, .complete, .global, .payload => unreachable, | ||
| 1347 | }) |fwd_idx| { | ||
| 1348 | if (try lookup.typeToIndex(ty, switch (kind) { | ||
| 1349 | .forward_parameter => .forward, | ||
| 1350 | .parameter => .complete, | ||
| 1351 | .forward, .complete, .global, .payload => unreachable, | ||
| 1352 | })) |array_idx| { | ||
| 1353 | self.storage = .{ .anon = undefined }; | ||
| 1354 | self.storage.anon.fields[0] = .{ | ||
| 1355 | .name = "array", | ||
| 1356 | .type = array_idx, | ||
| 1357 | .alignas = AlignAs.abiAlign(ty, lookup.getModule()), | ||
| 1358 | }; | ||
| 1359 | self.initAnon(kind, fwd_idx, 1); | ||
| 1360 | } else self.init(switch (kind) { | ||
| 1361 | .forward_parameter => .fwd_anon_struct, | ||
| 1362 | .parameter => .anon_struct, | ||
| 1363 | .forward, .complete, .global, .payload => unreachable, | ||
| 1364 | }); | ||
| 1365 | } else self.init(.anon_struct); | ||
| 1366 | } | ||
| 1367 | |||
| 1368 | pub fn initType(self: *@This(), ty: Type, kind: Kind, lookup: Lookup) !void { | ||
| 1369 | const mod = lookup.getModule(); | ||
| 1370 | const ip = &mod.intern_pool; | ||
| 1371 | |||
| 1372 | self.* = undefined; | ||
| 1373 | if (!ty.isFnOrHasRuntimeBitsIgnoreComptime(mod)) | ||
| 1374 | self.init(.void) | ||
| 1375 | else if (ty.isAbiInt(mod)) switch (ty.ip_index) { | ||
| 1376 | .usize_type => self.init(.uintptr_t), | ||
| 1377 | .isize_type => self.init(.intptr_t), | ||
| 1378 | .c_char_type => self.init(.char), | ||
| 1379 | .c_short_type => self.init(.short), | ||
| 1380 | .c_ushort_type => self.init(.@"unsigned short"), | ||
| 1381 | .c_int_type => self.init(.int), | ||
| 1382 | .c_uint_type => self.init(.@"unsigned int"), | ||
| 1383 | .c_long_type => self.init(.long), | ||
| 1384 | .c_ulong_type => self.init(.@"unsigned long"), | ||
| 1385 | .c_longlong_type => self.init(.@"long long"), | ||
| 1386 | .c_ulonglong_type => self.init(.@"unsigned long long"), | ||
| 1387 | else => switch (tagFromIntInfo(ty.intInfo(mod))) { | ||
| 1388 | .void => unreachable, | ||
| 1389 | else => |t| self.init(t), | ||
| 1390 | .array => switch (kind) { | ||
| 1391 | .forward, .complete, .global => { | ||
| 1392 | const abi_size = ty.abiSize(mod); | ||
| 1393 | const abi_align = ty.abiAlignment(mod).toByteUnits(0); | ||
| 1394 | self.storage = .{ .seq = .{ .base = .{ .tag = .array }, .data = .{ | ||
| 1395 | .len = @divExact(abi_size, abi_align), | ||
| 1396 | .elem_type = tagFromIntInfo(.{ | ||
| 1397 | .signedness = .unsigned, | ||
| 1398 | .bits = @intCast(abi_align * 8), | ||
| 1399 | }).toIndex(), | ||
| 1400 | } } }; | ||
| 1401 | self.value = .{ .cty = initPayload(&self.storage.seq) }; | ||
| 1402 | }, | ||
| 1403 | .forward_parameter, | ||
| 1404 | .parameter, | ||
| 1405 | => try self.initArrayParameter(ty, kind, lookup), | ||
| 1406 | .payload => unreachable, | ||
| 1407 | }, | ||
| 1408 | }, | ||
| 1409 | } else switch (ty.zigTypeTag(mod)) { | ||
| 1410 | .Frame => unreachable, | ||
| 1411 | .AnyFrame => unreachable, | ||
| 1412 | |||
| 1413 | .Int, | ||
| 1414 | .Enum, | ||
| 1415 | .ErrorSet, | ||
| 1416 | .Type, | ||
| 1417 | .Void, | ||
| 1418 | .NoReturn, | ||
| 1419 | .ComptimeFloat, | ||
| 1420 | .ComptimeInt, | ||
| 1421 | .Undefined, | ||
| 1422 | .Null, | ||
| 1423 | .EnumLiteral, | ||
| 1424 | => unreachable, | ||
| 1425 | |||
| 1426 | .Bool => self.init(.bool), | ||
| 1427 | |||
| 1428 | .Float => self.init(switch (ty.ip_index) { | ||
| 1429 | .f16_type => .zig_f16, | ||
| 1430 | .f32_type => .zig_f32, | ||
| 1431 | .f64_type => .zig_f64, | ||
| 1432 | .f80_type => .zig_f80, | ||
| 1433 | .f128_type => .zig_f128, | ||
| 1434 | .c_longdouble_type => .zig_c_longdouble, | ||
| 1435 | else => unreachable, | ||
| 1436 | }), | ||
| 1437 | |||
| 1438 | .Pointer => { | ||
| 1439 | const info = ty.ptrInfo(mod); | ||
| 1440 | switch (info.flags.size) { | ||
| 1441 | .Slice => { | ||
| 1442 | if (switch (kind) { | ||
| 1443 | .forward, .forward_parameter => @as(Index, undefined), | ||
| 1444 | .complete, .parameter, .global => try lookup.typeToIndex(ty, .forward), | ||
| 1445 | .payload => unreachable, | ||
| 1446 | }) |fwd_idx| { | ||
| 1447 | const ptr_ty = ty.slicePtrFieldType(mod); | ||
| 1448 | if (try lookup.typeToIndex(ptr_ty, kind)) |ptr_idx| { | ||
| 1449 | self.storage = .{ .anon = undefined }; | ||
| 1450 | self.storage.anon.fields[0] = .{ | ||
| 1451 | .name = "ptr", | ||
| 1452 | .type = ptr_idx, | ||
| 1453 | .alignas = AlignAs.abiAlign(ptr_ty, mod), | ||
| 1454 | }; | ||
| 1455 | self.storage.anon.fields[1] = .{ | ||
| 1456 | .name = "len", | ||
| 1457 | .type = Tag.uintptr_t.toIndex(), | ||
| 1458 | .alignas = AlignAs.abiAlign(Type.usize, mod), | ||
| 1459 | }; | ||
| 1460 | self.initAnon(kind, fwd_idx, 2); | ||
| 1461 | } else self.init(switch (kind) { | ||
| 1462 | .forward, .forward_parameter => .fwd_anon_struct, | ||
| 1463 | .complete, .parameter, .global => .anon_struct, | ||
| 1464 | .payload => unreachable, | ||
| 1465 | }); | ||
| 1466 | } else self.init(.anon_struct); | ||
| 1467 | }, | ||
| 1468 | |||
| 1469 | .One, .Many, .C => { | ||
| 1470 | const t: Tag = switch (info.flags.is_volatile) { | ||
| 1471 | false => switch (info.flags.is_const) { | ||
| 1472 | false => .pointer, | ||
| 1473 | true => .pointer_const, | ||
| 1474 | }, | ||
| 1475 | true => switch (info.flags.is_const) { | ||
| 1476 | false => .pointer_volatile, | ||
| 1477 | true => .pointer_const_volatile, | ||
| 1478 | }, | ||
| 1479 | }; | ||
| 1480 | |||
| 1481 | const pointee_ty = if (info.packed_offset.host_size > 0 and | ||
| 1482 | info.flags.vector_index == .none) | ||
| 1483 | try mod.intType(.unsigned, info.packed_offset.host_size * 8) | ||
| 1484 | else | ||
| 1485 | Type.fromInterned(info.child); | ||
| 1486 | |||
| 1487 | if (try lookup.typeToIndex(pointee_ty, .forward)) |child_idx| { | ||
| 1488 | self.storage = .{ .child = .{ | ||
| 1489 | .base = .{ .tag = t }, | ||
| 1490 | .data = child_idx, | ||
| 1491 | } }; | ||
| 1492 | self.value = .{ .cty = initPayload(&self.storage.child) }; | ||
| 1493 | } else self.init(t); | ||
| 1494 | }, | ||
| 1495 | } | ||
| 1496 | }, | ||
| 1497 | |||
| 1498 | .Struct, .Union => |zig_ty_tag| if (ty.containerLayout(mod) == .@"packed") { | ||
| 1499 | if (mod.typeToPackedStruct(ty)) |packed_struct| { | ||
| 1500 | try self.initType(Type.fromInterned(packed_struct.backingIntType(ip).*), kind, lookup); | ||
| 1501 | } else { | ||
| 1502 | const bits: u16 = @intCast(ty.bitSize(mod)); | ||
| 1503 | const int_ty = try mod.intType(.unsigned, bits); | ||
| 1504 | try self.initType(int_ty, kind, lookup); | ||
| 1505 | } | ||
| 1506 | } else if (ty.isTupleOrAnonStruct(mod)) { | ||
| 1507 | if (lookup.isMutable()) { | ||
| 1508 | for (0..switch (zig_ty_tag) { | ||
| 1509 | .Struct => ty.structFieldCount(mod), | ||
| 1510 | .Union => mod.typeToUnion(ty).?.field_types.len, | ||
| 1511 | else => unreachable, | ||
| 1512 | }) |field_i| { | ||
| 1513 | const field_ty = ty.structFieldType(field_i, mod); | ||
| 1514 | if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i, mod)) or | ||
| 1515 | !field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; | ||
| 1516 | _ = try lookup.typeToIndex(field_ty, switch (kind) { | ||
| 1517 | .forward, .forward_parameter => .forward, | ||
| 1518 | .complete, .parameter => .complete, | ||
| 1519 | .global => .global, | ||
| 1520 | .payload => unreachable, | ||
| 1521 | }); | ||
| 1522 | } | ||
| 1523 | switch (kind) { | ||
| 1524 | .forward, .forward_parameter => {}, | ||
| 1525 | .complete, .parameter, .global => _ = try lookup.typeToIndex(ty, .forward), | ||
| 1526 | .payload => unreachable, | ||
| 1527 | } | ||
| 1528 | } | ||
| 1529 | self.init(switch (kind) { | ||
| 1530 | .forward, .forward_parameter => switch (zig_ty_tag) { | ||
| 1531 | .Struct => .fwd_anon_struct, | ||
| 1532 | .Union => .fwd_anon_union, | ||
| 1533 | else => unreachable, | ||
| 1534 | }, | ||
| 1535 | .complete, .parameter, .global => switch (zig_ty_tag) { | ||
| 1536 | .Struct => .anon_struct, | ||
| 1537 | .Union => .anon_union, | ||
| 1538 | else => unreachable, | ||
| 1539 | }, | ||
| 1540 | .payload => unreachable, | ||
| 1541 | }); | ||
| 1542 | } else { | ||
| 1543 | const tag_ty = ty.unionTagTypeSafety(mod); | ||
| 1544 | const is_tagged_union_wrapper = kind != .payload and tag_ty != null; | ||
| 1545 | const is_struct = zig_ty_tag == .Struct or is_tagged_union_wrapper; | ||
| 1546 | switch (kind) { | ||
| 1547 | .forward, .forward_parameter => { | ||
| 1548 | self.storage = .{ .fwd = .{ | ||
| 1549 | .base = .{ .tag = if (is_struct) .fwd_struct else .fwd_union }, | ||
| 1550 | .data = ty.getOwnerDecl(mod), | ||
| 1551 | } }; | ||
| 1552 | self.value = .{ .cty = initPayload(&self.storage.fwd) }; | ||
| 1553 | }, | ||
| 1554 | .complete, .parameter, .global, .payload => if (is_tagged_union_wrapper) { | ||
| 1555 | const fwd_idx = try lookup.typeToIndex(ty, .forward); | ||
| 1556 | const payload_idx = try lookup.typeToIndex(ty, .payload); | ||
| 1557 | const tag_idx = try lookup.typeToIndex(tag_ty.?, kind); | ||
| 1558 | if (fwd_idx != null and payload_idx != null and tag_idx != null) { | ||
| 1559 | self.storage = .{ .anon = undefined }; | ||
| 1560 | var field_count: usize = 0; | ||
| 1561 | if (payload_idx != Tag.void.toIndex()) { | ||
| 1562 | self.storage.anon.fields[field_count] = .{ | ||
| 1563 | .name = "payload", | ||
| 1564 | .type = payload_idx.?, | ||
| 1565 | .alignas = AlignAs.unionPayloadAlign(ty, mod), | ||
| 1566 | }; | ||
| 1567 | field_count += 1; | ||
| 1568 | } | ||
| 1569 | if (tag_idx != Tag.void.toIndex()) { | ||
| 1570 | self.storage.anon.fields[field_count] = .{ | ||
| 1571 | .name = "tag", | ||
| 1572 | .type = tag_idx.?, | ||
| 1573 | .alignas = AlignAs.abiAlign(tag_ty.?, mod), | ||
| 1574 | }; | ||
| 1575 | field_count += 1; | ||
| 1576 | } | ||
| 1577 | self.storage.anon.pl = .{ .complete = .{ | ||
| 1578 | .base = .{ .tag = .@"struct" }, | ||
| 1579 | .data = .{ | ||
| 1580 | .fields = self.sortFields(field_count), | ||
| 1581 | .fwd_decl = fwd_idx.?, | ||
| 1582 | }, | ||
| 1583 | } }; | ||
| 1584 | self.value = .{ .cty = initPayload(&self.storage.anon.pl.complete) }; | ||
| 1585 | } else self.init(.@"struct"); | ||
| 1586 | } else if (kind == .payload and ty.unionHasAllZeroBitFieldTypes(mod)) { | ||
| 1587 | self.init(.void); | ||
| 1588 | } else { | ||
| 1589 | var is_packed = false; | ||
| 1590 | for (0..switch (zig_ty_tag) { | ||
| 1591 | .Struct => ty.structFieldCount(mod), | ||
| 1592 | .Union => mod.typeToUnion(ty).?.field_types.len, | ||
| 1593 | else => unreachable, | ||
| 1594 | }) |field_i| { | ||
| 1595 | const field_ty = ty.structFieldType(field_i, mod); | ||
| 1596 | if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; | ||
| 1597 | |||
| 1598 | const field_align = AlignAs.fieldAlign(ty, field_i, mod); | ||
| 1599 | if (field_align.abiOrder().compare(.lt)) { | ||
| 1600 | is_packed = true; | ||
| 1601 | if (!lookup.isMutable()) break; | ||
| 1602 | } | ||
| 1603 | |||
| 1604 | if (lookup.isMutable()) { | ||
| 1605 | _ = try lookup.typeToIndex(field_ty, switch (kind) { | ||
| 1606 | .forward, .forward_parameter => unreachable, | ||
| 1607 | .complete, .parameter, .payload => .complete, | ||
| 1608 | .global => .global, | ||
| 1609 | }); | ||
| 1610 | } | ||
| 1611 | } | ||
| 1612 | switch (kind) { | ||
| 1613 | .forward, .forward_parameter => unreachable, | ||
| 1614 | .complete, .parameter, .global => { | ||
| 1615 | _ = try lookup.typeToIndex(ty, .forward); | ||
| 1616 | self.init(if (is_struct) | ||
| 1617 | if (is_packed) .packed_struct else .@"struct" | ||
| 1618 | else if (is_packed) .packed_union else .@"union"); | ||
| 1619 | }, | ||
| 1620 | .payload => self.init(if (is_packed) | ||
| 1621 | .packed_unnamed_union | ||
| 1622 | else | ||
| 1623 | .unnamed_union), | ||
| 1624 | } | ||
| 1625 | }, | ||
| 1626 | } | ||
| 1627 | }, | ||
| 1628 | |||
| 1629 | .Array, .Vector => |zig_ty_tag| { | ||
| 1630 | switch (kind) { | ||
| 1631 | .forward, .complete, .global => { | ||
| 1632 | const t: Tag = switch (zig_ty_tag) { | ||
| 1633 | .Array => .array, | ||
| 1634 | .Vector => .vector, | ||
| 1635 | else => unreachable, | ||
| 1636 | }; | ||
| 1637 | if (try lookup.typeToIndex(ty.childType(mod), kind)) |child_idx| { | ||
| 1638 | self.storage = .{ .seq = .{ .base = .{ .tag = t }, .data = .{ | ||
| 1639 | .len = ty.arrayLenIncludingSentinel(mod), | ||
| 1640 | .elem_type = child_idx, | ||
| 1641 | } } }; | ||
| 1642 | self.value = .{ .cty = initPayload(&self.storage.seq) }; | ||
| 1643 | } else self.init(t); | ||
| 1644 | }, | ||
| 1645 | .forward_parameter, .parameter => try self.initArrayParameter(ty, kind, lookup), | ||
| 1646 | .payload => unreachable, | ||
| 1647 | } | ||
| 1648 | }, | ||
| 1649 | |||
| 1650 | .Optional => { | ||
| 1651 | const payload_ty = ty.optionalChild(mod); | ||
| 1652 | if (payload_ty.hasRuntimeBitsIgnoreComptime(mod)) { | ||
| 1653 | if (ty.optionalReprIsPayload(mod)) { | ||
| 1654 | try self.initType(payload_ty, kind, lookup); | ||
| 1655 | } else if (switch (kind) { | ||
| 1656 | .forward, .forward_parameter => @as(Index, undefined), | ||
| 1657 | .complete, .parameter, .global => try lookup.typeToIndex(ty, .forward), | ||
| 1658 | .payload => unreachable, | ||
| 1659 | }) |fwd_idx| { | ||
| 1660 | if (try lookup.typeToIndex(payload_ty, switch (kind) { | ||
| 1661 | .forward, .forward_parameter => .forward, | ||
| 1662 | .complete, .parameter => .complete, | ||
| 1663 | .global => .global, | ||
| 1664 | .payload => unreachable, | ||
| 1665 | })) |payload_idx| { | ||
| 1666 | self.storage = .{ .anon = undefined }; | ||
| 1667 | self.storage.anon.fields[0] = .{ | ||
| 1668 | .name = "payload", | ||
| 1669 | .type = payload_idx, | ||
| 1670 | .alignas = AlignAs.abiAlign(payload_ty, mod), | ||
| 1671 | }; | ||
| 1672 | self.storage.anon.fields[1] = .{ | ||
| 1673 | .name = "is_null", | ||
| 1674 | .type = Tag.bool.toIndex(), | ||
| 1675 | .alignas = AlignAs.abiAlign(Type.bool, mod), | ||
| 1676 | }; | ||
| 1677 | self.initAnon(kind, fwd_idx, 2); | ||
| 1678 | } else self.init(switch (kind) { | ||
| 1679 | .forward, .forward_parameter => .fwd_anon_struct, | ||
| 1680 | .complete, .parameter, .global => .anon_struct, | ||
| 1681 | .payload => unreachable, | ||
| 1682 | }); | ||
| 1683 | } else self.init(.anon_struct); | ||
| 1684 | } else self.init(.bool); | ||
| 1685 | }, | ||
| 1686 | |||
| 1687 | .ErrorUnion => { | ||
| 1688 | if (switch (kind) { | ||
| 1689 | .forward, .forward_parameter => @as(Index, undefined), | ||
| 1690 | .complete, .parameter, .global => try lookup.typeToIndex(ty, .forward), | ||
| 1691 | .payload => unreachable, | ||
| 1692 | }) |fwd_idx| { | ||
| 1693 | const payload_ty = ty.errorUnionPayload(mod); | ||
| 1694 | if (try lookup.typeToIndex(payload_ty, switch (kind) { | ||
| 1695 | .forward, .forward_parameter => .forward, | ||
| 1696 | .complete, .parameter => .complete, | ||
| 1697 | .global => .global, | ||
| 1698 | .payload => unreachable, | ||
| 1699 | })) |payload_idx| { | ||
| 1700 | const error_ty = ty.errorUnionSet(mod); | ||
| 1701 | if (payload_idx == Tag.void.toIndex()) { | ||
| 1702 | try self.initType(error_ty, kind, lookup); | ||
| 1703 | } else if (try lookup.typeToIndex(error_ty, kind)) |error_idx| { | ||
| 1704 | self.storage = .{ .anon = undefined }; | ||
| 1705 | self.storage.anon.fields[0] = .{ | ||
| 1706 | .name = "payload", | ||
| 1707 | .type = payload_idx, | ||
| 1708 | .alignas = AlignAs.abiAlign(payload_ty, mod), | ||
| 1709 | }; | ||
| 1710 | self.storage.anon.fields[1] = .{ | ||
| 1711 | .name = "error", | ||
| 1712 | .type = error_idx, | ||
| 1713 | .alignas = AlignAs.abiAlign(error_ty, mod), | ||
| 1714 | }; | ||
| 1715 | self.initAnon(kind, fwd_idx, 2); | ||
| 1716 | } else self.init(switch (kind) { | ||
| 1717 | .forward, .forward_parameter => .fwd_anon_struct, | ||
| 1718 | .complete, .parameter, .global => .anon_struct, | ||
| 1719 | .payload => unreachable, | ||
| 1720 | }); | ||
| 1721 | } else self.init(switch (kind) { | ||
| 1722 | .forward, .forward_parameter => .fwd_anon_struct, | ||
| 1723 | .complete, .parameter, .global => .anon_struct, | ||
| 1724 | .payload => unreachable, | ||
| 1725 | }); | ||
| 1726 | } else self.init(.anon_struct); | ||
| 1727 | }, | ||
| 1728 | |||
| 1729 | .Opaque => self.init(.void), | ||
| 1730 | |||
| 1731 | .Fn => { | ||
| 1732 | const info = mod.typeToFunc(ty).?; | ||
| 1733 | if (!info.is_generic) { | ||
| 1734 | if (lookup.isMutable()) { | ||
| 1735 | const param_kind: Kind = switch (kind) { | ||
| 1736 | .forward, .forward_parameter => .forward_parameter, | ||
| 1737 | .complete, .parameter, .global => .parameter, | ||
| 1738 | .payload => unreachable, | ||
| 1739 | }; | ||
| 1740 | _ = try lookup.typeToIndex(Type.fromInterned(info.return_type), param_kind); | ||
| 1741 | for (info.param_types.get(ip)) |param_type| { | ||
| 1742 | if (!Type.fromInterned(param_type).hasRuntimeBitsIgnoreComptime(mod)) continue; | ||
| 1743 | _ = try lookup.typeToIndex(Type.fromInterned(param_type), param_kind); | ||
| 1744 | } | ||
| 1745 | } | ||
| 1746 | self.init(if (info.is_var_args) .varargs_function else .function); | ||
| 1747 | } else self.init(.void); | ||
| 1748 | }, | ||
| 1749 | } | ||
| 1750 | } | ||
| 1751 | }; | ||
| 1752 | |||
| 1753 | pub fn copy(self: CType, arena: Allocator) !CType { | ||
| 1754 | return self.copyContext(struct { | ||
| 1755 | arena: Allocator, | ||
| 1756 | pub fn copyIndex(_: @This(), idx: Index) Index { | ||
| 1757 | return idx; | ||
| 1758 | } | ||
| 1759 | }{ .arena = arena }); | ||
| 1760 | } | ||
| 1761 | |||
| 1762 | fn copyFields(ctx: anytype, old_fields: Payload.Fields.Data) !Payload.Fields.Data { | ||
| 1763 | const new_fields = try ctx.arena.alloc(Payload.Fields.Field, old_fields.len); | ||
| 1764 | for (new_fields, old_fields) |*new_field, old_field| { | ||
| 1765 | new_field.name = try ctx.arena.dupeZ(u8, mem.span(old_field.name)); | ||
| 1766 | new_field.type = ctx.copyIndex(old_field.type); | ||
| 1767 | new_field.alignas = old_field.alignas; | ||
| 1768 | } | ||
| 1769 | return new_fields; | ||
| 1770 | } | ||
| 1771 | |||
| 1772 | fn copyParams(ctx: anytype, old_param_types: []const Index) ![]const Index { | ||
| 1773 | const new_param_types = try ctx.arena.alloc(Index, old_param_types.len); | ||
| 1774 | for (new_param_types, old_param_types) |*new_param_type, old_param_type| | ||
| 1775 | new_param_type.* = ctx.copyIndex(old_param_type); | ||
| 1776 | return new_param_types; | ||
| 1777 | } | ||
| 1778 | |||
| 1779 | pub fn copyContext(self: CType, ctx: anytype) !CType { | ||
| 1780 | switch (self.tag()) { | ||
| 1781 | .void, | ||
| 1782 | .char, | ||
| 1783 | .@"signed char", | ||
| 1784 | .short, | ||
| 1785 | .int, | ||
| 1786 | .long, | ||
| 1787 | .@"long long", | ||
| 1788 | ._Bool, | ||
| 1789 | .@"unsigned char", | ||
| 1790 | .@"unsigned short", | ||
| 1791 | .@"unsigned int", | ||
| 1792 | .@"unsigned long", | ||
| 1793 | .@"unsigned long long", | ||
| 1794 | .float, | ||
| 1795 | .double, | ||
| 1796 | .@"long double", | ||
| 1797 | .bool, | ||
| 1798 | .size_t, | ||
| 1799 | .ptrdiff_t, | ||
| 1800 | .uint8_t, | ||
| 1801 | .int8_t, | ||
| 1802 | .uint16_t, | ||
| 1803 | .int16_t, | ||
| 1804 | .uint32_t, | ||
| 1805 | .int32_t, | ||
| 1806 | .uint64_t, | ||
| 1807 | .int64_t, | ||
| 1808 | .uintptr_t, | ||
| 1809 | .intptr_t, | ||
| 1810 | .zig_u128, | ||
| 1811 | .zig_i128, | ||
| 1812 | .zig_f16, | ||
| 1813 | .zig_f32, | ||
| 1814 | .zig_f64, | ||
| 1815 | .zig_f80, | ||
| 1816 | .zig_f128, | ||
| 1817 | .zig_c_longdouble, | ||
| 1818 | => return self, | ||
| 1819 | |||
| 1820 | .pointer, | ||
| 1821 | .pointer_const, | ||
| 1822 | .pointer_volatile, | ||
| 1823 | .pointer_const_volatile, | ||
| 1824 | => { | ||
| 1825 | const pl = self.cast(Payload.Child).?; | ||
| 1826 | const new_pl = try ctx.arena.create(Payload.Child); | ||
| 1827 | new_pl.* = .{ .base = .{ .tag = pl.base.tag }, .data = ctx.copyIndex(pl.data) }; | ||
| 1828 | return initPayload(new_pl); | ||
| 1829 | }, | ||
| 1830 | |||
| 1831 | .array, | ||
| 1832 | .vector, | ||
| 1833 | => { | ||
| 1834 | const pl = self.cast(Payload.Sequence).?; | ||
| 1835 | const new_pl = try ctx.arena.create(Payload.Sequence); | ||
| 1836 | new_pl.* = .{ | ||
| 1837 | .base = .{ .tag = pl.base.tag }, | ||
| 1838 | .data = .{ .len = pl.data.len, .elem_type = ctx.copyIndex(pl.data.elem_type) }, | ||
| 1839 | }; | ||
| 1840 | return initPayload(new_pl); | ||
| 1841 | }, | ||
| 1842 | |||
| 1843 | .fwd_anon_struct, | ||
| 1844 | .fwd_anon_union, | ||
| 1845 | => { | ||
| 1846 | const pl = self.cast(Payload.Fields).?; | ||
| 1847 | const new_pl = try ctx.arena.create(Payload.Fields); | ||
| 1848 | new_pl.* = .{ | ||
| 1849 | .base = .{ .tag = pl.base.tag }, | ||
| 1850 | .data = try copyFields(ctx, pl.data), | ||
| 1851 | }; | ||
| 1852 | return initPayload(new_pl); | ||
| 1853 | }, | ||
| 1854 | |||
| 1855 | .fwd_struct, | ||
| 1856 | .fwd_union, | ||
| 1857 | => { | ||
| 1858 | const pl = self.cast(Payload.FwdDecl).?; | ||
| 1859 | const new_pl = try ctx.arena.create(Payload.FwdDecl); | ||
| 1860 | new_pl.* = .{ .base = .{ .tag = pl.base.tag }, .data = pl.data }; | ||
| 1861 | return initPayload(new_pl); | ||
| 1862 | }, | ||
| 1863 | |||
| 1864 | .unnamed_struct, | ||
| 1865 | .unnamed_union, | ||
| 1866 | .packed_unnamed_struct, | ||
| 1867 | .packed_unnamed_union, | ||
| 1868 | => { | ||
| 1869 | const pl = self.cast(Payload.Unnamed).?; | ||
| 1870 | const new_pl = try ctx.arena.create(Payload.Unnamed); | ||
| 1871 | new_pl.* = .{ .base = .{ .tag = pl.base.tag }, .data = .{ | ||
| 1872 | .fields = try copyFields(ctx, pl.data.fields), | ||
| 1873 | .owner_decl = pl.data.owner_decl, | ||
| 1874 | .id = pl.data.id, | ||
| 1875 | } }; | ||
| 1876 | return initPayload(new_pl); | ||
| 1877 | }, | ||
| 1878 | |||
| 1879 | .anon_struct, | ||
| 1880 | .anon_union, | ||
| 1881 | .@"struct", | ||
| 1882 | .@"union", | ||
| 1883 | .packed_struct, | ||
| 1884 | .packed_union, | ||
| 1885 | => { | ||
| 1886 | const pl = self.cast(Payload.Aggregate).?; | ||
| 1887 | const new_pl = try ctx.arena.create(Payload.Aggregate); | ||
| 1888 | new_pl.* = .{ .base = .{ .tag = pl.base.tag }, .data = .{ | ||
| 1889 | .fields = try copyFields(ctx, pl.data.fields), | ||
| 1890 | .fwd_decl = ctx.copyIndex(pl.data.fwd_decl), | ||
| 1891 | } }; | ||
| 1892 | return initPayload(new_pl); | ||
| 1893 | }, | ||
| 1894 | |||
| 1895 | .function, | ||
| 1896 | .varargs_function, | ||
| 1897 | => { | ||
| 1898 | const pl = self.cast(Payload.Function).?; | ||
| 1899 | const new_pl = try ctx.arena.create(Payload.Function); | ||
| 1900 | new_pl.* = .{ .base = .{ .tag = pl.base.tag }, .data = .{ | ||
| 1901 | .return_type = ctx.copyIndex(pl.data.return_type), | ||
| 1902 | .param_types = try copyParams(ctx, pl.data.param_types), | ||
| 1903 | } }; | ||
| 1904 | return initPayload(new_pl); | ||
| 1905 | }, | ||
| 1906 | } | ||
| 1907 | } | ||
| 1908 | |||
| 1909 | fn createFromType(store: *Store.Promoted, ty: Type, mod: *Module, kind: Kind) !CType { | ||
| 1910 | var convert: Convert = undefined; | ||
| 1911 | try convert.initType(ty, kind, .{ .imm = .{ .set = &store.set, .mod = mod } }); | ||
| 1912 | return createFromConvert(store, ty, mod, kind, &convert); | ||
| 1913 | } | ||
| 1914 | |||
| 1915 | fn createFromConvert( | ||
| 1916 | store: *Store.Promoted, | ||
| 1917 | ty: Type, | ||
| 1918 | mod: *Module, | ||
| 1919 | kind: Kind, | ||
| 1920 | convert: Convert, | ||
| 1921 | ) !CType { | ||
| 1922 | const ip = &mod.intern_pool; | ||
| 1923 | const arena = store.arena.allocator(); | ||
| 1924 | switch (convert.value) { | ||
| 1925 | .cty => |c| return c.copy(arena), | ||
| 1926 | .tag => |t| switch (t) { | ||
| 1927 | .fwd_anon_struct, | ||
| 1928 | .fwd_anon_union, | ||
| 1929 | .unnamed_struct, | ||
| 1930 | .unnamed_union, | ||
| 1931 | .packed_unnamed_struct, | ||
| 1932 | .packed_unnamed_union, | ||
| 1933 | .anon_struct, | ||
| 1934 | .anon_union, | ||
| 1935 | .@"struct", | ||
| 1936 | .@"union", | ||
| 1937 | .packed_struct, | ||
| 1938 | .packed_union, | ||
| 1939 | => { | ||
| 1940 | const zig_ty_tag = ty.zigTypeTag(mod); | ||
| 1941 | const fields_len = switch (zig_ty_tag) { | ||
| 1942 | .Struct => ty.structFieldCount(mod), | ||
| 1943 | .Union => mod.typeToUnion(ty).?.field_types.len, | ||
| 1944 | else => unreachable, | ||
| 1945 | }; | ||
| 1946 | |||
| 1947 | var c_fields_len: usize = 0; | ||
| 1948 | for (0..fields_len) |field_i| { | ||
| 1949 | const field_ty = ty.structFieldType(field_i, mod); | ||
| 1950 | if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i, mod)) or | ||
| 1951 | !field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; | ||
| 1952 | c_fields_len += 1; | ||
| 1953 | } | ||
| 1954 | |||
| 1955 | const fields_pl = try arena.alloc(Payload.Fields.Field, c_fields_len); | ||
| 1956 | var c_field_i: usize = 0; | ||
| 1957 | for (0..fields_len) |field_i_usize| { | ||
| 1958 | const field_i: u32 = @intCast(field_i_usize); | ||
| 1959 | const field_ty = ty.structFieldType(field_i, mod); | ||
| 1960 | if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i, mod)) or | ||
| 1961 | !field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; | ||
| 1962 | |||
| 1963 | defer c_field_i += 1; | ||
| 1964 | fields_pl[c_field_i] = .{ | ||
| 1965 | .name = try if (ty.isSimpleTuple(mod)) | ||
| 1966 | std.fmt.allocPrintZ(arena, "f{}", .{field_i}) | ||
| 1967 | else | ||
| 1968 | arena.dupeZ(u8, ip.stringToSlice(switch (zig_ty_tag) { | ||
| 1969 | .Struct => ty.legacyStructFieldName(field_i, mod), | ||
| 1970 | .Union => ip.loadUnionType(ty.toIntern()).loadTagType(ip).names.get(ip)[field_i], | ||
| 1971 | else => unreachable, | ||
| 1972 | })), | ||
| 1973 | .type = store.set.typeToIndex(field_ty, mod, switch (kind) { | ||
| 1974 | .forward, .forward_parameter => .forward, | ||
| 1975 | .complete, .parameter, .payload => .complete, | ||
| 1976 | .global => .global, | ||
| 1977 | }).?, | ||
| 1978 | .alignas = AlignAs.fieldAlign(ty, field_i, mod), | ||
| 1979 | }; | ||
| 1980 | } | ||
| 1981 | |||
| 1982 | switch (t) { | ||
| 1983 | .fwd_anon_struct, | ||
| 1984 | .fwd_anon_union, | ||
| 1985 | => { | ||
| 1986 | const anon_pl = try arena.create(Payload.Fields); | ||
| 1987 | anon_pl.* = .{ .base = .{ .tag = t }, .data = fields_pl }; | ||
| 1988 | return initPayload(anon_pl); | ||
| 1989 | }, | ||
| 1990 | |||
| 1991 | .unnamed_struct, | ||
| 1992 | .unnamed_union, | ||
| 1993 | .packed_unnamed_struct, | ||
| 1994 | .packed_unnamed_union, | ||
| 1995 | => { | ||
| 1996 | const unnamed_pl = try arena.create(Payload.Unnamed); | ||
| 1997 | unnamed_pl.* = .{ .base = .{ .tag = t }, .data = .{ | ||
| 1998 | .fields = fields_pl, | ||
| 1999 | .owner_decl = ty.getOwnerDecl(mod), | ||
| 2000 | .id = if (ty.unionTagTypeSafety(mod)) |_| 0 else unreachable, | ||
| 2001 | } }; | ||
| 2002 | return initPayload(unnamed_pl); | ||
| 2003 | }, | ||
| 2004 | |||
| 2005 | .anon_struct, | ||
| 2006 | .anon_union, | ||
| 2007 | .@"struct", | ||
| 2008 | .@"union", | ||
| 2009 | .packed_struct, | ||
| 2010 | .packed_union, | ||
| 2011 | => { | ||
| 2012 | const struct_pl = try arena.create(Payload.Aggregate); | ||
| 2013 | struct_pl.* = .{ .base = .{ .tag = t }, .data = .{ | ||
| 2014 | .fields = fields_pl, | ||
| 2015 | .fwd_decl = store.set.typeToIndex(ty, mod, .forward).?, | ||
| 2016 | } }; | ||
| 2017 | return initPayload(struct_pl); | ||
| 2018 | }, | ||
| 2019 | |||
| 2020 | else => unreachable, | ||
| 2021 | } | ||
| 2022 | }, | ||
| 2023 | |||
| 2024 | .function, | ||
| 2025 | .varargs_function, | ||
| 2026 | => { | ||
| 2027 | const info = mod.typeToFunc(ty).?; | ||
| 2028 | assert(!info.is_generic); | ||
| 2029 | const param_kind: Kind = switch (kind) { | ||
| 2030 | .forward, .forward_parameter => .forward_parameter, | ||
| 2031 | .complete, .parameter, .global => .parameter, | ||
| 2032 | .payload => unreachable, | ||
| 2033 | }; | ||
| 2034 | |||
| 2035 | var c_params_len: usize = 0; | ||
| 2036 | for (info.param_types.get(ip)) |param_type| { | ||
| 2037 | if (!Type.fromInterned(param_type).hasRuntimeBitsIgnoreComptime(mod)) continue; | ||
| 2038 | c_params_len += 1; | ||
| 2039 | } | ||
| 2040 | |||
| 2041 | const params_pl = try arena.alloc(Index, c_params_len); | ||
| 2042 | var c_param_i: usize = 0; | ||
| 2043 | for (info.param_types.get(ip)) |param_type| { | ||
| 2044 | if (!Type.fromInterned(param_type).hasRuntimeBitsIgnoreComptime(mod)) continue; | ||
| 2045 | params_pl[c_param_i] = store.set.typeToIndex(Type.fromInterned(param_type), mod, param_kind).?; | ||
| 2046 | c_param_i += 1; | ||
| 2047 | } | ||
| 2048 | |||
| 2049 | const fn_pl = try arena.create(Payload.Function); | ||
| 2050 | fn_pl.* = .{ .base = .{ .tag = t }, .data = .{ | ||
| 2051 | .return_type = store.set.typeToIndex(Type.fromInterned(info.return_type), mod, param_kind).?, | ||
| 2052 | .param_types = params_pl, | ||
| 2053 | } }; | ||
| 2054 | return initPayload(fn_pl); | ||
| 2055 | }, | ||
| 2056 | |||
| 2057 | else => unreachable, | ||
| 2058 | }, | ||
| 2059 | } | ||
| 2060 | } | ||
| 2061 | |||
| 2062 | pub const TypeAdapter64 = struct { | ||
| 2063 | kind: Kind, | ||
| 2064 | lookup: Convert.Lookup, | ||
| 2065 | convert: *const Convert, | ||
| 2066 | |||
| 2067 | fn eqlRecurse(self: @This(), ty: Type, cty: Index, kind: Kind) bool { | ||
| 2068 | assert(!self.lookup.isMutable()); | ||
| 2069 | |||
| 2070 | var convert: Convert = undefined; | ||
| 2071 | convert.initType(ty, kind, self.lookup) catch unreachable; | ||
| 2072 | |||
| 2073 | const self_recurse = @This(){ .kind = kind, .lookup = self.lookup, .convert = &convert }; | ||
| 2074 | return self_recurse.eql(ty, self.lookup.indexToCType(cty).?); | ||
| 2075 | } | ||
| 2076 | |||
| 2077 | pub fn eql(self: @This(), ty: Type, cty: CType) bool { | ||
| 2078 | const mod = self.lookup.getModule(); | ||
| 2079 | const ip = &mod.intern_pool; | ||
| 2080 | switch (self.convert.value) { | ||
| 2081 | .cty => |c| return c.eql(cty), | ||
| 2082 | .tag => |t| { | ||
| 2083 | if (t != cty.tag()) return false; | ||
| 2084 | |||
| 2085 | switch (t) { | ||
| 2086 | .fwd_anon_struct, | ||
| 2087 | .fwd_anon_union, | ||
| 2088 | => { | ||
| 2089 | if (!ty.isTupleOrAnonStruct(mod)) return false; | ||
| 2090 | |||
| 2091 | var name_buf: [ | ||
| 2092 | std.fmt.count("f{}", .{std.math.maxInt(usize)}) | ||
| 2093 | ]u8 = undefined; | ||
| 2094 | const c_fields = cty.cast(Payload.Fields).?.data; | ||
| 2095 | |||
| 2096 | const zig_ty_tag = ty.zigTypeTag(mod); | ||
| 2097 | var c_field_i: usize = 0; | ||
| 2098 | for (0..switch (zig_ty_tag) { | ||
| 2099 | .Struct => ty.structFieldCount(mod), | ||
| 2100 | .Union => mod.typeToUnion(ty).?.field_types.len, | ||
| 2101 | else => unreachable, | ||
| 2102 | }) |field_i_usize| { | ||
| 2103 | const field_i: u32 = @intCast(field_i_usize); | ||
| 2104 | const field_ty = ty.structFieldType(field_i, mod); | ||
| 2105 | if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i, mod)) or | ||
| 2106 | !field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; | ||
| 2107 | |||
| 2108 | defer c_field_i += 1; | ||
| 2109 | const c_field = &c_fields[c_field_i]; | ||
| 2110 | |||
| 2111 | if (!self.eqlRecurse(field_ty, c_field.type, switch (self.kind) { | ||
| 2112 | .forward, .forward_parameter => .forward, | ||
| 2113 | .complete, .parameter => .complete, | ||
| 2114 | .global => .global, | ||
| 2115 | .payload => unreachable, | ||
| 2116 | }) or !mem.eql( | ||
| 2117 | u8, | ||
| 2118 | if (ty.isSimpleTuple(mod)) | ||
| 2119 | std.fmt.bufPrintZ(&name_buf, "f{}", .{field_i}) catch unreachable | ||
| 2120 | else | ||
| 2121 | ip.stringToSlice(switch (zig_ty_tag) { | ||
| 2122 | .Struct => ty.legacyStructFieldName(field_i, mod), | ||
| 2123 | .Union => ip.loadUnionType(ty.toIntern()).loadTagType(ip).names.get(ip)[field_i], | ||
| 2124 | else => unreachable, | ||
| 2125 | }), | ||
| 2126 | mem.span(c_field.name), | ||
| 2127 | ) or AlignAs.fieldAlign(ty, field_i, mod).@"align" != | ||
| 2128 | c_field.alignas.@"align") return false; | ||
| 2129 | } | ||
| 2130 | return true; | ||
| 2131 | }, | ||
| 2132 | |||
| 2133 | .unnamed_struct, | ||
| 2134 | .unnamed_union, | ||
| 2135 | .packed_unnamed_struct, | ||
| 2136 | .packed_unnamed_union, | ||
| 2137 | => switch (self.kind) { | ||
| 2138 | .forward, .forward_parameter, .complete, .parameter, .global => unreachable, | ||
| 2139 | .payload => if (ty.unionTagTypeSafety(mod)) |_| { | ||
| 2140 | const data = cty.cast(Payload.Unnamed).?.data; | ||
| 2141 | return ty.getOwnerDecl(mod) == data.owner_decl and data.id == 0; | ||
| 2142 | } else unreachable, | ||
| 2143 | }, | ||
| 2144 | |||
| 2145 | .anon_struct, | ||
| 2146 | .anon_union, | ||
| 2147 | .@"struct", | ||
| 2148 | .@"union", | ||
| 2149 | .packed_struct, | ||
| 2150 | .packed_union, | ||
| 2151 | => return self.eqlRecurse( | ||
| 2152 | ty, | ||
| 2153 | cty.cast(Payload.Aggregate).?.data.fwd_decl, | ||
| 2154 | .forward, | ||
| 2155 | ), | ||
| 2156 | |||
| 2157 | .function, | ||
| 2158 | .varargs_function, | ||
| 2159 | => { | ||
| 2160 | if (ty.zigTypeTag(mod) != .Fn) return false; | ||
| 2161 | |||
| 2162 | const info = mod.typeToFunc(ty).?; | ||
| 2163 | assert(!info.is_generic); | ||
| 2164 | const data = cty.cast(Payload.Function).?.data; | ||
| 2165 | const param_kind: Kind = switch (self.kind) { | ||
| 2166 | .forward, .forward_parameter => .forward_parameter, | ||
| 2167 | .complete, .parameter, .global => .parameter, | ||
| 2168 | .payload => unreachable, | ||
| 2169 | }; | ||
| 2170 | |||
| 2171 | if (!self.eqlRecurse(Type.fromInterned(info.return_type), data.return_type, param_kind)) | ||
| 2172 | return false; | ||
| 2173 | |||
| 2174 | var c_param_i: usize = 0; | ||
| 2175 | for (info.param_types.get(ip)) |param_type| { | ||
| 2176 | if (!Type.fromInterned(param_type).hasRuntimeBitsIgnoreComptime(mod)) continue; | ||
| 2177 | |||
| 2178 | if (c_param_i >= data.param_types.len) return false; | ||
| 2179 | const param_cty = data.param_types[c_param_i]; | ||
| 2180 | c_param_i += 1; | ||
| 2181 | |||
| 2182 | if (!self.eqlRecurse(Type.fromInterned(param_type), param_cty, param_kind)) | ||
| 2183 | return false; | ||
| 2184 | } | ||
| 2185 | return c_param_i == data.param_types.len; | ||
| 2186 | }, | ||
| 2187 | |||
| 2188 | else => unreachable, | ||
| 2189 | } | ||
| 2190 | }, | ||
| 2191 | } | ||
| 2192 | } | ||
| 2193 | |||
| 2194 | pub fn hash(self: @This(), ty: Type) u64 { | ||
| 2195 | var hasher = std.hash.Wyhash.init(0); | ||
| 2196 | self.updateHasher(&hasher, ty); | ||
| 2197 | return hasher.final(); | ||
| 2198 | } | ||
| 2199 | |||
| 2200 | fn updateHasherRecurse(self: @This(), hasher: anytype, ty: Type, kind: Kind) void { | ||
| 2201 | assert(!self.lookup.isMutable()); | ||
| 2202 | |||
| 2203 | var convert: Convert = undefined; | ||
| 2204 | convert.initType(ty, kind, self.lookup) catch unreachable; | ||
| 2205 | |||
| 2206 | const self_recurse = @This(){ .kind = kind, .lookup = self.lookup, .convert = &convert }; | ||
| 2207 | self_recurse.updateHasher(hasher, ty); | ||
| 2208 | } | ||
| 2209 | |||
| 2210 | pub fn updateHasher(self: @This(), hasher: anytype, ty: Type) void { | ||
| 2211 | switch (self.convert.value) { | ||
| 2212 | .cty => |c| return c.updateHasher(hasher, self.lookup.getSet().?.*), | ||
| 2213 | .tag => |t| { | ||
| 2214 | autoHash(hasher, t); | ||
| 2215 | |||
| 2216 | const mod = self.lookup.getModule(); | ||
| 2217 | const ip = &mod.intern_pool; | ||
| 2218 | switch (t) { | ||
| 2219 | .fwd_anon_struct, | ||
| 2220 | .fwd_anon_union, | ||
| 2221 | => { | ||
| 2222 | var name_buf: [ | ||
| 2223 | std.fmt.count("f{}", .{std.math.maxInt(usize)}) | ||
| 2224 | ]u8 = undefined; | ||
| 2225 | |||
| 2226 | const zig_ty_tag = ty.zigTypeTag(mod); | ||
| 2227 | for (0..switch (ty.zigTypeTag(mod)) { | ||
| 2228 | .Struct => ty.structFieldCount(mod), | ||
| 2229 | .Union => mod.typeToUnion(ty).?.field_types.len, | ||
| 2230 | else => unreachable, | ||
| 2231 | }) |field_i_usize| { | ||
| 2232 | const field_i: u32 = @intCast(field_i_usize); | ||
| 2233 | const field_ty = ty.structFieldType(field_i, mod); | ||
| 2234 | if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i, mod)) or | ||
| 2235 | !field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; | ||
| 2236 | |||
| 2237 | self.updateHasherRecurse(hasher, field_ty, switch (self.kind) { | ||
| 2238 | .forward, .forward_parameter => .forward, | ||
| 2239 | .complete, .parameter => .complete, | ||
| 2240 | .global => .global, | ||
| 2241 | .payload => unreachable, | ||
| 2242 | }); | ||
| 2243 | hasher.update(if (ty.isSimpleTuple(mod)) | ||
| 2244 | std.fmt.bufPrint(&name_buf, "f{}", .{field_i}) catch unreachable | ||
| 2245 | else | ||
| 2246 | mod.intern_pool.stringToSlice(switch (zig_ty_tag) { | ||
| 2247 | .Struct => ty.legacyStructFieldName(field_i, mod), | ||
| 2248 | .Union => ip.loadUnionType(ty.toIntern()).loadTagType(ip).names.get(ip)[field_i], | ||
| 2249 | else => unreachable, | ||
| 2250 | })); | ||
| 2251 | autoHash(hasher, AlignAs.fieldAlign(ty, field_i, mod).@"align"); | ||
| 2252 | } | ||
| 2253 | }, | ||
| 2254 | |||
| 2255 | .unnamed_struct, | ||
| 2256 | .unnamed_union, | ||
| 2257 | .packed_unnamed_struct, | ||
| 2258 | .packed_unnamed_union, | ||
| 2259 | => switch (self.kind) { | ||
| 2260 | .forward, .forward_parameter, .complete, .parameter, .global => unreachable, | ||
| 2261 | .payload => if (ty.unionTagTypeSafety(mod)) |_| { | ||
| 2262 | autoHash(hasher, ty.getOwnerDecl(mod)); | ||
| 2263 | autoHash(hasher, @as(u32, 0)); | ||
| 2264 | } else unreachable, | ||
| 2265 | }, | ||
| 2266 | |||
| 2267 | .anon_struct, | ||
| 2268 | .anon_union, | ||
| 2269 | .@"struct", | ||
| 2270 | .@"union", | ||
| 2271 | .packed_struct, | ||
| 2272 | .packed_union, | ||
| 2273 | => self.updateHasherRecurse(hasher, ty, .forward), | ||
| 2274 | |||
| 2275 | .function, | ||
| 2276 | .varargs_function, | ||
| 2277 | => { | ||
| 2278 | const info = mod.typeToFunc(ty).?; | ||
| 2279 | assert(!info.is_generic); | ||
| 2280 | const param_kind: Kind = switch (self.kind) { | ||
| 2281 | .forward, .forward_parameter => .forward_parameter, | ||
| 2282 | .complete, .parameter, .global => .parameter, | ||
| 2283 | .payload => unreachable, | ||
| 2284 | }; | ||
| 2285 | |||
| 2286 | self.updateHasherRecurse(hasher, Type.fromInterned(info.return_type), param_kind); | ||
| 2287 | for (info.param_types.get(ip)) |param_type| { | ||
| 2288 | if (!Type.fromInterned(param_type).hasRuntimeBitsIgnoreComptime(mod)) continue; | ||
| 2289 | self.updateHasherRecurse(hasher, Type.fromInterned(param_type), param_kind); | ||
| 2290 | } | ||
| 2291 | }, | ||
| 2292 | |||
| 2293 | else => unreachable, | ||
| 2294 | } | ||
| 2295 | }, | ||
| 2296 | } | ||
| 2297 | } | ||
| 2298 | }; | ||
| 2299 | |||
| 2300 | pub const TypeAdapter32 = struct { | ||
| 2301 | kind: Kind, | ||
| 2302 | lookup: Convert.Lookup, | ||
| 2303 | convert: *const Convert, | ||
| 2304 | |||
| 2305 | fn to64(self: @This()) TypeAdapter64 { | ||
| 2306 | return .{ .kind = self.kind, .lookup = self.lookup, .convert = self.convert }; | ||
| 2307 | } | ||
| 2308 | |||
| 2309 | pub fn eql(self: @This(), ty: Type, cty: CType, cty_index: usize) bool { | ||
| 2310 | _ = cty_index; | ||
| 2311 | return self.to64().eql(ty, cty); | ||
| 2312 | } | ||
| 2313 | |||
| 2314 | pub fn hash(self: @This(), ty: Type) u32 { | ||
| 2315 | return @as(u32, @truncate(self.to64().hash(ty))); | ||
| 2316 | } | ||
| 2317 | }; | ||
| 2318 | }; | ||
src/codegen/llvm.zig+24-24| ... | @@ -2033,7 +2033,7 @@ pub const Object = struct { | ... | @@ -2033,7 +2033,7 @@ pub const Object = struct { |
| 2033 | owner_decl.src_node + 1, // Line | 2033 | owner_decl.src_node + 1, // Line |
| 2034 | try o.lowerDebugType(int_ty), | 2034 | try o.lowerDebugType(int_ty), |
| 2035 | ty.abiSize(mod) * 8, | 2035 | ty.abiSize(mod) * 8, |
| 2036 | ty.abiAlignment(mod).toByteUnits(0) * 8, | 2036 | (ty.abiAlignment(mod).toByteUnits() orelse 0) * 8, |
| 2037 | try o.builder.debugTuple(enumerators), | 2037 | try o.builder.debugTuple(enumerators), |
| 2038 | ); | 2038 | ); |
| 2039 | 2039 | ||
| ... | @@ -2120,7 +2120,7 @@ pub const Object = struct { | ... | @@ -2120,7 +2120,7 @@ pub const Object = struct { |
| 2120 | 0, // Line | 2120 | 0, // Line |
| 2121 | try o.lowerDebugType(ptr_ty), | 2121 | try o.lowerDebugType(ptr_ty), |
| 2122 | ptr_size * 8, | 2122 | ptr_size * 8, |
| 2123 | ptr_align.toByteUnits(0) * 8, | 2123 | (ptr_align.toByteUnits() orelse 0) * 8, |
| 2124 | 0, // Offset | 2124 | 0, // Offset |
| 2125 | ); | 2125 | ); |
| 2126 | 2126 | ||
| ... | @@ -2131,7 +2131,7 @@ pub const Object = struct { | ... | @@ -2131,7 +2131,7 @@ pub const Object = struct { |
| 2131 | 0, // Line | 2131 | 0, // Line |
| 2132 | try o.lowerDebugType(len_ty), | 2132 | try o.lowerDebugType(len_ty), |
| 2133 | len_size * 8, | 2133 | len_size * 8, |
| 2134 | len_align.toByteUnits(0) * 8, | 2134 | (len_align.toByteUnits() orelse 0) * 8, |
| 2135 | len_offset * 8, | 2135 | len_offset * 8, |
| 2136 | ); | 2136 | ); |
| 2137 | 2137 | ||
| ... | @@ -2142,7 +2142,7 @@ pub const Object = struct { | ... | @@ -2142,7 +2142,7 @@ pub const Object = struct { |
| 2142 | line, | 2142 | line, |
| 2143 | .none, // Underlying type | 2143 | .none, // Underlying type |
| 2144 | ty.abiSize(mod) * 8, | 2144 | ty.abiSize(mod) * 8, |
| 2145 | ty.abiAlignment(mod).toByteUnits(0) * 8, | 2145 | (ty.abiAlignment(mod).toByteUnits() orelse 0) * 8, |
| 2146 | try o.builder.debugTuple(&.{ | 2146 | try o.builder.debugTuple(&.{ |
| 2147 | debug_ptr_type, | 2147 | debug_ptr_type, |
| 2148 | debug_len_type, | 2148 | debug_len_type, |
| ... | @@ -2170,7 +2170,7 @@ pub const Object = struct { | ... | @@ -2170,7 +2170,7 @@ pub const Object = struct { |
| 2170 | 0, // Line | 2170 | 0, // Line |
| 2171 | debug_elem_ty, | 2171 | debug_elem_ty, |
| 2172 | target.ptrBitWidth(), | 2172 | target.ptrBitWidth(), |
| 2173 | ty.ptrAlignment(mod).toByteUnits(0) * 8, | 2173 | (ty.ptrAlignment(mod).toByteUnits() orelse 0) * 8, |
| 2174 | 0, // Offset | 2174 | 0, // Offset |
| 2175 | ); | 2175 | ); |
| 2176 | 2176 | ||
| ... | @@ -2217,7 +2217,7 @@ pub const Object = struct { | ... | @@ -2217,7 +2217,7 @@ pub const Object = struct { |
| 2217 | 0, // Line | 2217 | 0, // Line |
| 2218 | try o.lowerDebugType(ty.childType(mod)), | 2218 | try o.lowerDebugType(ty.childType(mod)), |
| 2219 | ty.abiSize(mod) * 8, | 2219 | ty.abiSize(mod) * 8, |
| 2220 | ty.abiAlignment(mod).toByteUnits(0) * 8, | 2220 | (ty.abiAlignment(mod).toByteUnits() orelse 0) * 8, |
| 2221 | try o.builder.debugTuple(&.{ | 2221 | try o.builder.debugTuple(&.{ |
| 2222 | try o.builder.debugSubrange( | 2222 | try o.builder.debugSubrange( |
| 2223 | try o.builder.debugConstant(try o.builder.intConst(.i64, 0)), | 2223 | try o.builder.debugConstant(try o.builder.intConst(.i64, 0)), |
| ... | @@ -2260,7 +2260,7 @@ pub const Object = struct { | ... | @@ -2260,7 +2260,7 @@ pub const Object = struct { |
| 2260 | 0, // Line | 2260 | 0, // Line |
| 2261 | debug_elem_type, | 2261 | debug_elem_type, |
| 2262 | ty.abiSize(mod) * 8, | 2262 | ty.abiSize(mod) * 8, |
| 2263 | ty.abiAlignment(mod).toByteUnits(0) * 8, | 2263 | (ty.abiAlignment(mod).toByteUnits() orelse 0) * 8, |
| 2264 | try o.builder.debugTuple(&.{ | 2264 | try o.builder.debugTuple(&.{ |
| 2265 | try o.builder.debugSubrange( | 2265 | try o.builder.debugSubrange( |
| 2266 | try o.builder.debugConstant(try o.builder.intConst(.i64, 0)), | 2266 | try o.builder.debugConstant(try o.builder.intConst(.i64, 0)), |
| ... | @@ -2316,7 +2316,7 @@ pub const Object = struct { | ... | @@ -2316,7 +2316,7 @@ pub const Object = struct { |
| 2316 | 0, // Line | 2316 | 0, // Line |
| 2317 | try o.lowerDebugType(child_ty), | 2317 | try o.lowerDebugType(child_ty), |
| 2318 | payload_size * 8, | 2318 | payload_size * 8, |
| 2319 | payload_align.toByteUnits(0) * 8, | 2319 | (payload_align.toByteUnits() orelse 0) * 8, |
| 2320 | 0, // Offset | 2320 | 0, // Offset |
| 2321 | ); | 2321 | ); |
| 2322 | 2322 | ||
| ... | @@ -2327,7 +2327,7 @@ pub const Object = struct { | ... | @@ -2327,7 +2327,7 @@ pub const Object = struct { |
| 2327 | 0, | 2327 | 0, |
| 2328 | try o.lowerDebugType(non_null_ty), | 2328 | try o.lowerDebugType(non_null_ty), |
| 2329 | non_null_size * 8, | 2329 | non_null_size * 8, |
| 2330 | non_null_align.toByteUnits(0) * 8, | 2330 | (non_null_align.toByteUnits() orelse 0) * 8, |
| 2331 | non_null_offset * 8, | 2331 | non_null_offset * 8, |
| 2332 | ); | 2332 | ); |
| 2333 | 2333 | ||
| ... | @@ -2338,7 +2338,7 @@ pub const Object = struct { | ... | @@ -2338,7 +2338,7 @@ pub const Object = struct { |
| 2338 | 0, // Line | 2338 | 0, // Line |
| 2339 | .none, // Underlying type | 2339 | .none, // Underlying type |
| 2340 | ty.abiSize(mod) * 8, | 2340 | ty.abiSize(mod) * 8, |
| 2341 | ty.abiAlignment(mod).toByteUnits(0) * 8, | 2341 | (ty.abiAlignment(mod).toByteUnits() orelse 0) * 8, |
| 2342 | try o.builder.debugTuple(&.{ | 2342 | try o.builder.debugTuple(&.{ |
| 2343 | debug_data_type, | 2343 | debug_data_type, |
| 2344 | debug_some_type, | 2344 | debug_some_type, |
| ... | @@ -2396,7 +2396,7 @@ pub const Object = struct { | ... | @@ -2396,7 +2396,7 @@ pub const Object = struct { |
| 2396 | 0, // Line | 2396 | 0, // Line |
| 2397 | try o.lowerDebugType(Type.anyerror), | 2397 | try o.lowerDebugType(Type.anyerror), |
| 2398 | error_size * 8, | 2398 | error_size * 8, |
| 2399 | error_align.toByteUnits(0) * 8, | 2399 | (error_align.toByteUnits() orelse 0) * 8, |
| 2400 | error_offset * 8, | 2400 | error_offset * 8, |
| 2401 | ); | 2401 | ); |
| 2402 | fields[payload_index] = try o.builder.debugMemberType( | 2402 | fields[payload_index] = try o.builder.debugMemberType( |
| ... | @@ -2406,7 +2406,7 @@ pub const Object = struct { | ... | @@ -2406,7 +2406,7 @@ pub const Object = struct { |
| 2406 | 0, // Line | 2406 | 0, // Line |
| 2407 | try o.lowerDebugType(payload_ty), | 2407 | try o.lowerDebugType(payload_ty), |
| 2408 | payload_size * 8, | 2408 | payload_size * 8, |
| 2409 | payload_align.toByteUnits(0) * 8, | 2409 | (payload_align.toByteUnits() orelse 0) * 8, |
| 2410 | payload_offset * 8, | 2410 | payload_offset * 8, |
| 2411 | ); | 2411 | ); |
| 2412 | 2412 | ||
| ... | @@ -2417,7 +2417,7 @@ pub const Object = struct { | ... | @@ -2417,7 +2417,7 @@ pub const Object = struct { |
| 2417 | 0, // Line | 2417 | 0, // Line |
| 2418 | .none, // Underlying type | 2418 | .none, // Underlying type |
| 2419 | ty.abiSize(mod) * 8, | 2419 | ty.abiSize(mod) * 8, |
| 2420 | ty.abiAlignment(mod).toByteUnits(0) * 8, | 2420 | (ty.abiAlignment(mod).toByteUnits() orelse 0) * 8, |
| 2421 | try o.builder.debugTuple(&fields), | 2421 | try o.builder.debugTuple(&fields), |
| 2422 | ); | 2422 | ); |
| 2423 | 2423 | ||
| ... | @@ -2485,7 +2485,7 @@ pub const Object = struct { | ... | @@ -2485,7 +2485,7 @@ pub const Object = struct { |
| 2485 | 0, | 2485 | 0, |
| 2486 | try o.lowerDebugType(Type.fromInterned(field_ty)), | 2486 | try o.lowerDebugType(Type.fromInterned(field_ty)), |
| 2487 | field_size * 8, | 2487 | field_size * 8, |
| 2488 | field_align.toByteUnits(0) * 8, | 2488 | (field_align.toByteUnits() orelse 0) * 8, |
| 2489 | field_offset * 8, | 2489 | field_offset * 8, |
| 2490 | )); | 2490 | )); |
| 2491 | } | 2491 | } |
| ... | @@ -2497,7 +2497,7 @@ pub const Object = struct { | ... | @@ -2497,7 +2497,7 @@ pub const Object = struct { |
| 2497 | 0, // Line | 2497 | 0, // Line |
| 2498 | .none, // Underlying type | 2498 | .none, // Underlying type |
| 2499 | ty.abiSize(mod) * 8, | 2499 | ty.abiSize(mod) * 8, |
| 2500 | ty.abiAlignment(mod).toByteUnits(0) * 8, | 2500 | (ty.abiAlignment(mod).toByteUnits() orelse 0) * 8, |
| 2501 | try o.builder.debugTuple(fields.items), | 2501 | try o.builder.debugTuple(fields.items), |
| 2502 | ); | 2502 | ); |
| 2503 | 2503 | ||
| ... | @@ -2566,7 +2566,7 @@ pub const Object = struct { | ... | @@ -2566,7 +2566,7 @@ pub const Object = struct { |
| 2566 | 0, // Line | 2566 | 0, // Line |
| 2567 | try o.lowerDebugType(field_ty), | 2567 | try o.lowerDebugType(field_ty), |
| 2568 | field_size * 8, | 2568 | field_size * 8, |
| 2569 | field_align.toByteUnits(0) * 8, | 2569 | (field_align.toByteUnits() orelse 0) * 8, |
| 2570 | field_offset * 8, | 2570 | field_offset * 8, |
| 2571 | )); | 2571 | )); |
| 2572 | } | 2572 | } |
| ... | @@ -2578,7 +2578,7 @@ pub const Object = struct { | ... | @@ -2578,7 +2578,7 @@ pub const Object = struct { |
| 2578 | 0, // Line | 2578 | 0, // Line |
| 2579 | .none, // Underlying type | 2579 | .none, // Underlying type |
| 2580 | ty.abiSize(mod) * 8, | 2580 | ty.abiSize(mod) * 8, |
| 2581 | ty.abiAlignment(mod).toByteUnits(0) * 8, | 2581 | (ty.abiAlignment(mod).toByteUnits() orelse 0) * 8, |
| 2582 | try o.builder.debugTuple(fields.items), | 2582 | try o.builder.debugTuple(fields.items), |
| 2583 | ); | 2583 | ); |
| 2584 | 2584 | ||
| ... | @@ -2621,7 +2621,7 @@ pub const Object = struct { | ... | @@ -2621,7 +2621,7 @@ pub const Object = struct { |
| 2621 | 0, // Line | 2621 | 0, // Line |
| 2622 | .none, // Underlying type | 2622 | .none, // Underlying type |
| 2623 | ty.abiSize(mod) * 8, | 2623 | ty.abiSize(mod) * 8, |
| 2624 | ty.abiAlignment(mod).toByteUnits(0) * 8, | 2624 | (ty.abiAlignment(mod).toByteUnits() orelse 0) * 8, |
| 2625 | try o.builder.debugTuple( | 2625 | try o.builder.debugTuple( |
| 2626 | &.{try o.lowerDebugType(Type.fromInterned(union_type.enum_tag_ty))}, | 2626 | &.{try o.lowerDebugType(Type.fromInterned(union_type.enum_tag_ty))}, |
| 2627 | ), | 2627 | ), |
| ... | @@ -2661,7 +2661,7 @@ pub const Object = struct { | ... | @@ -2661,7 +2661,7 @@ pub const Object = struct { |
| 2661 | 0, // Line | 2661 | 0, // Line |
| 2662 | try o.lowerDebugType(Type.fromInterned(field_ty)), | 2662 | try o.lowerDebugType(Type.fromInterned(field_ty)), |
| 2663 | field_size * 8, | 2663 | field_size * 8, |
| 2664 | field_align.toByteUnits(0) * 8, | 2664 | (field_align.toByteUnits() orelse 0) * 8, |
| 2665 | 0, // Offset | 2665 | 0, // Offset |
| 2666 | )); | 2666 | )); |
| 2667 | } | 2667 | } |
| ... | @@ -2680,7 +2680,7 @@ pub const Object = struct { | ... | @@ -2680,7 +2680,7 @@ pub const Object = struct { |
| 2680 | 0, // Line | 2680 | 0, // Line |
| 2681 | .none, // Underlying type | 2681 | .none, // Underlying type |
| 2682 | ty.abiSize(mod) * 8, | 2682 | ty.abiSize(mod) * 8, |
| 2683 | ty.abiAlignment(mod).toByteUnits(0) * 8, | 2683 | (ty.abiAlignment(mod).toByteUnits() orelse 0) * 8, |
| 2684 | try o.builder.debugTuple(fields.items), | 2684 | try o.builder.debugTuple(fields.items), |
| 2685 | ); | 2685 | ); |
| 2686 | 2686 | ||
| ... | @@ -2711,7 +2711,7 @@ pub const Object = struct { | ... | @@ -2711,7 +2711,7 @@ pub const Object = struct { |
| 2711 | 0, // Line | 2711 | 0, // Line |
| 2712 | try o.lowerDebugType(Type.fromInterned(union_type.enum_tag_ty)), | 2712 | try o.lowerDebugType(Type.fromInterned(union_type.enum_tag_ty)), |
| 2713 | layout.tag_size * 8, | 2713 | layout.tag_size * 8, |
| 2714 | layout.tag_align.toByteUnits(0) * 8, | 2714 | (layout.tag_align.toByteUnits() orelse 0) * 8, |
| 2715 | tag_offset * 8, | 2715 | tag_offset * 8, |
| 2716 | ); | 2716 | ); |
| 2717 | 2717 | ||
| ... | @@ -2722,7 +2722,7 @@ pub const Object = struct { | ... | @@ -2722,7 +2722,7 @@ pub const Object = struct { |
| 2722 | 0, // Line | 2722 | 0, // Line |
| 2723 | debug_union_type, | 2723 | debug_union_type, |
| 2724 | layout.payload_size * 8, | 2724 | layout.payload_size * 8, |
| 2725 | layout.payload_align.toByteUnits(0) * 8, | 2725 | (layout.payload_align.toByteUnits() orelse 0) * 8, |
| 2726 | payload_offset * 8, | 2726 | payload_offset * 8, |
| 2727 | ); | 2727 | ); |
| 2728 | 2728 | ||
| ... | @@ -2739,7 +2739,7 @@ pub const Object = struct { | ... | @@ -2739,7 +2739,7 @@ pub const Object = struct { |
| 2739 | 0, // Line | 2739 | 0, // Line |
| 2740 | .none, // Underlying type | 2740 | .none, // Underlying type |
| 2741 | ty.abiSize(mod) * 8, | 2741 | ty.abiSize(mod) * 8, |
| 2742 | ty.abiAlignment(mod).toByteUnits(0) * 8, | 2742 | (ty.abiAlignment(mod).toByteUnits() orelse 0) * 8, |
| 2743 | try o.builder.debugTuple(&full_fields), | 2743 | try o.builder.debugTuple(&full_fields), |
| 2744 | ); | 2744 | ); |
| 2745 | 2745 | ||
| ... | @@ -4473,7 +4473,7 @@ pub const Object = struct { | ... | @@ -4473,7 +4473,7 @@ pub const Object = struct { |
| 4473 | // The value cannot be undefined, because we use the `nonnull` annotation | 4473 | // The value cannot be undefined, because we use the `nonnull` annotation |
| 4474 | // for non-optional pointers. We also need to respect the alignment, even though | 4474 | // for non-optional pointers. We also need to respect the alignment, even though |
| 4475 | // the address will never be dereferenced. | 4475 | // the address will never be dereferenced. |
| 4476 | const int: u64 = ptr_ty.ptrInfo(mod).flags.alignment.toByteUnitsOptional() orelse | 4476 | const int: u64 = ptr_ty.ptrInfo(mod).flags.alignment.toByteUnits() orelse |
| 4477 | // Note that these 0xaa values are appropriate even in release-optimized builds | 4477 | // Note that these 0xaa values are appropriate even in release-optimized builds |
| 4478 | // because we need a well-defined value that is not null, and LLVM does not | 4478 | // because we need a well-defined value that is not null, and LLVM does not |
| 4479 | // have an "undef_but_not_null" attribute. As an example, if this `alloc` AIR | 4479 | // have an "undef_but_not_null" attribute. As an example, if this `alloc` AIR |
src/crash_report.zig+1-1| ... | @@ -172,7 +172,7 @@ pub fn attachSegfaultHandler() void { | ... | @@ -172,7 +172,7 @@ pub fn attachSegfaultHandler() void { |
| 172 | }; | 172 | }; |
| 173 | } | 173 | } |
| 174 | 174 | ||
| 175 | fn handleSegfaultPosix(sig: i32, info: *const posix.siginfo_t, ctx_ptr: ?*const anyopaque) callconv(.C) noreturn { | 175 | fn handleSegfaultPosix(sig: i32, info: *const posix.siginfo_t, ctx_ptr: ?*anyopaque) callconv(.C) noreturn { |
| 176 | // TODO: use alarm() here to prevent infinite loops | 176 | // TODO: use alarm() here to prevent infinite loops |
| 177 | PanicSwitch.preDispatch(); | 177 | PanicSwitch.preDispatch(); |
| 178 | 178 |
src/link.zig+31-64| ... | @@ -188,15 +188,10 @@ pub const File = struct { | ... | @@ -188,15 +188,10 @@ pub const File = struct { |
| 188 | emit: Compilation.Emit, | 188 | emit: Compilation.Emit, |
| 189 | options: OpenOptions, | 189 | options: OpenOptions, |
| 190 | ) !*File { | 190 | ) !*File { |
| 191 | const tag = Tag.fromObjectFormat(comp.root_mod.resolved_target.result.ofmt); | 191 | switch (Tag.fromObjectFormat(comp.root_mod.resolved_target.result.ofmt)) { |
| 192 | switch (tag) { | 192 | inline else => |tag| { |
| 193 | .c => { | 193 | if (tag != .c and build_options.only_c) unreachable; |
| 194 | const ptr = try C.open(arena, comp, emit, options); | 194 | const ptr = try tag.Type().open(arena, comp, emit, options); |
| 195 | return &ptr.base; | ||
| 196 | }, | ||
| 197 | inline else => |t| { | ||
| 198 | if (build_options.only_c) unreachable; | ||
| 199 | const ptr = try t.Type().open(arena, comp, emit, options); | ||
| 200 | return &ptr.base; | 195 | return &ptr.base; |
| 201 | }, | 196 | }, |
| 202 | } | 197 | } |
| ... | @@ -208,25 +203,17 @@ pub const File = struct { | ... | @@ -208,25 +203,17 @@ pub const File = struct { |
| 208 | emit: Compilation.Emit, | 203 | emit: Compilation.Emit, |
| 209 | options: OpenOptions, | 204 | options: OpenOptions, |
| 210 | ) !*File { | 205 | ) !*File { |
| 211 | const tag = Tag.fromObjectFormat(comp.root_mod.resolved_target.result.ofmt); | 206 | switch (Tag.fromObjectFormat(comp.root_mod.resolved_target.result.ofmt)) { |
| 212 | switch (tag) { | 207 | inline else => |tag| { |
| 213 | .c => { | 208 | if (tag != .c and build_options.only_c) unreachable; |
| 214 | const ptr = try C.createEmpty(arena, comp, emit, options); | 209 | const ptr = try tag.Type().createEmpty(arena, comp, emit, options); |
| 215 | return &ptr.base; | ||
| 216 | }, | ||
| 217 | inline else => |t| { | ||
| 218 | if (build_options.only_c) unreachable; | ||
| 219 | const ptr = try t.Type().createEmpty(arena, comp, emit, options); | ||
| 220 | return &ptr.base; | 210 | return &ptr.base; |
| 221 | }, | 211 | }, |
| 222 | } | 212 | } |
| 223 | } | 213 | } |
| 224 | 214 | ||
| 225 | pub fn cast(base: *File, comptime T: type) ?*T { | 215 | pub fn cast(base: *File, comptime T: type) ?*T { |
| 226 | if (base.tag != T.base_tag) | 216 | return if (base.tag == T.base_tag) @fieldParentPtr("base", base) else null; |
| 227 | return null; | ||
| 228 | |||
| 229 | return @fieldParentPtr(T, "base", base); | ||
| 230 | } | 217 | } |
| 231 | 218 | ||
| 232 | pub fn makeWritable(base: *File) !void { | 219 | pub fn makeWritable(base: *File) !void { |
| ... | @@ -383,7 +370,7 @@ pub const File = struct { | ... | @@ -383,7 +370,7 @@ pub const File = struct { |
| 383 | .c => unreachable, | 370 | .c => unreachable, |
| 384 | .nvptx => unreachable, | 371 | .nvptx => unreachable, |
| 385 | inline else => |t| { | 372 | inline else => |t| { |
| 386 | return @fieldParentPtr(t.Type(), "base", base).lowerUnnamedConst(val, decl_index); | 373 | return @as(*t.Type(), @fieldParentPtr("base", base)).lowerUnnamedConst(val, decl_index); |
| 387 | }, | 374 | }, |
| 388 | } | 375 | } |
| 389 | } | 376 | } |
| ... | @@ -402,7 +389,7 @@ pub const File = struct { | ... | @@ -402,7 +389,7 @@ pub const File = struct { |
| 402 | .c => unreachable, | 389 | .c => unreachable, |
| 403 | .nvptx => unreachable, | 390 | .nvptx => unreachable, |
| 404 | inline else => |t| { | 391 | inline else => |t| { |
| 405 | return @fieldParentPtr(t.Type(), "base", base).getGlobalSymbol(name, lib_name); | 392 | return @as(*t.Type(), @fieldParentPtr("base", base)).getGlobalSymbol(name, lib_name); |
| 406 | }, | 393 | }, |
| 407 | } | 394 | } |
| 408 | } | 395 | } |
| ... | @@ -412,12 +399,9 @@ pub const File = struct { | ... | @@ -412,12 +399,9 @@ pub const File = struct { |
| 412 | const decl = module.declPtr(decl_index); | 399 | const decl = module.declPtr(decl_index); |
| 413 | assert(decl.has_tv); | 400 | assert(decl.has_tv); |
| 414 | switch (base.tag) { | 401 | switch (base.tag) { |
| 415 | .c => { | ||
| 416 | return @fieldParentPtr(C, "base", base).updateDecl(module, decl_index); | ||
| 417 | }, | ||
| 418 | inline else => |tag| { | 402 | inline else => |tag| { |
| 419 | if (build_options.only_c) unreachable; | 403 | if (tag != .c and build_options.only_c) unreachable; |
| 420 | return @fieldParentPtr(tag.Type(), "base", base).updateDecl(module, decl_index); | 404 | return @as(*tag.Type(), @fieldParentPtr("base", base)).updateDecl(module, decl_index); |
| 421 | }, | 405 | }, |
| 422 | } | 406 | } |
| 423 | } | 407 | } |
| ... | @@ -431,12 +415,9 @@ pub const File = struct { | ... | @@ -431,12 +415,9 @@ pub const File = struct { |
| 431 | liveness: Liveness, | 415 | liveness: Liveness, |
| 432 | ) UpdateDeclError!void { | 416 | ) UpdateDeclError!void { |
| 433 | switch (base.tag) { | 417 | switch (base.tag) { |
| 434 | .c => { | ||
| 435 | return @fieldParentPtr(C, "base", base).updateFunc(module, func_index, air, liveness); | ||
| 436 | }, | ||
| 437 | inline else => |tag| { | 418 | inline else => |tag| { |
| 438 | if (build_options.only_c) unreachable; | 419 | if (tag != .c and build_options.only_c) unreachable; |
| 439 | return @fieldParentPtr(tag.Type(), "base", base).updateFunc(module, func_index, air, liveness); | 420 | return @as(*tag.Type(), @fieldParentPtr("base", base)).updateFunc(module, func_index, air, liveness); |
| 440 | }, | 421 | }, |
| 441 | } | 422 | } |
| 442 | } | 423 | } |
| ... | @@ -446,12 +427,9 @@ pub const File = struct { | ... | @@ -446,12 +427,9 @@ pub const File = struct { |
| 446 | assert(decl.has_tv); | 427 | assert(decl.has_tv); |
| 447 | switch (base.tag) { | 428 | switch (base.tag) { |
| 448 | .spirv, .nvptx => {}, | 429 | .spirv, .nvptx => {}, |
| 449 | .c => { | ||
| 450 | return @fieldParentPtr(C, "base", base).updateDeclLineNumber(module, decl_index); | ||
| 451 | }, | ||
| 452 | inline else => |tag| { | 430 | inline else => |tag| { |
| 453 | if (build_options.only_c) unreachable; | 431 | if (tag != .c and build_options.only_c) unreachable; |
| 454 | return @fieldParentPtr(tag.Type(), "base", base).updateDeclLineNumber(module, decl_index); | 432 | return @as(*tag.Type(), @fieldParentPtr("base", base)).updateDeclLineNumber(module, decl_index); |
| 455 | }, | 433 | }, |
| 456 | } | 434 | } |
| 457 | } | 435 | } |
| ... | @@ -473,11 +451,9 @@ pub const File = struct { | ... | @@ -473,11 +451,9 @@ pub const File = struct { |
| 473 | base.releaseLock(); | 451 | base.releaseLock(); |
| 474 | if (base.file) |f| f.close(); | 452 | if (base.file) |f| f.close(); |
| 475 | switch (base.tag) { | 453 | switch (base.tag) { |
| 476 | .c => @fieldParentPtr(C, "base", base).deinit(), | ||
| 477 | |||
| 478 | inline else => |tag| { | 454 | inline else => |tag| { |
| 479 | if (build_options.only_c) unreachable; | 455 | if (tag != .c and build_options.only_c) unreachable; |
| 480 | @fieldParentPtr(tag.Type(), "base", base).deinit(); | 456 | @as(*tag.Type(), @fieldParentPtr("base", base)).deinit(); |
| 481 | }, | 457 | }, |
| 482 | } | 458 | } |
| 483 | } | 459 | } |
| ... | @@ -560,7 +536,7 @@ pub const File = struct { | ... | @@ -560,7 +536,7 @@ pub const File = struct { |
| 560 | pub fn flush(base: *File, arena: Allocator, prog_node: *std.Progress.Node) FlushError!void { | 536 | pub fn flush(base: *File, arena: Allocator, prog_node: *std.Progress.Node) FlushError!void { |
| 561 | if (build_options.only_c) { | 537 | if (build_options.only_c) { |
| 562 | assert(base.tag == .c); | 538 | assert(base.tag == .c); |
| 563 | return @fieldParentPtr(C, "base", base).flush(arena, prog_node); | 539 | return @as(*C, @fieldParentPtr("base", base)).flush(arena, prog_node); |
| 564 | } | 540 | } |
| 565 | const comp = base.comp; | 541 | const comp = base.comp; |
| 566 | if (comp.clang_preprocessor_mode == .yes or comp.clang_preprocessor_mode == .pch) { | 542 | if (comp.clang_preprocessor_mode == .yes or comp.clang_preprocessor_mode == .pch) { |
| ... | @@ -587,7 +563,7 @@ pub const File = struct { | ... | @@ -587,7 +563,7 @@ pub const File = struct { |
| 587 | } | 563 | } |
| 588 | switch (base.tag) { | 564 | switch (base.tag) { |
| 589 | inline else => |tag| { | 565 | inline else => |tag| { |
| 590 | return @fieldParentPtr(tag.Type(), "base", base).flush(arena, prog_node); | 566 | return @as(*tag.Type(), @fieldParentPtr("base", base)).flush(arena, prog_node); |
| 591 | }, | 567 | }, |
| 592 | } | 568 | } |
| 593 | } | 569 | } |
| ... | @@ -596,12 +572,9 @@ pub const File = struct { | ... | @@ -596,12 +572,9 @@ pub const File = struct { |
| 596 | /// rather than final output mode. | 572 | /// rather than final output mode. |
| 597 | pub fn flushModule(base: *File, arena: Allocator, prog_node: *std.Progress.Node) FlushError!void { | 573 | pub fn flushModule(base: *File, arena: Allocator, prog_node: *std.Progress.Node) FlushError!void { |
| 598 | switch (base.tag) { | 574 | switch (base.tag) { |
| 599 | .c => { | ||
| 600 | return @fieldParentPtr(C, "base", base).flushModule(arena, prog_node); | ||
| 601 | }, | ||
| 602 | inline else => |tag| { | 575 | inline else => |tag| { |
| 603 | if (build_options.only_c) unreachable; | 576 | if (tag != .c and build_options.only_c) unreachable; |
| 604 | return @fieldParentPtr(tag.Type(), "base", base).flushModule(arena, prog_node); | 577 | return @as(*tag.Type(), @fieldParentPtr("base", base)).flushModule(arena, prog_node); |
| 605 | }, | 578 | }, |
| 606 | } | 579 | } |
| 607 | } | 580 | } |
| ... | @@ -609,12 +582,9 @@ pub const File = struct { | ... | @@ -609,12 +582,9 @@ pub const File = struct { |
| 609 | /// Called when a Decl is deleted from the Module. | 582 | /// Called when a Decl is deleted from the Module. |
| 610 | pub fn freeDecl(base: *File, decl_index: InternPool.DeclIndex) void { | 583 | pub fn freeDecl(base: *File, decl_index: InternPool.DeclIndex) void { |
| 611 | switch (base.tag) { | 584 | switch (base.tag) { |
| 612 | .c => { | ||
| 613 | @fieldParentPtr(C, "base", base).freeDecl(decl_index); | ||
| 614 | }, | ||
| 615 | inline else => |tag| { | 585 | inline else => |tag| { |
| 616 | if (build_options.only_c) unreachable; | 586 | if (tag != .c and build_options.only_c) unreachable; |
| 617 | @fieldParentPtr(tag.Type(), "base", base).freeDecl(decl_index); | 587 | @as(*tag.Type(), @fieldParentPtr("base", base)).freeDecl(decl_index); |
| 618 | }, | 588 | }, |
| 619 | } | 589 | } |
| 620 | } | 590 | } |
| ... | @@ -635,12 +605,9 @@ pub const File = struct { | ... | @@ -635,12 +605,9 @@ pub const File = struct { |
| 635 | exports: []const *Module.Export, | 605 | exports: []const *Module.Export, |
| 636 | ) UpdateExportsError!void { | 606 | ) UpdateExportsError!void { |
| 637 | switch (base.tag) { | 607 | switch (base.tag) { |
| 638 | .c => { | ||
| 639 | return @fieldParentPtr(C, "base", base).updateExports(module, exported, exports); | ||
| 640 | }, | ||
| 641 | inline else => |tag| { | 608 | inline else => |tag| { |
| 642 | if (build_options.only_c) unreachable; | 609 | if (tag != .c and build_options.only_c) unreachable; |
| 643 | return @fieldParentPtr(tag.Type(), "base", base).updateExports(module, exported, exports); | 610 | return @as(*tag.Type(), @fieldParentPtr("base", base)).updateExports(module, exported, exports); |
| 644 | }, | 611 | }, |
| 645 | } | 612 | } |
| 646 | } | 613 | } |
| ... | @@ -664,7 +631,7 @@ pub const File = struct { | ... | @@ -664,7 +631,7 @@ pub const File = struct { |
| 664 | .spirv => unreachable, | 631 | .spirv => unreachable, |
| 665 | .nvptx => unreachable, | 632 | .nvptx => unreachable, |
| 666 | inline else => |tag| { | 633 | inline else => |tag| { |
| 667 | return @fieldParentPtr(tag.Type(), "base", base).getDeclVAddr(decl_index, reloc_info); | 634 | return @as(*tag.Type(), @fieldParentPtr("base", base)).getDeclVAddr(decl_index, reloc_info); |
| 668 | }, | 635 | }, |
| 669 | } | 636 | } |
| 670 | } | 637 | } |
| ... | @@ -683,7 +650,7 @@ pub const File = struct { | ... | @@ -683,7 +650,7 @@ pub const File = struct { |
| 683 | .spirv => unreachable, | 650 | .spirv => unreachable, |
| 684 | .nvptx => unreachable, | 651 | .nvptx => unreachable, |
| 685 | inline else => |tag| { | 652 | inline else => |tag| { |
| 686 | return @fieldParentPtr(tag.Type(), "base", base).lowerAnonDecl(decl_val, decl_align, src_loc); | 653 | return @as(*tag.Type(), @fieldParentPtr("base", base)).lowerAnonDecl(decl_val, decl_align, src_loc); |
| 687 | }, | 654 | }, |
| 688 | } | 655 | } |
| 689 | } | 656 | } |
| ... | @@ -695,7 +662,7 @@ pub const File = struct { | ... | @@ -695,7 +662,7 @@ pub const File = struct { |
| 695 | .spirv => unreachable, | 662 | .spirv => unreachable, |
| 696 | .nvptx => unreachable, | 663 | .nvptx => unreachable, |
| 697 | inline else => |tag| { | 664 | inline else => |tag| { |
| 698 | return @fieldParentPtr(tag.Type(), "base", base).getAnonDeclVAddr(decl_val, reloc_info); | 665 | return @as(*tag.Type(), @fieldParentPtr("base", base)).getAnonDeclVAddr(decl_val, reloc_info); |
| 699 | }, | 666 | }, |
| 700 | } | 667 | } |
| 701 | } | 668 | } |
| ... | @@ -714,7 +681,7 @@ pub const File = struct { | ... | @@ -714,7 +681,7 @@ pub const File = struct { |
| 714 | => {}, | 681 | => {}, |
| 715 | 682 | ||
| 716 | inline else => |tag| { | 683 | inline else => |tag| { |
| 717 | return @fieldParentPtr(tag.Type(), "base", base).deleteDeclExport(decl_index, name); | 684 | return @as(*tag.Type(), @fieldParentPtr("base", base)).deleteDeclExport(decl_index, name); |
| 718 | }, | 685 | }, |
| 719 | } | 686 | } |
| 720 | } | 687 | } |
src/link/C.zig+157-164| ... | @@ -6,7 +6,8 @@ const fs = std.fs; | ... | @@ -6,7 +6,8 @@ const fs = std.fs; |
| 6 | 6 | ||
| 7 | const C = @This(); | 7 | const C = @This(); |
| 8 | const build_options = @import("build_options"); | 8 | const build_options = @import("build_options"); |
| 9 | const Module = @import("../Module.zig"); | 9 | const Zcu = @import("../Module.zig"); |
| 10 | const Module = @import("../Package/Module.zig"); | ||
| 10 | const InternPool = @import("../InternPool.zig"); | 11 | const InternPool = @import("../InternPool.zig"); |
| 11 | const Alignment = InternPool.Alignment; | 12 | const Alignment = InternPool.Alignment; |
| 12 | const Compilation = @import("../Compilation.zig"); | 13 | const Compilation = @import("../Compilation.zig"); |
| ... | @@ -68,13 +69,13 @@ pub const DeclBlock = struct { | ... | @@ -68,13 +69,13 @@ pub const DeclBlock = struct { |
| 68 | fwd_decl: String = String.empty, | 69 | fwd_decl: String = String.empty, |
| 69 | /// Each `Decl` stores a set of used `CType`s. In `flush()`, we iterate | 70 | /// Each `Decl` stores a set of used `CType`s. In `flush()`, we iterate |
| 70 | /// over each `Decl` and generate the definition for each used `CType` once. | 71 | /// over each `Decl` and generate the definition for each used `CType` once. |
| 71 | ctypes: codegen.CType.Store = .{}, | 72 | ctype_pool: codegen.CType.Pool = codegen.CType.Pool.empty, |
| 72 | /// Key and Value storage use the ctype arena. | 73 | /// May contain string references to ctype_pool |
| 73 | lazy_fns: codegen.LazyFnMap = .{}, | 74 | lazy_fns: codegen.LazyFnMap = .{}, |
| 74 | 75 | ||
| 75 | fn deinit(db: *DeclBlock, gpa: Allocator) void { | 76 | fn deinit(db: *DeclBlock, gpa: Allocator) void { |
| 76 | db.lazy_fns.deinit(gpa); | 77 | db.lazy_fns.deinit(gpa); |
| 77 | db.ctypes.deinit(gpa); | 78 | db.ctype_pool.deinit(gpa); |
| 78 | db.* = undefined; | 79 | db.* = undefined; |
| 79 | } | 80 | } |
| 80 | }; | 81 | }; |
| ... | @@ -177,23 +178,24 @@ pub fn freeDecl(self: *C, decl_index: InternPool.DeclIndex) void { | ... | @@ -177,23 +178,24 @@ pub fn freeDecl(self: *C, decl_index: InternPool.DeclIndex) void { |
| 177 | 178 | ||
| 178 | pub fn updateFunc( | 179 | pub fn updateFunc( |
| 179 | self: *C, | 180 | self: *C, |
| 180 | module: *Module, | 181 | zcu: *Zcu, |
| 181 | func_index: InternPool.Index, | 182 | func_index: InternPool.Index, |
| 182 | air: Air, | 183 | air: Air, |
| 183 | liveness: Liveness, | 184 | liveness: Liveness, |
| 184 | ) !void { | 185 | ) !void { |
| 185 | const gpa = self.base.comp.gpa; | 186 | const gpa = self.base.comp.gpa; |
| 186 | 187 | ||
| 187 | const func = module.funcInfo(func_index); | 188 | const func = zcu.funcInfo(func_index); |
| 188 | const decl_index = func.owner_decl; | 189 | const decl_index = func.owner_decl; |
| 189 | const decl = module.declPtr(decl_index); | 190 | const decl = zcu.declPtr(decl_index); |
| 190 | const gop = try self.decl_table.getOrPut(gpa, decl_index); | 191 | const gop = try self.decl_table.getOrPut(gpa, decl_index); |
| 191 | if (!gop.found_existing) gop.value_ptr.* = .{}; | 192 | if (!gop.found_existing) gop.value_ptr.* = .{}; |
| 192 | const ctypes = &gop.value_ptr.ctypes; | 193 | const ctype_pool = &gop.value_ptr.ctype_pool; |
| 193 | const lazy_fns = &gop.value_ptr.lazy_fns; | 194 | const lazy_fns = &gop.value_ptr.lazy_fns; |
| 194 | const fwd_decl = &self.fwd_decl_buf; | 195 | const fwd_decl = &self.fwd_decl_buf; |
| 195 | const code = &self.code_buf; | 196 | const code = &self.code_buf; |
| 196 | ctypes.clearRetainingCapacity(gpa); | 197 | try ctype_pool.init(gpa); |
| 198 | ctype_pool.clearRetainingCapacity(); | ||
| 197 | lazy_fns.clearRetainingCapacity(); | 199 | lazy_fns.clearRetainingCapacity(); |
| 198 | fwd_decl.clearRetainingCapacity(); | 200 | fwd_decl.clearRetainingCapacity(); |
| 199 | code.clearRetainingCapacity(); | 201 | code.clearRetainingCapacity(); |
| ... | @@ -206,12 +208,14 @@ pub fn updateFunc( | ... | @@ -206,12 +208,14 @@ pub fn updateFunc( |
| 206 | .object = .{ | 208 | .object = .{ |
| 207 | .dg = .{ | 209 | .dg = .{ |
| 208 | .gpa = gpa, | 210 | .gpa = gpa, |
| 209 | .module = module, | 211 | .zcu = zcu, |
| 212 | .mod = zcu.namespacePtr(decl.src_namespace).file_scope.mod, | ||
| 210 | .error_msg = null, | 213 | .error_msg = null, |
| 211 | .pass = .{ .decl = decl_index }, | 214 | .pass = .{ .decl = decl_index }, |
| 212 | .is_naked_fn = decl.typeOf(module).fnCallingConvention(module) == .Naked, | 215 | .is_naked_fn = decl.typeOf(zcu).fnCallingConvention(zcu) == .Naked, |
| 213 | .fwd_decl = fwd_decl.toManaged(gpa), | 216 | .fwd_decl = fwd_decl.toManaged(gpa), |
| 214 | .ctypes = ctypes.*, | 217 | .ctype_pool = ctype_pool.*, |
| 218 | .scratch = .{}, | ||
| 215 | .anon_decl_deps = self.anon_decls, | 219 | .anon_decl_deps = self.anon_decls, |
| 216 | .aligned_anon_decls = self.aligned_anon_decls, | 220 | .aligned_anon_decls = self.aligned_anon_decls, |
| 217 | }, | 221 | }, |
| ... | @@ -220,36 +224,32 @@ pub fn updateFunc( | ... | @@ -220,36 +224,32 @@ pub fn updateFunc( |
| 220 | }, | 224 | }, |
| 221 | .lazy_fns = lazy_fns.*, | 225 | .lazy_fns = lazy_fns.*, |
| 222 | }; | 226 | }; |
| 223 | |||
| 224 | function.object.indent_writer = .{ .underlying_writer = function.object.code.writer() }; | 227 | function.object.indent_writer = .{ .underlying_writer = function.object.code.writer() }; |
| 225 | defer { | 228 | defer { |
| 226 | self.anon_decls = function.object.dg.anon_decl_deps; | 229 | self.anon_decls = function.object.dg.anon_decl_deps; |
| 227 | self.aligned_anon_decls = function.object.dg.aligned_anon_decls; | 230 | self.aligned_anon_decls = function.object.dg.aligned_anon_decls; |
| 228 | fwd_decl.* = function.object.dg.fwd_decl.moveToUnmanaged(); | 231 | fwd_decl.* = function.object.dg.fwd_decl.moveToUnmanaged(); |
| 232 | ctype_pool.* = function.object.dg.ctype_pool.move(); | ||
| 233 | ctype_pool.freeUnusedCapacity(gpa); | ||
| 234 | function.object.dg.scratch.deinit(gpa); | ||
| 235 | lazy_fns.* = function.lazy_fns.move(); | ||
| 236 | lazy_fns.shrinkAndFree(gpa, lazy_fns.count()); | ||
| 229 | code.* = function.object.code.moveToUnmanaged(); | 237 | code.* = function.object.code.moveToUnmanaged(); |
| 230 | function.deinit(); | 238 | function.deinit(); |
| 231 | } | 239 | } |
| 232 | 240 | ||
| 233 | codegen.genFunc(&function) catch |err| switch (err) { | 241 | codegen.genFunc(&function) catch |err| switch (err) { |
| 234 | error.AnalysisFail => { | 242 | error.AnalysisFail => { |
| 235 | try module.failed_decls.put(gpa, decl_index, function.object.dg.error_msg.?); | 243 | try zcu.failed_decls.put(gpa, decl_index, function.object.dg.error_msg.?); |
| 236 | return; | 244 | return; |
| 237 | }, | 245 | }, |
| 238 | else => |e| return e, | 246 | else => |e| return e, |
| 239 | }; | 247 | }; |
| 240 | |||
| 241 | ctypes.* = function.object.dg.ctypes.move(); | ||
| 242 | lazy_fns.* = function.lazy_fns.move(); | ||
| 243 | |||
| 244 | // Free excess allocated memory for this Decl. | ||
| 245 | ctypes.shrinkAndFree(gpa, ctypes.count()); | ||
| 246 | lazy_fns.shrinkAndFree(gpa, lazy_fns.count()); | ||
| 247 | |||
| 248 | gop.value_ptr.code = try self.addString(function.object.code.items); | ||
| 249 | gop.value_ptr.fwd_decl = try self.addString(function.object.dg.fwd_decl.items); | 248 | gop.value_ptr.fwd_decl = try self.addString(function.object.dg.fwd_decl.items); |
| 249 | gop.value_ptr.code = try self.addString(function.object.code.items); | ||
| 250 | } | 250 | } |
| 251 | 251 | ||
| 252 | fn updateAnonDecl(self: *C, module: *Module, i: usize) !void { | 252 | fn updateAnonDecl(self: *C, zcu: *Zcu, i: usize) !void { |
| 253 | const gpa = self.base.comp.gpa; | 253 | const gpa = self.base.comp.gpa; |
| 254 | const anon_decl = self.anon_decls.keys()[i]; | 254 | const anon_decl = self.anon_decls.keys()[i]; |
| 255 | 255 | ||
| ... | @@ -261,12 +261,14 @@ fn updateAnonDecl(self: *C, module: *Module, i: usize) !void { | ... | @@ -261,12 +261,14 @@ fn updateAnonDecl(self: *C, module: *Module, i: usize) !void { |
| 261 | var object: codegen.Object = .{ | 261 | var object: codegen.Object = .{ |
| 262 | .dg = .{ | 262 | .dg = .{ |
| 263 | .gpa = gpa, | 263 | .gpa = gpa, |
| 264 | .module = module, | 264 | .zcu = zcu, |
| 265 | .mod = zcu.root_mod, | ||
| 265 | .error_msg = null, | 266 | .error_msg = null, |
| 266 | .pass = .{ .anon = anon_decl }, | 267 | .pass = .{ .anon = anon_decl }, |
| 267 | .is_naked_fn = false, | 268 | .is_naked_fn = false, |
| 268 | .fwd_decl = fwd_decl.toManaged(gpa), | 269 | .fwd_decl = fwd_decl.toManaged(gpa), |
| 269 | .ctypes = .{}, | 270 | .ctype_pool = codegen.CType.Pool.empty, |
| 271 | .scratch = .{}, | ||
| 270 | .anon_decl_deps = self.anon_decls, | 272 | .anon_decl_deps = self.anon_decls, |
| 271 | .aligned_anon_decls = self.aligned_anon_decls, | 273 | .aligned_anon_decls = self.aligned_anon_decls, |
| 272 | }, | 274 | }, |
| ... | @@ -274,62 +276,64 @@ fn updateAnonDecl(self: *C, module: *Module, i: usize) !void { | ... | @@ -274,62 +276,64 @@ fn updateAnonDecl(self: *C, module: *Module, i: usize) !void { |
| 274 | .indent_writer = undefined, // set later so we can get a pointer to object.code | 276 | .indent_writer = undefined, // set later so we can get a pointer to object.code |
| 275 | }; | 277 | }; |
| 276 | object.indent_writer = .{ .underlying_writer = object.code.writer() }; | 278 | object.indent_writer = .{ .underlying_writer = object.code.writer() }; |
| 277 | |||
| 278 | defer { | 279 | defer { |
| 279 | self.anon_decls = object.dg.anon_decl_deps; | 280 | self.anon_decls = object.dg.anon_decl_deps; |
| 280 | self.aligned_anon_decls = object.dg.aligned_anon_decls; | 281 | self.aligned_anon_decls = object.dg.aligned_anon_decls; |
| 281 | object.dg.ctypes.deinit(object.dg.gpa); | ||
| 282 | fwd_decl.* = object.dg.fwd_decl.moveToUnmanaged(); | 282 | fwd_decl.* = object.dg.fwd_decl.moveToUnmanaged(); |
| 283 | object.dg.ctype_pool.deinit(object.dg.gpa); | ||
| 284 | object.dg.scratch.deinit(gpa); | ||
| 283 | code.* = object.code.moveToUnmanaged(); | 285 | code.* = object.code.moveToUnmanaged(); |
| 284 | } | 286 | } |
| 287 | try object.dg.ctype_pool.init(gpa); | ||
| 285 | 288 | ||
| 286 | const c_value: codegen.CValue = .{ .constant = anon_decl }; | 289 | const c_value: codegen.CValue = .{ .constant = Value.fromInterned(anon_decl) }; |
| 287 | const alignment: Alignment = self.aligned_anon_decls.get(anon_decl) orelse .none; | 290 | const alignment: Alignment = self.aligned_anon_decls.get(anon_decl) orelse .none; |
| 288 | codegen.genDeclValue(&object, Value.fromInterned(anon_decl), false, c_value, alignment, .none) catch |err| switch (err) { | 291 | codegen.genDeclValue(&object, c_value.constant, false, c_value, alignment, .none) catch |err| switch (err) { |
| 289 | error.AnalysisFail => { | 292 | error.AnalysisFail => { |
| 290 | @panic("TODO: C backend AnalysisFail on anonymous decl"); | 293 | @panic("TODO: C backend AnalysisFail on anonymous decl"); |
| 291 | //try module.failed_decls.put(gpa, decl_index, object.dg.error_msg.?); | 294 | //try zcu.failed_decls.put(gpa, decl_index, object.dg.error_msg.?); |
| 292 | //return; | 295 | //return; |
| 293 | }, | 296 | }, |
| 294 | else => |e| return e, | 297 | else => |e| return e, |
| 295 | }; | 298 | }; |
| 296 | 299 | ||
| 297 | // Free excess allocated memory for this Decl. | 300 | object.dg.ctype_pool.freeUnusedCapacity(gpa); |
| 298 | object.dg.ctypes.shrinkAndFree(gpa, object.dg.ctypes.count()); | ||
| 299 | |||
| 300 | object.dg.anon_decl_deps.values()[i] = .{ | 301 | object.dg.anon_decl_deps.values()[i] = .{ |
| 301 | .code = try self.addString(object.code.items), | 302 | .code = try self.addString(object.code.items), |
| 302 | .fwd_decl = try self.addString(object.dg.fwd_decl.items), | 303 | .fwd_decl = try self.addString(object.dg.fwd_decl.items), |
| 303 | .ctypes = object.dg.ctypes.move(), | 304 | .ctype_pool = object.dg.ctype_pool.move(), |
| 304 | }; | 305 | }; |
| 305 | } | 306 | } |
| 306 | 307 | ||
| 307 | pub fn updateDecl(self: *C, module: *Module, decl_index: InternPool.DeclIndex) !void { | 308 | pub fn updateDecl(self: *C, zcu: *Zcu, decl_index: InternPool.DeclIndex) !void { |
| 308 | const tracy = trace(@src()); | 309 | const tracy = trace(@src()); |
| 309 | defer tracy.end(); | 310 | defer tracy.end(); |
| 310 | 311 | ||
| 311 | const gpa = self.base.comp.gpa; | 312 | const gpa = self.base.comp.gpa; |
| 312 | 313 | ||
| 314 | const decl = zcu.declPtr(decl_index); | ||
| 313 | const gop = try self.decl_table.getOrPut(gpa, decl_index); | 315 | const gop = try self.decl_table.getOrPut(gpa, decl_index); |
| 314 | if (!gop.found_existing) { | 316 | errdefer _ = self.decl_table.pop(); |
| 315 | gop.value_ptr.* = .{}; | 317 | if (!gop.found_existing) gop.value_ptr.* = .{}; |
| 316 | } | 318 | const ctype_pool = &gop.value_ptr.ctype_pool; |
| 317 | const ctypes = &gop.value_ptr.ctypes; | ||
| 318 | const fwd_decl = &self.fwd_decl_buf; | 319 | const fwd_decl = &self.fwd_decl_buf; |
| 319 | const code = &self.code_buf; | 320 | const code = &self.code_buf; |
| 320 | ctypes.clearRetainingCapacity(gpa); | 321 | try ctype_pool.init(gpa); |
| 322 | ctype_pool.clearRetainingCapacity(); | ||
| 321 | fwd_decl.clearRetainingCapacity(); | 323 | fwd_decl.clearRetainingCapacity(); |
| 322 | code.clearRetainingCapacity(); | 324 | code.clearRetainingCapacity(); |
| 323 | 325 | ||
| 324 | var object: codegen.Object = .{ | 326 | var object: codegen.Object = .{ |
| 325 | .dg = .{ | 327 | .dg = .{ |
| 326 | .gpa = gpa, | 328 | .gpa = gpa, |
| 327 | .module = module, | 329 | .zcu = zcu, |
| 330 | .mod = zcu.namespacePtr(decl.src_namespace).file_scope.mod, | ||
| 328 | .error_msg = null, | 331 | .error_msg = null, |
| 329 | .pass = .{ .decl = decl_index }, | 332 | .pass = .{ .decl = decl_index }, |
| 330 | .is_naked_fn = false, | 333 | .is_naked_fn = false, |
| 331 | .fwd_decl = fwd_decl.toManaged(gpa), | 334 | .fwd_decl = fwd_decl.toManaged(gpa), |
| 332 | .ctypes = ctypes.*, | 335 | .ctype_pool = ctype_pool.*, |
| 336 | .scratch = .{}, | ||
| 333 | .anon_decl_deps = self.anon_decls, | 337 | .anon_decl_deps = self.anon_decls, |
| 334 | .aligned_anon_decls = self.aligned_anon_decls, | 338 | .aligned_anon_decls = self.aligned_anon_decls, |
| 335 | }, | 339 | }, |
| ... | @@ -340,33 +344,29 @@ pub fn updateDecl(self: *C, module: *Module, decl_index: InternPool.DeclIndex) ! | ... | @@ -340,33 +344,29 @@ pub fn updateDecl(self: *C, module: *Module, decl_index: InternPool.DeclIndex) ! |
| 340 | defer { | 344 | defer { |
| 341 | self.anon_decls = object.dg.anon_decl_deps; | 345 | self.anon_decls = object.dg.anon_decl_deps; |
| 342 | self.aligned_anon_decls = object.dg.aligned_anon_decls; | 346 | self.aligned_anon_decls = object.dg.aligned_anon_decls; |
| 343 | object.dg.ctypes.deinit(object.dg.gpa); | ||
| 344 | fwd_decl.* = object.dg.fwd_decl.moveToUnmanaged(); | 347 | fwd_decl.* = object.dg.fwd_decl.moveToUnmanaged(); |
| 348 | ctype_pool.* = object.dg.ctype_pool.move(); | ||
| 349 | ctype_pool.freeUnusedCapacity(gpa); | ||
| 350 | object.dg.scratch.deinit(gpa); | ||
| 345 | code.* = object.code.moveToUnmanaged(); | 351 | code.* = object.code.moveToUnmanaged(); |
| 346 | } | 352 | } |
| 347 | 353 | ||
| 348 | codegen.genDecl(&object) catch |err| switch (err) { | 354 | codegen.genDecl(&object) catch |err| switch (err) { |
| 349 | error.AnalysisFail => { | 355 | error.AnalysisFail => { |
| 350 | try module.failed_decls.put(gpa, decl_index, object.dg.error_msg.?); | 356 | try zcu.failed_decls.put(gpa, decl_index, object.dg.error_msg.?); |
| 351 | return; | 357 | return; |
| 352 | }, | 358 | }, |
| 353 | else => |e| return e, | 359 | else => |e| return e, |
| 354 | }; | 360 | }; |
| 355 | |||
| 356 | ctypes.* = object.dg.ctypes.move(); | ||
| 357 | |||
| 358 | // Free excess allocated memory for this Decl. | ||
| 359 | ctypes.shrinkAndFree(gpa, ctypes.count()); | ||
| 360 | |||
| 361 | gop.value_ptr.code = try self.addString(object.code.items); | 361 | gop.value_ptr.code = try self.addString(object.code.items); |
| 362 | gop.value_ptr.fwd_decl = try self.addString(object.dg.fwd_decl.items); | 362 | gop.value_ptr.fwd_decl = try self.addString(object.dg.fwd_decl.items); |
| 363 | } | 363 | } |
| 364 | 364 | ||
| 365 | pub fn updateDeclLineNumber(self: *C, module: *Module, decl_index: InternPool.DeclIndex) !void { | 365 | pub fn updateDeclLineNumber(self: *C, zcu: *Zcu, decl_index: InternPool.DeclIndex) !void { |
| 366 | // The C backend does not have the ability to fix line numbers without re-generating | 366 | // The C backend does not have the ability to fix line numbers without re-generating |
| 367 | // the entire Decl. | 367 | // the entire Decl. |
| 368 | _ = self; | 368 | _ = self; |
| 369 | _ = module; | 369 | _ = zcu; |
| 370 | _ = decl_index; | 370 | _ = decl_index; |
| 371 | } | 371 | } |
| 372 | 372 | ||
| ... | @@ -399,22 +399,25 @@ pub fn flushModule(self: *C, arena: Allocator, prog_node: *std.Progress.Node) !v | ... | @@ -399,22 +399,25 @@ pub fn flushModule(self: *C, arena: Allocator, prog_node: *std.Progress.Node) !v |
| 399 | 399 | ||
| 400 | const comp = self.base.comp; | 400 | const comp = self.base.comp; |
| 401 | const gpa = comp.gpa; | 401 | const gpa = comp.gpa; |
| 402 | const module = self.base.comp.module.?; | 402 | const zcu = self.base.comp.module.?; |
| 403 | 403 | ||
| 404 | { | 404 | { |
| 405 | var i: usize = 0; | 405 | var i: usize = 0; |
| 406 | while (i < self.anon_decls.count()) : (i += 1) { | 406 | while (i < self.anon_decls.count()) : (i += 1) { |
| 407 | try updateAnonDecl(self, module, i); | 407 | try updateAnonDecl(self, zcu, i); |
| 408 | } | 408 | } |
| 409 | } | 409 | } |
| 410 | 410 | ||
| 411 | // This code path happens exclusively with -ofmt=c. The flush logic for | 411 | // This code path happens exclusively with -ofmt=c. The flush logic for |
| 412 | // emit-h is in `flushEmitH` below. | 412 | // emit-h is in `flushEmitH` below. |
| 413 | 413 | ||
| 414 | var f: Flush = .{}; | 414 | var f: Flush = .{ |
| 415 | .ctype_pool = codegen.CType.Pool.empty, | ||
| 416 | .lazy_ctype_pool = codegen.CType.Pool.empty, | ||
| 417 | }; | ||
| 415 | defer f.deinit(gpa); | 418 | defer f.deinit(gpa); |
| 416 | 419 | ||
| 417 | const abi_defines = try self.abiDefines(module.getTarget()); | 420 | const abi_defines = try self.abiDefines(zcu.getTarget()); |
| 418 | defer abi_defines.deinit(); | 421 | defer abi_defines.deinit(); |
| 419 | 422 | ||
| 420 | // Covers defines, zig.h, ctypes, asm, lazy fwd. | 423 | // Covers defines, zig.h, ctypes, asm, lazy fwd. |
| ... | @@ -429,7 +432,7 @@ pub fn flushModule(self: *C, arena: Allocator, prog_node: *std.Progress.Node) !v | ... | @@ -429,7 +432,7 @@ pub fn flushModule(self: *C, arena: Allocator, prog_node: *std.Progress.Node) !v |
| 429 | { | 432 | { |
| 430 | var asm_buf = f.asm_buf.toManaged(gpa); | 433 | var asm_buf = f.asm_buf.toManaged(gpa); |
| 431 | defer f.asm_buf = asm_buf.moveToUnmanaged(); | 434 | defer f.asm_buf = asm_buf.moveToUnmanaged(); |
| 432 | try codegen.genGlobalAsm(module, asm_buf.writer()); | 435 | try codegen.genGlobalAsm(zcu, asm_buf.writer()); |
| 433 | f.appendBufAssumeCapacity(asm_buf.items); | 436 | f.appendBufAssumeCapacity(asm_buf.items); |
| 434 | } | 437 | } |
| 435 | 438 | ||
| ... | @@ -438,7 +441,8 @@ pub fn flushModule(self: *C, arena: Allocator, prog_node: *std.Progress.Node) !v | ... | @@ -438,7 +441,8 @@ pub fn flushModule(self: *C, arena: Allocator, prog_node: *std.Progress.Node) !v |
| 438 | 441 | ||
| 439 | self.lazy_fwd_decl_buf.clearRetainingCapacity(); | 442 | self.lazy_fwd_decl_buf.clearRetainingCapacity(); |
| 440 | self.lazy_code_buf.clearRetainingCapacity(); | 443 | self.lazy_code_buf.clearRetainingCapacity(); |
| 441 | try self.flushErrDecls(&f.lazy_ctypes); | 444 | try f.lazy_ctype_pool.init(gpa); |
| 445 | try self.flushErrDecls(zcu, &f.lazy_ctype_pool); | ||
| 442 | 446 | ||
| 443 | // Unlike other backends, the .c code we are emitting has order-dependent decls. | 447 | // Unlike other backends, the .c code we are emitting has order-dependent decls. |
| 444 | // `CType`s, forward decls, and non-functions first. | 448 | // `CType`s, forward decls, and non-functions first. |
| ... | @@ -446,34 +450,35 @@ pub fn flushModule(self: *C, arena: Allocator, prog_node: *std.Progress.Node) !v | ... | @@ -446,34 +450,35 @@ pub fn flushModule(self: *C, arena: Allocator, prog_node: *std.Progress.Node) !v |
| 446 | { | 450 | { |
| 447 | var export_names: std.AutoHashMapUnmanaged(InternPool.NullTerminatedString, void) = .{}; | 451 | var export_names: std.AutoHashMapUnmanaged(InternPool.NullTerminatedString, void) = .{}; |
| 448 | defer export_names.deinit(gpa); | 452 | defer export_names.deinit(gpa); |
| 449 | try export_names.ensureTotalCapacity(gpa, @intCast(module.decl_exports.entries.len)); | 453 | try export_names.ensureTotalCapacity(gpa, @intCast(zcu.decl_exports.entries.len)); |
| 450 | for (module.decl_exports.values()) |exports| for (exports.items) |@"export"| | 454 | for (zcu.decl_exports.values()) |exports| for (exports.items) |@"export"| |
| 451 | try export_names.put(gpa, @"export".opts.name, {}); | 455 | try export_names.put(gpa, @"export".opts.name, {}); |
| 452 | 456 | ||
| 453 | for (self.anon_decls.values()) |*decl_block| { | 457 | for (self.anon_decls.values()) |*decl_block| { |
| 454 | try self.flushDeclBlock(&f, decl_block, export_names, .none); | 458 | try self.flushDeclBlock(zcu, zcu.root_mod, &f, decl_block, export_names, .none); |
| 455 | } | 459 | } |
| 456 | 460 | ||
| 457 | for (self.decl_table.keys(), self.decl_table.values()) |decl_index, *decl_block| { | 461 | for (self.decl_table.keys(), self.decl_table.values()) |decl_index, *decl_block| { |
| 458 | assert(module.declPtr(decl_index).has_tv); | 462 | const decl = zcu.declPtr(decl_index); |
| 459 | const decl = module.declPtr(decl_index); | 463 | assert(decl.has_tv); |
| 460 | const extern_symbol_name = if (decl.isExtern(module)) decl.name.toOptional() else .none; | 464 | const extern_symbol_name = if (decl.isExtern(zcu)) decl.name.toOptional() else .none; |
| 461 | try self.flushDeclBlock(&f, decl_block, export_names, extern_symbol_name); | 465 | const mod = zcu.namespacePtr(decl.src_namespace).file_scope.mod; |
| 466 | try self.flushDeclBlock(zcu, mod, &f, decl_block, export_names, extern_symbol_name); | ||
| 462 | } | 467 | } |
| 463 | } | 468 | } |
| 464 | 469 | ||
| 465 | { | 470 | { |
| 466 | // We need to flush lazy ctypes after flushing all decls but before flushing any decl ctypes. | 471 | // We need to flush lazy ctypes after flushing all decls but before flushing any decl ctypes. |
| 467 | // This ensures that every lazy CType.Index exactly matches the global CType.Index. | 472 | // This ensures that every lazy CType.Index exactly matches the global CType.Index. |
| 468 | assert(f.ctypes.count() == 0); | 473 | try f.ctype_pool.init(gpa); |
| 469 | try self.flushCTypes(&f, .flush, f.lazy_ctypes); | 474 | try self.flushCTypes(zcu, &f, .flush, &f.lazy_ctype_pool); |
| 470 | 475 | ||
| 471 | for (self.anon_decls.keys(), self.anon_decls.values()) |anon_decl, decl_block| { | 476 | for (self.anon_decls.keys(), self.anon_decls.values()) |anon_decl, decl_block| { |
| 472 | try self.flushCTypes(&f, .{ .anon = anon_decl }, decl_block.ctypes); | 477 | try self.flushCTypes(zcu, &f, .{ .anon = anon_decl }, &decl_block.ctype_pool); |
| 473 | } | 478 | } |
| 474 | 479 | ||
| 475 | for (self.decl_table.keys(), self.decl_table.values()) |decl_index, decl_block| { | 480 | for (self.decl_table.keys(), self.decl_table.values()) |decl_index, decl_block| { |
| 476 | try self.flushCTypes(&f, .{ .decl = decl_index }, decl_block.ctypes); | 481 | try self.flushCTypes(zcu, &f, .{ .decl = decl_index }, &decl_block.ctype_pool); |
| 477 | } | 482 | } |
| 478 | } | 483 | } |
| 479 | 484 | ||
| ... | @@ -504,11 +509,11 @@ pub fn flushModule(self: *C, arena: Allocator, prog_node: *std.Progress.Node) !v | ... | @@ -504,11 +509,11 @@ pub fn flushModule(self: *C, arena: Allocator, prog_node: *std.Progress.Node) !v |
| 504 | } | 509 | } |
| 505 | 510 | ||
| 506 | const Flush = struct { | 511 | const Flush = struct { |
| 507 | ctypes: codegen.CType.Store = .{}, | 512 | ctype_pool: codegen.CType.Pool, |
| 508 | ctypes_map: std.ArrayListUnmanaged(codegen.CType.Index) = .{}, | 513 | ctype_global_from_decl_map: std.ArrayListUnmanaged(codegen.CType) = .{}, |
| 509 | ctypes_buf: std.ArrayListUnmanaged(u8) = .{}, | 514 | ctypes_buf: std.ArrayListUnmanaged(u8) = .{}, |
| 510 | 515 | ||
| 511 | lazy_ctypes: codegen.CType.Store = .{}, | 516 | lazy_ctype_pool: codegen.CType.Pool, |
| 512 | lazy_fns: LazyFns = .{}, | 517 | lazy_fns: LazyFns = .{}, |
| 513 | 518 | ||
| 514 | asm_buf: std.ArrayListUnmanaged(u8) = .{}, | 519 | asm_buf: std.ArrayListUnmanaged(u8) = .{}, |
| ... | @@ -530,10 +535,11 @@ const Flush = struct { | ... | @@ -530,10 +535,11 @@ const Flush = struct { |
| 530 | f.all_buffers.deinit(gpa); | 535 | f.all_buffers.deinit(gpa); |
| 531 | f.asm_buf.deinit(gpa); | 536 | f.asm_buf.deinit(gpa); |
| 532 | f.lazy_fns.deinit(gpa); | 537 | f.lazy_fns.deinit(gpa); |
| 533 | f.lazy_ctypes.deinit(gpa); | 538 | f.lazy_ctype_pool.deinit(gpa); |
| 534 | f.ctypes_buf.deinit(gpa); | 539 | f.ctypes_buf.deinit(gpa); |
| 535 | f.ctypes_map.deinit(gpa); | 540 | assert(f.ctype_global_from_decl_map.items.len == 0); |
| 536 | f.ctypes.deinit(gpa); | 541 | f.ctype_global_from_decl_map.deinit(gpa); |
| 542 | f.ctype_pool.deinit(gpa); | ||
| 537 | } | 543 | } |
| 538 | }; | 544 | }; |
| 539 | 545 | ||
| ... | @@ -543,91 +549,62 @@ const FlushDeclError = error{ | ... | @@ -543,91 +549,62 @@ const FlushDeclError = error{ |
| 543 | 549 | ||
| 544 | fn flushCTypes( | 550 | fn flushCTypes( |
| 545 | self: *C, | 551 | self: *C, |
| 552 | zcu: *Zcu, | ||
| 546 | f: *Flush, | 553 | f: *Flush, |
| 547 | pass: codegen.DeclGen.Pass, | 554 | pass: codegen.DeclGen.Pass, |
| 548 | decl_ctypes: codegen.CType.Store, | 555 | decl_ctype_pool: *const codegen.CType.Pool, |
| 549 | ) FlushDeclError!void { | 556 | ) FlushDeclError!void { |
| 550 | const gpa = self.base.comp.gpa; | 557 | const gpa = self.base.comp.gpa; |
| 551 | const mod = self.base.comp.module.?; | 558 | const global_ctype_pool = &f.ctype_pool; |
| 552 | 559 | ||
| 553 | const decl_ctypes_len = decl_ctypes.count(); | 560 | const global_from_decl_map = &f.ctype_global_from_decl_map; |
| 554 | f.ctypes_map.clearRetainingCapacity(); | 561 | assert(global_from_decl_map.items.len == 0); |
| 555 | try f.ctypes_map.ensureTotalCapacity(gpa, decl_ctypes_len); | 562 | try global_from_decl_map.ensureTotalCapacity(gpa, decl_ctype_pool.items.len); |
| 556 | 563 | defer global_from_decl_map.clearRetainingCapacity(); | |
| 557 | var global_ctypes = f.ctypes.promote(gpa); | ||
| 558 | defer f.ctypes.demote(global_ctypes); | ||
| 559 | 564 | ||
| 560 | var ctypes_buf = f.ctypes_buf.toManaged(gpa); | 565 | var ctypes_buf = f.ctypes_buf.toManaged(gpa); |
| 561 | defer f.ctypes_buf = ctypes_buf.moveToUnmanaged(); | 566 | defer f.ctypes_buf = ctypes_buf.moveToUnmanaged(); |
| 562 | const writer = ctypes_buf.writer(); | 567 | const writer = ctypes_buf.writer(); |
| 563 | 568 | ||
| 564 | const slice = decl_ctypes.set.map.entries.slice(); | 569 | for (0..decl_ctype_pool.items.len) |decl_ctype_pool_index| { |
| 565 | for (slice.items(.key), 0..) |decl_cty, decl_i| { | 570 | const PoolAdapter = struct { |
| 566 | const Context = struct { | 571 | global_from_decl_map: []const codegen.CType, |
| 567 | arena: Allocator, | 572 | pub fn eql(pool_adapter: @This(), decl_ctype: codegen.CType, global_ctype: codegen.CType) bool { |
| 568 | ctypes_map: []codegen.CType.Index, | 573 | return if (decl_ctype.toPoolIndex()) |decl_pool_index| |
| 569 | cached_hash: codegen.CType.Store.Set.Map.Hash, | 574 | decl_pool_index < pool_adapter.global_from_decl_map.len and |
| 570 | idx: codegen.CType.Index, | 575 | pool_adapter.global_from_decl_map[decl_pool_index].eql(global_ctype) |
| 571 | 576 | else | |
| 572 | pub fn hash(ctx: @This(), _: codegen.CType) codegen.CType.Store.Set.Map.Hash { | 577 | decl_ctype.index == global_ctype.index; |
| 573 | return ctx.cached_hash; | ||
| 574 | } | ||
| 575 | pub fn eql(ctx: @This(), lhs: codegen.CType, rhs: codegen.CType, _: usize) bool { | ||
| 576 | return lhs.eqlContext(rhs, ctx); | ||
| 577 | } | ||
| 578 | pub fn eqlIndex( | ||
| 579 | ctx: @This(), | ||
| 580 | lhs_idx: codegen.CType.Index, | ||
| 581 | rhs_idx: codegen.CType.Index, | ||
| 582 | ) bool { | ||
| 583 | if (lhs_idx < codegen.CType.Tag.no_payload_count or | ||
| 584 | rhs_idx < codegen.CType.Tag.no_payload_count) return lhs_idx == rhs_idx; | ||
| 585 | const lhs_i = lhs_idx - codegen.CType.Tag.no_payload_count; | ||
| 586 | if (lhs_i >= ctx.ctypes_map.len) return false; | ||
| 587 | return ctx.ctypes_map[lhs_i] == rhs_idx; | ||
| 588 | } | 578 | } |
| 589 | pub fn copyIndex(ctx: @This(), idx: codegen.CType.Index) codegen.CType.Index { | 579 | pub fn copy(pool_adapter: @This(), decl_ctype: codegen.CType) codegen.CType { |
| 590 | if (idx < codegen.CType.Tag.no_payload_count) return idx; | 580 | return if (decl_ctype.toPoolIndex()) |decl_pool_index| |
| 591 | return ctx.ctypes_map[idx - codegen.CType.Tag.no_payload_count]; | 581 | pool_adapter.global_from_decl_map[decl_pool_index] |
| 582 | else | ||
| 583 | decl_ctype; | ||
| 592 | } | 584 | } |
| 593 | }; | 585 | }; |
| 594 | const decl_idx = @as(codegen.CType.Index, @intCast(codegen.CType.Tag.no_payload_count + decl_i)); | 586 | const decl_ctype = codegen.CType.fromPoolIndex(decl_ctype_pool_index); |
| 595 | const ctx = Context{ | 587 | const global_ctype, const found_existing = try global_ctype_pool.getOrPutAdapted( |
| 596 | .arena = global_ctypes.arena.allocator(), | 588 | gpa, |
| 597 | .ctypes_map = f.ctypes_map.items, | 589 | decl_ctype_pool, |
| 598 | .cached_hash = decl_ctypes.indexToHash(decl_idx), | 590 | decl_ctype, |
| 599 | .idx = decl_idx, | 591 | PoolAdapter{ .global_from_decl_map = global_from_decl_map.items }, |
| 600 | }; | 592 | ); |
| 601 | const gop = try global_ctypes.set.map.getOrPutContextAdapted(gpa, decl_cty, ctx, .{ | 593 | global_from_decl_map.appendAssumeCapacity(global_ctype); |
| 602 | .store = &global_ctypes.set, | ||
| 603 | }); | ||
| 604 | const global_idx = | ||
| 605 | @as(codegen.CType.Index, @intCast(codegen.CType.Tag.no_payload_count + gop.index)); | ||
| 606 | f.ctypes_map.appendAssumeCapacity(global_idx); | ||
| 607 | if (!gop.found_existing) { | ||
| 608 | errdefer _ = global_ctypes.set.map.pop(); | ||
| 609 | gop.key_ptr.* = try decl_cty.copyContext(ctx); | ||
| 610 | } | ||
| 611 | if (std.debug.runtime_safety) { | ||
| 612 | const global_cty = &global_ctypes.set.map.entries.items(.key)[gop.index]; | ||
| 613 | assert(global_cty == gop.key_ptr); | ||
| 614 | assert(decl_cty.eqlContext(global_cty.*, ctx)); | ||
| 615 | assert(decl_cty.hash(decl_ctypes.set) == global_cty.hash(global_ctypes.set)); | ||
| 616 | } | ||
| 617 | try codegen.genTypeDecl( | 594 | try codegen.genTypeDecl( |
| 618 | mod, | 595 | zcu, |
| 619 | writer, | 596 | writer, |
| 620 | global_ctypes.set, | 597 | global_ctype_pool, |
| 621 | global_idx, | 598 | global_ctype, |
| 622 | pass, | 599 | pass, |
| 623 | decl_ctypes.set, | 600 | decl_ctype_pool, |
| 624 | decl_idx, | 601 | decl_ctype, |
| 625 | gop.found_existing, | 602 | found_existing, |
| 626 | ); | 603 | ); |
| 627 | } | 604 | } |
| 628 | } | 605 | } |
| 629 | 606 | ||
| 630 | fn flushErrDecls(self: *C, ctypes: *codegen.CType.Store) FlushDeclError!void { | 607 | fn flushErrDecls(self: *C, zcu: *Zcu, ctype_pool: *codegen.CType.Pool) FlushDeclError!void { |
| 631 | const gpa = self.base.comp.gpa; | 608 | const gpa = self.base.comp.gpa; |
| 632 | 609 | ||
| 633 | const fwd_decl = &self.lazy_fwd_decl_buf; | 610 | const fwd_decl = &self.lazy_fwd_decl_buf; |
| ... | @@ -636,12 +613,14 @@ fn flushErrDecls(self: *C, ctypes: *codegen.CType.Store) FlushDeclError!void { | ... | @@ -636,12 +613,14 @@ fn flushErrDecls(self: *C, ctypes: *codegen.CType.Store) FlushDeclError!void { |
| 636 | var object = codegen.Object{ | 613 | var object = codegen.Object{ |
| 637 | .dg = .{ | 614 | .dg = .{ |
| 638 | .gpa = gpa, | 615 | .gpa = gpa, |
| 639 | .module = self.base.comp.module.?, | 616 | .zcu = zcu, |
| 617 | .mod = zcu.root_mod, | ||
| 640 | .error_msg = null, | 618 | .error_msg = null, |
| 641 | .pass = .flush, | 619 | .pass = .flush, |
| 642 | .is_naked_fn = false, | 620 | .is_naked_fn = false, |
| 643 | .fwd_decl = fwd_decl.toManaged(gpa), | 621 | .fwd_decl = fwd_decl.toManaged(gpa), |
| 644 | .ctypes = ctypes.*, | 622 | .ctype_pool = ctype_pool.*, |
| 623 | .scratch = .{}, | ||
| 645 | .anon_decl_deps = self.anon_decls, | 624 | .anon_decl_deps = self.anon_decls, |
| 646 | .aligned_anon_decls = self.aligned_anon_decls, | 625 | .aligned_anon_decls = self.aligned_anon_decls, |
| 647 | }, | 626 | }, |
| ... | @@ -652,8 +631,10 @@ fn flushErrDecls(self: *C, ctypes: *codegen.CType.Store) FlushDeclError!void { | ... | @@ -652,8 +631,10 @@ fn flushErrDecls(self: *C, ctypes: *codegen.CType.Store) FlushDeclError!void { |
| 652 | defer { | 631 | defer { |
| 653 | self.anon_decls = object.dg.anon_decl_deps; | 632 | self.anon_decls = object.dg.anon_decl_deps; |
| 654 | self.aligned_anon_decls = object.dg.aligned_anon_decls; | 633 | self.aligned_anon_decls = object.dg.aligned_anon_decls; |
| 655 | object.dg.ctypes.deinit(gpa); | ||
| 656 | fwd_decl.* = object.dg.fwd_decl.moveToUnmanaged(); | 634 | fwd_decl.* = object.dg.fwd_decl.moveToUnmanaged(); |
| 635 | ctype_pool.* = object.dg.ctype_pool.move(); | ||
| 636 | ctype_pool.freeUnusedCapacity(gpa); | ||
| 637 | object.dg.scratch.deinit(gpa); | ||
| 657 | code.* = object.code.moveToUnmanaged(); | 638 | code.* = object.code.moveToUnmanaged(); |
| 658 | } | 639 | } |
| 659 | 640 | ||
| ... | @@ -661,13 +642,14 @@ fn flushErrDecls(self: *C, ctypes: *codegen.CType.Store) FlushDeclError!void { | ... | @@ -661,13 +642,14 @@ fn flushErrDecls(self: *C, ctypes: *codegen.CType.Store) FlushDeclError!void { |
| 661 | error.AnalysisFail => unreachable, | 642 | error.AnalysisFail => unreachable, |
| 662 | else => |e| return e, | 643 | else => |e| return e, |
| 663 | }; | 644 | }; |
| 664 | |||
| 665 | ctypes.* = object.dg.ctypes.move(); | ||
| 666 | } | 645 | } |
| 667 | 646 | ||
| 668 | fn flushLazyFn( | 647 | fn flushLazyFn( |
| 669 | self: *C, | 648 | self: *C, |
| 670 | ctypes: *codegen.CType.Store, | 649 | zcu: *Zcu, |
| 650 | mod: *Module, | ||
| 651 | ctype_pool: *codegen.CType.Pool, | ||
| 652 | lazy_ctype_pool: *const codegen.CType.Pool, | ||
| 671 | lazy_fn: codegen.LazyFnMap.Entry, | 653 | lazy_fn: codegen.LazyFnMap.Entry, |
| 672 | ) FlushDeclError!void { | 654 | ) FlushDeclError!void { |
| 673 | const gpa = self.base.comp.gpa; | 655 | const gpa = self.base.comp.gpa; |
| ... | @@ -678,12 +660,14 @@ fn flushLazyFn( | ... | @@ -678,12 +660,14 @@ fn flushLazyFn( |
| 678 | var object = codegen.Object{ | 660 | var object = codegen.Object{ |
| 679 | .dg = .{ | 661 | .dg = .{ |
| 680 | .gpa = gpa, | 662 | .gpa = gpa, |
| 681 | .module = self.base.comp.module.?, | 663 | .zcu = zcu, |
| 664 | .mod = mod, | ||
| 682 | .error_msg = null, | 665 | .error_msg = null, |
| 683 | .pass = .flush, | 666 | .pass = .flush, |
| 684 | .is_naked_fn = false, | 667 | .is_naked_fn = false, |
| 685 | .fwd_decl = fwd_decl.toManaged(gpa), | 668 | .fwd_decl = fwd_decl.toManaged(gpa), |
| 686 | .ctypes = ctypes.*, | 669 | .ctype_pool = ctype_pool.*, |
| 670 | .scratch = .{}, | ||
| 687 | .anon_decl_deps = .{}, | 671 | .anon_decl_deps = .{}, |
| 688 | .aligned_anon_decls = .{}, | 672 | .aligned_anon_decls = .{}, |
| 689 | }, | 673 | }, |
| ... | @@ -696,20 +680,27 @@ fn flushLazyFn( | ... | @@ -696,20 +680,27 @@ fn flushLazyFn( |
| 696 | // `updateFunc()` does. | 680 | // `updateFunc()` does. |
| 697 | assert(object.dg.anon_decl_deps.count() == 0); | 681 | assert(object.dg.anon_decl_deps.count() == 0); |
| 698 | assert(object.dg.aligned_anon_decls.count() == 0); | 682 | assert(object.dg.aligned_anon_decls.count() == 0); |
| 699 | object.dg.ctypes.deinit(gpa); | ||
| 700 | fwd_decl.* = object.dg.fwd_decl.moveToUnmanaged(); | 683 | fwd_decl.* = object.dg.fwd_decl.moveToUnmanaged(); |
| 684 | ctype_pool.* = object.dg.ctype_pool.move(); | ||
| 685 | ctype_pool.freeUnusedCapacity(gpa); | ||
| 686 | object.dg.scratch.deinit(gpa); | ||
| 701 | code.* = object.code.moveToUnmanaged(); | 687 | code.* = object.code.moveToUnmanaged(); |
| 702 | } | 688 | } |
| 703 | 689 | ||
| 704 | codegen.genLazyFn(&object, lazy_fn) catch |err| switch (err) { | 690 | codegen.genLazyFn(&object, lazy_ctype_pool, lazy_fn) catch |err| switch (err) { |
| 705 | error.AnalysisFail => unreachable, | 691 | error.AnalysisFail => unreachable, |
| 706 | else => |e| return e, | 692 | else => |e| return e, |
| 707 | }; | 693 | }; |
| 708 | |||
| 709 | ctypes.* = object.dg.ctypes.move(); | ||
| 710 | } | 694 | } |
| 711 | 695 | ||
| 712 | fn flushLazyFns(self: *C, f: *Flush, lazy_fns: codegen.LazyFnMap) FlushDeclError!void { | 696 | fn flushLazyFns( |
| 697 | self: *C, | ||
| 698 | zcu: *Zcu, | ||
| 699 | mod: *Module, | ||
| 700 | f: *Flush, | ||
| 701 | lazy_ctype_pool: *const codegen.CType.Pool, | ||
| 702 | lazy_fns: codegen.LazyFnMap, | ||
| 703 | ) FlushDeclError!void { | ||
| 713 | const gpa = self.base.comp.gpa; | 704 | const gpa = self.base.comp.gpa; |
| 714 | try f.lazy_fns.ensureUnusedCapacity(gpa, @intCast(lazy_fns.count())); | 705 | try f.lazy_fns.ensureUnusedCapacity(gpa, @intCast(lazy_fns.count())); |
| 715 | 706 | ||
| ... | @@ -718,19 +709,21 @@ fn flushLazyFns(self: *C, f: *Flush, lazy_fns: codegen.LazyFnMap) FlushDeclError | ... | @@ -718,19 +709,21 @@ fn flushLazyFns(self: *C, f: *Flush, lazy_fns: codegen.LazyFnMap) FlushDeclError |
| 718 | const gop = f.lazy_fns.getOrPutAssumeCapacity(entry.key_ptr.*); | 709 | const gop = f.lazy_fns.getOrPutAssumeCapacity(entry.key_ptr.*); |
| 719 | if (gop.found_existing) continue; | 710 | if (gop.found_existing) continue; |
| 720 | gop.value_ptr.* = {}; | 711 | gop.value_ptr.* = {}; |
| 721 | try self.flushLazyFn(&f.lazy_ctypes, entry); | 712 | try self.flushLazyFn(zcu, mod, &f.lazy_ctype_pool, lazy_ctype_pool, entry); |
| 722 | } | 713 | } |
| 723 | } | 714 | } |
| 724 | 715 | ||
| 725 | fn flushDeclBlock( | 716 | fn flushDeclBlock( |
| 726 | self: *C, | 717 | self: *C, |
| 718 | zcu: *Zcu, | ||
| 719 | mod: *Module, | ||
| 727 | f: *Flush, | 720 | f: *Flush, |
| 728 | decl_block: *DeclBlock, | 721 | decl_block: *DeclBlock, |
| 729 | export_names: std.AutoHashMapUnmanaged(InternPool.NullTerminatedString, void), | 722 | export_names: std.AutoHashMapUnmanaged(InternPool.NullTerminatedString, void), |
| 730 | extern_symbol_name: InternPool.OptionalNullTerminatedString, | 723 | extern_symbol_name: InternPool.OptionalNullTerminatedString, |
| 731 | ) FlushDeclError!void { | 724 | ) FlushDeclError!void { |
| 732 | const gpa = self.base.comp.gpa; | 725 | const gpa = self.base.comp.gpa; |
| 733 | try self.flushLazyFns(f, decl_block.lazy_fns); | 726 | try self.flushLazyFns(zcu, mod, f, &decl_block.ctype_pool, decl_block.lazy_fns); |
| 734 | try f.all_buffers.ensureUnusedCapacity(gpa, 1); | 727 | try f.all_buffers.ensureUnusedCapacity(gpa, 1); |
| 735 | fwd_decl: { | 728 | fwd_decl: { |
| 736 | if (extern_symbol_name.unwrap()) |name| { | 729 | if (extern_symbol_name.unwrap()) |name| { |
| ... | @@ -740,15 +733,15 @@ fn flushDeclBlock( | ... | @@ -740,15 +733,15 @@ fn flushDeclBlock( |
| 740 | } | 733 | } |
| 741 | } | 734 | } |
| 742 | 735 | ||
| 743 | pub fn flushEmitH(module: *Module) !void { | 736 | pub fn flushEmitH(zcu: *Zcu) !void { |
| 744 | const tracy = trace(@src()); | 737 | const tracy = trace(@src()); |
| 745 | defer tracy.end(); | 738 | defer tracy.end(); |
| 746 | 739 | ||
| 747 | const emit_h = module.emit_h orelse return; | 740 | const emit_h = zcu.emit_h orelse return; |
| 748 | 741 | ||
| 749 | // We collect a list of buffers to write, and write them all at once with pwritev 😎 | 742 | // We collect a list of buffers to write, and write them all at once with pwritev 😎 |
| 750 | const num_buffers = emit_h.decl_table.count() + 1; | 743 | const num_buffers = emit_h.decl_table.count() + 1; |
| 751 | var all_buffers = try std.ArrayList(std.posix.iovec_const).initCapacity(module.gpa, num_buffers); | 744 | var all_buffers = try std.ArrayList(std.posix.iovec_const).initCapacity(zcu.gpa, num_buffers); |
| 752 | defer all_buffers.deinit(); | 745 | defer all_buffers.deinit(); |
| 753 | 746 | ||
| 754 | var file_size: u64 = zig_h.len; | 747 | var file_size: u64 = zig_h.len; |
| ... | @@ -771,7 +764,7 @@ pub fn flushEmitH(module: *Module) !void { | ... | @@ -771,7 +764,7 @@ pub fn flushEmitH(module: *Module) !void { |
| 771 | } | 764 | } |
| 772 | } | 765 | } |
| 773 | 766 | ||
| 774 | const directory = emit_h.loc.directory orelse module.comp.local_cache_directory; | 767 | const directory = emit_h.loc.directory orelse zcu.comp.local_cache_directory; |
| 775 | const file = try directory.handle.createFile(emit_h.loc.basename, .{ | 768 | const file = try directory.handle.createFile(emit_h.loc.basename, .{ |
| 776 | // We set the end position explicitly below; by not truncating the file, we possibly | 769 | // We set the end position explicitly below; by not truncating the file, we possibly |
| 777 | // make it easier on the file system by doing 1 reallocation instead of two. | 770 | // make it easier on the file system by doing 1 reallocation instead of two. |
| ... | @@ -785,12 +778,12 @@ pub fn flushEmitH(module: *Module) !void { | ... | @@ -785,12 +778,12 @@ pub fn flushEmitH(module: *Module) !void { |
| 785 | 778 | ||
| 786 | pub fn updateExports( | 779 | pub fn updateExports( |
| 787 | self: *C, | 780 | self: *C, |
| 788 | module: *Module, | 781 | zcu: *Zcu, |
| 789 | exported: Module.Exported, | 782 | exported: Zcu.Exported, |
| 790 | exports: []const *Module.Export, | 783 | exports: []const *Zcu.Export, |
| 791 | ) !void { | 784 | ) !void { |
| 792 | _ = exports; | 785 | _ = exports; |
| 793 | _ = exported; | 786 | _ = exported; |
| 794 | _ = module; | 787 | _ = zcu; |
| 795 | _ = self; | 788 | _ = self; |
| 796 | } | 789 | } |
src/link/Coff.zig+3-3| ... | @@ -1223,7 +1223,7 @@ fn lowerConst(self: *Coff, name: []const u8, val: Value, required_alignment: Int | ... | @@ -1223,7 +1223,7 @@ fn lowerConst(self: *Coff, name: []const u8, val: Value, required_alignment: Int |
| 1223 | atom.getSymbolPtr(self).value = try self.allocateAtom( | 1223 | atom.getSymbolPtr(self).value = try self.allocateAtom( |
| 1224 | atom_index, | 1224 | atom_index, |
| 1225 | atom.size, | 1225 | atom.size, |
| 1226 | @intCast(required_alignment.toByteUnitsOptional().?), | 1226 | @intCast(required_alignment.toByteUnits().?), |
| 1227 | ); | 1227 | ); |
| 1228 | errdefer self.freeAtom(atom_index); | 1228 | errdefer self.freeAtom(atom_index); |
| 1229 | 1229 | ||
| ... | @@ -1344,7 +1344,7 @@ fn updateLazySymbolAtom( | ... | @@ -1344,7 +1344,7 @@ fn updateLazySymbolAtom( |
| 1344 | symbol.section_number = @as(coff.SectionNumber, @enumFromInt(section_index + 1)); | 1344 | symbol.section_number = @as(coff.SectionNumber, @enumFromInt(section_index + 1)); |
| 1345 | symbol.type = .{ .complex_type = .NULL, .base_type = .NULL }; | 1345 | symbol.type = .{ .complex_type = .NULL, .base_type = .NULL }; |
| 1346 | 1346 | ||
| 1347 | const vaddr = try self.allocateAtom(atom_index, code_len, @intCast(required_alignment.toByteUnits(0))); | 1347 | const vaddr = try self.allocateAtom(atom_index, code_len, @intCast(required_alignment.toByteUnits() orelse 0)); |
| 1348 | errdefer self.freeAtom(atom_index); | 1348 | errdefer self.freeAtom(atom_index); |
| 1349 | 1349 | ||
| 1350 | log.debug("allocated atom for {s} at 0x{x}", .{ name, vaddr }); | 1350 | log.debug("allocated atom for {s} at 0x{x}", .{ name, vaddr }); |
| ... | @@ -1428,7 +1428,7 @@ fn updateDeclCode(self: *Coff, decl_index: InternPool.DeclIndex, code: []u8, com | ... | @@ -1428,7 +1428,7 @@ fn updateDeclCode(self: *Coff, decl_index: InternPool.DeclIndex, code: []u8, com |
| 1428 | const decl_name = mod.intern_pool.stringToSlice(try decl.fullyQualifiedName(mod)); | 1428 | const decl_name = mod.intern_pool.stringToSlice(try decl.fullyQualifiedName(mod)); |
| 1429 | 1429 | ||
| 1430 | log.debug("updateDeclCode {s}{*}", .{ decl_name, decl }); | 1430 | log.debug("updateDeclCode {s}{*}", .{ decl_name, decl }); |
| 1431 | const required_alignment: u32 = @intCast(decl.getAlignment(mod).toByteUnits(0)); | 1431 | const required_alignment: u32 = @intCast(decl.getAlignment(mod).toByteUnits() orelse 0); |
| 1432 | 1432 | ||
| 1433 | const decl_metadata = self.decls.get(decl_index).?; | 1433 | const decl_metadata = self.decls.get(decl_index).?; |
| 1434 | const atom_index = decl_metadata.atom; | 1434 | const atom_index = decl_metadata.atom; |
src/link/Elf.zig+1-1| ... | @@ -4051,7 +4051,7 @@ fn updateSectionSizes(self: *Elf) !void { | ... | @@ -4051,7 +4051,7 @@ fn updateSectionSizes(self: *Elf) !void { |
| 4051 | const padding = offset - shdr.sh_size; | 4051 | const padding = offset - shdr.sh_size; |
| 4052 | atom_ptr.value = offset; | 4052 | atom_ptr.value = offset; |
| 4053 | shdr.sh_size += padding + atom_ptr.size; | 4053 | shdr.sh_size += padding + atom_ptr.size; |
| 4054 | shdr.sh_addralign = @max(shdr.sh_addralign, atom_ptr.alignment.toByteUnits(1)); | 4054 | shdr.sh_addralign = @max(shdr.sh_addralign, atom_ptr.alignment.toByteUnits() orelse 1); |
| 4055 | } | 4055 | } |
| 4056 | } | 4056 | } |
| 4057 | 4057 |
src/link/Elf/Atom.zig+1-1| ... | @@ -208,7 +208,7 @@ pub fn allocate(self: *Atom, elf_file: *Elf) !void { | ... | @@ -208,7 +208,7 @@ pub fn allocate(self: *Atom, elf_file: *Elf) !void { |
| 208 | zig_object.debug_aranges_section_dirty = true; | 208 | zig_object.debug_aranges_section_dirty = true; |
| 209 | } | 209 | } |
| 210 | } | 210 | } |
| 211 | shdr.sh_addralign = @max(shdr.sh_addralign, self.alignment.toByteUnitsOptional().?); | 211 | shdr.sh_addralign = @max(shdr.sh_addralign, self.alignment.toByteUnits().?); |
| 212 | 212 | ||
| 213 | // This function can also reallocate an atom. | 213 | // This function can also reallocate an atom. |
| 214 | // In this case we need to "unplug" it from its previous location before | 214 | // In this case we need to "unplug" it from its previous location before |
src/link/Elf/ZigObject.zig+1-1| ... | @@ -313,7 +313,7 @@ pub fn inputShdr(self: ZigObject, atom_index: Atom.Index, elf_file: *Elf) elf.El | ... | @@ -313,7 +313,7 @@ pub fn inputShdr(self: ZigObject, atom_index: Atom.Index, elf_file: *Elf) elf.El |
| 313 | shdr.sh_addr = 0; | 313 | shdr.sh_addr = 0; |
| 314 | shdr.sh_offset = 0; | 314 | shdr.sh_offset = 0; |
| 315 | shdr.sh_size = atom.size; | 315 | shdr.sh_size = atom.size; |
| 316 | shdr.sh_addralign = atom.alignment.toByteUnits(1); | 316 | shdr.sh_addralign = atom.alignment.toByteUnits() orelse 1; |
| 317 | return shdr; | 317 | return shdr; |
| 318 | } | 318 | } |
| 319 | 319 |
src/link/Elf/relocatable.zig+1-1| ... | @@ -330,7 +330,7 @@ fn updateSectionSizes(elf_file: *Elf) !void { | ... | @@ -330,7 +330,7 @@ fn updateSectionSizes(elf_file: *Elf) !void { |
| 330 | const padding = offset - shdr.sh_size; | 330 | const padding = offset - shdr.sh_size; |
| 331 | atom_ptr.value = offset; | 331 | atom_ptr.value = offset; |
| 332 | shdr.sh_size += padding + atom_ptr.size; | 332 | shdr.sh_size += padding + atom_ptr.size; |
| 333 | shdr.sh_addralign = @max(shdr.sh_addralign, atom_ptr.alignment.toByteUnits(1)); | 333 | shdr.sh_addralign = @max(shdr.sh_addralign, atom_ptr.alignment.toByteUnits() orelse 1); |
| 334 | } | 334 | } |
| 335 | } | 335 | } |
| 336 | 336 |
src/link/Elf/thunks.zig+1-1| ... | @@ -63,7 +63,7 @@ fn advance(shdr: *elf.Elf64_Shdr, size: u64, alignment: Atom.Alignment) !u64 { | ... | @@ -63,7 +63,7 @@ fn advance(shdr: *elf.Elf64_Shdr, size: u64, alignment: Atom.Alignment) !u64 { |
| 63 | const offset = alignment.forward(shdr.sh_size); | 63 | const offset = alignment.forward(shdr.sh_size); |
| 64 | const padding = offset - shdr.sh_size; | 64 | const padding = offset - shdr.sh_size; |
| 65 | shdr.sh_size += padding + size; | 65 | shdr.sh_size += padding + size; |
| 66 | shdr.sh_addralign = @max(shdr.sh_addralign, alignment.toByteUnits(1)); | 66 | shdr.sh_addralign = @max(shdr.sh_addralign, alignment.toByteUnits() orelse 1); |
| 67 | return offset; | 67 | return offset; |
| 68 | } | 68 | } |
| 69 | 69 |
src/link/MachO.zig+1-1| ... | @@ -2060,7 +2060,7 @@ fn calcSectionSizes(self: *MachO) !void { | ... | @@ -2060,7 +2060,7 @@ fn calcSectionSizes(self: *MachO) !void { |
| 2060 | 2060 | ||
| 2061 | for (atoms.items) |atom_index| { | 2061 | for (atoms.items) |atom_index| { |
| 2062 | const atom = self.getAtom(atom_index).?; | 2062 | const atom = self.getAtom(atom_index).?; |
| 2063 | const atom_alignment = atom.alignment.toByteUnits(1); | 2063 | const atom_alignment = atom.alignment.toByteUnits() orelse 1; |
| 2064 | const offset = mem.alignForward(u64, header.size, atom_alignment); | 2064 | const offset = mem.alignForward(u64, header.size, atom_alignment); |
| 2065 | const padding = offset - header.size; | 2065 | const padding = offset - header.size; |
| 2066 | atom.value = offset; | 2066 | atom.value = offset; |
src/link/MachO/relocatable.zig+1-1| ... | @@ -380,7 +380,7 @@ fn calcSectionSizes(macho_file: *MachO) !void { | ... | @@ -380,7 +380,7 @@ fn calcSectionSizes(macho_file: *MachO) !void { |
| 380 | if (atoms.items.len == 0) continue; | 380 | if (atoms.items.len == 0) continue; |
| 381 | for (atoms.items) |atom_index| { | 381 | for (atoms.items) |atom_index| { |
| 382 | const atom = macho_file.getAtom(atom_index).?; | 382 | const atom = macho_file.getAtom(atom_index).?; |
| 383 | const atom_alignment = atom.alignment.toByteUnits(1); | 383 | const atom_alignment = atom.alignment.toByteUnits() orelse 1; |
| 384 | const offset = mem.alignForward(u64, header.size, atom_alignment); | 384 | const offset = mem.alignForward(u64, header.size, atom_alignment); |
| 385 | const padding = offset - header.size; | 385 | const padding = offset - header.size; |
| 386 | atom.value = offset; | 386 | atom.value = offset; |
src/link/Wasm.zig+1-1| ... | @@ -2263,7 +2263,7 @@ fn setupMemory(wasm: *Wasm) !void { | ... | @@ -2263,7 +2263,7 @@ fn setupMemory(wasm: *Wasm) !void { |
| 2263 | } | 2263 | } |
| 2264 | if (wasm.findGlobalSymbol("__tls_align")) |loc| { | 2264 | if (wasm.findGlobalSymbol("__tls_align")) |loc| { |
| 2265 | const sym = loc.getSymbol(wasm); | 2265 | const sym = loc.getSymbol(wasm); |
| 2266 | wasm.wasm_globals.items[sym.index - wasm.imported_globals_count].init.i32_const = @intCast(segment.alignment.toByteUnitsOptional().?); | 2266 | wasm.wasm_globals.items[sym.index - wasm.imported_globals_count].init.i32_const = @intCast(segment.alignment.toByteUnits().?); |
| 2267 | } | 2267 | } |
| 2268 | if (wasm.findGlobalSymbol("__tls_base")) |loc| { | 2268 | if (wasm.findGlobalSymbol("__tls_base")) |loc| { |
| 2269 | const sym = loc.getSymbol(wasm); | 2269 | const sym = loc.getSymbol(wasm); |
src/link/tapi/parse.zig+15-24| ... | @@ -29,34 +29,28 @@ pub const Node = struct { | ... | @@ -29,34 +29,28 @@ pub const Node = struct { |
| 29 | map, | 29 | map, |
| 30 | list, | 30 | list, |
| 31 | value, | 31 | value, |
| 32 | |||
| 33 | pub fn Type(comptime tag: Tag) type { | ||
| 34 | return switch (tag) { | ||
| 35 | .doc => Doc, | ||
| 36 | .map => Map, | ||
| 37 | .list => List, | ||
| 38 | .value => Value, | ||
| 39 | }; | ||
| 40 | } | ||
| 32 | }; | 41 | }; |
| 33 | 42 | ||
| 34 | pub fn cast(self: *const Node, comptime T: type) ?*const T { | 43 | pub fn cast(self: *const Node, comptime T: type) ?*const T { |
| 35 | if (self.tag != T.base_tag) { | 44 | if (self.tag != T.base_tag) { |
| 36 | return null; | 45 | return null; |
| 37 | } | 46 | } |
| 38 | return @fieldParentPtr(T, "base", self); | 47 | return @fieldParentPtr("base", self); |
| 39 | } | 48 | } |
| 40 | 49 | ||
| 41 | pub fn deinit(self: *Node, allocator: Allocator) void { | 50 | pub fn deinit(self: *Node, allocator: Allocator) void { |
| 42 | switch (self.tag) { | 51 | switch (self.tag) { |
| 43 | .doc => { | 52 | inline else => |tag| { |
| 44 | const parent = @fieldParentPtr(Node.Doc, "base", self); | 53 | const parent: *tag.Type() = @fieldParentPtr("base", self); |
| 45 | parent.deinit(allocator); | ||
| 46 | allocator.destroy(parent); | ||
| 47 | }, | ||
| 48 | .map => { | ||
| 49 | const parent = @fieldParentPtr(Node.Map, "base", self); | ||
| 50 | parent.deinit(allocator); | ||
| 51 | allocator.destroy(parent); | ||
| 52 | }, | ||
| 53 | .list => { | ||
| 54 | const parent = @fieldParentPtr(Node.List, "base", self); | ||
| 55 | parent.deinit(allocator); | ||
| 56 | allocator.destroy(parent); | ||
| 57 | }, | ||
| 58 | .value => { | ||
| 59 | const parent = @fieldParentPtr(Node.Value, "base", self); | ||
| 60 | parent.deinit(allocator); | 54 | parent.deinit(allocator); |
| 61 | allocator.destroy(parent); | 55 | allocator.destroy(parent); |
| 62 | }, | 56 | }, |
| ... | @@ -69,12 +63,9 @@ pub const Node = struct { | ... | @@ -69,12 +63,9 @@ pub const Node = struct { |
| 69 | options: std.fmt.FormatOptions, | 63 | options: std.fmt.FormatOptions, |
| 70 | writer: anytype, | 64 | writer: anytype, |
| 71 | ) !void { | 65 | ) !void { |
| 72 | return switch (self.tag) { | 66 | switch (self.tag) { |
| 73 | .doc => @fieldParentPtr(Node.Doc, "base", self).format(fmt, options, writer), | 67 | inline else => |tag| return @as(*tag.Type(), @fieldParentPtr("base", self)).format(fmt, options, writer), |
| 74 | .map => @fieldParentPtr(Node.Map, "base", self).format(fmt, options, writer), | 68 | } |
| 75 | .list => @fieldParentPtr(Node.List, "base", self).format(fmt, options, writer), | ||
| 76 | .value => @fieldParentPtr(Node.Value, "base", self).format(fmt, options, writer), | ||
| 77 | }; | ||
| 78 | } | 69 | } |
| 79 | 70 | ||
| 80 | pub const Doc = struct { | 71 | pub const Doc = struct { |
src/main.zig+1-5| ... | @@ -3544,11 +3544,7 @@ fn createModule( | ... | @@ -3544,11 +3544,7 @@ fn createModule( |
| 3544 | // If the target is not overridden, use the parent's target. Of course, | 3544 | // If the target is not overridden, use the parent's target. Of course, |
| 3545 | // if this is the root module then we need to proceed to resolve the | 3545 | // if this is the root module then we need to proceed to resolve the |
| 3546 | // target. | 3546 | // target. |
| 3547 | if (cli_mod.target_arch_os_abi == null and | 3547 | if (cli_mod.target_arch_os_abi == null and cli_mod.target_mcpu == null) { |
| 3548 | cli_mod.target_mcpu == null and | ||
| 3549 | create_module.dynamic_linker == null and | ||
| 3550 | create_module.object_format == null) | ||
| 3551 | { | ||
| 3552 | if (parent) |p| break :t p.resolved_target; | 3548 | if (parent) |p| break :t p.resolved_target; |
| 3553 | } | 3549 | } |
| 3554 | 3550 |
src/print_value.zig+1-1| ... | @@ -80,7 +80,7 @@ pub fn print( | ... | @@ -80,7 +80,7 @@ pub fn print( |
| 80 | inline .u64, .i64, .big_int => |x| try writer.print("{}", .{x}), | 80 | inline .u64, .i64, .big_int => |x| try writer.print("{}", .{x}), |
| 81 | .lazy_align => |ty| if (opt_sema) |sema| { | 81 | .lazy_align => |ty| if (opt_sema) |sema| { |
| 82 | const a = (try Type.fromInterned(ty).abiAlignmentAdvanced(mod, .{ .sema = sema })).scalar; | 82 | const a = (try Type.fromInterned(ty).abiAlignmentAdvanced(mod, .{ .sema = sema })).scalar; |
| 83 | try writer.print("{}", .{a.toByteUnits(0)}); | 83 | try writer.print("{}", .{a.toByteUnits() orelse 0}); |
| 84 | } else try writer.print("@alignOf({})", .{Type.fromInterned(ty).fmt(mod)}), | 84 | } else try writer.print("@alignOf({})", .{Type.fromInterned(ty).fmt(mod)}), |
| 85 | .lazy_size => |ty| if (opt_sema) |sema| { | 85 | .lazy_size => |ty| if (opt_sema) |sema| { |
| 86 | const s = (try Type.fromInterned(ty).abiSizeAdvanced(mod, .{ .sema = sema })).scalar; | 86 | const s = (try Type.fromInterned(ty).abiSizeAdvanced(mod, .{ .sema = sema })).scalar; |
src/print_zir.zig+15-8| ... | @@ -355,7 +355,6 @@ const Writer = struct { | ... | @@ -355,7 +355,6 @@ const Writer = struct { |
| 355 | .atomic_rmw => try self.writeAtomicRmw(stream, inst), | 355 | .atomic_rmw => try self.writeAtomicRmw(stream, inst), |
| 356 | .shuffle => try self.writeShuffle(stream, inst), | 356 | .shuffle => try self.writeShuffle(stream, inst), |
| 357 | .mul_add => try self.writeMulAdd(stream, inst), | 357 | .mul_add => try self.writeMulAdd(stream, inst), |
| 358 | .field_parent_ptr => try self.writeFieldParentPtr(stream, inst), | ||
| 359 | .builtin_call => try self.writeBuiltinCall(stream, inst), | 358 | .builtin_call => try self.writeBuiltinCall(stream, inst), |
| 360 | 359 | ||
| 361 | .field_type_ref => try self.writeFieldTypeRef(stream, inst), | 360 | .field_type_ref => try self.writeFieldTypeRef(stream, inst), |
| ... | @@ -609,6 +608,7 @@ const Writer = struct { | ... | @@ -609,6 +608,7 @@ const Writer = struct { |
| 609 | 608 | ||
| 610 | .restore_err_ret_index => try self.writeRestoreErrRetIndex(stream, extended), | 609 | .restore_err_ret_index => try self.writeRestoreErrRetIndex(stream, extended), |
| 611 | .closure_get => try self.writeClosureGet(stream, extended), | 610 | .closure_get => try self.writeClosureGet(stream, extended), |
| 611 | .field_parent_ptr => try self.writeFieldParentPtr(stream, extended), | ||
| 612 | } | 612 | } |
| 613 | } | 613 | } |
| 614 | 614 | ||
| ... | @@ -901,16 +901,21 @@ const Writer = struct { | ... | @@ -901,16 +901,21 @@ const Writer = struct { |
| 901 | try self.writeSrc(stream, inst_data.src()); | 901 | try self.writeSrc(stream, inst_data.src()); |
| 902 | } | 902 | } |
| 903 | 903 | ||
| 904 | fn writeFieldParentPtr(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void { | 904 | fn writeFieldParentPtr(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void { |
| 905 | const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; | 905 | const extra = self.code.extraData(Zir.Inst.FieldParentPtr, extended.operand).data; |
| 906 | const extra = self.code.extraData(Zir.Inst.FieldParentPtr, inst_data.payload_index).data; | 906 | const FlagsInt = @typeInfo(Zir.Inst.FullPtrCastFlags).Struct.backing_integer.?; |
| 907 | try self.writeInstRef(stream, extra.parent_type); | 907 | const flags: Zir.Inst.FullPtrCastFlags = @bitCast(@as(FlagsInt, @truncate(extended.small))); |
| 908 | if (flags.align_cast) try stream.writeAll("align_cast, "); | ||
| 909 | if (flags.addrspace_cast) try stream.writeAll("addrspace_cast, "); | ||
| 910 | if (flags.const_cast) try stream.writeAll("const_cast, "); | ||
| 911 | if (flags.volatile_cast) try stream.writeAll("volatile_cast, "); | ||
| 912 | try self.writeInstRef(stream, extra.parent_ptr_type); | ||
| 908 | try stream.writeAll(", "); | 913 | try stream.writeAll(", "); |
| 909 | try self.writeInstRef(stream, extra.field_name); | 914 | try self.writeInstRef(stream, extra.field_name); |
| 910 | try stream.writeAll(", "); | 915 | try stream.writeAll(", "); |
| 911 | try self.writeInstRef(stream, extra.field_ptr); | 916 | try self.writeInstRef(stream, extra.field_ptr); |
| 912 | try stream.writeAll(") "); | 917 | try stream.writeAll(") "); |
| 913 | try self.writeSrc(stream, inst_data.src()); | 918 | try self.writeSrc(stream, extra.src()); |
| 914 | } | 919 | } |
| 915 | 920 | ||
| 916 | fn writeBuiltinAsyncCall(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void { | 921 | fn writeBuiltinAsyncCall(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void { |
| ... | @@ -1069,7 +1074,8 @@ const Writer = struct { | ... | @@ -1069,7 +1074,8 @@ const Writer = struct { |
| 1069 | } | 1074 | } |
| 1070 | 1075 | ||
| 1071 | fn writePtrCastFull(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void { | 1076 | fn writePtrCastFull(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void { |
| 1072 | const flags = @as(Zir.Inst.FullPtrCastFlags, @bitCast(@as(u5, @truncate(extended.small)))); | 1077 | const FlagsInt = @typeInfo(Zir.Inst.FullPtrCastFlags).Struct.backing_integer.?; |
| 1078 | const flags: Zir.Inst.FullPtrCastFlags = @bitCast(@as(FlagsInt, @truncate(extended.small))); | ||
| 1073 | const extra = self.code.extraData(Zir.Inst.BinNode, extended.operand).data; | 1079 | const extra = self.code.extraData(Zir.Inst.BinNode, extended.operand).data; |
| 1074 | const src = LazySrcLoc.nodeOffset(extra.node); | 1080 | const src = LazySrcLoc.nodeOffset(extra.node); |
| 1075 | if (flags.ptr_cast) try stream.writeAll("ptr_cast, "); | 1081 | if (flags.ptr_cast) try stream.writeAll("ptr_cast, "); |
| ... | @@ -1085,7 +1091,8 @@ const Writer = struct { | ... | @@ -1085,7 +1091,8 @@ const Writer = struct { |
| 1085 | } | 1091 | } |
| 1086 | 1092 | ||
| 1087 | fn writePtrCastNoDest(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void { | 1093 | fn writePtrCastNoDest(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void { |
| 1088 | const flags = @as(Zir.Inst.FullPtrCastFlags, @bitCast(@as(u5, @truncate(extended.small)))); | 1094 | const FlagsInt = @typeInfo(Zir.Inst.FullPtrCastFlags).Struct.backing_integer.?; |
| 1095 | const flags: Zir.Inst.FullPtrCastFlags = @bitCast(@as(FlagsInt, @truncate(extended.small))); | ||
| 1089 | const extra = self.code.extraData(Zir.Inst.UnNode, extended.operand).data; | 1096 | const extra = self.code.extraData(Zir.Inst.UnNode, extended.operand).data; |
| 1090 | const src = LazySrcLoc.nodeOffset(extra.node); | 1097 | const src = LazySrcLoc.nodeOffset(extra.node); |
| 1091 | if (flags.const_cast) try stream.writeAll("const_cast, "); | 1098 | if (flags.const_cast) try stream.writeAll("const_cast, "); |
src/register_manager.zig+1-1| ... | @@ -59,7 +59,7 @@ pub fn RegisterManager( | ... | @@ -59,7 +59,7 @@ pub fn RegisterManager( |
| 59 | pub const RegisterBitSet = StaticBitSet(tracked_registers.len); | 59 | pub const RegisterBitSet = StaticBitSet(tracked_registers.len); |
| 60 | 60 | ||
| 61 | fn getFunction(self: *Self) *Function { | 61 | fn getFunction(self: *Self) *Function { |
| 62 | return @fieldParentPtr(Function, "register_manager", self); | 62 | return @alignCast(@fieldParentPtr("register_manager", self)); |
| 63 | } | 63 | } |
| 64 | 64 | ||
| 65 | fn excludeRegister(reg: Register, register_class: RegisterBitSet) bool { | 65 | fn excludeRegister(reg: Register, register_class: RegisterBitSet) bool { |
src/target.zig+1-1| ... | @@ -525,7 +525,7 @@ pub fn backendSupportsFeature( | ... | @@ -525,7 +525,7 @@ pub fn backendSupportsFeature( |
| 525 | .error_return_trace => use_llvm, | 525 | .error_return_trace => use_llvm, |
| 526 | .is_named_enum_value => use_llvm, | 526 | .is_named_enum_value => use_llvm, |
| 527 | .error_set_has_value => use_llvm or cpu_arch.isWasm(), | 527 | .error_set_has_value => use_llvm or cpu_arch.isWasm(), |
| 528 | .field_reordering => use_llvm, | 528 | .field_reordering => ofmt == .c or use_llvm, |
| 529 | .safety_checked_instructions => use_llvm, | 529 | .safety_checked_instructions => use_llvm, |
| 530 | }; | 530 | }; |
| 531 | } | 531 | } |
src/type.zig+25-27| ... | @@ -203,7 +203,7 @@ pub const Type = struct { | ... | @@ -203,7 +203,7 @@ pub const Type = struct { |
| 203 | info.flags.alignment | 203 | info.flags.alignment |
| 204 | else | 204 | else |
| 205 | Type.fromInterned(info.child).abiAlignment(mod); | 205 | Type.fromInterned(info.child).abiAlignment(mod); |
| 206 | try writer.print("align({d}", .{alignment.toByteUnits(0)}); | 206 | try writer.print("align({d}", .{alignment.toByteUnits() orelse 0}); |
| 207 | 207 | ||
| 208 | if (info.packed_offset.bit_offset != 0 or info.packed_offset.host_size != 0) { | 208 | if (info.packed_offset.bit_offset != 0 or info.packed_offset.host_size != 0) { |
| 209 | try writer.print(":{d}:{d}", .{ | 209 | try writer.print(":{d}:{d}", .{ |
| ... | @@ -863,7 +863,7 @@ pub const Type = struct { | ... | @@ -863,7 +863,7 @@ pub const Type = struct { |
| 863 | pub fn lazyAbiAlignment(ty: Type, mod: *Module) !Value { | 863 | pub fn lazyAbiAlignment(ty: Type, mod: *Module) !Value { |
| 864 | switch (try ty.abiAlignmentAdvanced(mod, .lazy)) { | 864 | switch (try ty.abiAlignmentAdvanced(mod, .lazy)) { |
| 865 | .val => |val| return val, | 865 | .val => |val| return val, |
| 866 | .scalar => |x| return mod.intValue(Type.comptime_int, x.toByteUnits(0)), | 866 | .scalar => |x| return mod.intValue(Type.comptime_int, x.toByteUnits() orelse 0), |
| 867 | } | 867 | } |
| 868 | } | 868 | } |
| 869 | 869 | ||
| ... | @@ -905,7 +905,7 @@ pub const Type = struct { | ... | @@ -905,7 +905,7 @@ pub const Type = struct { |
| 905 | return .{ .scalar = intAbiAlignment(int_type.bits, target) }; | 905 | return .{ .scalar = intAbiAlignment(int_type.bits, target) }; |
| 906 | }, | 906 | }, |
| 907 | .ptr_type, .anyframe_type => { | 907 | .ptr_type, .anyframe_type => { |
| 908 | return .{ .scalar = Alignment.fromByteUnits(@divExact(target.ptrBitWidth(), 8)) }; | 908 | return .{ .scalar = ptrAbiAlignment(target) }; |
| 909 | }, | 909 | }, |
| 910 | .array_type => |array_type| { | 910 | .array_type => |array_type| { |
| 911 | return Type.fromInterned(array_type.child).abiAlignmentAdvanced(mod, strat); | 911 | return Type.fromInterned(array_type.child).abiAlignmentAdvanced(mod, strat); |
| ... | @@ -920,6 +920,9 @@ pub const Type = struct { | ... | @@ -920,6 +920,9 @@ pub const Type = struct { |
| 920 | const alignment = std.math.ceilPowerOfTwoAssert(u32, bytes); | 920 | const alignment = std.math.ceilPowerOfTwoAssert(u32, bytes); |
| 921 | return .{ .scalar = Alignment.fromByteUnits(alignment) }; | 921 | return .{ .scalar = Alignment.fromByteUnits(alignment) }; |
| 922 | }, | 922 | }, |
| 923 | .stage2_c => { | ||
| 924 | return Type.fromInterned(vector_type.child).abiAlignmentAdvanced(mod, strat); | ||
| 925 | }, | ||
| 923 | .stage2_x86_64 => { | 926 | .stage2_x86_64 => { |
| 924 | if (vector_type.child == .bool_type) { | 927 | if (vector_type.child == .bool_type) { |
| 925 | if (vector_type.len > 256 and std.Target.x86.featureSetHas(target.cpu.features, .avx512f)) return .{ .scalar = .@"64" }; | 928 | if (vector_type.len > 256 and std.Target.x86.featureSetHas(target.cpu.features, .avx512f)) return .{ .scalar = .@"64" }; |
| ... | @@ -966,12 +969,12 @@ pub const Type = struct { | ... | @@ -966,12 +969,12 @@ pub const Type = struct { |
| 966 | 969 | ||
| 967 | .usize, | 970 | .usize, |
| 968 | .isize, | 971 | .isize, |
| 972 | => return .{ .scalar = intAbiAlignment(target.ptrBitWidth(), target) }, | ||
| 973 | |||
| 969 | .export_options, | 974 | .export_options, |
| 970 | .extern_options, | 975 | .extern_options, |
| 971 | .type_info, | 976 | .type_info, |
| 972 | => return .{ | 977 | => return .{ .scalar = ptrAbiAlignment(target) }, |
| 973 | .scalar = Alignment.fromByteUnits(@divExact(target.ptrBitWidth(), 8)), | ||
| 974 | }, | ||
| 975 | 978 | ||
| 976 | .c_char => return .{ .scalar = cTypeAlign(target, .char) }, | 979 | .c_char => return .{ .scalar = cTypeAlign(target, .char) }, |
| 977 | .c_short => return .{ .scalar = cTypeAlign(target, .short) }, | 980 | .c_short => return .{ .scalar = cTypeAlign(target, .short) }, |
| ... | @@ -1160,9 +1163,7 @@ pub const Type = struct { | ... | @@ -1160,9 +1163,7 @@ pub const Type = struct { |
| 1160 | const child_type = ty.optionalChild(mod); | 1163 | const child_type = ty.optionalChild(mod); |
| 1161 | 1164 | ||
| 1162 | switch (child_type.zigTypeTag(mod)) { | 1165 | switch (child_type.zigTypeTag(mod)) { |
| 1163 | .Pointer => return .{ | 1166 | .Pointer => return .{ .scalar = ptrAbiAlignment(target) }, |
| 1164 | .scalar = Alignment.fromByteUnits(@divExact(target.ptrBitWidth(), 8)), | ||
| 1165 | }, | ||
| 1166 | .ErrorSet => return abiAlignmentAdvanced(Type.anyerror, mod, strat), | 1167 | .ErrorSet => return abiAlignmentAdvanced(Type.anyerror, mod, strat), |
| 1167 | .NoReturn => return .{ .scalar = .@"1" }, | 1168 | .NoReturn => return .{ .scalar = .@"1" }, |
| 1168 | else => {}, | 1169 | else => {}, |
| ... | @@ -1274,6 +1275,10 @@ pub const Type = struct { | ... | @@ -1274,6 +1275,10 @@ pub const Type = struct { |
| 1274 | const total_bits = elem_bits * vector_type.len; | 1275 | const total_bits = elem_bits * vector_type.len; |
| 1275 | break :total_bytes (total_bits + 7) / 8; | 1276 | break :total_bytes (total_bits + 7) / 8; |
| 1276 | }, | 1277 | }, |
| 1278 | .stage2_c => total_bytes: { | ||
| 1279 | const elem_bytes: u32 = @intCast((try Type.fromInterned(vector_type.child).abiSizeAdvanced(mod, strat)).scalar); | ||
| 1280 | break :total_bytes elem_bytes * vector_type.len; | ||
| 1281 | }, | ||
| 1277 | .stage2_x86_64 => total_bytes: { | 1282 | .stage2_x86_64 => total_bytes: { |
| 1278 | if (vector_type.child == .bool_type) break :total_bytes std.math.divCeil(u32, vector_type.len, 8) catch unreachable; | 1283 | if (vector_type.child == .bool_type) break :total_bytes std.math.divCeil(u32, vector_type.len, 8) catch unreachable; |
| 1279 | const elem_bytes: u32 = @intCast((try Type.fromInterned(vector_type.child).abiSizeAdvanced(mod, strat)).scalar); | 1284 | const elem_bytes: u32 = @intCast((try Type.fromInterned(vector_type.child).abiSizeAdvanced(mod, strat)).scalar); |
| ... | @@ -1527,15 +1532,19 @@ pub const Type = struct { | ... | @@ -1527,15 +1532,19 @@ pub const Type = struct { |
| 1527 | // guaranteed to be >= that of bool's (1 byte) the added size is exactly equal | 1532 | // guaranteed to be >= that of bool's (1 byte) the added size is exactly equal |
| 1528 | // to the child type's ABI alignment. | 1533 | // to the child type's ABI alignment. |
| 1529 | return AbiSizeAdvanced{ | 1534 | return AbiSizeAdvanced{ |
| 1530 | .scalar = child_ty.abiAlignment(mod).toByteUnits(0) + payload_size, | 1535 | .scalar = (child_ty.abiAlignment(mod).toByteUnits() orelse 0) + payload_size, |
| 1531 | }; | 1536 | }; |
| 1532 | } | 1537 | } |
| 1533 | 1538 | ||
| 1534 | fn intAbiSize(bits: u16, target: Target) u64 { | 1539 | pub fn ptrAbiAlignment(target: Target) Alignment { |
| 1540 | return Alignment.fromNonzeroByteUnits(@divExact(target.ptrBitWidth(), 8)); | ||
| 1541 | } | ||
| 1542 | |||
| 1543 | pub fn intAbiSize(bits: u16, target: Target) u64 { | ||
| 1535 | return intAbiAlignment(bits, target).forward(@as(u16, @intCast((@as(u17, bits) + 7) / 8))); | 1544 | return intAbiAlignment(bits, target).forward(@as(u16, @intCast((@as(u17, bits) + 7) / 8))); |
| 1536 | } | 1545 | } |
| 1537 | 1546 | ||
| 1538 | fn intAbiAlignment(bits: u16, target: Target) Alignment { | 1547 | pub fn intAbiAlignment(bits: u16, target: Target) Alignment { |
| 1539 | return Alignment.fromByteUnits(@min( | 1548 | return Alignment.fromByteUnits(@min( |
| 1540 | std.math.ceilPowerOfTwoPromote(u16, @as(u16, @intCast((@as(u17, bits) + 7) / 8))), | 1549 | std.math.ceilPowerOfTwoPromote(u16, @as(u16, @intCast((@as(u17, bits) + 7) / 8))), |
| 1541 | target.maxIntAlignment(), | 1550 | target.maxIntAlignment(), |
| ... | @@ -1572,7 +1581,7 @@ pub const Type = struct { | ... | @@ -1572,7 +1581,7 @@ pub const Type = struct { |
| 1572 | if (len == 0) return 0; | 1581 | if (len == 0) return 0; |
| 1573 | const elem_ty = Type.fromInterned(array_type.child); | 1582 | const elem_ty = Type.fromInterned(array_type.child); |
| 1574 | const elem_size = @max( | 1583 | const elem_size = @max( |
| 1575 | (try elem_ty.abiAlignmentAdvanced(mod, strat)).scalar.toByteUnits(0), | 1584 | (try elem_ty.abiAlignmentAdvanced(mod, strat)).scalar.toByteUnits() orelse 0, |
| 1576 | (try elem_ty.abiSizeAdvanced(mod, strat)).scalar, | 1585 | (try elem_ty.abiSizeAdvanced(mod, strat)).scalar, |
| 1577 | ); | 1586 | ); |
| 1578 | if (elem_size == 0) return 0; | 1587 | if (elem_size == 0) return 0; |
| ... | @@ -3016,26 +3025,15 @@ pub const Type = struct { | ... | @@ -3016,26 +3025,15 @@ pub const Type = struct { |
| 3016 | } | 3025 | } |
| 3017 | 3026 | ||
| 3018 | /// Returns none in the case of a tuple which uses the integer index as the field name. | 3027 | /// Returns none in the case of a tuple which uses the integer index as the field name. |
| 3019 | pub fn structFieldName(ty: Type, field_index: u32, mod: *Module) InternPool.OptionalNullTerminatedString { | 3028 | pub fn structFieldName(ty: Type, index: usize, mod: *Module) InternPool.OptionalNullTerminatedString { |
| 3020 | const ip = &mod.intern_pool; | 3029 | const ip = &mod.intern_pool; |
| 3021 | return switch (ip.indexToKey(ty.toIntern())) { | 3030 | return switch (ip.indexToKey(ty.toIntern())) { |
| 3022 | .struct_type => ip.loadStructType(ty.toIntern()).fieldName(ip, field_index), | 3031 | .struct_type => ip.loadStructType(ty.toIntern()).fieldName(ip, index), |
| 3023 | .anon_struct_type => |anon_struct| anon_struct.fieldName(ip, field_index), | 3032 | .anon_struct_type => |anon_struct| anon_struct.fieldName(ip, index), |
| 3024 | else => unreachable, | 3033 | else => unreachable, |
| 3025 | }; | 3034 | }; |
| 3026 | } | 3035 | } |
| 3027 | 3036 | ||
| 3028 | /// When struct types have no field names, the names are implicitly understood to be | ||
| 3029 | /// strings corresponding to the field indexes in declaration order. It used to be the | ||
| 3030 | /// case that a NullTerminatedString would be stored for each field in this case, however, | ||
| 3031 | /// now, callers must handle the possibility that there are no names stored at all. | ||
| 3032 | /// Here we fake the previous behavior. Probably something better could be done by examining | ||
| 3033 | /// all the callsites of this function. | ||
| 3034 | pub fn legacyStructFieldName(ty: Type, i: u32, mod: *Module) InternPool.NullTerminatedString { | ||
| 3035 | return ty.structFieldName(i, mod).unwrap() orelse | ||
| 3036 | mod.intern_pool.getOrPutStringFmt(mod.gpa, "{d}", .{i}) catch @panic("OOM"); | ||
| 3037 | } | ||
| 3038 | |||
| 3039 | pub fn structFieldCount(ty: Type, mod: *Module) u32 { | 3037 | pub fn structFieldCount(ty: Type, mod: *Module) u32 { |
| 3040 | const ip = &mod.intern_pool; | 3038 | const ip = &mod.intern_pool; |
| 3041 | return switch (ip.indexToKey(ty.toIntern())) { | 3039 | return switch (ip.indexToKey(ty.toIntern())) { |
stage1/zig.h+13-14| ... | @@ -130,22 +130,18 @@ typedef char bool; | ... | @@ -130,22 +130,18 @@ typedef char bool; |
| 130 | #define zig_restrict | 130 | #define zig_restrict |
| 131 | #endif | 131 | #endif |
| 132 | 132 | ||
| 133 | #if __STDC_VERSION__ >= 201112L | 133 | #if zig_has_attribute(aligned) |
| 134 | #define zig_align(alignment) _Alignas(alignment) | 134 | #define zig_under_align(alignment) __attribute__((aligned(alignment))) |
| 135 | #elif zig_has_attribute(aligned) | ||
| 136 | #define zig_align(alignment) __attribute__((aligned(alignment))) | ||
| 137 | #elif _MSC_VER | 135 | #elif _MSC_VER |
| 138 | #define zig_align(alignment) __declspec(align(alignment)) | 136 | #define zig_under_align(alignment) __declspec(align(alignment)) |
| 139 | #else | 137 | #else |
| 140 | #define zig_align zig_align_unavailable | 138 | #define zig_under_align zig_align_unavailable |
| 141 | #endif | 139 | #endif |
| 142 | 140 | ||
| 143 | #if zig_has_attribute(aligned) | 141 | #if __STDC_VERSION__ >= 201112L |
| 144 | #define zig_under_align(alignment) __attribute__((aligned(alignment))) | 142 | #define zig_align(alignment) _Alignas(alignment) |
| 145 | #elif _MSC_VER | ||
| 146 | #define zig_under_align(alignment) zig_align(alignment) | ||
| 147 | #else | 143 | #else |
| 148 | #define zig_align zig_align_unavailable | 144 | #define zig_align(alignment) zig_under_align(alignment) |
| 149 | #endif | 145 | #endif |
| 150 | 146 | ||
| 151 | #if zig_has_attribute(aligned) | 147 | #if zig_has_attribute(aligned) |
| ... | @@ -165,11 +161,14 @@ typedef char bool; | ... | @@ -165,11 +161,14 @@ typedef char bool; |
| 165 | #endif | 161 | #endif |
| 166 | 162 | ||
| 167 | #if zig_has_attribute(section) | 163 | #if zig_has_attribute(section) |
| 168 | #define zig_linksection(name, def, ...) def __attribute__((section(name))) | 164 | #define zig_linksection(name) __attribute__((section(name))) |
| 165 | #define zig_linksection_fn zig_linksection | ||
| 169 | #elif _MSC_VER | 166 | #elif _MSC_VER |
| 170 | #define zig_linksection(name, def, ...) __pragma(section(name, __VA_ARGS__)) __declspec(allocate(name)) def | 167 | #define zig_linksection(name) __pragma(section(name, read, write)) __declspec(allocate(name)) |
| 168 | #define zig_linksection_fn(name) __pragma(section(name, read, execute)) __declspec(code_seg(name)) | ||
| 171 | #else | 169 | #else |
| 172 | #define zig_linksection(name, def, ...) zig_linksection_unavailable | 170 | #define zig_linksection(name) zig_linksection_unavailable |
| 171 | #define zig_linksection_fn zig_linksection | ||
| 173 | #endif | 172 | #endif |
| 174 | 173 | ||
| 175 | #if zig_has_builtin(unreachable) || defined(zig_gnuc) | 174 | #if zig_has_builtin(unreachable) || defined(zig_gnuc) |
stage1/zig1.wasm| Binary files a/stage1/zig1.wasm and b/stage1/zig1.wasm differ | |||
test/behavior/align.zig+1-2| ... | @@ -624,7 +624,6 @@ test "sub-aligned pointer field access" { | ... | @@ -624,7 +624,6 @@ test "sub-aligned pointer field access" { |
| 624 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | 624 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 625 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | 625 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 626 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; | 626 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; |
| 627 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | ||
| 628 | 627 | ||
| 629 | // Originally reported at https://github.com/ziglang/zig/issues/14904 | 628 | // Originally reported at https://github.com/ziglang/zig/issues/14904 |
| 630 | 629 | ||
| ... | @@ -694,5 +693,5 @@ test "zero-bit fields in extern struct pad fields appropriately" { | ... | @@ -694,5 +693,5 @@ test "zero-bit fields in extern struct pad fields appropriately" { |
| 694 | try expect(@intFromPtr(&s) % 2 == 0); | 693 | try expect(@intFromPtr(&s) % 2 == 0); |
| 695 | try expect(@intFromPtr(&s.y) - @intFromPtr(&s.x) == 2); | 694 | try expect(@intFromPtr(&s.y) - @intFromPtr(&s.x) == 2); |
| 696 | try expect(@intFromPtr(&s.y) == @intFromPtr(&s.a)); | 695 | try expect(@intFromPtr(&s.y) == @intFromPtr(&s.a)); |
| 697 | try expect(@fieldParentPtr(S, "a", &s.a) == &s); | 696 | try expect(@as(*S, @fieldParentPtr("a", &s.a)) == &s); |
| 698 | } | 697 | } |
test/behavior/field_parent_ptr.zig+1882-84| ... | @@ -1,126 +1,1924 @@ | ... | @@ -1,126 +1,1924 @@ |
| 1 | const expect = @import("std").testing.expect; | 1 | const expect = @import("std").testing.expect; |
| 2 | const builtin = @import("builtin"); | 2 | const builtin = @import("builtin"); |
| 3 | 3 | ||
| 4 | test "@fieldParentPtr non-first field" { | 4 | test "@fieldParentPtr struct" { |
| 5 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | 5 | const C = struct { |
| 6 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 6 | a: bool = true, |
| 7 | b: f32 = 3.14, | ||
| 8 | c: struct { u8 } = .{42}, | ||
| 9 | d: i32 = 12345, | ||
| 10 | }; | ||
| 7 | 11 | ||
| 8 | try testParentFieldPtr(&foo.c); | 12 | { |
| 9 | try comptime testParentFieldPtr(&foo.c); | 13 | const c: C = .{ .a = false }; |
| 14 | const pcf = &c.a; | ||
| 15 | const pc: *const C = @alignCast(@fieldParentPtr("a", pcf)); | ||
| 16 | try expect(pc == &c); | ||
| 17 | } | ||
| 18 | { | ||
| 19 | const c: C = .{ .a = false }; | ||
| 20 | const pcf = &c.a; | ||
| 21 | var pc: *const C = undefined; | ||
| 22 | pc = @alignCast(@fieldParentPtr("a", pcf)); | ||
| 23 | try expect(pc == &c); | ||
| 24 | } | ||
| 25 | { | ||
| 26 | const c: C = .{ .a = false }; | ||
| 27 | var pcf: @TypeOf(&c.a) = undefined; | ||
| 28 | pcf = &c.a; | ||
| 29 | var pc: *const C = undefined; | ||
| 30 | pc = @alignCast(@fieldParentPtr("a", pcf)); | ||
| 31 | try expect(pc == &c); | ||
| 32 | } | ||
| 33 | { | ||
| 34 | var c: C = undefined; | ||
| 35 | c = .{ .a = false }; | ||
| 36 | var pcf: @TypeOf(&c.a) = undefined; | ||
| 37 | pcf = &c.a; | ||
| 38 | var pc: *C = undefined; | ||
| 39 | pc = @alignCast(@fieldParentPtr("a", pcf)); | ||
| 40 | try expect(pc == &c); | ||
| 41 | } | ||
| 42 | |||
| 43 | { | ||
| 44 | const c: C = .{ .b = 666.667 }; | ||
| 45 | const pcf = &c.b; | ||
| 46 | const pc: *const C = @alignCast(@fieldParentPtr("b", pcf)); | ||
| 47 | try expect(pc == &c); | ||
| 48 | } | ||
| 49 | { | ||
| 50 | const c: C = .{ .b = 666.667 }; | ||
| 51 | const pcf = &c.b; | ||
| 52 | var pc: *const C = undefined; | ||
| 53 | pc = @alignCast(@fieldParentPtr("b", pcf)); | ||
| 54 | try expect(pc == &c); | ||
| 55 | } | ||
| 56 | { | ||
| 57 | const c: C = .{ .b = 666.667 }; | ||
| 58 | var pcf: @TypeOf(&c.b) = undefined; | ||
| 59 | pcf = &c.b; | ||
| 60 | var pc: *const C = undefined; | ||
| 61 | pc = @alignCast(@fieldParentPtr("b", pcf)); | ||
| 62 | try expect(pc == &c); | ||
| 63 | } | ||
| 64 | { | ||
| 65 | var c: C = undefined; | ||
| 66 | c = .{ .b = 666.667 }; | ||
| 67 | var pcf: @TypeOf(&c.b) = undefined; | ||
| 68 | pcf = &c.b; | ||
| 69 | var pc: *C = undefined; | ||
| 70 | pc = @alignCast(@fieldParentPtr("b", pcf)); | ||
| 71 | try expect(pc == &c); | ||
| 72 | } | ||
| 73 | |||
| 74 | { | ||
| 75 | const c: C = .{ .c = .{255} }; | ||
| 76 | const pcf = &c.c; | ||
| 77 | const pc: *const C = @alignCast(@fieldParentPtr("c", pcf)); | ||
| 78 | try expect(pc == &c); | ||
| 79 | } | ||
| 80 | { | ||
| 81 | const c: C = .{ .c = .{255} }; | ||
| 82 | const pcf = &c.c; | ||
| 83 | var pc: *const C = undefined; | ||
| 84 | pc = @alignCast(@fieldParentPtr("c", pcf)); | ||
| 85 | try expect(pc == &c); | ||
| 86 | } | ||
| 87 | { | ||
| 88 | const c: C = .{ .c = .{255} }; | ||
| 89 | var pcf: @TypeOf(&c.c) = undefined; | ||
| 90 | pcf = &c.c; | ||
| 91 | var pc: *const C = undefined; | ||
| 92 | pc = @alignCast(@fieldParentPtr("c", pcf)); | ||
| 93 | try expect(pc == &c); | ||
| 94 | } | ||
| 95 | { | ||
| 96 | var c: C = undefined; | ||
| 97 | c = .{ .c = .{255} }; | ||
| 98 | var pcf: @TypeOf(&c.c) = undefined; | ||
| 99 | pcf = &c.c; | ||
| 100 | var pc: *C = undefined; | ||
| 101 | pc = @alignCast(@fieldParentPtr("c", pcf)); | ||
| 102 | try expect(pc == &c); | ||
| 103 | } | ||
| 104 | |||
| 105 | { | ||
| 106 | const c: C = .{ .d = -1111111111 }; | ||
| 107 | const pcf = &c.d; | ||
| 108 | const pc: *const C = @alignCast(@fieldParentPtr("d", pcf)); | ||
| 109 | try expect(pc == &c); | ||
| 110 | } | ||
| 111 | { | ||
| 112 | const c: C = .{ .d = -1111111111 }; | ||
| 113 | const pcf = &c.d; | ||
| 114 | var pc: *const C = undefined; | ||
| 115 | pc = @alignCast(@fieldParentPtr("d", pcf)); | ||
| 116 | try expect(pc == &c); | ||
| 117 | } | ||
| 118 | { | ||
| 119 | const c: C = .{ .d = -1111111111 }; | ||
| 120 | var pcf: @TypeOf(&c.d) = undefined; | ||
| 121 | pcf = &c.d; | ||
| 122 | var pc: *const C = undefined; | ||
| 123 | pc = @alignCast(@fieldParentPtr("d", pcf)); | ||
| 124 | try expect(pc == &c); | ||
| 125 | } | ||
| 126 | { | ||
| 127 | var c: C = undefined; | ||
| 128 | c = .{ .d = -1111111111 }; | ||
| 129 | var pcf: @TypeOf(&c.d) = undefined; | ||
| 130 | pcf = &c.d; | ||
| 131 | var pc: *C = undefined; | ||
| 132 | pc = @alignCast(@fieldParentPtr("d", pcf)); | ||
| 133 | try expect(pc == &c); | ||
| 134 | } | ||
| 10 | } | 135 | } |
| 11 | 136 | ||
| 12 | test "@fieldParentPtr first field" { | 137 | test "@fieldParentPtr extern struct" { |
| 13 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | 138 | const C = extern struct { |
| 14 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 139 | a: bool = true, |
| 140 | b: f32 = 3.14, | ||
| 141 | c: extern struct { x: u8 } = .{ .x = 42 }, | ||
| 142 | d: i32 = 12345, | ||
| 143 | }; | ||
| 144 | |||
| 145 | { | ||
| 146 | const c: C = .{ .a = false }; | ||
| 147 | const pcf = &c.a; | ||
| 148 | const pc: *const C = @alignCast(@fieldParentPtr("a", pcf)); | ||
| 149 | try expect(pc == &c); | ||
| 150 | } | ||
| 151 | { | ||
| 152 | const c: C = .{ .a = false }; | ||
| 153 | const pcf = &c.a; | ||
| 154 | var pc: *const C = undefined; | ||
| 155 | pc = @alignCast(@fieldParentPtr("a", pcf)); | ||
| 156 | try expect(pc == &c); | ||
| 157 | } | ||
| 158 | { | ||
| 159 | const c: C = .{ .a = false }; | ||
| 160 | var pcf: @TypeOf(&c.a) = undefined; | ||
| 161 | pcf = &c.a; | ||
| 162 | var pc: *const C = undefined; | ||
| 163 | pc = @alignCast(@fieldParentPtr("a", pcf)); | ||
| 164 | try expect(pc == &c); | ||
| 165 | } | ||
| 166 | { | ||
| 167 | var c: C = undefined; | ||
| 168 | c = .{ .a = false }; | ||
| 169 | var pcf: @TypeOf(&c.a) = undefined; | ||
| 170 | pcf = &c.a; | ||
| 171 | var pc: *C = undefined; | ||
| 172 | pc = @alignCast(@fieldParentPtr("a", pcf)); | ||
| 173 | try expect(pc == &c); | ||
| 174 | } | ||
| 175 | |||
| 176 | { | ||
| 177 | const c: C = .{ .b = 666.667 }; | ||
| 178 | const pcf = &c.b; | ||
| 179 | const pc: *const C = @alignCast(@fieldParentPtr("b", pcf)); | ||
| 180 | try expect(pc == &c); | ||
| 181 | } | ||
| 182 | { | ||
| 183 | const c: C = .{ .b = 666.667 }; | ||
| 184 | const pcf = &c.b; | ||
| 185 | var pc: *const C = undefined; | ||
| 186 | pc = @alignCast(@fieldParentPtr("b", pcf)); | ||
| 187 | try expect(pc == &c); | ||
| 188 | } | ||
| 189 | { | ||
| 190 | const c: C = .{ .b = 666.667 }; | ||
| 191 | var pcf: @TypeOf(&c.b) = undefined; | ||
| 192 | pcf = &c.b; | ||
| 193 | var pc: *const C = undefined; | ||
| 194 | pc = @alignCast(@fieldParentPtr("b", pcf)); | ||
| 195 | try expect(pc == &c); | ||
| 196 | } | ||
| 197 | { | ||
| 198 | var c: C = undefined; | ||
| 199 | c = .{ .b = 666.667 }; | ||
| 200 | var pcf: @TypeOf(&c.b) = undefined; | ||
| 201 | pcf = &c.b; | ||
| 202 | var pc: *C = undefined; | ||
| 203 | pc = @alignCast(@fieldParentPtr("b", pcf)); | ||
| 204 | try expect(pc == &c); | ||
| 205 | } | ||
| 15 | 206 | ||
| 16 | try testParentFieldPtrFirst(&foo.a); | 207 | { |
| 17 | try comptime testParentFieldPtrFirst(&foo.a); | 208 | const c: C = .{ .c = .{ .x = 255 } }; |
| 209 | const pcf = &c.c; | ||
| 210 | const pc: *const C = @alignCast(@fieldParentPtr("c", pcf)); | ||
| 211 | try expect(pc == &c); | ||
| 212 | } | ||
| 213 | { | ||
| 214 | const c: C = .{ .c = .{ .x = 255 } }; | ||
| 215 | const pcf = &c.c; | ||
| 216 | var pc: *const C = undefined; | ||
| 217 | pc = @alignCast(@fieldParentPtr("c", pcf)); | ||
| 218 | try expect(pc == &c); | ||
| 219 | } | ||
| 220 | { | ||
| 221 | const c: C = .{ .c = .{ .x = 255 } }; | ||
| 222 | var pcf: @TypeOf(&c.c) = undefined; | ||
| 223 | pcf = &c.c; | ||
| 224 | var pc: *const C = undefined; | ||
| 225 | pc = @alignCast(@fieldParentPtr("c", pcf)); | ||
| 226 | try expect(pc == &c); | ||
| 227 | } | ||
| 228 | { | ||
| 229 | var c: C = undefined; | ||
| 230 | c = .{ .c = .{ .x = 255 } }; | ||
| 231 | var pcf: @TypeOf(&c.c) = undefined; | ||
| 232 | pcf = &c.c; | ||
| 233 | var pc: *C = undefined; | ||
| 234 | pc = @alignCast(@fieldParentPtr("c", pcf)); | ||
| 235 | try expect(pc == &c); | ||
| 236 | } | ||
| 237 | |||
| 238 | { | ||
| 239 | const c: C = .{ .d = -1111111111 }; | ||
| 240 | const pcf = &c.d; | ||
| 241 | const pc: *const C = @alignCast(@fieldParentPtr("d", pcf)); | ||
| 242 | try expect(pc == &c); | ||
| 243 | } | ||
| 244 | { | ||
| 245 | const c: C = .{ .d = -1111111111 }; | ||
| 246 | const pcf = &c.d; | ||
| 247 | var pc: *const C = undefined; | ||
| 248 | pc = @alignCast(@fieldParentPtr("d", pcf)); | ||
| 249 | try expect(pc == &c); | ||
| 250 | } | ||
| 251 | { | ||
| 252 | const c: C = .{ .d = -1111111111 }; | ||
| 253 | var pcf: @TypeOf(&c.d) = undefined; | ||
| 254 | pcf = &c.d; | ||
| 255 | var pc: *const C = undefined; | ||
| 256 | pc = @alignCast(@fieldParentPtr("d", pcf)); | ||
| 257 | try expect(pc == &c); | ||
| 258 | } | ||
| 259 | { | ||
| 260 | var c: C = undefined; | ||
| 261 | c = .{ .d = -1111111111 }; | ||
| 262 | var pcf: @TypeOf(&c.d) = undefined; | ||
| 263 | pcf = &c.d; | ||
| 264 | var pc: *C = undefined; | ||
| 265 | pc = @alignCast(@fieldParentPtr("d", pcf)); | ||
| 266 | try expect(pc == &c); | ||
| 267 | } | ||
| 18 | } | 268 | } |
| 19 | 269 | ||
| 20 | const Foo = struct { | 270 | test "@fieldParentPtr extern struct first zero-bit field" { |
| 21 | a: bool, | 271 | const C = extern struct { |
| 22 | b: f32, | 272 | a: u0 = 0, |
| 23 | c: i32, | 273 | b: f32 = 3.14, |
| 24 | d: i32, | 274 | c: i32 = 12345, |
| 25 | }; | 275 | }; |
| 26 | 276 | ||
| 27 | const foo = Foo{ | 277 | { |
| 28 | .a = true, | 278 | const c: C = .{ .a = 0 }; |
| 29 | .b = 0.123, | 279 | const pcf = &c.a; |
| 30 | .c = 1234, | 280 | const pc: *const C = @alignCast(@fieldParentPtr("a", pcf)); |
| 31 | .d = -10, | 281 | try expect(pc == &c); |
| 32 | }; | 282 | } |
| 283 | { | ||
| 284 | const c: C = .{ .a = 0 }; | ||
| 285 | const pcf = &c.a; | ||
| 286 | var pc: *const C = undefined; | ||
| 287 | pc = @alignCast(@fieldParentPtr("a", pcf)); | ||
| 288 | try expect(pc == &c); | ||
| 289 | } | ||
| 290 | { | ||
| 291 | const c: C = .{ .a = 0 }; | ||
| 292 | var pcf: @TypeOf(&c.a) = undefined; | ||
| 293 | pcf = &c.a; | ||
| 294 | var pc: *const C = undefined; | ||
| 295 | pc = @alignCast(@fieldParentPtr("a", pcf)); | ||
| 296 | try expect(pc == &c); | ||
| 297 | } | ||
| 298 | { | ||
| 299 | var c: C = undefined; | ||
| 300 | c = .{ .a = 0 }; | ||
| 301 | var pcf: @TypeOf(&c.a) = undefined; | ||
| 302 | pcf = &c.a; | ||
| 303 | var pc: *C = undefined; | ||
| 304 | pc = @alignCast(@fieldParentPtr("a", pcf)); | ||
| 305 | try expect(pc == &c); | ||
| 306 | } | ||
| 33 | 307 | ||
| 34 | fn testParentFieldPtr(c: *const i32) !void { | 308 | { |
| 35 | try expect(c == &foo.c); | 309 | const c: C = .{ .b = 666.667 }; |
| 310 | const pcf = &c.b; | ||
| 311 | const pc: *const C = @alignCast(@fieldParentPtr("b", pcf)); | ||
| 312 | try expect(pc == &c); | ||
| 313 | } | ||
| 314 | { | ||
| 315 | const c: C = .{ .b = 666.667 }; | ||
| 316 | const pcf = &c.b; | ||
| 317 | var pc: *const C = undefined; | ||
| 318 | pc = @alignCast(@fieldParentPtr("b", pcf)); | ||
| 319 | try expect(pc == &c); | ||
| 320 | } | ||
| 321 | { | ||
| 322 | const c: C = .{ .b = 666.667 }; | ||
| 323 | var pcf: @TypeOf(&c.b) = undefined; | ||
| 324 | pcf = &c.b; | ||
| 325 | var pc: *const C = undefined; | ||
| 326 | pc = @alignCast(@fieldParentPtr("b", pcf)); | ||
| 327 | try expect(pc == &c); | ||
| 328 | } | ||
| 329 | { | ||
| 330 | var c: C = undefined; | ||
| 331 | c = .{ .b = 666.667 }; | ||
| 332 | var pcf: @TypeOf(&c.b) = undefined; | ||
| 333 | pcf = &c.b; | ||
| 334 | var pc: *C = undefined; | ||
| 335 | pc = @alignCast(@fieldParentPtr("b", pcf)); | ||
| 336 | try expect(pc == &c); | ||
| 337 | } | ||
| 36 | 338 | ||
| 37 | const base = @fieldParentPtr(Foo, "c", c); | 339 | { |
| 38 | try expect(base == &foo); | 340 | const c: C = .{ .c = -1111111111 }; |
| 39 | try expect(&base.c == c); | 341 | const pcf = &c.c; |
| 342 | const pc: *const C = @alignCast(@fieldParentPtr("c", pcf)); | ||
| 343 | try expect(pc == &c); | ||
| 344 | } | ||
| 345 | { | ||
| 346 | const c: C = .{ .c = -1111111111 }; | ||
| 347 | const pcf = &c.c; | ||
| 348 | var pc: *const C = undefined; | ||
| 349 | pc = @alignCast(@fieldParentPtr("c", pcf)); | ||
| 350 | try expect(pc == &c); | ||
| 351 | } | ||
| 352 | { | ||
| 353 | const c: C = .{ .c = -1111111111 }; | ||
| 354 | var pcf: @TypeOf(&c.c) = undefined; | ||
| 355 | pcf = &c.c; | ||
| 356 | var pc: *const C = undefined; | ||
| 357 | pc = @alignCast(@fieldParentPtr("c", pcf)); | ||
| 358 | try expect(pc == &c); | ||
| 359 | } | ||
| 360 | { | ||
| 361 | var c: C = undefined; | ||
| 362 | c = .{ .c = -1111111111 }; | ||
| 363 | var pcf: @TypeOf(&c.c) = undefined; | ||
| 364 | pcf = &c.c; | ||
| 365 | var pc: *C = undefined; | ||
| 366 | pc = @alignCast(@fieldParentPtr("c", pcf)); | ||
| 367 | try expect(pc == &c); | ||
| 368 | } | ||
| 40 | } | 369 | } |
| 41 | 370 | ||
| 42 | fn testParentFieldPtrFirst(a: *const bool) !void { | 371 | test "@fieldParentPtr extern struct middle zero-bit field" { |
| 43 | try expect(a == &foo.a); | 372 | const C = extern struct { |
| 373 | a: f32 = 3.14, | ||
| 374 | b: u0 = 0, | ||
| 375 | c: i32 = 12345, | ||
| 376 | }; | ||
| 377 | |||
| 378 | { | ||
| 379 | const c: C = .{ .a = 666.667 }; | ||
| 380 | const pcf = &c.a; | ||
| 381 | const pc: *const C = @alignCast(@fieldParentPtr("a", pcf)); | ||
| 382 | try expect(pc == &c); | ||
| 383 | } | ||
| 384 | { | ||
| 385 | const c: C = .{ .a = 666.667 }; | ||
| 386 | const pcf = &c.a; | ||
| 387 | var pc: *const C = undefined; | ||
| 388 | pc = @alignCast(@fieldParentPtr("a", pcf)); | ||
| 389 | try expect(pc == &c); | ||
| 390 | } | ||
| 391 | { | ||
| 392 | const c: C = .{ .a = 666.667 }; | ||
| 393 | var pcf: @TypeOf(&c.a) = undefined; | ||
| 394 | pcf = &c.a; | ||
| 395 | var pc: *const C = undefined; | ||
| 396 | pc = @alignCast(@fieldParentPtr("a", pcf)); | ||
| 397 | try expect(pc == &c); | ||
| 398 | } | ||
| 399 | { | ||
| 400 | var c: C = undefined; | ||
| 401 | c = .{ .a = 666.667 }; | ||
| 402 | var pcf: @TypeOf(&c.a) = undefined; | ||
| 403 | pcf = &c.a; | ||
| 404 | var pc: *C = undefined; | ||
| 405 | pc = @alignCast(@fieldParentPtr("a", pcf)); | ||
| 406 | try expect(pc == &c); | ||
| 407 | } | ||
| 44 | 408 | ||
| 45 | const base = @fieldParentPtr(Foo, "a", a); | 409 | { |
| 46 | try expect(base == &foo); | 410 | const c: C = .{ .b = 0 }; |
| 47 | try expect(&base.a == a); | 411 | const pcf = &c.b; |
| 412 | const pc: *const C = @alignCast(@fieldParentPtr("b", pcf)); | ||
| 413 | try expect(pc == &c); | ||
| 414 | } | ||
| 415 | { | ||
| 416 | const c: C = .{ .b = 0 }; | ||
| 417 | const pcf = &c.b; | ||
| 418 | var pc: *const C = undefined; | ||
| 419 | pc = @alignCast(@fieldParentPtr("b", pcf)); | ||
| 420 | try expect(pc == &c); | ||
| 421 | } | ||
| 422 | { | ||
| 423 | const c: C = .{ .b = 0 }; | ||
| 424 | var pcf: @TypeOf(&c.b) = undefined; | ||
| 425 | pcf = &c.b; | ||
| 426 | var pc: *const C = undefined; | ||
| 427 | pc = @alignCast(@fieldParentPtr("b", pcf)); | ||
| 428 | try expect(pc == &c); | ||
| 429 | } | ||
| 430 | { | ||
| 431 | var c: C = undefined; | ||
| 432 | c = .{ .b = 0 }; | ||
| 433 | var pcf: @TypeOf(&c.b) = undefined; | ||
| 434 | pcf = &c.b; | ||
| 435 | var pc: *C = undefined; | ||
| 436 | pc = @alignCast(@fieldParentPtr("b", pcf)); | ||
| 437 | try expect(pc == &c); | ||
| 438 | } | ||
| 439 | |||
| 440 | { | ||
| 441 | const c: C = .{ .c = -1111111111 }; | ||
| 442 | const pcf = &c.c; | ||
| 443 | const pc: *const C = @alignCast(@fieldParentPtr("c", pcf)); | ||
| 444 | try expect(pc == &c); | ||
| 445 | } | ||
| 446 | { | ||
| 447 | const c: C = .{ .c = -1111111111 }; | ||
| 448 | const pcf = &c.c; | ||
| 449 | var pc: *const C = undefined; | ||
| 450 | pc = @alignCast(@fieldParentPtr("c", pcf)); | ||
| 451 | try expect(pc == &c); | ||
| 452 | } | ||
| 453 | { | ||
| 454 | const c: C = .{ .c = -1111111111 }; | ||
| 455 | var pcf: @TypeOf(&c.c) = undefined; | ||
| 456 | pcf = &c.c; | ||
| 457 | var pc: *const C = undefined; | ||
| 458 | pc = @alignCast(@fieldParentPtr("c", pcf)); | ||
| 459 | try expect(pc == &c); | ||
| 460 | } | ||
| 461 | { | ||
| 462 | var c: C = undefined; | ||
| 463 | c = .{ .c = -1111111111 }; | ||
| 464 | var pcf: @TypeOf(&c.c) = undefined; | ||
| 465 | pcf = &c.c; | ||
| 466 | var pc: *C = undefined; | ||
| 467 | pc = @alignCast(@fieldParentPtr("c", pcf)); | ||
| 468 | try expect(pc == &c); | ||
| 469 | } | ||
| 48 | } | 470 | } |
| 49 | 471 | ||
| 50 | test "@fieldParentPtr untagged union" { | 472 | test "@fieldParentPtr extern struct last zero-bit field" { |
| 51 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | 473 | const C = extern struct { |
| 52 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 474 | a: f32 = 3.14, |
| 53 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 475 | b: i32 = 12345, |
| 476 | c: u0 = 0, | ||
| 477 | }; | ||
| 478 | |||
| 479 | { | ||
| 480 | const c: C = .{ .a = 666.667 }; | ||
| 481 | const pcf = &c.a; | ||
| 482 | const pc: *const C = @alignCast(@fieldParentPtr("a", pcf)); | ||
| 483 | try expect(pc == &c); | ||
| 484 | } | ||
| 485 | { | ||
| 486 | const c: C = .{ .a = 666.667 }; | ||
| 487 | const pcf = &c.a; | ||
| 488 | var pc: *const C = undefined; | ||
| 489 | pc = @alignCast(@fieldParentPtr("a", pcf)); | ||
| 490 | try expect(pc == &c); | ||
| 491 | } | ||
| 492 | { | ||
| 493 | const c: C = .{ .a = 666.667 }; | ||
| 494 | var pcf: @TypeOf(&c.a) = undefined; | ||
| 495 | pcf = &c.a; | ||
| 496 | var pc: *const C = undefined; | ||
| 497 | pc = @alignCast(@fieldParentPtr("a", pcf)); | ||
| 498 | try expect(pc == &c); | ||
| 499 | } | ||
| 500 | { | ||
| 501 | var c: C = undefined; | ||
| 502 | c = .{ .a = 666.667 }; | ||
| 503 | var pcf: @TypeOf(&c.a) = undefined; | ||
| 504 | pcf = &c.a; | ||
| 505 | var pc: *C = undefined; | ||
| 506 | pc = @alignCast(@fieldParentPtr("a", pcf)); | ||
| 507 | try expect(pc == &c); | ||
| 508 | } | ||
| 509 | |||
| 510 | { | ||
| 511 | const c: C = .{ .b = -1111111111 }; | ||
| 512 | const pcf = &c.b; | ||
| 513 | const pc: *const C = @alignCast(@fieldParentPtr("b", pcf)); | ||
| 514 | try expect(pc == &c); | ||
| 515 | } | ||
| 516 | { | ||
| 517 | const c: C = .{ .b = -1111111111 }; | ||
| 518 | const pcf = &c.b; | ||
| 519 | var pc: *const C = undefined; | ||
| 520 | pc = @alignCast(@fieldParentPtr("b", pcf)); | ||
| 521 | try expect(pc == &c); | ||
| 522 | } | ||
| 523 | { | ||
| 524 | const c: C = .{ .b = -1111111111 }; | ||
| 525 | var pcf: @TypeOf(&c.b) = undefined; | ||
| 526 | pcf = &c.b; | ||
| 527 | var pc: *const C = undefined; | ||
| 528 | pc = @alignCast(@fieldParentPtr("b", pcf)); | ||
| 529 | try expect(pc == &c); | ||
| 530 | } | ||
| 531 | { | ||
| 532 | var c: C = undefined; | ||
| 533 | c = .{ .b = -1111111111 }; | ||
| 534 | var pcf: @TypeOf(&c.b) = undefined; | ||
| 535 | pcf = &c.b; | ||
| 536 | var pc: *C = undefined; | ||
| 537 | pc = @alignCast(@fieldParentPtr("b", pcf)); | ||
| 538 | try expect(pc == &c); | ||
| 539 | } | ||
| 540 | |||
| 541 | { | ||
| 542 | const c: C = .{ .c = 0 }; | ||
| 543 | const pcf = &c.c; | ||
| 544 | const pc: *const C = @alignCast(@fieldParentPtr("c", pcf)); | ||
| 545 | try expect(pc == &c); | ||
| 546 | } | ||
| 547 | { | ||
| 548 | const c: C = .{ .c = 0 }; | ||
| 549 | const pcf = &c.c; | ||
| 550 | var pc: *const C = undefined; | ||
| 551 | pc = @alignCast(@fieldParentPtr("c", pcf)); | ||
| 552 | try expect(pc == &c); | ||
| 553 | } | ||
| 554 | { | ||
| 555 | const c: C = .{ .c = 0 }; | ||
| 556 | var pcf: @TypeOf(&c.c) = undefined; | ||
| 557 | pcf = &c.c; | ||
| 558 | var pc: *const C = undefined; | ||
| 559 | pc = @alignCast(@fieldParentPtr("c", pcf)); | ||
| 560 | try expect(pc == &c); | ||
| 561 | } | ||
| 562 | { | ||
| 563 | var c: C = undefined; | ||
| 564 | c = .{ .c = 0 }; | ||
| 565 | var pcf: @TypeOf(&c.c) = undefined; | ||
| 566 | pcf = &c.c; | ||
| 567 | var pc: *C = undefined; | ||
| 568 | pc = @alignCast(@fieldParentPtr("c", pcf)); | ||
| 569 | try expect(pc == &c); | ||
| 570 | } | ||
| 571 | } | ||
| 572 | |||
| 573 | test "@fieldParentPtr unaligned packed struct" { | ||
| 574 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | ||
| 575 | if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; | ||
| 576 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; | ||
| 577 | |||
| 578 | const C = packed struct { | ||
| 579 | a: bool = true, | ||
| 580 | b: f32 = 3.14, | ||
| 581 | c: packed struct { x: u8 } = .{ .x = 42 }, | ||
| 582 | d: i32 = 12345, | ||
| 583 | }; | ||
| 584 | |||
| 585 | { | ||
| 586 | const c: C = .{ .a = false }; | ||
| 587 | const pcf = &c.a; | ||
| 588 | const pc: *const C = @alignCast(@fieldParentPtr("a", pcf)); | ||
| 589 | try expect(pc == &c); | ||
| 590 | } | ||
| 591 | { | ||
| 592 | const c: C = .{ .a = false }; | ||
| 593 | const pcf = &c.a; | ||
| 594 | var pc: *const C = undefined; | ||
| 595 | pc = @alignCast(@fieldParentPtr("a", pcf)); | ||
| 596 | try expect(pc == &c); | ||
| 597 | } | ||
| 598 | { | ||
| 599 | const c: C = .{ .a = false }; | ||
| 600 | var pcf: @TypeOf(&c.a) = undefined; | ||
| 601 | pcf = &c.a; | ||
| 602 | var pc: *const C = undefined; | ||
| 603 | pc = @alignCast(@fieldParentPtr("a", pcf)); | ||
| 604 | try expect(pc == &c); | ||
| 605 | } | ||
| 606 | { | ||
| 607 | var c: C = undefined; | ||
| 608 | c = .{ .a = false }; | ||
| 609 | var pcf: @TypeOf(&c.a) = undefined; | ||
| 610 | pcf = &c.a; | ||
| 611 | var pc: *C = undefined; | ||
| 612 | pc = @alignCast(@fieldParentPtr("a", pcf)); | ||
| 613 | try expect(pc == &c); | ||
| 614 | } | ||
| 615 | |||
| 616 | { | ||
| 617 | const c: C = .{ .b = 666.667 }; | ||
| 618 | const pcf = &c.b; | ||
| 619 | const pc: *const C = @alignCast(@fieldParentPtr("b", pcf)); | ||
| 620 | try expect(pc == &c); | ||
| 621 | } | ||
| 622 | { | ||
| 623 | const c: C = .{ .b = 666.667 }; | ||
| 624 | const pcf = &c.b; | ||
| 625 | var pc: *const C = undefined; | ||
| 626 | pc = @alignCast(@fieldParentPtr("b", pcf)); | ||
| 627 | try expect(pc == &c); | ||
| 628 | } | ||
| 629 | { | ||
| 630 | const c: C = .{ .b = 666.667 }; | ||
| 631 | var pcf: @TypeOf(&c.b) = undefined; | ||
| 632 | pcf = &c.b; | ||
| 633 | var pc: *const C = undefined; | ||
| 634 | pc = @alignCast(@fieldParentPtr("b", pcf)); | ||
| 635 | try expect(pc == &c); | ||
| 636 | } | ||
| 637 | { | ||
| 638 | var c: C = undefined; | ||
| 639 | c = .{ .b = 666.667 }; | ||
| 640 | var pcf: @TypeOf(&c.b) = undefined; | ||
| 641 | pcf = &c.b; | ||
| 642 | var pc: *C = undefined; | ||
| 643 | pc = @alignCast(@fieldParentPtr("b", pcf)); | ||
| 644 | try expect(pc == &c); | ||
| 645 | } | ||
| 54 | 646 | ||
| 55 | try testFieldParentPtrUnion(&bar.c); | 647 | { |
| 56 | try comptime testFieldParentPtrUnion(&bar.c); | 648 | const c: C = .{ .c = .{ .x = 255 } }; |
| 649 | const pcf = &c.c; | ||
| 650 | const pc: *const C = @alignCast(@fieldParentPtr("c", pcf)); | ||
| 651 | try expect(pc == &c); | ||
| 652 | } | ||
| 653 | { | ||
| 654 | const c: C = .{ .c = .{ .x = 255 } }; | ||
| 655 | const pcf = &c.c; | ||
| 656 | var pc: *const C = undefined; | ||
| 657 | pc = @alignCast(@fieldParentPtr("c", pcf)); | ||
| 658 | try expect(pc == &c); | ||
| 659 | } | ||
| 660 | { | ||
| 661 | const c: C = .{ .c = .{ .x = 255 } }; | ||
| 662 | var pcf: @TypeOf(&c.c) = undefined; | ||
| 663 | pcf = &c.c; | ||
| 664 | var pc: *const C = undefined; | ||
| 665 | pc = @alignCast(@fieldParentPtr("c", pcf)); | ||
| 666 | try expect(pc == &c); | ||
| 667 | } | ||
| 668 | { | ||
| 669 | var c: C = undefined; | ||
| 670 | c = .{ .c = .{ .x = 255 } }; | ||
| 671 | var pcf: @TypeOf(&c.c) = undefined; | ||
| 672 | pcf = &c.c; | ||
| 673 | var pc: *C = undefined; | ||
| 674 | pc = @alignCast(@fieldParentPtr("c", pcf)); | ||
| 675 | try expect(pc == &c); | ||
| 676 | } | ||
| 677 | |||
| 678 | { | ||
| 679 | const c: C = .{ .d = -1111111111 }; | ||
| 680 | const pcf = &c.d; | ||
| 681 | const pc: *const C = @alignCast(@fieldParentPtr("d", pcf)); | ||
| 682 | try expect(pc == &c); | ||
| 683 | } | ||
| 684 | { | ||
| 685 | const c: C = .{ .d = -1111111111 }; | ||
| 686 | const pcf = &c.d; | ||
| 687 | var pc: *const C = undefined; | ||
| 688 | pc = @alignCast(@fieldParentPtr("d", pcf)); | ||
| 689 | try expect(pc == &c); | ||
| 690 | } | ||
| 691 | { | ||
| 692 | const c: C = .{ .d = -1111111111 }; | ||
| 693 | var pcf: @TypeOf(&c.d) = undefined; | ||
| 694 | pcf = &c.d; | ||
| 695 | var pc: *const C = undefined; | ||
| 696 | pc = @alignCast(@fieldParentPtr("d", pcf)); | ||
| 697 | try expect(pc == &c); | ||
| 698 | } | ||
| 699 | { | ||
| 700 | var c: C = undefined; | ||
| 701 | c = .{ .d = -1111111111 }; | ||
| 702 | var pcf: @TypeOf(&c.d) = undefined; | ||
| 703 | pcf = &c.d; | ||
| 704 | var pc: *C = undefined; | ||
| 705 | pc = @alignCast(@fieldParentPtr("d", pcf)); | ||
| 706 | try expect(pc == &c); | ||
| 707 | } | ||
| 57 | } | 708 | } |
| 58 | 709 | ||
| 59 | const Bar = union(enum) { | 710 | test "@fieldParentPtr aligned packed struct" { |
| 60 | a: bool, | 711 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; |
| 61 | b: f32, | 712 | if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; |
| 62 | c: i32, | 713 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; |
| 63 | d: i32, | 714 | |
| 64 | }; | 715 | const C = packed struct { |
| 716 | a: f32 = 3.14, | ||
| 717 | b: i32 = 12345, | ||
| 718 | c: packed struct { x: u8 } = .{ .x = 42 }, | ||
| 719 | d: bool = true, | ||
| 720 | }; | ||
| 721 | |||
| 722 | { | ||
| 723 | const c: C = .{ .a = 666.667 }; | ||
| 724 | const pcf = &c.a; | ||
| 725 | const pc: *const C = @alignCast(@fieldParentPtr("a", pcf)); | ||
| 726 | try expect(pc == &c); | ||
| 727 | } | ||
| 728 | { | ||
| 729 | const c: C = .{ .a = 666.667 }; | ||
| 730 | const pcf = &c.a; | ||
| 731 | var pc: *const C = undefined; | ||
| 732 | pc = @alignCast(@fieldParentPtr("a", pcf)); | ||
| 733 | try expect(pc == &c); | ||
| 734 | } | ||
| 735 | { | ||
| 736 | const c: C = .{ .a = 666.667 }; | ||
| 737 | var pcf: @TypeOf(&c.a) = undefined; | ||
| 738 | pcf = &c.a; | ||
| 739 | var pc: *const C = undefined; | ||
| 740 | pc = @alignCast(@fieldParentPtr("a", pcf)); | ||
| 741 | try expect(pc == &c); | ||
| 742 | } | ||
| 743 | { | ||
| 744 | var c: C = undefined; | ||
| 745 | c = .{ .a = 666.667 }; | ||
| 746 | var pcf: @TypeOf(&c.a) = undefined; | ||
| 747 | pcf = &c.a; | ||
| 748 | var pc: *C = undefined; | ||
| 749 | pc = @alignCast(@fieldParentPtr("a", pcf)); | ||
| 750 | try expect(pc == &c); | ||
| 751 | } | ||
| 752 | |||
| 753 | { | ||
| 754 | const c: C = .{ .b = -1111111111 }; | ||
| 755 | const pcf = &c.b; | ||
| 756 | const pc: *const C = @alignCast(@fieldParentPtr("b", pcf)); | ||
| 757 | try expect(pc == &c); | ||
| 758 | } | ||
| 759 | { | ||
| 760 | const c: C = .{ .b = -1111111111 }; | ||
| 761 | const pcf = &c.b; | ||
| 762 | var pc: *const C = undefined; | ||
| 763 | pc = @alignCast(@fieldParentPtr("b", pcf)); | ||
| 764 | try expect(pc == &c); | ||
| 765 | } | ||
| 766 | { | ||
| 767 | const c: C = .{ .b = -1111111111 }; | ||
| 768 | var pcf: @TypeOf(&c.b) = undefined; | ||
| 769 | pcf = &c.b; | ||
| 770 | var pc: *const C = undefined; | ||
| 771 | pc = @alignCast(@fieldParentPtr("b", pcf)); | ||
| 772 | try expect(pc == &c); | ||
| 773 | } | ||
| 774 | { | ||
| 775 | var c: C = undefined; | ||
| 776 | c = .{ .b = -1111111111 }; | ||
| 777 | var pcf: @TypeOf(&c.b) = undefined; | ||
| 778 | pcf = &c.b; | ||
| 779 | var pc: *C = undefined; | ||
| 780 | pc = @alignCast(@fieldParentPtr("b", pcf)); | ||
| 781 | try expect(pc == &c); | ||
| 782 | } | ||
| 783 | |||
| 784 | { | ||
| 785 | const c: C = .{ .c = .{ .x = 255 } }; | ||
| 786 | const pcf = &c.c; | ||
| 787 | const pc: *const C = @alignCast(@fieldParentPtr("c", pcf)); | ||
| 788 | try expect(pc == &c); | ||
| 789 | } | ||
| 790 | { | ||
| 791 | const c: C = .{ .c = .{ .x = 255 } }; | ||
| 792 | const pcf = &c.c; | ||
| 793 | var pc: *const C = undefined; | ||
| 794 | pc = @alignCast(@fieldParentPtr("c", pcf)); | ||
| 795 | try expect(pc == &c); | ||
| 796 | } | ||
| 797 | { | ||
| 798 | const c: C = .{ .c = .{ .x = 255 } }; | ||
| 799 | var pcf: @TypeOf(&c.c) = undefined; | ||
| 800 | pcf = &c.c; | ||
| 801 | var pc: *const C = undefined; | ||
| 802 | pc = @alignCast(@fieldParentPtr("c", pcf)); | ||
| 803 | try expect(pc == &c); | ||
| 804 | } | ||
| 805 | { | ||
| 806 | var c: C = undefined; | ||
| 807 | c = .{ .c = .{ .x = 255 } }; | ||
| 808 | var pcf: @TypeOf(&c.c) = undefined; | ||
| 809 | pcf = &c.c; | ||
| 810 | var pc: *C = undefined; | ||
| 811 | pc = @alignCast(@fieldParentPtr("c", pcf)); | ||
| 812 | try expect(pc == &c); | ||
| 813 | } | ||
| 814 | |||
| 815 | { | ||
| 816 | const c: C = .{ .d = false }; | ||
| 817 | const pcf = &c.d; | ||
| 818 | const pc: *const C = @alignCast(@fieldParentPtr("d", pcf)); | ||
| 819 | try expect(pc == &c); | ||
| 820 | } | ||
| 821 | { | ||
| 822 | const c: C = .{ .d = false }; | ||
| 823 | const pcf = &c.d; | ||
| 824 | var pc: *const C = undefined; | ||
| 825 | pc = @alignCast(@fieldParentPtr("d", pcf)); | ||
| 826 | try expect(pc == &c); | ||
| 827 | } | ||
| 828 | { | ||
| 829 | const c: C = .{ .d = false }; | ||
| 830 | var pcf: @TypeOf(&c.d) = undefined; | ||
| 831 | pcf = &c.d; | ||
| 832 | var pc: *const C = undefined; | ||
| 833 | pc = @alignCast(@fieldParentPtr("d", pcf)); | ||
| 834 | try expect(pc == &c); | ||
| 835 | } | ||
| 836 | { | ||
| 837 | var c: C = undefined; | ||
| 838 | c = .{ .d = false }; | ||
| 839 | var pcf: @TypeOf(&c.d) = undefined; | ||
| 840 | pcf = &c.d; | ||
| 841 | var pc: *C = undefined; | ||
| 842 | pc = @alignCast(@fieldParentPtr("d", pcf)); | ||
| 843 | try expect(pc == &c); | ||
| 844 | } | ||
| 845 | } | ||
| 846 | |||
| 847 | test "@fieldParentPtr nested packed struct" { | ||
| 848 | if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; | ||
| 849 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; | ||
| 850 | |||
| 851 | { | ||
| 852 | const C = packed struct { | ||
| 853 | a: u8, | ||
| 854 | b: packed struct { | ||
| 855 | a: u8, | ||
| 856 | b: packed struct { | ||
| 857 | a: u8, | ||
| 858 | }, | ||
| 859 | }, | ||
| 860 | }; | ||
| 861 | |||
| 862 | { | ||
| 863 | const c: C = .{ .a = 0, .b = .{ .a = 0, .b = .{ .a = 0 } } }; | ||
| 864 | const pcbba = &c.b.b.a; | ||
| 865 | const pcbb: @TypeOf(&c.b.b) = @alignCast(@fieldParentPtr("a", pcbba)); | ||
| 866 | try expect(pcbb == &c.b.b); | ||
| 867 | const pcb: @TypeOf(&c.b) = @alignCast(@fieldParentPtr("b", pcbb)); | ||
| 868 | try expect(pcb == &c.b); | ||
| 869 | const pc: *const C = @alignCast(@fieldParentPtr("b", pcb)); | ||
| 870 | try expect(pc == &c); | ||
| 871 | } | ||
| 872 | |||
| 873 | { | ||
| 874 | var c: C = undefined; | ||
| 875 | c = .{ .a = 0, .b = .{ .a = 0, .b = .{ .a = 0 } } }; | ||
| 876 | var pcbba: @TypeOf(&c.b.b.a) = undefined; | ||
| 877 | pcbba = &c.b.b.a; | ||
| 878 | var pcbb: @TypeOf(&c.b.b) = undefined; | ||
| 879 | pcbb = @alignCast(@fieldParentPtr("a", pcbba)); | ||
| 880 | try expect(pcbb == &c.b.b); | ||
| 881 | var pcb: @TypeOf(&c.b) = undefined; | ||
| 882 | pcb = @alignCast(@fieldParentPtr("b", pcbb)); | ||
| 883 | try expect(pcb == &c.b); | ||
| 884 | var pc: *C = undefined; | ||
| 885 | pc = @alignCast(@fieldParentPtr("b", pcb)); | ||
| 886 | try expect(pc == &c); | ||
| 887 | } | ||
| 888 | } | ||
| 889 | |||
| 890 | { | ||
| 891 | const C = packed struct { | ||
| 892 | a: u8, | ||
| 893 | b: packed struct { | ||
| 894 | a: u9, | ||
| 895 | b: packed struct { | ||
| 896 | a: u8, | ||
| 897 | }, | ||
| 898 | }, | ||
| 899 | }; | ||
| 900 | |||
| 901 | { | ||
| 902 | const c: C = .{ .a = 0, .b = .{ .a = 0, .b = .{ .a = 0 } } }; | ||
| 903 | const pcbba = &c.b.b.a; | ||
| 904 | const pcbb: @TypeOf(&c.b.b) = @alignCast(@fieldParentPtr("a", pcbba)); | ||
| 905 | try expect(pcbb == &c.b.b); | ||
| 906 | const pcb: @TypeOf(&c.b) = @alignCast(@fieldParentPtr("b", pcbb)); | ||
| 907 | try expect(pcb == &c.b); | ||
| 908 | const pc: *const C = @alignCast(@fieldParentPtr("b", pcb)); | ||
| 909 | try expect(pc == &c); | ||
| 910 | } | ||
| 911 | |||
| 912 | { | ||
| 913 | var c: C = undefined; | ||
| 914 | c = .{ .a = 0, .b = .{ .a = 0, .b = .{ .a = 0 } } }; | ||
| 915 | var pcbba: @TypeOf(&c.b.b.a) = undefined; | ||
| 916 | pcbba = &c.b.b.a; | ||
| 917 | var pcbb: @TypeOf(&c.b.b) = undefined; | ||
| 918 | pcbb = @alignCast(@fieldParentPtr("a", pcbba)); | ||
| 919 | try expect(pcbb == &c.b.b); | ||
| 920 | var pcb: @TypeOf(&c.b) = undefined; | ||
| 921 | pcb = @alignCast(@fieldParentPtr("b", pcbb)); | ||
| 922 | try expect(pcb == &c.b); | ||
| 923 | var pc: *C = undefined; | ||
| 924 | pc = @alignCast(@fieldParentPtr("b", pcb)); | ||
| 925 | try expect(pc == &c); | ||
| 926 | } | ||
| 927 | } | ||
| 928 | |||
| 929 | { | ||
| 930 | const C = packed struct { | ||
| 931 | a: u9, | ||
| 932 | b: packed struct { | ||
| 933 | a: u7, | ||
| 934 | b: packed struct { | ||
| 935 | a: u8, | ||
| 936 | }, | ||
| 937 | }, | ||
| 938 | }; | ||
| 939 | |||
| 940 | { | ||
| 941 | const c: C = .{ .a = 0, .b = .{ .a = 0, .b = .{ .a = 0 } } }; | ||
| 942 | const pcbba = &c.b.b.a; | ||
| 943 | const pcbb: @TypeOf(&c.b.b) = @alignCast(@fieldParentPtr("a", pcbba)); | ||
| 944 | try expect(pcbb == &c.b.b); | ||
| 945 | const pcb: @TypeOf(&c.b) = @alignCast(@fieldParentPtr("b", pcbb)); | ||
| 946 | try expect(pcb == &c.b); | ||
| 947 | const pc: *const C = @alignCast(@fieldParentPtr("b", pcb)); | ||
| 948 | try expect(pc == &c); | ||
| 949 | } | ||
| 950 | |||
| 951 | { | ||
| 952 | var c: C = undefined; | ||
| 953 | c = .{ .a = 0, .b = .{ .a = 0, .b = .{ .a = 0 } } }; | ||
| 954 | var pcbba: @TypeOf(&c.b.b.a) = undefined; | ||
| 955 | pcbba = &c.b.b.a; | ||
| 956 | var pcbb: @TypeOf(&c.b.b) = undefined; | ||
| 957 | pcbb = @alignCast(@fieldParentPtr("a", pcbba)); | ||
| 958 | try expect(pcbb == &c.b.b); | ||
| 959 | var pcb: @TypeOf(&c.b) = undefined; | ||
| 960 | pcb = @alignCast(@fieldParentPtr("b", pcbb)); | ||
| 961 | try expect(pcb == &c.b); | ||
| 962 | var pc: *C = undefined; | ||
| 963 | pc = @alignCast(@fieldParentPtr("b", pcb)); | ||
| 964 | try expect(pc == &c); | ||
| 965 | } | ||
| 966 | } | ||
| 65 | 967 | ||
| 66 | const bar = Bar{ .c = 42 }; | 968 | { |
| 969 | const C = packed struct { | ||
| 970 | a: u9, | ||
| 971 | b: packed struct { | ||
| 972 | a: u8, | ||
| 973 | b: packed struct { | ||
| 974 | a: u8, | ||
| 975 | }, | ||
| 976 | }, | ||
| 977 | }; | ||
| 67 | 978 | ||
| 68 | fn testFieldParentPtrUnion(c: *const i32) !void { | 979 | { |
| 69 | try expect(c == &bar.c); | 980 | const c: C = .{ .a = 0, .b = .{ .a = 0, .b = .{ .a = 0 } } }; |
| 981 | const pcbba = &c.b.b.a; | ||
| 982 | const pcbb: @TypeOf(&c.b.b) = @alignCast(@fieldParentPtr("a", pcbba)); | ||
| 983 | try expect(pcbb == &c.b.b); | ||
| 984 | const pcb: @TypeOf(&c.b) = @alignCast(@fieldParentPtr("b", pcbb)); | ||
| 985 | try expect(pcb == &c.b); | ||
| 986 | const pc: *const C = @alignCast(@fieldParentPtr("b", pcb)); | ||
| 987 | try expect(pc == &c); | ||
| 988 | } | ||
| 70 | 989 | ||
| 71 | const base = @fieldParentPtr(Bar, "c", c); | 990 | { |
| 72 | try expect(base == &bar); | 991 | var c: C = undefined; |
| 73 | try expect(&base.c == c); | 992 | c = .{ .a = 0, .b = .{ .a = 0, .b = .{ .a = 0 } } }; |
| 993 | var pcbba: @TypeOf(&c.b.b.a) = undefined; | ||
| 994 | pcbba = &c.b.b.a; | ||
| 995 | var pcbb: @TypeOf(&c.b.b) = undefined; | ||
| 996 | pcbb = @alignCast(@fieldParentPtr("a", pcbba)); | ||
| 997 | try expect(pcbb == &c.b.b); | ||
| 998 | var pcb: @TypeOf(&c.b) = undefined; | ||
| 999 | pcb = @alignCast(@fieldParentPtr("b", pcbb)); | ||
| 1000 | try expect(pcb == &c.b); | ||
| 1001 | var pc: *C = undefined; | ||
| 1002 | pc = @alignCast(@fieldParentPtr("b", pcb)); | ||
| 1003 | try expect(pc == &c); | ||
| 1004 | } | ||
| 1005 | } | ||
| 1006 | } | ||
| 1007 | |||
| 1008 | test "@fieldParentPtr packed struct first zero-bit field" { | ||
| 1009 | if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; | ||
| 1010 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; | ||
| 1011 | |||
| 1012 | const C = packed struct { | ||
| 1013 | a: u0 = 0, | ||
| 1014 | b: f32 = 3.14, | ||
| 1015 | c: i32 = 12345, | ||
| 1016 | }; | ||
| 1017 | |||
| 1018 | { | ||
| 1019 | const c: C = .{ .a = 0 }; | ||
| 1020 | const pcf = &c.a; | ||
| 1021 | const pc: *const C = @alignCast(@fieldParentPtr("a", pcf)); | ||
| 1022 | try expect(pc == &c); | ||
| 1023 | } | ||
| 1024 | { | ||
| 1025 | const c: C = .{ .a = 0 }; | ||
| 1026 | const pcf = &c.a; | ||
| 1027 | var pc: *const C = undefined; | ||
| 1028 | pc = @alignCast(@fieldParentPtr("a", pcf)); | ||
| 1029 | try expect(pc == &c); | ||
| 1030 | } | ||
| 1031 | { | ||
| 1032 | const c: C = .{ .a = 0 }; | ||
| 1033 | var pcf: @TypeOf(&c.a) = undefined; | ||
| 1034 | pcf = &c.a; | ||
| 1035 | var pc: *const C = undefined; | ||
| 1036 | pc = @alignCast(@fieldParentPtr("a", pcf)); | ||
| 1037 | try expect(pc == &c); | ||
| 1038 | } | ||
| 1039 | { | ||
| 1040 | var c: C = undefined; | ||
| 1041 | c = .{ .a = 0 }; | ||
| 1042 | var pcf: @TypeOf(&c.a) = undefined; | ||
| 1043 | pcf = &c.a; | ||
| 1044 | var pc: *C = undefined; | ||
| 1045 | pc = @alignCast(@fieldParentPtr("a", pcf)); | ||
| 1046 | try expect(pc == &c); | ||
| 1047 | } | ||
| 1048 | |||
| 1049 | { | ||
| 1050 | const c: C = .{ .b = 666.667 }; | ||
| 1051 | const pcf = &c.b; | ||
| 1052 | const pc: *const C = @alignCast(@fieldParentPtr("b", pcf)); | ||
| 1053 | try expect(pc == &c); | ||
| 1054 | } | ||
| 1055 | { | ||
| 1056 | const c: C = .{ .b = 666.667 }; | ||
| 1057 | const pcf = &c.b; | ||
| 1058 | var pc: *const C = undefined; | ||
| 1059 | pc = @alignCast(@fieldParentPtr("b", pcf)); | ||
| 1060 | try expect(pc == &c); | ||
| 1061 | } | ||
| 1062 | { | ||
| 1063 | const c: C = .{ .b = 666.667 }; | ||
| 1064 | var pcf: @TypeOf(&c.b) = undefined; | ||
| 1065 | pcf = &c.b; | ||
| 1066 | var pc: *const C = undefined; | ||
| 1067 | pc = @alignCast(@fieldParentPtr("b", pcf)); | ||
| 1068 | try expect(pc == &c); | ||
| 1069 | } | ||
| 1070 | { | ||
| 1071 | var c: C = undefined; | ||
| 1072 | c = .{ .b = 666.667 }; | ||
| 1073 | var pcf: @TypeOf(&c.b) = undefined; | ||
| 1074 | pcf = &c.b; | ||
| 1075 | var pc: *C = undefined; | ||
| 1076 | pc = @alignCast(@fieldParentPtr("b", pcf)); | ||
| 1077 | try expect(pc == &c); | ||
| 1078 | } | ||
| 1079 | |||
| 1080 | { | ||
| 1081 | const c: C = .{ .c = -1111111111 }; | ||
| 1082 | const pcf = &c.c; | ||
| 1083 | const pc: *const C = @alignCast(@fieldParentPtr("c", pcf)); | ||
| 1084 | try expect(pc == &c); | ||
| 1085 | } | ||
| 1086 | { | ||
| 1087 | const c: C = .{ .c = -1111111111 }; | ||
| 1088 | const pcf = &c.c; | ||
| 1089 | var pc: *const C = undefined; | ||
| 1090 | pc = @alignCast(@fieldParentPtr("c", pcf)); | ||
| 1091 | try expect(pc == &c); | ||
| 1092 | } | ||
| 1093 | { | ||
| 1094 | const c: C = .{ .c = -1111111111 }; | ||
| 1095 | var pcf: @TypeOf(&c.c) = undefined; | ||
| 1096 | pcf = &c.c; | ||
| 1097 | var pc: *const C = undefined; | ||
| 1098 | pc = @alignCast(@fieldParentPtr("c", pcf)); | ||
| 1099 | try expect(pc == &c); | ||
| 1100 | } | ||
| 1101 | { | ||
| 1102 | var c: C = undefined; | ||
| 1103 | c = .{ .c = -1111111111 }; | ||
| 1104 | var pcf: @TypeOf(&c.c) = undefined; | ||
| 1105 | pcf = &c.c; | ||
| 1106 | var pc: *C = undefined; | ||
| 1107 | pc = @alignCast(@fieldParentPtr("c", pcf)); | ||
| 1108 | try expect(pc == &c); | ||
| 1109 | } | ||
| 1110 | } | ||
| 1111 | |||
| 1112 | test "@fieldParentPtr packed struct middle zero-bit field" { | ||
| 1113 | if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; | ||
| 1114 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; | ||
| 1115 | |||
| 1116 | const C = packed struct { | ||
| 1117 | a: f32 = 3.14, | ||
| 1118 | b: u0 = 0, | ||
| 1119 | c: i32 = 12345, | ||
| 1120 | }; | ||
| 1121 | |||
| 1122 | { | ||
| 1123 | const c: C = .{ .a = 666.667 }; | ||
| 1124 | const pcf = &c.a; | ||
| 1125 | const pc: *const C = @alignCast(@fieldParentPtr("a", pcf)); | ||
| 1126 | try expect(pc == &c); | ||
| 1127 | } | ||
| 1128 | { | ||
| 1129 | const c: C = .{ .a = 666.667 }; | ||
| 1130 | const pcf = &c.a; | ||
| 1131 | var pc: *const C = undefined; | ||
| 1132 | pc = @alignCast(@fieldParentPtr("a", pcf)); | ||
| 1133 | try expect(pc == &c); | ||
| 1134 | } | ||
| 1135 | { | ||
| 1136 | const c: C = .{ .a = 666.667 }; | ||
| 1137 | var pcf: @TypeOf(&c.a) = undefined; | ||
| 1138 | pcf = &c.a; | ||
| 1139 | var pc: *const C = undefined; | ||
| 1140 | pc = @alignCast(@fieldParentPtr("a", pcf)); | ||
| 1141 | try expect(pc == &c); | ||
| 1142 | } | ||
| 1143 | { | ||
| 1144 | var c: C = undefined; | ||
| 1145 | c = .{ .a = 666.667 }; | ||
| 1146 | var pcf: @TypeOf(&c.a) = undefined; | ||
| 1147 | pcf = &c.a; | ||
| 1148 | var pc: *C = undefined; | ||
| 1149 | pc = @alignCast(@fieldParentPtr("a", pcf)); | ||
| 1150 | try expect(pc == &c); | ||
| 1151 | } | ||
| 1152 | |||
| 1153 | { | ||
| 1154 | const c: C = .{ .b = 0 }; | ||
| 1155 | const pcf = &c.b; | ||
| 1156 | const pc: *const C = @alignCast(@fieldParentPtr("b", pcf)); | ||
| 1157 | try expect(pc == &c); | ||
| 1158 | } | ||
| 1159 | { | ||
| 1160 | const c: C = .{ .b = 0 }; | ||
| 1161 | const pcf = &c.b; | ||
| 1162 | var pc: *const C = undefined; | ||
| 1163 | pc = @alignCast(@fieldParentPtr("b", pcf)); | ||
| 1164 | try expect(pc == &c); | ||
| 1165 | } | ||
| 1166 | { | ||
| 1167 | const c: C = .{ .b = 0 }; | ||
| 1168 | var pcf: @TypeOf(&c.b) = undefined; | ||
| 1169 | pcf = &c.b; | ||
| 1170 | var pc: *const C = undefined; | ||
| 1171 | pc = @alignCast(@fieldParentPtr("b", pcf)); | ||
| 1172 | try expect(pc == &c); | ||
| 1173 | } | ||
| 1174 | { | ||
| 1175 | var c: C = undefined; | ||
| 1176 | c = .{ .b = 0 }; | ||
| 1177 | var pcf: @TypeOf(&c.b) = undefined; | ||
| 1178 | pcf = &c.b; | ||
| 1179 | var pc: *C = undefined; | ||
| 1180 | pc = @alignCast(@fieldParentPtr("b", pcf)); | ||
| 1181 | try expect(pc == &c); | ||
| 1182 | } | ||
| 1183 | |||
| 1184 | { | ||
| 1185 | const c: C = .{ .c = -1111111111 }; | ||
| 1186 | const pcf = &c.c; | ||
| 1187 | const pc: *const C = @alignCast(@fieldParentPtr("c", pcf)); | ||
| 1188 | try expect(pc == &c); | ||
| 1189 | } | ||
| 1190 | { | ||
| 1191 | const c: C = .{ .c = -1111111111 }; | ||
| 1192 | const pcf = &c.c; | ||
| 1193 | var pc: *const C = undefined; | ||
| 1194 | pc = @alignCast(@fieldParentPtr("c", pcf)); | ||
| 1195 | try expect(pc == &c); | ||
| 1196 | } | ||
| 1197 | { | ||
| 1198 | const c: C = .{ .c = -1111111111 }; | ||
| 1199 | var pcf: @TypeOf(&c.c) = undefined; | ||
| 1200 | pcf = &c.c; | ||
| 1201 | var pc: *const C = undefined; | ||
| 1202 | pc = @alignCast(@fieldParentPtr("c", pcf)); | ||
| 1203 | try expect(pc == &c); | ||
| 1204 | } | ||
| 1205 | { | ||
| 1206 | var c: C = undefined; | ||
| 1207 | c = .{ .c = -1111111111 }; | ||
| 1208 | var pcf: @TypeOf(&c.c) = undefined; | ||
| 1209 | pcf = &c.c; | ||
| 1210 | var pc: *C = undefined; | ||
| 1211 | pc = @alignCast(@fieldParentPtr("c", pcf)); | ||
| 1212 | try expect(pc == &c); | ||
| 1213 | } | ||
| 1214 | } | ||
| 1215 | |||
| 1216 | test "@fieldParentPtr packed struct last zero-bit field" { | ||
| 1217 | if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; | ||
| 1218 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; | ||
| 1219 | |||
| 1220 | const C = packed struct { | ||
| 1221 | a: f32 = 3.14, | ||
| 1222 | b: i32 = 12345, | ||
| 1223 | c: u0 = 0, | ||
| 1224 | }; | ||
| 1225 | |||
| 1226 | { | ||
| 1227 | const c: C = .{ .a = 666.667 }; | ||
| 1228 | const pcf = &c.a; | ||
| 1229 | const pc: *const C = @alignCast(@fieldParentPtr("a", pcf)); | ||
| 1230 | try expect(pc == &c); | ||
| 1231 | } | ||
| 1232 | { | ||
| 1233 | const c: C = .{ .a = 666.667 }; | ||
| 1234 | const pcf = &c.a; | ||
| 1235 | var pc: *const C = undefined; | ||
| 1236 | pc = @alignCast(@fieldParentPtr("a", pcf)); | ||
| 1237 | try expect(pc == &c); | ||
| 1238 | } | ||
| 1239 | { | ||
| 1240 | const c: C = .{ .a = 666.667 }; | ||
| 1241 | var pcf: @TypeOf(&c.a) = undefined; | ||
| 1242 | pcf = &c.a; | ||
| 1243 | var pc: *const C = undefined; | ||
| 1244 | pc = @alignCast(@fieldParentPtr("a", pcf)); | ||
| 1245 | try expect(pc == &c); | ||
| 1246 | } | ||
| 1247 | { | ||
| 1248 | var c: C = undefined; | ||
| 1249 | c = .{ .a = 666.667 }; | ||
| 1250 | var pcf: @TypeOf(&c.a) = undefined; | ||
| 1251 | pcf = &c.a; | ||
| 1252 | var pc: *C = undefined; | ||
| 1253 | pc = @alignCast(@fieldParentPtr("a", pcf)); | ||
| 1254 | try expect(pc == &c); | ||
| 1255 | } | ||
| 1256 | |||
| 1257 | { | ||
| 1258 | const c: C = .{ .b = -1111111111 }; | ||
| 1259 | const pcf = &c.b; | ||
| 1260 | const pc: *const C = @alignCast(@fieldParentPtr("b", pcf)); | ||
| 1261 | try expect(pc == &c); | ||
| 1262 | } | ||
| 1263 | { | ||
| 1264 | const c: C = .{ .b = -1111111111 }; | ||
| 1265 | const pcf = &c.b; | ||
| 1266 | var pc: *const C = undefined; | ||
| 1267 | pc = @alignCast(@fieldParentPtr("b", pcf)); | ||
| 1268 | try expect(pc == &c); | ||
| 1269 | } | ||
| 1270 | { | ||
| 1271 | const c: C = .{ .b = -1111111111 }; | ||
| 1272 | var pcf: @TypeOf(&c.b) = undefined; | ||
| 1273 | pcf = &c.b; | ||
| 1274 | var pc: *const C = undefined; | ||
| 1275 | pc = @alignCast(@fieldParentPtr("b", pcf)); | ||
| 1276 | try expect(pc == &c); | ||
| 1277 | } | ||
| 1278 | { | ||
| 1279 | var c: C = undefined; | ||
| 1280 | c = .{ .b = -1111111111 }; | ||
| 1281 | var pcf: @TypeOf(&c.b) = undefined; | ||
| 1282 | pcf = &c.b; | ||
| 1283 | var pc: *C = undefined; | ||
| 1284 | pc = @alignCast(@fieldParentPtr("b", pcf)); | ||
| 1285 | try expect(pc == &c); | ||
| 1286 | } | ||
| 1287 | |||
| 1288 | { | ||
| 1289 | const c: C = .{ .c = 0 }; | ||
| 1290 | const pcf = &c.c; | ||
| 1291 | const pc: *const C = @alignCast(@fieldParentPtr("c", pcf)); | ||
| 1292 | try expect(pc == &c); | ||
| 1293 | } | ||
| 1294 | { | ||
| 1295 | const c: C = .{ .c = 0 }; | ||
| 1296 | const pcf = &c.c; | ||
| 1297 | var pc: *const C = undefined; | ||
| 1298 | pc = @alignCast(@fieldParentPtr("c", pcf)); | ||
| 1299 | try expect(pc == &c); | ||
| 1300 | } | ||
| 1301 | { | ||
| 1302 | const c: C = .{ .c = 0 }; | ||
| 1303 | var pcf: @TypeOf(&c.c) = undefined; | ||
| 1304 | pcf = &c.c; | ||
| 1305 | var pc: *const C = undefined; | ||
| 1306 | pc = @alignCast(@fieldParentPtr("c", pcf)); | ||
| 1307 | try expect(pc == &c); | ||
| 1308 | } | ||
| 1309 | { | ||
| 1310 | var c: C = undefined; | ||
| 1311 | c = .{ .c = 0 }; | ||
| 1312 | var pcf: @TypeOf(&c.c) = undefined; | ||
| 1313 | pcf = &c.c; | ||
| 1314 | var pc: *C = undefined; | ||
| 1315 | pc = @alignCast(@fieldParentPtr("c", pcf)); | ||
| 1316 | try expect(pc == &c); | ||
| 1317 | } | ||
| 74 | } | 1318 | } |
| 75 | 1319 | ||
| 76 | test "@fieldParentPtr tagged union" { | 1320 | test "@fieldParentPtr tagged union" { |
| 77 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | 1321 | const C = union(enum) { |
| 78 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 1322 | a: bool, |
| 79 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 1323 | b: f32, |
| 1324 | c: struct { u8 }, | ||
| 1325 | d: i32, | ||
| 1326 | }; | ||
| 1327 | |||
| 1328 | { | ||
| 1329 | const c: C = .{ .a = false }; | ||
| 1330 | const pcf = &c.a; | ||
| 1331 | const pc: *const C = @alignCast(@fieldParentPtr("a", pcf)); | ||
| 1332 | try expect(pc == &c); | ||
| 1333 | } | ||
| 1334 | { | ||
| 1335 | const c: C = .{ .a = false }; | ||
| 1336 | const pcf = &c.a; | ||
| 1337 | var pc: *const C = undefined; | ||
| 1338 | pc = @alignCast(@fieldParentPtr("a", pcf)); | ||
| 1339 | try expect(pc == &c); | ||
| 1340 | } | ||
| 1341 | { | ||
| 1342 | const c: C = .{ .a = false }; | ||
| 1343 | var pcf: @TypeOf(&c.a) = undefined; | ||
| 1344 | pcf = &c.a; | ||
| 1345 | var pc: *const C = undefined; | ||
| 1346 | pc = @alignCast(@fieldParentPtr("a", pcf)); | ||
| 1347 | try expect(pc == &c); | ||
| 1348 | } | ||
| 1349 | { | ||
| 1350 | var c: C = undefined; | ||
| 1351 | c = .{ .a = false }; | ||
| 1352 | var pcf: @TypeOf(&c.a) = undefined; | ||
| 1353 | pcf = &c.a; | ||
| 1354 | var pc: *C = undefined; | ||
| 1355 | pc = @alignCast(@fieldParentPtr("a", pcf)); | ||
| 1356 | try expect(pc == &c); | ||
| 1357 | } | ||
| 1358 | |||
| 1359 | { | ||
| 1360 | const c: C = .{ .b = 0 }; | ||
| 1361 | const pcf = &c.b; | ||
| 1362 | const pc: *const C = @alignCast(@fieldParentPtr("b", pcf)); | ||
| 1363 | try expect(pc == &c); | ||
| 1364 | } | ||
| 1365 | { | ||
| 1366 | const c: C = .{ .b = 0 }; | ||
| 1367 | const pcf = &c.b; | ||
| 1368 | var pc: *const C = undefined; | ||
| 1369 | pc = @alignCast(@fieldParentPtr("b", pcf)); | ||
| 1370 | try expect(pc == &c); | ||
| 1371 | } | ||
| 1372 | { | ||
| 1373 | const c: C = .{ .b = 0 }; | ||
| 1374 | var pcf: @TypeOf(&c.b) = undefined; | ||
| 1375 | pcf = &c.b; | ||
| 1376 | var pc: *const C = undefined; | ||
| 1377 | pc = @alignCast(@fieldParentPtr("b", pcf)); | ||
| 1378 | try expect(pc == &c); | ||
| 1379 | } | ||
| 1380 | { | ||
| 1381 | var c: C = undefined; | ||
| 1382 | c = .{ .b = 0 }; | ||
| 1383 | var pcf: @TypeOf(&c.b) = undefined; | ||
| 1384 | pcf = &c.b; | ||
| 1385 | var pc: *C = undefined; | ||
| 1386 | pc = @alignCast(@fieldParentPtr("b", pcf)); | ||
| 1387 | try expect(pc == &c); | ||
| 1388 | } | ||
| 1389 | |||
| 1390 | { | ||
| 1391 | const c: C = .{ .c = .{255} }; | ||
| 1392 | const pcf = &c.c; | ||
| 1393 | const pc: *const C = @alignCast(@fieldParentPtr("c", pcf)); | ||
| 1394 | try expect(pc == &c); | ||
| 1395 | } | ||
| 1396 | { | ||
| 1397 | const c: C = .{ .c = .{255} }; | ||
| 1398 | const pcf = &c.c; | ||
| 1399 | var pc: *const C = undefined; | ||
| 1400 | pc = @alignCast(@fieldParentPtr("c", pcf)); | ||
| 1401 | try expect(pc == &c); | ||
| 1402 | } | ||
| 1403 | { | ||
| 1404 | const c: C = .{ .c = .{255} }; | ||
| 1405 | var pcf: @TypeOf(&c.c) = undefined; | ||
| 1406 | pcf = &c.c; | ||
| 1407 | var pc: *const C = undefined; | ||
| 1408 | pc = @alignCast(@fieldParentPtr("c", pcf)); | ||
| 1409 | try expect(pc == &c); | ||
| 1410 | } | ||
| 1411 | { | ||
| 1412 | var c: C = undefined; | ||
| 1413 | c = .{ .c = .{255} }; | ||
| 1414 | var pcf: @TypeOf(&c.c) = undefined; | ||
| 1415 | pcf = &c.c; | ||
| 1416 | var pc: *C = undefined; | ||
| 1417 | pc = @alignCast(@fieldParentPtr("c", pcf)); | ||
| 1418 | try expect(pc == &c); | ||
| 1419 | } | ||
| 80 | 1420 | ||
| 81 | try testFieldParentPtrTaggedUnion(&bar_tagged.c); | 1421 | { |
| 82 | try comptime testFieldParentPtrTaggedUnion(&bar_tagged.c); | 1422 | const c: C = .{ .d = -1111111111 }; |
| 1423 | const pcf = &c.d; | ||
| 1424 | const pc: *const C = @alignCast(@fieldParentPtr("d", pcf)); | ||
| 1425 | try expect(pc == &c); | ||
| 1426 | } | ||
| 1427 | { | ||
| 1428 | const c: C = .{ .d = -1111111111 }; | ||
| 1429 | const pcf = &c.d; | ||
| 1430 | var pc: *const C = undefined; | ||
| 1431 | pc = @alignCast(@fieldParentPtr("d", pcf)); | ||
| 1432 | try expect(pc == &c); | ||
| 1433 | } | ||
| 1434 | { | ||
| 1435 | const c: C = .{ .d = -1111111111 }; | ||
| 1436 | var pcf: @TypeOf(&c.d) = undefined; | ||
| 1437 | pcf = &c.d; | ||
| 1438 | var pc: *const C = undefined; | ||
| 1439 | pc = @alignCast(@fieldParentPtr("d", pcf)); | ||
| 1440 | try expect(pc == &c); | ||
| 1441 | } | ||
| 1442 | { | ||
| 1443 | var c: C = undefined; | ||
| 1444 | c = .{ .d = -1111111111 }; | ||
| 1445 | var pcf: @TypeOf(&c.d) = undefined; | ||
| 1446 | pcf = &c.d; | ||
| 1447 | var pc: *C = undefined; | ||
| 1448 | pc = @alignCast(@fieldParentPtr("d", pcf)); | ||
| 1449 | try expect(pc == &c); | ||
| 1450 | } | ||
| 83 | } | 1451 | } |
| 84 | 1452 | ||
| 85 | const BarTagged = union(enum) { | 1453 | test "@fieldParentPtr untagged union" { |
| 86 | a: bool, | 1454 | const C = union { |
| 87 | b: f32, | 1455 | a: bool, |
| 88 | c: i32, | 1456 | b: f32, |
| 89 | d: i32, | 1457 | c: struct { u8 }, |
| 90 | }; | 1458 | d: i32, |
| 1459 | }; | ||
| 1460 | |||
| 1461 | { | ||
| 1462 | const c: C = .{ .a = false }; | ||
| 1463 | const pcf = &c.a; | ||
| 1464 | const pc: *const C = @alignCast(@fieldParentPtr("a", pcf)); | ||
| 1465 | try expect(pc == &c); | ||
| 1466 | } | ||
| 1467 | { | ||
| 1468 | const c: C = .{ .a = false }; | ||
| 1469 | const pcf = &c.a; | ||
| 1470 | var pc: *const C = undefined; | ||
| 1471 | pc = @alignCast(@fieldParentPtr("a", pcf)); | ||
| 1472 | try expect(pc == &c); | ||
| 1473 | } | ||
| 1474 | { | ||
| 1475 | const c: C = .{ .a = false }; | ||
| 1476 | var pcf: @TypeOf(&c.a) = undefined; | ||
| 1477 | pcf = &c.a; | ||
| 1478 | var pc: *const C = undefined; | ||
| 1479 | pc = @alignCast(@fieldParentPtr("a", pcf)); | ||
| 1480 | try expect(pc == &c); | ||
| 1481 | } | ||
| 1482 | { | ||
| 1483 | var c: C = undefined; | ||
| 1484 | c = .{ .a = false }; | ||
| 1485 | var pcf: @TypeOf(&c.a) = undefined; | ||
| 1486 | pcf = &c.a; | ||
| 1487 | var pc: *C = undefined; | ||
| 1488 | pc = @alignCast(@fieldParentPtr("a", pcf)); | ||
| 1489 | try expect(pc == &c); | ||
| 1490 | } | ||
| 91 | 1491 | ||
| 92 | const bar_tagged = BarTagged{ .c = 42 }; | 1492 | { |
| 1493 | const c: C = .{ .b = 0 }; | ||
| 1494 | const pcf = &c.b; | ||
| 1495 | const pc: *const C = @alignCast(@fieldParentPtr("b", pcf)); | ||
| 1496 | try expect(pc == &c); | ||
| 1497 | } | ||
| 1498 | { | ||
| 1499 | const c: C = .{ .b = 0 }; | ||
| 1500 | const pcf = &c.b; | ||
| 1501 | var pc: *const C = undefined; | ||
| 1502 | pc = @alignCast(@fieldParentPtr("b", pcf)); | ||
| 1503 | try expect(pc == &c); | ||
| 1504 | } | ||
| 1505 | { | ||
| 1506 | const c: C = .{ .b = 0 }; | ||
| 1507 | var pcf: @TypeOf(&c.b) = undefined; | ||
| 1508 | pcf = &c.b; | ||
| 1509 | var pc: *const C = undefined; | ||
| 1510 | pc = @alignCast(@fieldParentPtr("b", pcf)); | ||
| 1511 | try expect(pc == &c); | ||
| 1512 | } | ||
| 1513 | { | ||
| 1514 | var c: C = undefined; | ||
| 1515 | c = .{ .b = 0 }; | ||
| 1516 | var pcf: @TypeOf(&c.b) = undefined; | ||
| 1517 | pcf = &c.b; | ||
| 1518 | var pc: *C = undefined; | ||
| 1519 | pc = @alignCast(@fieldParentPtr("b", pcf)); | ||
| 1520 | try expect(pc == &c); | ||
| 1521 | } | ||
| 93 | 1522 | ||
| 94 | fn testFieldParentPtrTaggedUnion(c: *const i32) !void { | 1523 | { |
| 95 | try expect(c == &bar_tagged.c); | 1524 | const c: C = .{ .c = .{255} }; |
| 1525 | const pcf = &c.c; | ||
| 1526 | const pc: *const C = @alignCast(@fieldParentPtr("c", pcf)); | ||
| 1527 | try expect(pc == &c); | ||
| 1528 | } | ||
| 1529 | { | ||
| 1530 | const c: C = .{ .c = .{255} }; | ||
| 1531 | const pcf = &c.c; | ||
| 1532 | var pc: *const C = undefined; | ||
| 1533 | pc = @alignCast(@fieldParentPtr("c", pcf)); | ||
| 1534 | try expect(pc == &c); | ||
| 1535 | } | ||
| 1536 | { | ||
| 1537 | const c: C = .{ .c = .{255} }; | ||
| 1538 | var pcf: @TypeOf(&c.c) = undefined; | ||
| 1539 | pcf = &c.c; | ||
| 1540 | var pc: *const C = undefined; | ||
| 1541 | pc = @alignCast(@fieldParentPtr("c", pcf)); | ||
| 1542 | try expect(pc == &c); | ||
| 1543 | } | ||
| 1544 | { | ||
| 1545 | var c: C = undefined; | ||
| 1546 | c = .{ .c = .{255} }; | ||
| 1547 | var pcf: @TypeOf(&c.c) = undefined; | ||
| 1548 | pcf = &c.c; | ||
| 1549 | var pc: *C = undefined; | ||
| 1550 | pc = @alignCast(@fieldParentPtr("c", pcf)); | ||
| 1551 | try expect(pc == &c); | ||
| 1552 | } | ||
| 96 | 1553 | ||
| 97 | const base = @fieldParentPtr(BarTagged, "c", c); | 1554 | { |
| 98 | try expect(base == &bar_tagged); | 1555 | const c: C = .{ .d = -1111111111 }; |
| 99 | try expect(&base.c == c); | 1556 | const pcf = &c.d; |
| 1557 | const pc: *const C = @alignCast(@fieldParentPtr("d", pcf)); | ||
| 1558 | try expect(pc == &c); | ||
| 1559 | } | ||
| 1560 | { | ||
| 1561 | const c: C = .{ .d = -1111111111 }; | ||
| 1562 | const pcf = &c.d; | ||
| 1563 | var pc: *const C = undefined; | ||
| 1564 | pc = @alignCast(@fieldParentPtr("d", pcf)); | ||
| 1565 | try expect(pc == &c); | ||
| 1566 | } | ||
| 1567 | { | ||
| 1568 | const c: C = .{ .d = -1111111111 }; | ||
| 1569 | var pcf: @TypeOf(&c.d) = undefined; | ||
| 1570 | pcf = &c.d; | ||
| 1571 | var pc: *const C = undefined; | ||
| 1572 | pc = @alignCast(@fieldParentPtr("d", pcf)); | ||
| 1573 | try expect(pc == &c); | ||
| 1574 | } | ||
| 1575 | { | ||
| 1576 | var c: C = undefined; | ||
| 1577 | c = .{ .d = -1111111111 }; | ||
| 1578 | var pcf: @TypeOf(&c.d) = undefined; | ||
| 1579 | pcf = &c.d; | ||
| 1580 | var pc: *C = undefined; | ||
| 1581 | pc = @alignCast(@fieldParentPtr("d", pcf)); | ||
| 1582 | try expect(pc == &c); | ||
| 1583 | } | ||
| 100 | } | 1584 | } |
| 101 | 1585 | ||
| 102 | test "@fieldParentPtr extern union" { | 1586 | test "@fieldParentPtr extern union" { |
| 103 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | 1587 | const C = extern union { |
| 104 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 1588 | a: bool, |
| 105 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 1589 | b: f32, |
| 1590 | c: extern struct { x: u8 }, | ||
| 1591 | d: i32, | ||
| 1592 | }; | ||
| 1593 | |||
| 1594 | { | ||
| 1595 | const c: C = .{ .a = false }; | ||
| 1596 | const pcf = &c.a; | ||
| 1597 | const pc: *const C = @alignCast(@fieldParentPtr("a", pcf)); | ||
| 1598 | try expect(pc == &c); | ||
| 1599 | } | ||
| 1600 | { | ||
| 1601 | const c: C = .{ .a = false }; | ||
| 1602 | const pcf = &c.a; | ||
| 1603 | var pc: *const C = undefined; | ||
| 1604 | pc = @alignCast(@fieldParentPtr("a", pcf)); | ||
| 1605 | try expect(pc == &c); | ||
| 1606 | } | ||
| 1607 | { | ||
| 1608 | const c: C = .{ .a = false }; | ||
| 1609 | var pcf: @TypeOf(&c.a) = undefined; | ||
| 1610 | pcf = &c.a; | ||
| 1611 | var pc: *const C = undefined; | ||
| 1612 | pc = @alignCast(@fieldParentPtr("a", pcf)); | ||
| 1613 | try expect(pc == &c); | ||
| 1614 | } | ||
| 1615 | { | ||
| 1616 | var c: C = undefined; | ||
| 1617 | c = .{ .a = false }; | ||
| 1618 | var pcf: @TypeOf(&c.a) = undefined; | ||
| 1619 | pcf = &c.a; | ||
| 1620 | var pc: *C = undefined; | ||
| 1621 | pc = @alignCast(@fieldParentPtr("a", pcf)); | ||
| 1622 | try expect(pc == &c); | ||
| 1623 | } | ||
| 1624 | |||
| 1625 | { | ||
| 1626 | const c: C = .{ .b = 0 }; | ||
| 1627 | const pcf = &c.b; | ||
| 1628 | const pc: *const C = @alignCast(@fieldParentPtr("b", pcf)); | ||
| 1629 | try expect(pc == &c); | ||
| 1630 | } | ||
| 1631 | { | ||
| 1632 | const c: C = .{ .b = 0 }; | ||
| 1633 | const pcf = &c.b; | ||
| 1634 | var pc: *const C = undefined; | ||
| 1635 | pc = @alignCast(@fieldParentPtr("b", pcf)); | ||
| 1636 | try expect(pc == &c); | ||
| 1637 | } | ||
| 1638 | { | ||
| 1639 | const c: C = .{ .b = 0 }; | ||
| 1640 | var pcf: @TypeOf(&c.b) = undefined; | ||
| 1641 | pcf = &c.b; | ||
| 1642 | var pc: *const C = undefined; | ||
| 1643 | pc = @alignCast(@fieldParentPtr("b", pcf)); | ||
| 1644 | try expect(pc == &c); | ||
| 1645 | } | ||
| 1646 | { | ||
| 1647 | var c: C = undefined; | ||
| 1648 | c = .{ .b = 0 }; | ||
| 1649 | var pcf: @TypeOf(&c.b) = undefined; | ||
| 1650 | pcf = &c.b; | ||
| 1651 | var pc: *C = undefined; | ||
| 1652 | pc = @alignCast(@fieldParentPtr("b", pcf)); | ||
| 1653 | try expect(pc == &c); | ||
| 1654 | } | ||
| 1655 | |||
| 1656 | { | ||
| 1657 | const c: C = .{ .c = .{ .x = 255 } }; | ||
| 1658 | const pcf = &c.c; | ||
| 1659 | const pc: *const C = @alignCast(@fieldParentPtr("c", pcf)); | ||
| 1660 | try expect(pc == &c); | ||
| 1661 | } | ||
| 1662 | { | ||
| 1663 | const c: C = .{ .c = .{ .x = 255 } }; | ||
| 1664 | const pcf = &c.c; | ||
| 1665 | var pc: *const C = undefined; | ||
| 1666 | pc = @alignCast(@fieldParentPtr("c", pcf)); | ||
| 1667 | try expect(pc == &c); | ||
| 1668 | } | ||
| 1669 | { | ||
| 1670 | const c: C = .{ .c = .{ .x = 255 } }; | ||
| 1671 | var pcf: @TypeOf(&c.c) = undefined; | ||
| 1672 | pcf = &c.c; | ||
| 1673 | var pc: *const C = undefined; | ||
| 1674 | pc = @alignCast(@fieldParentPtr("c", pcf)); | ||
| 1675 | try expect(pc == &c); | ||
| 1676 | } | ||
| 1677 | { | ||
| 1678 | var c: C = undefined; | ||
| 1679 | c = .{ .c = .{ .x = 255 } }; | ||
| 1680 | var pcf: @TypeOf(&c.c) = undefined; | ||
| 1681 | pcf = &c.c; | ||
| 1682 | var pc: *C = undefined; | ||
| 1683 | pc = @alignCast(@fieldParentPtr("c", pcf)); | ||
| 1684 | try expect(pc == &c); | ||
| 1685 | } | ||
| 1686 | |||
| 1687 | { | ||
| 1688 | const c: C = .{ .d = -1111111111 }; | ||
| 1689 | const pcf = &c.d; | ||
| 1690 | const pc: *const C = @alignCast(@fieldParentPtr("d", pcf)); | ||
| 1691 | try expect(pc == &c); | ||
| 1692 | } | ||
| 1693 | { | ||
| 1694 | const c: C = .{ .d = -1111111111 }; | ||
| 1695 | const pcf = &c.d; | ||
| 1696 | var pc: *const C = undefined; | ||
| 1697 | pc = @alignCast(@fieldParentPtr("d", pcf)); | ||
| 1698 | try expect(pc == &c); | ||
| 1699 | } | ||
| 1700 | { | ||
| 1701 | const c: C = .{ .d = -1111111111 }; | ||
| 1702 | var pcf: @TypeOf(&c.d) = undefined; | ||
| 1703 | pcf = &c.d; | ||
| 1704 | var pc: *const C = undefined; | ||
| 1705 | pc = @alignCast(@fieldParentPtr("d", pcf)); | ||
| 1706 | try expect(pc == &c); | ||
| 1707 | } | ||
| 1708 | { | ||
| 1709 | var c: C = undefined; | ||
| 1710 | c = .{ .d = -1111111111 }; | ||
| 1711 | var pcf: @TypeOf(&c.d) = undefined; | ||
| 1712 | pcf = &c.d; | ||
| 1713 | var pc: *C = undefined; | ||
| 1714 | pc = @alignCast(@fieldParentPtr("d", pcf)); | ||
| 1715 | try expect(pc == &c); | ||
| 1716 | } | ||
| 1717 | } | ||
| 1718 | |||
| 1719 | test "@fieldParentPtr packed union" { | ||
| 1720 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; | ||
| 1721 | |||
| 1722 | const C = packed union { | ||
| 1723 | a: bool, | ||
| 1724 | b: f32, | ||
| 1725 | c: packed struct { x: u8 }, | ||
| 1726 | d: i32, | ||
| 1727 | }; | ||
| 1728 | |||
| 1729 | { | ||
| 1730 | const c: C = .{ .a = false }; | ||
| 1731 | const pcf = &c.a; | ||
| 1732 | const pc: *const C = @alignCast(@fieldParentPtr("a", pcf)); | ||
| 1733 | try expect(pc == &c); | ||
| 1734 | } | ||
| 1735 | { | ||
| 1736 | const c: C = .{ .a = false }; | ||
| 1737 | const pcf = &c.a; | ||
| 1738 | var pc: *const C = undefined; | ||
| 1739 | pc = @alignCast(@fieldParentPtr("a", pcf)); | ||
| 1740 | try expect(pc == &c); | ||
| 1741 | } | ||
| 1742 | { | ||
| 1743 | const c: C = .{ .a = false }; | ||
| 1744 | var pcf: @TypeOf(&c.a) = undefined; | ||
| 1745 | pcf = &c.a; | ||
| 1746 | var pc: *const C = undefined; | ||
| 1747 | pc = @alignCast(@fieldParentPtr("a", pcf)); | ||
| 1748 | try expect(pc == &c); | ||
| 1749 | } | ||
| 1750 | { | ||
| 1751 | var c: C = undefined; | ||
| 1752 | c = .{ .a = false }; | ||
| 1753 | var pcf: @TypeOf(&c.a) = undefined; | ||
| 1754 | pcf = &c.a; | ||
| 1755 | var pc: *C = undefined; | ||
| 1756 | pc = @alignCast(@fieldParentPtr("a", pcf)); | ||
| 1757 | try expect(pc == &c); | ||
| 1758 | } | ||
| 1759 | |||
| 1760 | { | ||
| 1761 | const c: C = .{ .b = 0 }; | ||
| 1762 | const pcf = &c.b; | ||
| 1763 | const pc: *const C = @alignCast(@fieldParentPtr("b", pcf)); | ||
| 1764 | try expect(pc == &c); | ||
| 1765 | } | ||
| 1766 | { | ||
| 1767 | const c: C = .{ .b = 0 }; | ||
| 1768 | const pcf = &c.b; | ||
| 1769 | var pc: *const C = undefined; | ||
| 1770 | pc = @alignCast(@fieldParentPtr("b", pcf)); | ||
| 1771 | try expect(pc == &c); | ||
| 1772 | } | ||
| 1773 | { | ||
| 1774 | const c: C = .{ .b = 0 }; | ||
| 1775 | var pcf: @TypeOf(&c.b) = undefined; | ||
| 1776 | pcf = &c.b; | ||
| 1777 | var pc: *const C = undefined; | ||
| 1778 | pc = @alignCast(@fieldParentPtr("b", pcf)); | ||
| 1779 | try expect(pc == &c); | ||
| 1780 | } | ||
| 1781 | { | ||
| 1782 | var c: C = undefined; | ||
| 1783 | c = .{ .b = 0 }; | ||
| 1784 | var pcf: @TypeOf(&c.b) = undefined; | ||
| 1785 | pcf = &c.b; | ||
| 1786 | var pc: *C = undefined; | ||
| 1787 | pc = @alignCast(@fieldParentPtr("b", pcf)); | ||
| 1788 | try expect(pc == &c); | ||
| 1789 | } | ||
| 1790 | |||
| 1791 | { | ||
| 1792 | const c: C = .{ .c = .{ .x = 255 } }; | ||
| 1793 | const pcf = &c.c; | ||
| 1794 | const pc: *const C = @alignCast(@fieldParentPtr("c", pcf)); | ||
| 1795 | try expect(pc == &c); | ||
| 1796 | } | ||
| 1797 | { | ||
| 1798 | const c: C = .{ .c = .{ .x = 255 } }; | ||
| 1799 | const pcf = &c.c; | ||
| 1800 | var pc: *const C = undefined; | ||
| 1801 | pc = @alignCast(@fieldParentPtr("c", pcf)); | ||
| 1802 | try expect(pc == &c); | ||
| 1803 | } | ||
| 1804 | { | ||
| 1805 | const c: C = .{ .c = .{ .x = 255 } }; | ||
| 1806 | var pcf: @TypeOf(&c.c) = undefined; | ||
| 1807 | pcf = &c.c; | ||
| 1808 | var pc: *const C = undefined; | ||
| 1809 | pc = @alignCast(@fieldParentPtr("c", pcf)); | ||
| 1810 | try expect(pc == &c); | ||
| 1811 | } | ||
| 1812 | { | ||
| 1813 | var c: C = undefined; | ||
| 1814 | c = .{ .c = .{ .x = 255 } }; | ||
| 1815 | var pcf: @TypeOf(&c.c) = undefined; | ||
| 1816 | pcf = &c.c; | ||
| 1817 | var pc: *C = undefined; | ||
| 1818 | pc = @alignCast(@fieldParentPtr("c", pcf)); | ||
| 1819 | try expect(pc == &c); | ||
| 1820 | } | ||
| 106 | 1821 | ||
| 107 | try testFieldParentPtrExternUnion(&bar_extern.c); | 1822 | { |
| 108 | try comptime testFieldParentPtrExternUnion(&bar_extern.c); | 1823 | const c: C = .{ .d = -1111111111 }; |
| 1824 | const pcf = &c.d; | ||
| 1825 | const pc: *const C = @alignCast(@fieldParentPtr("d", pcf)); | ||
| 1826 | try expect(pc == &c); | ||
| 1827 | } | ||
| 1828 | { | ||
| 1829 | const c: C = .{ .d = -1111111111 }; | ||
| 1830 | const pcf = &c.d; | ||
| 1831 | var pc: *const C = undefined; | ||
| 1832 | pc = @alignCast(@fieldParentPtr("d", pcf)); | ||
| 1833 | try expect(pc == &c); | ||
| 1834 | } | ||
| 1835 | { | ||
| 1836 | const c: C = .{ .d = -1111111111 }; | ||
| 1837 | var pcf: @TypeOf(&c.d) = undefined; | ||
| 1838 | pcf = &c.d; | ||
| 1839 | var pc: *const C = undefined; | ||
| 1840 | pc = @alignCast(@fieldParentPtr("d", pcf)); | ||
| 1841 | try expect(pc == &c); | ||
| 1842 | } | ||
| 1843 | { | ||
| 1844 | var c: C = undefined; | ||
| 1845 | c = .{ .d = -1111111111 }; | ||
| 1846 | var pcf: @TypeOf(&c.d) = undefined; | ||
| 1847 | pcf = &c.d; | ||
| 1848 | var pc: *C = undefined; | ||
| 1849 | pc = @alignCast(@fieldParentPtr("d", pcf)); | ||
| 1850 | try expect(pc == &c); | ||
| 1851 | } | ||
| 109 | } | 1852 | } |
| 110 | 1853 | ||
| 111 | const BarExtern = extern union { | 1854 | test "@fieldParentPtr tagged union all zero-bit fields" { |
| 112 | a: bool, | 1855 | if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; |
| 113 | b: f32, | 1856 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; |
| 114 | c: i32, | ||
| 115 | d: i32, | ||
| 116 | }; | ||
| 117 | 1857 | ||
| 118 | const bar_extern = BarExtern{ .c = 42 }; | 1858 | const C = union(enum) { |
| 1859 | a: u0, | ||
| 1860 | b: i0, | ||
| 1861 | }; | ||
| 119 | 1862 | ||
| 120 | fn testFieldParentPtrExternUnion(c: *const i32) !void { | 1863 | { |
| 121 | try expect(c == &bar_extern.c); | 1864 | const c: C = .{ .a = 0 }; |
| 1865 | const pcf = &c.a; | ||
| 1866 | const pc: *const C = @alignCast(@fieldParentPtr("a", pcf)); | ||
| 1867 | try expect(pc == &c); | ||
| 1868 | } | ||
| 1869 | { | ||
| 1870 | const c: C = .{ .a = 0 }; | ||
| 1871 | const pcf = &c.a; | ||
| 1872 | var pc: *const C = undefined; | ||
| 1873 | pc = @alignCast(@fieldParentPtr("a", pcf)); | ||
| 1874 | try expect(pc == &c); | ||
| 1875 | } | ||
| 1876 | { | ||
| 1877 | const c: C = .{ .a = 0 }; | ||
| 1878 | var pcf: @TypeOf(&c.a) = undefined; | ||
| 1879 | pcf = &c.a; | ||
| 1880 | var pc: *const C = undefined; | ||
| 1881 | pc = @alignCast(@fieldParentPtr("a", pcf)); | ||
| 1882 | try expect(pc == &c); | ||
| 1883 | } | ||
| 1884 | { | ||
| 1885 | var c: C = undefined; | ||
| 1886 | c = .{ .a = 0 }; | ||
| 1887 | var pcf: @TypeOf(&c.a) = undefined; | ||
| 1888 | pcf = &c.a; | ||
| 1889 | var pc: *C = undefined; | ||
| 1890 | pc = @alignCast(@fieldParentPtr("a", pcf)); | ||
| 1891 | try expect(pc == &c); | ||
| 1892 | } | ||
| 122 | 1893 | ||
| 123 | const base = @fieldParentPtr(BarExtern, "c", c); | 1894 | { |
| 124 | try expect(base == &bar_extern); | 1895 | const c: C = .{ .b = 0 }; |
| 125 | try expect(&base.c == c); | 1896 | const pcf = &c.b; |
| 1897 | const pc: *const C = @alignCast(@fieldParentPtr("b", pcf)); | ||
| 1898 | try expect(pc == &c); | ||
| 1899 | } | ||
| 1900 | { | ||
| 1901 | const c: C = .{ .b = 0 }; | ||
| 1902 | const pcf = &c.b; | ||
| 1903 | var pc: *const C = undefined; | ||
| 1904 | pc = @alignCast(@fieldParentPtr("b", pcf)); | ||
| 1905 | try expect(pc == &c); | ||
| 1906 | } | ||
| 1907 | { | ||
| 1908 | const c: C = .{ .b = 0 }; | ||
| 1909 | var pcf: @TypeOf(&c.b) = undefined; | ||
| 1910 | pcf = &c.b; | ||
| 1911 | var pc: *const C = undefined; | ||
| 1912 | pc = @alignCast(@fieldParentPtr("b", pcf)); | ||
| 1913 | try expect(pc == &c); | ||
| 1914 | } | ||
| 1915 | { | ||
| 1916 | var c: C = undefined; | ||
| 1917 | c = .{ .b = 0 }; | ||
| 1918 | var pcf: @TypeOf(&c.b) = undefined; | ||
| 1919 | pcf = &c.b; | ||
| 1920 | var pc: *C = undefined; | ||
| 1921 | pc = @alignCast(@fieldParentPtr("b", pcf)); | ||
| 1922 | try expect(pc == &c); | ||
| 1923 | } | ||
| 126 | } | 1924 | } |
test/behavior/struct.zig+6-6| ... | @@ -1392,13 +1392,13 @@ test "fieldParentPtr of a zero-bit field" { | ... | @@ -1392,13 +1392,13 @@ test "fieldParentPtr of a zero-bit field" { |
| 1392 | { | 1392 | { |
| 1393 | const a = A{ .u = 0 }; | 1393 | const a = A{ .u = 0 }; |
| 1394 | const b_ptr = &a.b; | 1394 | const b_ptr = &a.b; |
| 1395 | const a_ptr = @fieldParentPtr(A, "b", b_ptr); | 1395 | const a_ptr: *const A = @fieldParentPtr("b", b_ptr); |
| 1396 | try std.testing.expectEqual(&a, a_ptr); | 1396 | try std.testing.expectEqual(&a, a_ptr); |
| 1397 | } | 1397 | } |
| 1398 | { | 1398 | { |
| 1399 | var a = A{ .u = 0 }; | 1399 | var a = A{ .u = 0 }; |
| 1400 | const b_ptr = &a.b; | 1400 | const b_ptr = &a.b; |
| 1401 | const a_ptr = @fieldParentPtr(A, "b", b_ptr); | 1401 | const a_ptr: *A = @fieldParentPtr("b", b_ptr); |
| 1402 | try std.testing.expectEqual(&a, a_ptr); | 1402 | try std.testing.expectEqual(&a, a_ptr); |
| 1403 | } | 1403 | } |
| 1404 | } | 1404 | } |
| ... | @@ -1406,17 +1406,17 @@ test "fieldParentPtr of a zero-bit field" { | ... | @@ -1406,17 +1406,17 @@ test "fieldParentPtr of a zero-bit field" { |
| 1406 | { | 1406 | { |
| 1407 | const a = A{ .u = 0 }; | 1407 | const a = A{ .u = 0 }; |
| 1408 | const c_ptr = &a.b.c; | 1408 | const c_ptr = &a.b.c; |
| 1409 | const b_ptr = @fieldParentPtr(@TypeOf(a.b), "c", c_ptr); | 1409 | const b_ptr: @TypeOf(&a.b) = @fieldParentPtr("c", c_ptr); |
| 1410 | try std.testing.expectEqual(&a.b, b_ptr); | 1410 | try std.testing.expectEqual(&a.b, b_ptr); |
| 1411 | const a_ptr = @fieldParentPtr(A, "b", b_ptr); | 1411 | const a_ptr: *const A = @fieldParentPtr("b", b_ptr); |
| 1412 | try std.testing.expectEqual(&a, a_ptr); | 1412 | try std.testing.expectEqual(&a, a_ptr); |
| 1413 | } | 1413 | } |
| 1414 | { | 1414 | { |
| 1415 | var a = A{ .u = 0 }; | 1415 | var a = A{ .u = 0 }; |
| 1416 | const c_ptr = &a.b.c; | 1416 | const c_ptr = &a.b.c; |
| 1417 | const b_ptr = @fieldParentPtr(@TypeOf(a.b), "c", c_ptr); | 1417 | const b_ptr: @TypeOf(&a.b) = @fieldParentPtr("c", c_ptr); |
| 1418 | try std.testing.expectEqual(&a.b, b_ptr); | 1418 | try std.testing.expectEqual(&a.b, b_ptr); |
| 1419 | const a_ptr = @fieldParentPtr(A, "b", b_ptr); | 1419 | const a_ptr: *const A = @fieldParentPtr("b", b_ptr); |
| 1420 | try std.testing.expectEqual(&a, a_ptr); | 1420 | try std.testing.expectEqual(&a, a_ptr); |
| 1421 | } | 1421 | } |
| 1422 | } | 1422 | } |
test/behavior/tuple.zig+2-2| ... | @@ -222,7 +222,7 @@ test "fieldParentPtr of tuple" { | ... | @@ -222,7 +222,7 @@ test "fieldParentPtr of tuple" { |
| 222 | var x: u32 = 0; | 222 | var x: u32 = 0; |
| 223 | _ = &x; | 223 | _ = &x; |
| 224 | const tuple = .{ x, x }; | 224 | const tuple = .{ x, x }; |
| 225 | try testing.expect(&tuple == @fieldParentPtr(@TypeOf(tuple), "1", &tuple[1])); | 225 | try testing.expect(&tuple == @as(@TypeOf(&tuple), @fieldParentPtr("1", &tuple[1]))); |
| 226 | } | 226 | } |
| 227 | 227 | ||
| 228 | test "fieldParentPtr of anon struct" { | 228 | test "fieldParentPtr of anon struct" { |
| ... | @@ -233,7 +233,7 @@ test "fieldParentPtr of anon struct" { | ... | @@ -233,7 +233,7 @@ test "fieldParentPtr of anon struct" { |
| 233 | var x: u32 = 0; | 233 | var x: u32 = 0; |
| 234 | _ = &x; | 234 | _ = &x; |
| 235 | const anon_st = .{ .foo = x, .bar = x }; | 235 | const anon_st = .{ .foo = x, .bar = x }; |
| 236 | try testing.expect(&anon_st == @fieldParentPtr(@TypeOf(anon_st), "bar", &anon_st.bar)); | 236 | try testing.expect(&anon_st == @as(@TypeOf(&anon_st), @fieldParentPtr("bar", &anon_st.bar))); |
| 237 | } | 237 | } |
| 238 | 238 | ||
| 239 | test "offsetOf tuple" { | 239 | test "offsetOf tuple" { |
test/behavior/vector.zig+4| ... | @@ -1176,18 +1176,22 @@ test "@shlWithOverflow" { | ... | @@ -1176,18 +1176,22 @@ test "@shlWithOverflow" { |
| 1176 | test "alignment of vectors" { | 1176 | test "alignment of vectors" { |
| 1177 | try expect(@alignOf(@Vector(2, u8)) == switch (builtin.zig_backend) { | 1177 | try expect(@alignOf(@Vector(2, u8)) == switch (builtin.zig_backend) { |
| 1178 | else => 2, | 1178 | else => 2, |
| 1179 | .stage2_c => @alignOf(u8), | ||
| 1179 | .stage2_x86_64 => 16, | 1180 | .stage2_x86_64 => 16, |
| 1180 | }); | 1181 | }); |
| 1181 | try expect(@alignOf(@Vector(2, u1)) == switch (builtin.zig_backend) { | 1182 | try expect(@alignOf(@Vector(2, u1)) == switch (builtin.zig_backend) { |
| 1182 | else => 1, | 1183 | else => 1, |
| 1184 | .stage2_c => @alignOf(u1), | ||
| 1183 | .stage2_x86_64 => 16, | 1185 | .stage2_x86_64 => 16, |
| 1184 | }); | 1186 | }); |
| 1185 | try expect(@alignOf(@Vector(1, u1)) == switch (builtin.zig_backend) { | 1187 | try expect(@alignOf(@Vector(1, u1)) == switch (builtin.zig_backend) { |
| 1186 | else => 1, | 1188 | else => 1, |
| 1189 | .stage2_c => @alignOf(u1), | ||
| 1187 | .stage2_x86_64 => 16, | 1190 | .stage2_x86_64 => 16, |
| 1188 | }); | 1191 | }); |
| 1189 | try expect(@alignOf(@Vector(2, u16)) == switch (builtin.zig_backend) { | 1192 | try expect(@alignOf(@Vector(2, u16)) == switch (builtin.zig_backend) { |
| 1190 | else => 4, | 1193 | else => 4, |
| 1194 | .stage2_c => @alignOf(u16), | ||
| 1191 | .stage2_x86_64 => 16, | 1195 | .stage2_x86_64 => 16, |
| 1192 | }); | 1196 | }); |
| 1193 | } | 1197 | } |
test/cases/compile_errors/fieldParentPtr-bad_field_name.zig+2-2| ... | @@ -2,12 +2,12 @@ const Foo = extern struct { | ... | @@ -2,12 +2,12 @@ const Foo = extern struct { |
| 2 | derp: i32, | 2 | derp: i32, |
| 3 | }; | 3 | }; |
| 4 | export fn foo(a: *i32) *Foo { | 4 | export fn foo(a: *i32) *Foo { |
| 5 | return @fieldParentPtr(Foo, "a", a); | 5 | return @fieldParentPtr("a", a); |
| 6 | } | 6 | } |
| 7 | 7 | ||
| 8 | // error | 8 | // error |
| 9 | // backend=stage2 | 9 | // backend=stage2 |
| 10 | // target=native | 10 | // target=native |
| 11 | // | 11 | // |
| 12 | // :5:33: error: no field named 'a' in struct 'tmp.Foo' | 12 | // :5:28: error: no field named 'a' in struct 'tmp.Foo' |
| 13 | // :1:20: note: struct declared here | 13 | // :1:20: note: struct declared here |
test/cases/compile_errors/fieldParentPtr-comptime_field_ptr_not_based_on_struct.zig+2-2| ... | @@ -9,7 +9,7 @@ const foo = Foo{ | ... | @@ -9,7 +9,7 @@ const foo = Foo{ |
| 9 | 9 | ||
| 10 | comptime { | 10 | comptime { |
| 11 | const field_ptr: *i32 = @ptrFromInt(0x1234); | 11 | const field_ptr: *i32 = @ptrFromInt(0x1234); |
| 12 | const another_foo_ptr = @fieldParentPtr(Foo, "b", field_ptr); | 12 | const another_foo_ptr: *const Foo = @fieldParentPtr("b", field_ptr); |
| 13 | _ = another_foo_ptr; | 13 | _ = another_foo_ptr; |
| 14 | } | 14 | } |
| 15 | 15 | ||
| ... | @@ -17,4 +17,4 @@ comptime { | ... | @@ -17,4 +17,4 @@ comptime { |
| 17 | // backend=stage2 | 17 | // backend=stage2 |
| 18 | // target=native | 18 | // target=native |
| 19 | // | 19 | // |
| 20 | // :12:55: error: pointer value not based on parent struct | 20 | // :12:62: error: pointer value not based on parent struct |
test/cases/compile_errors/fieldParentPtr-comptime_wrong_field_index.zig+2-2| ... | @@ -8,7 +8,7 @@ const foo = Foo{ | ... | @@ -8,7 +8,7 @@ const foo = Foo{ |
| 8 | }; | 8 | }; |
| 9 | 9 | ||
| 10 | comptime { | 10 | comptime { |
| 11 | const another_foo_ptr = @fieldParentPtr(Foo, "b", &foo.a); | 11 | const another_foo_ptr: *const Foo = @fieldParentPtr("b", &foo.a); |
| 12 | _ = another_foo_ptr; | 12 | _ = another_foo_ptr; |
| 13 | } | 13 | } |
| 14 | 14 | ||
| ... | @@ -16,5 +16,5 @@ comptime { | ... | @@ -16,5 +16,5 @@ comptime { |
| 16 | // backend=stage2 | 16 | // backend=stage2 |
| 17 | // target=native | 17 | // target=native |
| 18 | // | 18 | // |
| 19 | // :11:29: error: field 'b' has index '1' but pointer value is index '0' of struct 'tmp.Foo' | 19 | // :11:41: error: field 'b' has index '1' but pointer value is index '0' of struct 'tmp.Foo' |
| 20 | // :1:13: note: struct declared here | 20 | // :1:13: note: struct declared here |
test/cases/compile_errors/fieldParentPtr-field_pointer_is_not_pointer.zig+3-3| ... | @@ -1,12 +1,12 @@ | ... | @@ -1,12 +1,12 @@ |
| 1 | const Foo = extern struct { | 1 | const Foo = extern struct { |
| 2 | a: i32, | 2 | a: i32, |
| 3 | }; | 3 | }; |
| 4 | export fn foo(a: i32) *Foo { | 4 | export fn foo(a: i32) *const Foo { |
| 5 | return @fieldParentPtr(Foo, "a", a); | 5 | return @fieldParentPtr("a", a); |
| 6 | } | 6 | } |
| 7 | 7 | ||
| 8 | // error | 8 | // error |
| 9 | // backend=stage2 | 9 | // backend=stage2 |
| 10 | // target=native | 10 | // target=native |
| 11 | // | 11 | // |
| 12 | // :5:38: error: expected pointer type, found 'i32' | 12 | // :5:33: error: expected pointer type, found 'i32' |
test/cases/compile_errors/fieldParentPtr-non_pointer.zig created+10| ... | @@ -0,0 +1,10 @@ | ||
| 1 | const Foo = i32; | ||
| 2 | export fn foo(a: *i32) Foo { | ||
| 3 | return @fieldParentPtr("a", a); | ||
| 4 | } | ||
| 5 | |||
| 6 | // error | ||
| 7 | // backend=llvm | ||
| 8 | // target=native | ||
| 9 | // | ||
| 10 | // :3:12: error: expected pointer type, found 'i32' | ||
test/cases/compile_errors/fieldParentPtr-non_struct.zig deleted-10| ... | @@ -1,10 +0,0 @@ | ||
| 1 | const Foo = i32; | ||
| 2 | export fn foo(a: *i32) *Foo { | ||
| 3 | return @fieldParentPtr(Foo, "a", a); | ||
| 4 | } | ||
| 5 | |||
| 6 | // error | ||
| 7 | // backend=llvm | ||
| 8 | // target=native | ||
| 9 | // | ||
| 10 | // :3:28: error: expected struct or union type, found 'i32' | ||
test/cases/compile_errors/fieldParentPtr_on_comptime_field.zig+2-2| ... | @@ -5,7 +5,7 @@ pub export fn entry1() void { | ... | @@ -5,7 +5,7 @@ pub export fn entry1() void { |
| 5 | @offsetOf(T, "a"); | 5 | @offsetOf(T, "a"); |
| 6 | } | 6 | } |
| 7 | pub export fn entry2() void { | 7 | pub export fn entry2() void { |
| 8 | @fieldParentPtr(T, "a", undefined); | 8 | @as(*T, @fieldParentPtr("a", undefined)); |
| 9 | } | 9 | } |
| 10 | 10 | ||
| 11 | // error | 11 | // error |
| ... | @@ -13,4 +13,4 @@ pub export fn entry2() void { | ... | @@ -13,4 +13,4 @@ pub export fn entry2() void { |
| 13 | // target=native | 13 | // target=native |
| 14 | // | 14 | // |
| 15 | // :5:5: error: no offset available for comptime field | 15 | // :5:5: error: no offset available for comptime field |
| 16 | // :8:5: error: cannot get @fieldParentPtr of a comptime field | 16 | // :8:29: error: cannot get @fieldParentPtr of a comptime field |
test/cases/compile_errors/increase_pointer_alignment_in_ptrCast.zig+1-1| ... | @@ -8,7 +8,7 @@ export fn entry() u32 { | ... | @@ -8,7 +8,7 @@ export fn entry() u32 { |
| 8 | // backend=stage2 | 8 | // backend=stage2 |
| 9 | // target=native | 9 | // target=native |
| 10 | // | 10 | // |
| 11 | // :3:23: error: cast increases pointer alignment | 11 | // :3:23: error: @ptrCast increases pointer alignment |
| 12 | // :3:32: note: '*u8' has alignment '1' | 12 | // :3:32: note: '*u8' has alignment '1' |
| 13 | // :3:23: note: '*u32' has alignment '4' | 13 | // :3:23: note: '*u32' has alignment '4' |
| 14 | // :3:23: note: use @alignCast to assert pointer alignment | 14 | // :3:23: note: use @alignCast to assert pointer alignment |
test/cases/compile_errors/invalid_bit_pointer.zig created+13| ... | @@ -0,0 +1,13 @@ | ||
| 1 | comptime { | ||
| 2 | _ = *align(1:32:4) u8; | ||
| 3 | } | ||
| 4 | comptime { | ||
| 5 | _ = *align(1:25:4) u8; | ||
| 6 | } | ||
| 7 | |||
| 8 | // error | ||
| 9 | // backend=stage2 | ||
| 10 | // target=native | ||
| 11 | // | ||
| 12 | // :2:18: error: packed type 'u8' at bit offset 32 starts 0 bits after the end of a 4 byte host integer | ||
| 13 | // :5:18: error: packed type 'u8' at bit offset 25 ends 1 bits after the end of a 4 byte host integer | ||
test/cases/compile_errors/nested_ptr_cast_bad_operand.zig+1-1| ... | @@ -16,7 +16,7 @@ export fn c() void { | ... | @@ -16,7 +16,7 @@ export fn c() void { |
| 16 | // | 16 | // |
| 17 | // :3:45: error: null pointer casted to type '*const u32' | 17 | // :3:45: error: null pointer casted to type '*const u32' |
| 18 | // :6:34: error: expected pointer type, found 'comptime_int' | 18 | // :6:34: error: expected pointer type, found 'comptime_int' |
| 19 | // :9:22: error: cast increases pointer alignment | 19 | // :9:22: error: @ptrCast increases pointer alignment |
| 20 | // :9:71: note: '?*const u8' has alignment '1' | 20 | // :9:71: note: '?*const u8' has alignment '1' |
| 21 | // :9:22: note: '?*f32' has alignment '4' | 21 | // :9:22: note: '?*f32' has alignment '4' |
| 22 | // :9:22: note: use @alignCast to assert pointer alignment | 22 | // :9:22: note: use @alignCast to assert pointer alignment |
test/cases/compile_errors/ptrCast_discards_const_qualifier.zig+1-1| ... | @@ -8,5 +8,5 @@ export fn entry() void { | ... | @@ -8,5 +8,5 @@ export fn entry() void { |
| 8 | // backend=stage2 | 8 | // backend=stage2 |
| 9 | // target=native | 9 | // target=native |
| 10 | // | 10 | // |
| 11 | // :3:21: error: cast discards const qualifier | 11 | // :3:21: error: @ptrCast discards const qualifier |
| 12 | // :3:21: note: use @constCast to discard const qualifier | 12 | // :3:21: note: use @constCast to discard const qualifier |
test/standalone/cmakedefine/build.zig+1-1| ... | @@ -86,7 +86,7 @@ fn compare_headers(step: *std.Build.Step, prog_node: *std.Progress.Node) !void { | ... | @@ -86,7 +86,7 @@ fn compare_headers(step: *std.Build.Step, prog_node: *std.Progress.Node) !void { |
| 86 | const expected_fmt = "expected_{s}"; | 86 | const expected_fmt = "expected_{s}"; |
| 87 | 87 | ||
| 88 | for (step.dependencies.items) |config_header_step| { | 88 | for (step.dependencies.items) |config_header_step| { |
| 89 | const config_header = @fieldParentPtr(ConfigHeader, "step", config_header_step); | 89 | const config_header: *ConfigHeader = @fieldParentPtr("step", config_header_step); |
| 90 | 90 | ||
| 91 | const zig_header_path = config_header.output_file.path orelse @panic("Could not locate header file"); | 91 | const zig_header_path = config_header.output_file.path orelse @panic("Could not locate header file"); |
| 92 | 92 |
test/tests.zig+12-5| ... | @@ -1164,19 +1164,26 @@ pub fn addModuleTests(b: *std.Build, options: ModuleTestOptions) *Step { | ... | @@ -1164,19 +1164,26 @@ pub fn addModuleTests(b: *std.Build, options: ModuleTestOptions) *Step { |
| 1164 | compile_c.addCSourceFile(.{ | 1164 | compile_c.addCSourceFile(.{ |
| 1165 | .file = these_tests.getEmittedBin(), | 1165 | .file = these_tests.getEmittedBin(), |
| 1166 | .flags = &.{ | 1166 | .flags = &.{ |
| 1167 | // TODO output -std=c89 compatible C code | 1167 | // Tracking issue for making the C backend generate C89 compatible code: |
| 1168 | // https://github.com/ziglang/zig/issues/19468 | ||
| 1168 | "-std=c99", | 1169 | "-std=c99", |
| 1169 | "-pedantic", | 1170 | "-pedantic", |
| 1170 | "-Werror", | 1171 | "-Werror", |
| 1171 | // TODO stop violating these pedantic errors. spotted everywhere | 1172 | |
| 1173 | // Tracking issue for making the C backend generate code | ||
| 1174 | // that does not trigger warnings: | ||
| 1175 | // https://github.com/ziglang/zig/issues/19467 | ||
| 1176 | |||
| 1177 | // spotted everywhere | ||
| 1172 | "-Wno-builtin-requires-header", | 1178 | "-Wno-builtin-requires-header", |
| 1173 | // TODO stop violating these pedantic errors. spotted on linux | 1179 | |
| 1174 | "-Wno-address-of-packed-member", | 1180 | // spotted on linux |
| 1175 | "-Wno-gnu-folding-constant", | 1181 | "-Wno-gnu-folding-constant", |
| 1176 | "-Wno-incompatible-function-pointer-types", | 1182 | "-Wno-incompatible-function-pointer-types", |
| 1177 | "-Wno-incompatible-pointer-types", | 1183 | "-Wno-incompatible-pointer-types", |
| 1178 | "-Wno-overlength-strings", | 1184 | "-Wno-overlength-strings", |
| 1179 | // TODO stop violating these pedantic errors. spotted on darwin | 1185 | |
| 1186 | // spotted on darwin | ||
| 1180 | "-Wno-dollar-in-identifier-extension", | 1187 | "-Wno-dollar-in-identifier-extension", |
| 1181 | "-Wno-absolute-value", | 1188 | "-Wno-absolute-value", |
| 1182 | }, | 1189 | }, |
tools/lldb_pretty_printers.py+4-4| ... | @@ -354,7 +354,7 @@ def InstRef_SummaryProvider(value, _=None): | ... | @@ -354,7 +354,7 @@ def InstRef_SummaryProvider(value, _=None): |
| 354 | def InstIndex_SummaryProvider(value, _=None): | 354 | def InstIndex_SummaryProvider(value, _=None): |
| 355 | return 'instructions[%d]' % value.unsigned | 355 | return 'instructions[%d]' % value.unsigned |
| 356 | 356 | ||
| 357 | class Module_Decl__Module_Decl_Index_SynthProvider: | 357 | class zig_DeclIndex_SynthProvider: |
| 358 | def __init__(self, value, _=None): self.value = value | 358 | def __init__(self, value, _=None): self.value = value |
| 359 | def update(self): | 359 | def update(self): |
| 360 | try: | 360 | try: |
| ... | @@ -425,7 +425,7 @@ def InternPool_Find(thread): | ... | @@ -425,7 +425,7 @@ def InternPool_Find(thread): |
| 425 | for frame in thread: | 425 | for frame in thread: |
| 426 | ip = frame.FindVariable('ip') or frame.FindVariable('intern_pool') | 426 | ip = frame.FindVariable('ip') or frame.FindVariable('intern_pool') |
| 427 | if ip: return ip | 427 | if ip: return ip |
| 428 | mod = frame.FindVariable('mod') or frame.FindVariable('module') | 428 | mod = frame.FindVariable('zcu') or frame.FindVariable('mod') or frame.FindVariable('module') |
| 429 | if mod: | 429 | if mod: |
| 430 | ip = mod.GetChildMemberWithName('intern_pool') | 430 | ip = mod.GetChildMemberWithName('intern_pool') |
| 431 | if ip: return ip | 431 | if ip: return ip |
| ... | @@ -617,7 +617,7 @@ type_tag_handlers = { | ... | @@ -617,7 +617,7 @@ type_tag_handlers = { |
| 617 | 617 | ||
| 618 | def value_Value_str_lit(payload): | 618 | def value_Value_str_lit(payload): |
| 619 | for frame in payload.thread: | 619 | for frame in payload.thread: |
| 620 | mod = frame.FindVariable('mod') or frame.FindVariable('module') | 620 | mod = frame.FindVariable('zcu') or frame.FindVariable('mod') or frame.FindVariable('module') |
| 621 | if mod: break | 621 | if mod: break |
| 622 | else: return | 622 | else: return |
| 623 | return '"%s"' % zig_String_decode(mod.GetChildMemberWithName('string_literal_bytes').GetChildMemberWithName('items'), payload.GetChildMemberWithName('index').unsigned, payload.GetChildMemberWithName('len').unsigned) | 623 | return '"%s"' % zig_String_decode(mod.GetChildMemberWithName('string_literal_bytes').GetChildMemberWithName('items'), payload.GetChildMemberWithName('index').unsigned, payload.GetChildMemberWithName('len').unsigned) |
| ... | @@ -714,7 +714,7 @@ def __lldb_init_module(debugger, _=None): | ... | @@ -714,7 +714,7 @@ def __lldb_init_module(debugger, _=None): |
| 714 | add(debugger, category='zig.stage2', type='Air.Inst::Air.Inst.Index', identifier='InstIndex', summary=True) | 714 | add(debugger, category='zig.stage2', type='Air.Inst::Air.Inst.Index', identifier='InstIndex', summary=True) |
| 715 | add(debugger, category='zig.stage2', regex=True, type=MultiArrayList_Entry('Air\\.Inst'), identifier='TagAndPayload', synth=True, inline_children=True, summary=True) | 715 | add(debugger, category='zig.stage2', regex=True, type=MultiArrayList_Entry('Air\\.Inst'), identifier='TagAndPayload', synth=True, inline_children=True, summary=True) |
| 716 | add(debugger, category='zig.stage2', regex=True, type='^Air\\.Inst\\.Data\\.Data__struct_[1-9][0-9]*$', inline_children=True, summary=True) | 716 | add(debugger, category='zig.stage2', regex=True, type='^Air\\.Inst\\.Data\\.Data__struct_[1-9][0-9]*$', inline_children=True, summary=True) |
| 717 | add(debugger, category='zig.stage2', type='Module.Decl::Module.Decl.Index', synth=True) | 717 | add(debugger, category='zig.stage2', type='zig.DeclIndex', synth=True) |
| 718 | add(debugger, category='zig.stage2', type='Module.Namespace::Module.Namespace.Index', synth=True) | 718 | add(debugger, category='zig.stage2', type='Module.Namespace::Module.Namespace.Index', synth=True) |
| 719 | add(debugger, category='zig.stage2', type='Module.LazySrcLoc', identifier='zig_TaggedUnion', synth=True) | 719 | add(debugger, category='zig.stage2', type='Module.LazySrcLoc', identifier='zig_TaggedUnion', synth=True) |
| 720 | add(debugger, category='zig.stage2', type='InternPool.Index', synth=True) | 720 | add(debugger, category='zig.stage2', type='InternPool.Index', synth=True) |