authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-03-31 01:47:23-07:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2024-03-31 01:47:23-07:00
loga6ed3e6d29b0e2cedfc20048b014cff4e0ae4eaa
tree11b933e936d64f00a7a820a21afe2633b34d5941
parentaff71c6132fd17c6fa455a6e7b9f53567e3e55b2
parente5ba70bb5c176ba553a5458f89004b44da2b93d6
signaturebadge-check Signed by PGP key B5690EEEBB952194

Merge pull request #19470 from jacobly0/field-parent-ptr

Rework `@fieldParentPtr` to use RLS

105 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 };
2422
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:
3109fn setYBasedOnX(x: *f32, y: f32) void {3109fn 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}
3113test "field parent pointer" {3113test "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#}
87588758
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};
3838
39fn beforePreprocess(pragma: *Pragma, comp: *Compilation) void {39fn 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}
4343
44fn beforeParse(pragma: *Pragma, comp: *Compilation) void {44fn 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}
4949
50fn afterParse(pragma: *Pragma, comp: *Compilation) void {50fn 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}
6161
62fn deinit(pragma: *Pragma, comp: *Compilation) void {62fn 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}
109109
110fn preprocessorHandler(pragma: *Pragma, pp: *Preprocessor, start_idx: TokenIndex) Pragma.Error!void {110fn 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;
114114
...@@ -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}
175175
176fn parserHandler(pragma: *Pragma, p: *Parser, start_idx: TokenIndex) Compilation.Error!void {176fn 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}
2323
24fn deinit(pragma: *Pragma, comp: *Compilation) void {24fn 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}
2828
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}
2828
29fn afterParse(pragma: *Pragma, _: *Compilation) void {29fn 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}
3333
34fn deinit(pragma: *Pragma, comp: *Compilation) void {34fn 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}
3939
40fn preprocessorHandler(pragma: *Pragma, pp: *Preprocessor, start_idx: TokenIndex) Pragma.Error!void {40fn 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}
2525
26fn deinit(pragma: *Pragma, comp: *Compilation) void {26fn 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}
3131
32fn parserHandler(pragma: *Pragma, p: *Parser, start_idx: TokenIndex) Compilation.Error!void {32fn 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 {
1616
17pub fn deinit(obj: *Object) void {17pub 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) {
3232
33pub fn getSection(obj: *Object, section: Section) !*std.ArrayList(u8) {33pub 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}
6060
61pub fn addRelocation(obj: *Object, name: []const u8, section: Section, address: u64, addend: i64) !void {61pub 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}
6767
68pub fn finish(obj: *Object, file: std.fs.File) !void {68pub 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 };
11001100
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 }
11351135
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;
410410
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));
413413
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;
14961496
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}
20862086
2087fn renderRecord(c: *Context, node: Node) !NodeIndex {2087fn 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}
24882488
2489fn renderPrefixOp(c: *Context, node: Node, tag: std.zig.Ast.Node.Tag, tok_tag: TokenTag, bytes: []const u8) !NodeIndex {2489fn 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}
25002500
2501fn renderBinOpGrouped(c: *Context, node: Node, tag: std.zig.Ast.Node.Tag, tok_tag: TokenTag, bytes: []const u8) !NodeIndex {2501fn 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}
25132513
2514fn renderBinOp(c: *Context, node: Node, tag: std.zig.Ast.Node.Tag, tok_tag: TokenTag, bytes: []const u8) !NodeIndex {2514fn 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 }
2020
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 }
2424
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 {
174174
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 instead231 .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 parent234 .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 EOF238 .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 writeAccelerators240 .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 writeStringTable256 .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 }
262262
...@@ -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.NoSpaceLeft1342 /// 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 }
14931493
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));
14961496
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, then1581 // 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 what1582 // 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);
15861586
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, then1611 // 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 what1612 // 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 of1658 // 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();
17051705
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));
17081708
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 parser1960 // 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 text2178 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 parser2184 // 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 parser2202 // 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));
22202220
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)).?;
23002300
2301 // Ensure that all parts are cleared for each version, to properly account for2301 // 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 {
24162416
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);
24222422
...@@ -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;
25072507
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();
25122512
...@@ -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 }
5454
...@@ -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 {
10621062
1063fn makeUninstall(uninstall_step: *Step, prog_node: *std.Progress.Node) anyerror!void {1063fn 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);
10671067
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 {
231231
232pub fn cast(step: *Step, comptime T: type) ?*T {232pub 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 {
49fn make(step: *Step, prog_node: *std.Progress.Node) !void {49fn 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);
5353
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);
534534
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
918fn make(step: *Step, prog_node: *std.Progress.Node) !void {918fn 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);
922922
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)
167fn make(step: *Step, prog_node: *std.Progress.Node) !void {167fn 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;
173173
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 {
4747
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);
5151
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
121121
122fn make(step: *Step, prog_node: *std.Progress.Node) !void {122fn 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();
127127
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 {
6363
64fn make(step: *Step, prog_node: *std.Progress.Node) !void {64fn 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(
43fn make(step: *Step, prog_node: *std.Progress.Node) !void {43fn 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 {
9292
93fn make(step: *Step, prog_node: *std.Progress.Node) !void {93fn 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);
9696
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;
416416
417 const b = step.owner;417 const b = step.owner;
418 const self = @fieldParentPtr(Options, "step", step);418 const self: *Options = @fieldParentPtr("step", step);
419419
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;
2929
30 const b = step.owner;30 const b = step.owner;
31 const self = @fieldParentPtr(RemoveDir, "step", step);31 const self: *RemoveDir = @fieldParentPtr("step", step);
3232
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 {
497fn make(step: *Step, prog_node: *std.Progress.Node) !void {497fn 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();
502502
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 {
118118
119fn make(step: *Step, prog_node: *std.Progress.Node) !void {119fn 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);
122122
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 {
141fn make(step: *Step, prog_node: *std.Progress.Node) !void {141fn 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);
145145
146 // Writing to source files is kind of an extra capability of this146 // Writing to source files is kind of an extra capability of this
147 // WriteFile - arguably it should be a different step. But anyway here147 // 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 };
645645
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;
649649
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;
661661
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 };
700700
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;
704704
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 } },
8989
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);
9494
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 {
11501150
1151/// Renamed from `sigaction` to `Sigaction` to avoid conflict with function name.1151/// Renamed from `sigaction` to `Sigaction` to avoid conflict with function name.
1152pub const Sigaction = extern struct {1152pub 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;
11551155
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 };
690pub const sig_atomic_t = c_int;690pub const sig_atomic_t = c_int;
691691
692pub const Sigaction = extern struct {692pub 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;
695695
696 /// signal handler696 /// 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};
704704
705pub const sig_t = *const fn (c_int) callconv(.C) void;705pub const sig_t = *const fn (i32) callconv(.C) void;
706706
707pub const SOCK = struct {707pub 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;
11711171
1172/// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall.1172/// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall.
1173pub const Sigaction = extern struct {1173pub 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;
11761176
1177 /// signal handler1177 /// 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.
502pub const Sigaction = extern struct {502pub 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;
505505
506 /// signal handler506 /// 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 {
864864
865/// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall.865/// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall.
866pub const Sigaction = extern struct {866pub 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;
869869
870 /// signal handler870 /// 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 {
842842
843/// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall.843/// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall.
844pub const Sigaction = extern struct {844pub 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;
847847
848 /// signal handler848 /// 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 {
874874
875/// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall.875/// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall.
876pub const Sigaction = extern struct {876pub 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;
879879
880 /// signal options880 /// 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}
25722572
2573fn handleSegfaultPosix(sig: i32, info: *const posix.siginfo_t, ctx_ptr: ?*const anyopaque) callconv(.C) noreturn {2573fn 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 crash2574 // 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 repeated2575 // 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();
110110
111 const node = @fieldParentPtr(Node, "data", connection);111 const node: *Node = @fieldParentPtr("data", connection);
112112
113 pool.used.remove(node);113 pool.used.remove(node);
114114
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};
696696
697pub const Sigaction = extern struct {697pub 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;
700700
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
4301pub const app_mask: sigset_t = [2]u32{ 0xfffffffc, 0x7fffffff } ++ [_]u32{0xffffffff} ** 30;4301pub const app_mask: sigset_t = [2]u32{ 0xfffffffc, 0x7fffffff } ++ [_]u32{0xffffffff} ** 30;
43024302
4303const k_sigaction_funcs = struct {4303const 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};
43074307
...@@ -4328,8 +4328,8 @@ pub const k_sigaction = switch (native_arch) {...@@ -4328,8 +4328,8 @@ pub const k_sigaction = switch (native_arch) {
43284328
4329/// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall.4329/// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall.
4330pub const Sigaction = extern struct {4330pub 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;
43334333
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;
186pub const siginfo_t = c_long;186pub 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.
188pub const Sigaction = extern struct {188pub 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;
191191
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}
599599
600fn noopSigHandler(_: c_int) callconv(.C) void {}600fn 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 };
317317
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 on319 /// 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 }
332331
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);
88558856
8857 const FlagsInt = @typeInfo(Zir.Inst.FullPtrCastFlags).Struct.backing_integer.?;
8856 var flags: Zir.Inst.FullPtrCastFlags = .{};8858 var flags: Zir.Inst.FullPtrCastFlags = .{};
88578859
8858 // Note that all pointer cast builtins have one parameter, so we only need8860 // 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 }
88718873
8872 if (node_datas[node].lhs == 0) break; // 0 args8874 if (node_datas[node].lhs == 0) break; // 0 args
8873 if (node_datas[node].rhs != 0) break; // 2 args
88748875
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 }
88798897
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 }
88978925
8898 const flags_i: u5 = @bitCast(flags);8926 const flags_int: FlagsInt = @bitCast(flags);
8899 assert(flags_i != 0);8927 assert(flags_int != 0);
89008928
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 representation8931 // 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 needed8940 // 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);
93809408
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 },
94539481
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;
1170111730
11702 return @fieldParentPtr(T, "base", base);11731 return @alignCast(@fieldParentPtr("base", base));
11703 }11732 }
1170411733
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,
20672067
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 };
33643364
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 };
33703375
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 }
415415
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 }
419419
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_restrict130#define zig_restrict
131#endif131#endif
132132
133#if __STDC_VERSION__ >= 201112L133#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_VER135#elif _MSC_VER
138#define zig_align(alignment) __declspec(align(alignment))136#define zig_under_align(alignment) __declspec(align(alignment))
139#else137#else
140#define zig_align zig_align_unavailable138#define zig_under_align zig_align_unavailable
141#endif139#endif
142140
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#else143#else
148#define zig_align zig_align_unavailable144#define zig_align(alignment) zig_under_align(alignment)
149#endif145#endif
150146
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#endif161#endif
166162
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_VER166#elif _MSC_VER
170#define zig_linksection(name, def, ...) __pragma(section(name, __VA_ARGS__)) __declspec(allocate(name)) def167#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#else169#else
172#define zig_linksection(name, def, ...) zig_linksection_unavailable170#define zig_linksection(name) zig_linksection_unavailable
171#define zig_linksection_fn zig_linksection
173#endif172#endif
174173
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
34513451
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);
34673472
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 _,
38813881
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 }
38883888
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 },
52905290
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 }
304304
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 {
309309
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 body1297 .value_placeholder => unreachable, // never appears in a body
1298 .field_parent_ptr => try sema.zirFieldParentPtr(block, extended),
1299 };1299 };
1300 },1300 },
13011301
...@@ -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 }
65146514
...@@ -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 else17810 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;
1980519811
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 }
1980919825
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}
2274222758
22743fn zirPtrCastFull(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref {22759fn 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}
2276222777
...@@ -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}
2278022796
...@@ -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 }
2282422841
...@@ -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) and23127 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(
2317123188
23172fn zirPtrCastNoDest(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref {23189fn 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}
2484524860
24846fn zirFieldParentPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {24861fn 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;
2486224864
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);
2486724885
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 }
2488624906
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);
2488924911
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 );
2489724947
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);
2491424957
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 }
2491724972
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", .{});
2492624984
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: {
2493424992 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}
2494825007
24949fn zirMinMax(25008fn 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 else29196 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 else241 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 })).scalar244 (try Type.fromInterned(ty).abiSizeAdvanced(mod, .{ .sema = sema })).scalar
245 else245 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 pointer1296 // 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 aligment1298 // 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 alignment1300 // 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 offsets1302 // 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 );
25242524
...@@ -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 }
42104210
...@@ -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);
79257924
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 else7929 ptr_field_ty.ptrInfo(mod).packed_offset.bit_offset, 8),
7931 07930 };
7932 else
7933 @intCast(container_ty.structFieldOffset(index, mod));
79347931
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}
79437940
7944fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {7941fn 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 {
79587955
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 };
79677961
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 {
82398233
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 };
82438242
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() and8244 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_mcv8246 src_mcv
8248 else8247 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}
82538252
...@@ -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(
1895918958
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 }
549549
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().?;
552552
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 }
904904
src/codegen/c.zig+1907-1884
...@@ -5,12 +5,13 @@ const mem = std.mem;...@@ -5,12 +5,13 @@ const mem = std.mem;
5const log = std.log.scoped(.c);5const log = std.log.scoped(.c);
66
7const link = @import("../link.zig");7const link = @import("../link.zig");
8const Module = @import("../Module.zig");8const Zcu = @import("../Module.zig");
9const Module = @import("../Package/Module.zig");
9const Compilation = @import("../Compilation.zig");10const Compilation = @import("../Compilation.zig");
10const Value = @import("../Value.zig");11const Value = @import("../Value.zig");
11const Type = @import("../type.zig").Type;12const Type = @import("../type.zig").Type;
12const C = link.File.C;13const C = link.File.C;
13const Decl = Module.Decl;14const Decl = Zcu.Decl;
14const trace = @import("../tracy.zig").trace;15const trace = @import("../tracy.zig").trace;
15const LazySrcLoc = std.zig.LazySrcLoc;16const LazySrcLoc = std.zig.LazySrcLoc;
16const Air = @import("../Air.zig");17const Air = @import("../Air.zig");
...@@ -21,7 +22,7 @@ const Alignment = InternPool.Alignment;...@@ -21,7 +22,7 @@ const Alignment = InternPool.Alignment;
21const BigIntLimb = std.math.big.Limb;22const BigIntLimb = std.math.big.Limb;
22const BigInt = std.math.big.int;23const BigInt = std.math.big.int;
2324
24pub const CType = @import("c/type.zig").CType;25pub const CType = @import("c/Type.zig");
2526
26pub const CValue = union(enum) {27pub 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 parameters35 /// Index into the parameters
35 arg: usize,36 arg: usize,
36 /// The array field of a parameter37 /// 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};
63pub const LazyFnValue = struct {64pub const LazyFnValue = struct {
64 fn_name: []const u8,65 fn_name: CType.String,
65 data: Data,66 data: Data,
6667
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};
73pub const LazyFnMap = std.AutoArrayHashMapUnmanaged(LazyFnKey, LazyFnValue);74pub const LazyFnMap = std.AutoArrayHashMapUnmanaged(LazyFnKey, LazyFnValue);
7475
75const LoopDepth = u16;
76const Local = struct {76const 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 },
7982
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};
8487
85const LocalIndex = u16;88const LocalIndex = u16;
86const LocalType = struct { cty_idx: CType.Index, alignas: CType.AlignAs };89const LocalType = struct { ctype: CType, alignas: CType.AlignAs };
87const LocalsList = std.AutoArrayHashMapUnmanaged(LocalIndex, void);90const LocalsList = std.AutoArrayHashMapUnmanaged(LocalIndex, void);
88const LocalsMap = std.AutoArrayHashMapUnmanaged(LocalType, LocalsList);91const LocalsMap = std.AutoArrayHashMapUnmanaged(LocalType, LocalsList);
8992
...@@ -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.*;
302306
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);
306310
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 };
320326
321 gop.value_ptr.* = result;327 gop.value_ptr.* = result;
322 return result;328 return result;
323 }329 }
324330
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 }
344349
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 }
354356
355 /// Only allocates the local; does not print anything. Will attempt to re-use locals, so should357 /// 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 }
367373 return result;
368 return try f.allocLocalValue(ty, alignment);
369 }374 }
370375
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 }
383408
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 }
399427
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 }
415443
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 }
432463
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 }
436467
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 }
440471
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 }
444475
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 }
448479
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 }
460483
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 }
464487
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 }
468491
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();
474500
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 }
500521
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 }
511531
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 }
516536
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};
522542
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.
525pub const Object = struct {545pub 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.
543pub const DeclGen = struct {563pub 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 this574 /// 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 {
566588
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 }
576598
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);
589611
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 }
594617
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 }
608623
609 assert(Value.fromInterned(decl_val).getVariable(mod) == null);624 assert(decl_val.getVariable(zcu) == null);
610625
611 // We shouldn't cast C function pointers as this is UB (when you call626 // 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 function627 // them). The analysis until now should ensure that the C function
613 // pointers are compatible. If they are not, then there is a bug628 // 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(')');
624642
625 // Indicate that the anon decl should be rendered to the output so that643 // 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.* = .{};
630648
631 // Only insert an alignment entry if the alignment is greater than ABI649 // 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 else658 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);
657675
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 }
662682
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);
668688
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);
670690
671 // We shouldn't cast C function pointers as this is UB (when you call691 // 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 function692 // them). The analysis until now should ensure that the C function
673 // pointers are compatible. If they are not, then there is a bug693 // 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 }
685708
686 /// Renders a "parent" pointer by recursing to the root decl/variable709 /// 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);
778811
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;
809853
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 };
815858
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 values862 // 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 values901 => 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);
1131979
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;
1134982
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 };
1142990
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 }
1151999
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 get1047 // 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);
12471094
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);
12511098
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 }
12711117
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.
12891139
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 else1149 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;
13371187
1338 if (!empty) try writer.writeByte(',');1188 if (!empty) try writer.writeByte(',');
13391189
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);
13491201
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 }
13631215
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;
13701222
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);
13881239
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);
13911242
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;
13941245
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 }
14001251
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 {
14131264
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;
14191270
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(", ");
14441294
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_off1301 // 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;
14561306
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(')');
14611311
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 };
14701320
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 }
14791328
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 }
15071356
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 }
15251374
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 }
15461395
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 }
15741423
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;
15881694
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);
15921698
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 ");
16041710
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, .{});
16061712
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 {
16111717
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 {
16281734
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 {
16421748
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.name1759 exports.items[export_index].opts.name
1654 else if (fn_decl.isExtern(mod))1760 else if (fn_decl.isExtern(zcu))
1655 fn_decl.name1761 fn_decl.name
1656 else1762 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 }
16911797
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 }
16951802
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 }
17071806
1708 /// Renders a type as a single identifier, generating intermediate typedefs1807 /// 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 }
17221821
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 }
17291826
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 },
17391836
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);
17701865
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;
17761871
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 or1875 const needs_cast = src_int_info == null or
1781 (toCIntBits(dest_int_info.bits) != toCIntBits(src_int_info.?.bits) or1876 (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 }
18551957
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 }
18721971
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 }
18781978
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 }
18881988
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 {
19112018
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 {
19502048
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 == .weak2077 exports.items[0].opts.linkage == .weak
1979 else2078 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.name2092 exports.items[0].opts.name
1994 else if (variable.is_extern)2093 else if (variable.is_extern)
1995 decl.name2094 decl.name
...@@ -2007,23 +2106,23 @@ pub const DeclGen = struct {...@@ -2007,23 +2106,23 @@ pub const DeclGen = struct {
2007 }2106 }
20082107
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);
20122111
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 }
20352134
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 }
20392138
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 }
20432142
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 else2154 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 }
20642161
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 }
20732169
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 };
20792175
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 }
20892182
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};
2135fn renderTypeName(2228fn renderAlignedTypeName(w: anytype, ctype: CType) !void {
2136 mod: *Module,2229 try w.print("anon__aligned_{d}", .{@intFromEnum(ctype.index)});
2230}
2231fn 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) {
21442240 .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}
2166fn renderTypePrefix(2247fn 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)),
21762259
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 },
22442275
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 },
22592304
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 },
22672317
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}", .{
22712321 @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 },
22842337
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}
2331fn renderTypeSuffix(2364fn 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 ),
23942384 .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 }
24022389
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 },
24142393 .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 }
24382398
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(')');
24622417
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}
2467fn renderAggregateFields(2422fn 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}
24912463
2492pub fn genTypeDecl(2464pub 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,
25112483 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 },
25602501 .flush => {},
2561 else => unreachable,
2562 }2502 }
2563 },2503 },
25642504 .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}
25682546
2569pub fn genGlobalAsm(mod: *Module, writer: anytype) !void {2547pub 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}
25742552
2575pub fn genErrDecls(o: *Object) !void {2553pub 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();
25792557
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 empty2559 // 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);
26022580
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];
26082586
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 } });
26182596
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 }
26252610
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 });
26302615
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();
26502640
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();
26592649
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;
26622652
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}
27092699
2710pub fn genLazyFn(o: *Object, lazy_fn: LazyFnMap.Entry) !void {2700pub 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));
27342724
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);
27472734
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 });
27592747
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);
27722761
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");
27822771
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();
28002791
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);
28062797
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 ");
28132804
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 {
28192810
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(' ');
28242817
...@@ -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();
28862879
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);
28922884
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);
29032895
2904 if (variable.is_extern) return;2896 if (variable.is_extern) return;
29052897
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}
29262917
...@@ -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();
29372928
2938 const ty = val.typeOf(mod);2929 const ty = val.typeOf(zcu);
29392930
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(
29582949
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 ");
29612952 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}
29702959
...@@ -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();
29742963
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();
29792968
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}
30613050
3062fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutOfMemory }!void {3051fn 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);
30663055
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 else3093 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}
33603349
3361fn airPtrElemVal(f: *Function, inst: Air.Inst.Index) !CValue {3350fn 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}
33863375
3387fn airPtrElemPtr(f: *Function, inst: Air.Inst.Index) !CValue {3376fn 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;
33913380
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);
33963384
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}
34223410
3423fn airSliceElemVal(f: *Function, inst: Air.Inst.Index) !CValue {3411fn 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}
34483436
3449fn airSliceElemPtr(f: *Function, inst: Air.Inst.Index) !CValue {3437fn 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;
34533441
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);
34583446
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}
34783466
3479fn airArrayElemVal(f: *Function, inst: Air.Inst.Index) !CValue {3467fn 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}
35043492
3505fn airAlloc(f: *Function, inst: Air.Inst.Index) !CValue {3493fn 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 };
35103498
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}
35203511
3521fn airRetPtr(f: *Function, inst: Air.Inst.Index) !CValue {3512fn 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 };
35263517
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}
35363530
3537fn airArg(f: *Function, inst: Air.Inst.Index) !CValue {3531fn 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);
35403534
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 else3539 else
3546 .{ .arg = i };3540 .{ .arg_array = i };
35473541
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}
35603554
3561fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue {3555fn 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;
35643558
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);
35693563
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});
35783572
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 else3575 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;
35853579
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);
36043598
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);
36073601
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))));
36093603
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}
36473641
3648fn airRet(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValue {3642fn 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);
36563650
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}
36973694
3698fn airIntCast(f: *Function, inst: Air.Inst.Index) !CValue {3695fn 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;
37013698
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});
37043701
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);
37093706
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}
37233720
3724fn airTrunc(f: *Function, inst: Air.Inst.Index) !CValue {3721fn 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;
37273724
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) orelse3731 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);
37393736
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) orelse3773 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);
37783776
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 }
38003798
...@@ -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}
38223820
3823fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {3821fn 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;
38273825
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);
38313829
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);
38343832
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;
38363834
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 }
38493847
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 else3850 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;
38563854
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 same3862 // 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));
38673865
3868 // If the source is a constant, writeCValue will emit a brace initialization3866 // 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);
38973895
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);
39003898
3901 const src_bits = src_ty.bitSize(mod);3899 const src_bits = src_ty.bitSize(zcu);
39023900
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);
39133911
3914 const mask_val = try mod.intValue_big(host_ty, mask.toConst());3912 const mask_val = try zcu.intValue_big(host_ty, mask.toConst());
39153913
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 }
39393937
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}
39613959
3962fn airOverflow(f: *Function, inst: Air.Inst.Index, operation: []const u8, info: BuiltinInfo) !CValue {3960fn 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;
39663964
...@@ -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:
39703968
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);
39743972
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}
39993997
4000fn airNot(f: *Function, inst: Air.Inst.Index) !CValue {3998fn 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);
40064004
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);
40404038
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);
40754073
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 });
40934091
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;
41224120
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);
41474145
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}
41854183
4186fn airPtrAddSub(f: *Function, inst: Air.Inst.Index, operator: u8) !CValue {4184fn 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;
41904188
...@@ -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 });
41944192
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);
41984196
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(" = ");
42054203
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 operation4205 // 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 UB4206 // 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}
42334231
4234fn airMinMax(f: *Function, inst: Air.Inst.Index, operator: u8, operation: []const u8) !CValue {4232fn 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;
42374235
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);
42404238
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}
42754273
4276fn airSlice(f: *Function, inst: Air.Inst.Index) !CValue {4274fn 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;
42804278
...@@ -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 });
42844282
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);
42874285
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;
43184313
...@@ -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, .{
43384333 .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 }
43584354
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 }).?;
43654361 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);
43684366
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 }
44214422
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");
44324436
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;
44364440
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}
44664470
4467fn airDbgInlineBlock(f: *Function, inst: Air.Inst.Index) !CValue {4471fn 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}
44784482
4479fn airDbgVar(f: *Function, inst: Air.Inst.Index) !CValue {4483fn 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);
44854489
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}
44974501
4498fn lowerBlock(f: *Function, inst: Air.Inst.Index, body: []const Air.Inst.Index) !CValue {4502fn 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);
45014505
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();
45054509
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 else4513 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();
45274531
4528 // noreturn blocks have no `br` instructions reaching them, so we don't want a label4532 // 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}
45444548
4545fn airTryPtr(f: *Function, inst: Air.Inst.Index) !CValue {4549fn 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}
45534557
...@@ -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);
45694573
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,
46624666
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;
46654669
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};
46944698
4695fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !LocalResult {4699fn 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();
46994704
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 and4708 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 }
47124717
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");
47534758
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;
47614766
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 else4792 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}
49134923
4914fn airSwitchBr(f: *Function, inst: Air.Inst.Index) !CValue {4924fn 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();
49224932
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}
49955005
4996fn asmInputNeedsLocal(f: *Function, constraint: []const u8, value: CValue) bool {5006fn 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}
50145024
5015fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {5025fn 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;
50415054
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 {
50575070
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 else5265 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 }
52565273
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 };
52595276
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;
52805297
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 }
52935310
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();
52985315
5299 const rhs = if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod))5316 const rhs = if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu))
5300 Value.true5317 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}
53225339
5323fn airOptionalPayload(f: *Function, inst: Air.Inst.Index) !CValue {5340fn 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;
53265343
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);
53305347
5331 const payload_ty = opt_ty.optionalChild(mod);5348 const payload_ty = opt_ty.optionalChild(zcu);
53325349
5333 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {5350 if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) {
5334 return .none;5351 return .none;
5335 }5352 }
53365353
...@@ -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);
53405357
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}
53565373
5357fn airOptionalPayloadPtr(f: *Function, inst: Air.Inst.Index) !CValue {5374fn 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;
53605377
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);
53675384
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 }
53715388
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);
53745391
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 C5394 // *?*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}
53875404
5388fn airOptionalPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue {5405fn 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);
53955412
5396 const opt_ty = operand_ty.childType(mod);5413 const opt_ty = operand_ty.childType(zcu);
53975414
5398 const inst_ty = f.typeOfIndex(inst);5415 const inst_ty = f.typeOfIndex(inst);
53995416
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");
54175434
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 else5483 else
5450 break :blk .begin;5484 .begin,
5451 }5485 }
54525486 },
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;
54585492 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 else5494 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 and5505 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 else5507 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 else5512 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}
54975529
5498fn airStructFieldPtr(f: *Function, inst: Air.Inst.Index) !CValue {5530fn 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}
55165548
5517fn airFieldParentPtr(f: *Function, inst: Air.Inst.Index) !CValue {5549fn 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;
55215553
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);
55245556
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(')');
55355567
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);
55405572
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);
55555585
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 }
55675599
...@@ -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);
55825614
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);
55855617
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(')');
55925624
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);
56035633
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 }
56165648
...@@ -5619,13 +5651,13 @@ fn fieldPtr(...@@ -5619,13 +5651,13 @@ fn fieldPtr(
5619}5651}
56205652
5621fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {5653fn 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;
56265658
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();
56375669
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);
56405683
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);
56505685
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);
56525687
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))));
56555693
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).signedness5695 try f.writeCValue(writer, temp_local, .Other);
5658 else5696 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("((");
56615699 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);
56915706 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;
57045721
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 else5737 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" => {
57215750 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
57305759 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 }
57345771
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) -> E5788/// *(E!T) -> E
5758/// Note that the result is never a pointer.5789/// Note that the result is never a pointer.
5759fn airUnwrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue {5790fn 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;
57625793
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});
57675798
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);
57735804
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(" = ");
57825813
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 else5820 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}
57995827
5800fn airUnwrapErrUnionPay(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValue {5828fn 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;
58035831
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;
58095837
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;
58135841
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}
58355863
5836fn airWrapOptional(f: *Function, inst: Air.Inst.Index) !CValue {5864fn 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;
58395867
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}
58675895
5868fn airWrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue {5896fn 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;
58715899
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});
58785906
...@@ -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}
59065934
5907fn airErrUnionPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue {5935fn 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);
59135941
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);
59165945
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");
59315955
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}
59575981
5958fn airWrapErrUnionPay(f: *Function, inst: Air.Inst.Index) !CValue {5982fn 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;
59615985
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});
59685992
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 else6006 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}
59916014
5992fn airIsErr(f: *Function, inst: Air.Inst.Index, is_ptr: bool, operator: []const u8) !CValue {6015fn 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;
59956018
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);
60046027
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);
60076031 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 else6036 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 else6038 else
6016 try f.writeCValue(writer, operand, .Other)6039 try f.writeCValue(writer, operand, .Other)
6017 else6040 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}
60266049
6027fn airArrayToSlice(f: *Function, inst: Air.Inst.Index) !CValue {6050fn 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;
60306054
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);
60376062 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("; ");
60506063
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 }
60546099
6055 return local;6100 return local;
6056}6101}
60576102
6058fn airFloatCast(f: *Function, inst: Air.Inst.Index) !CValue {6103fn 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;
60616106
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 else6120 else
6076 unreachable;6121 unreachable;
60776122
...@@ -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}
61076152
6108fn airIntFromPtr(f: *Function, inst: Air.Inst.Index) !CValue {6153fn 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;
61116156
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;
61406185
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);
61476192
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;
61506195
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;
61846229
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;
61886233
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 });
61926237
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);
61966241
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;
61996244
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 });
62416286
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);
62466291
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;
62496294
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}
62856330
6286fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue {6331fn 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);
62966341
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 });
63006345
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 unreachable6347 zcu.intType(.unsigned, @as(u16, @intCast(ty.abiSize(zcu) * 8))) catch unreachable
6303 else6348 else
6304 ty;6349 ty;
63056350
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}
63906435
6391fn airAtomicRmw(f: *Function, inst: Air.Inst.Index) !CValue {6436fn 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);
64006445
...@@ -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 });
64046449
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;
64096454
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);
64376482
...@@ -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}
64456490
6446fn airAtomicLoad(f: *Function, inst: Air.Inst.Index) !CValue {6491fn 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);
64536498
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 unreachable6500 zcu.intType(.unsigned, @as(u16, @intCast(ty.abiSize(zcu) * 8))) catch unreachable
6456 else6501 else
6457 ty;6502 ty;
64586503
...@@ -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");
64786523
6479 return local;6524 return local;
6480}6525}
64816526
6482fn airAtomicStore(f: *Function, inst: Air.Inst.Index, order: [*:0]const u8) !CValue {6527fn 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);
64896534
...@@ -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 });
64936538
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 unreachable6540 zcu.intType(.unsigned, @as(u16, @intCast(ty.abiSize(zcu) * 8))) catch unreachable
6496 else6541 else
6497 ty;6542 ty;
64986543
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);
65136558
...@@ -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}
65166561
6517fn writeSliceOrPtr(f: *Function, writer: anytype, ptr: CValue, ptr_ty: Type) !void {6562fn 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}
65256570
6526fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {6571fn 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();
65366581
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 }
65426587
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;
65586603
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 }
65676612
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 get6614 // 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 assignable6616 // 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);
66216666
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;
66356680
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}
66476692
6648fn airMemcpy(f: *Function, inst: Air.Inst.Index) !CValue {6693fn 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");
66826717
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}
66866721
6687fn airSetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue {6722fn 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 });
66936728
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).?;
66986733
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}
67076742
6708fn airGetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue {6743fn 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;
67116746
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});
67146749
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;
67186753
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}
67296764
6730fn airTagName(f: *Function, inst: Air.Inst.Index) !CValue {6765fn 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;
67336768
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}
67666801
6767fn airSplat(f: *Function, inst: Air.Inst.Index) !CValue {6802fn 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;
67706805
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});
67736808
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);
67766811
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}
68216856
6822fn airShuffle(f: *Function, inst: Air.Inst.Index) !CValue {6857fn 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;
68266861
...@@ -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("] = ");
68416876
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)));
68446879
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 }
68506885
...@@ -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}
68536888
6854fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue {6889fn 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;
68576892
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();
68636898
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(" = ");
69206955
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}
70087043
7009fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {7044fn 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 {
70287063
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);
70577091 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 else7095 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 },
70717105 .@"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);
70737109
7074 var bit_offset: u64 = 0;7110 const bit_offset_ty = try zcu.intType(.unsigned, Type.smallestUnsignedBits(int_info.bits - 1));
70757111
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;
70817113
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('(');
71007138
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(')');
71247155
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(')');
71287162
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}
71377189
7138fn airUnionInit(f: *Function, inst: Air.Inst.Index) !CValue {7190fn 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;
71437195
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});
71507202
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 }
71607212
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).?;
71657217 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);
71697218
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}
71867235
7187fn airPrefetch(f: *Function, inst: Air.Inst.Index) !CValue {7236fn 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;
71907239
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 else7250 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}
72437292
7244fn airFloatNeg(f: *Function, inst: Air.Inst.Index) !CValue {7293fn 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;
72477296
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});
72507299
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);
72537302
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}
72697318
7270fn airAbs(f: *Function, inst: Air.Inst.Index) !CValue {7319fn 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);
72767325
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}
72877336
7288fn unFloatOp(f: *Function, inst: Air.Inst.Index, operand: CValue, ty: Type, operation: []const u8) !CValue {7337fn 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);
72917340
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}
73177366
7318fn airBinFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CValue {7367fn 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;
73217370
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 });
73257374
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);
73287377
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}
73477396
7348fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue {7397fn 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;
73527401
...@@ -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 });
73577406
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);
73607409
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}
73827431
7383fn airCVaStart(f: *Function, inst: Air.Inst.Index) !CValue {7432fn 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;
73907439
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}
75917640
7592fn compilerRtAbbrev(ty: Type, mod: *Module) []const u8 {7641fn 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};
7750fn formatIntLiteral(7798fn 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;
77587807
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);
77757824
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));
77807829
...@@ -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));
77907839
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();
77947843
...@@ -7800,45 +7849,45 @@ fn formatIntLiteral(...@@ -7800,45 +7849,45 @@ fn formatIntLiteral(
7800 defer allocator.free(wrap.limbs);7849 defer allocator.free(wrap.limbs);
78017850
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) or7880 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 });
78397888
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);
78427891
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;
78837932
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 signed7950 // 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();
79047953
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 }
79157964
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}
79287977
7929const Materialize = struct {7978const Materialize = struct {
...@@ -7966,10 +8015,10 @@ const Materialize = struct {...@@ -7966,10 +8015,10 @@ const Materialize = struct {
7966};8015};
79678016
7968const Assignment = struct {8017const Assignment = struct {
7969 cty: CType.Index,8018 ctype: CType,
79708019
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 }
79748023
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 }
80068055
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,
80178066
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);
80248071
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();
80358080
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};
80568101
8057fn lowerFnRetTy(ret_ty: Type, mod: *Module) !Type {8102fn 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
8079fn 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}
80858108
...@@ -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 @@
1index: CType.Index,
2
3pub fn fromPoolIndex(pool_index: usize) CType {
4 return .{ .index = @enumFromInt(CType.Index.first_pool_index + pool_index) };
5}
6
7pub 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
16pub fn eql(lhs: CType, rhs: CType) bool {
17 return lhs.index == rhs.index;
18}
19
20pub fn isBool(ctype: CType) bool {
21 return switch (ctype.index) {
22 ._Bool, .bool => true,
23 else => false,
24 };
25}
26
27pub 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
59pub 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
92pub 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
108pub 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
135pub 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
153pub fn toSignedness(ctype: CType, s: std.builtin.Signedness) CType {
154 return switch (s) {
155 .unsigned => ctype.toUnsigned(),
156 .signed => ctype.toSigned(),
157 };
158}
159
160pub 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
192pub 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
253pub 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
306pub 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
321pub 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
361pub 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
567pub 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
574fn 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
597const 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
666const 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
676pub 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
713pub 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
727pub 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
910pub 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
2451pub 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
2484const Alignment = @import("../../InternPool.zig").Alignment;
2485const assert = std.debug.assert;
2486const CType = @This();
2487const DeclIndex = std.zig.DeclIndex;
2488const Module = @import("../../Package/Module.zig");
2489const std = @import("std");
2490const Type = @import("../../type.zig").Type;
2491const Zcu = @import("../../Module.zig");
src/codegen/c/type.zig deleted-2318
...@@ -1,2318 +0,0 @@
1const std = @import("std");
2const mem = std.mem;
3const Allocator = mem.Allocator;
4const assert = std.debug.assert;
5const autoHash = std.hash.autoHash;
6const Target = std.Target;
7
8const Alignment = @import("../../InternPool.zig").Alignment;
9const Module = @import("../../Module.zig");
10const InternPool = @import("../../InternPool.zig");
11const Type = @import("../../type.zig").Type;
12
13pub 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, // Line2033 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 );
20392039
...@@ -2120,7 +2120,7 @@ pub const Object = struct {...@@ -2120,7 +2120,7 @@ pub const Object = struct {
2120 0, // Line2120 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, // Offset2124 0, // Offset
2125 );2125 );
21262126
...@@ -2131,7 +2131,7 @@ pub const Object = struct {...@@ -2131,7 +2131,7 @@ pub const Object = struct {
2131 0, // Line2131 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 );
21372137
...@@ -2142,7 +2142,7 @@ pub const Object = struct {...@@ -2142,7 +2142,7 @@ pub const Object = struct {
2142 line,2142 line,
2143 .none, // Underlying type2143 .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, // Line2170 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, // Offset2174 0, // Offset
2175 );2175 );
21762176
...@@ -2217,7 +2217,7 @@ pub const Object = struct {...@@ -2217,7 +2217,7 @@ pub const Object = struct {
2217 0, // Line2217 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, // Line2260 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, // Line2316 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, // Offset2320 0, // Offset
2321 );2321 );
23222322
...@@ -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 );
23332333
...@@ -2338,7 +2338,7 @@ pub const Object = struct {...@@ -2338,7 +2338,7 @@ pub const Object = struct {
2338 0, // Line2338 0, // Line
2339 .none, // Underlying type2339 .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, // Line2396 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, // Line2406 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 );
24122412
...@@ -2417,7 +2417,7 @@ pub const Object = struct {...@@ -2417,7 +2417,7 @@ pub const Object = struct {
2417 0, // Line2417 0, // Line
2418 .none, // Underlying type2418 .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 );
24232423
...@@ -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, // Line2497 0, // Line
2498 .none, // Underlying type2498 .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 );
25032503
...@@ -2566,7 +2566,7 @@ pub const Object = struct {...@@ -2566,7 +2566,7 @@ pub const Object = struct {
2566 0, // Line2566 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, // Line2578 0, // Line
2579 .none, // Underlying type2579 .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 );
25842584
...@@ -2621,7 +2621,7 @@ pub const Object = struct {...@@ -2621,7 +2621,7 @@ pub const Object = struct {
2621 0, // Line2621 0, // Line
2622 .none, // Underlying type2622 .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, // Line2661 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, // Offset2665 0, // Offset
2666 ));2666 ));
2667 }2667 }
...@@ -2680,7 +2680,7 @@ pub const Object = struct {...@@ -2680,7 +2680,7 @@ pub const Object = struct {
2680 0, // Line2680 0, // Line
2681 .none, // Underlying type2681 .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 );
26862686
...@@ -2711,7 +2711,7 @@ pub const Object = struct {...@@ -2711,7 +2711,7 @@ pub const Object = struct {
2711 0, // Line2711 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 );
27172717
...@@ -2722,7 +2722,7 @@ pub const Object = struct {...@@ -2722,7 +2722,7 @@ pub const Object = struct {
2722 0, // Line2722 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 );
27282728
...@@ -2739,7 +2739,7 @@ pub const Object = struct {...@@ -2739,7 +2739,7 @@ pub const Object = struct {
2739 0, // Line2739 0, // Line
2740 .none, // Underlying type2740 .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 );
27452745
...@@ -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` annotation4473 // The value cannot be undefined, because we use the `nonnull` annotation
4474 // for non-optional pointers. We also need to respect the alignment, even though4474 // 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() orelse4476 const int: u64 = ptr_ty.ptrInfo(mod).flags.alignment.toByteUnits() orelse
4477 // Note that these 0xaa values are appropriate even in release-optimized builds4477 // 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 not4478 // 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` AIR4479 // 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}
174174
175fn handleSegfaultPosix(sig: i32, info: *const posix.siginfo_t, ctx_ptr: ?*const anyopaque) callconv(.C) noreturn {175fn handleSegfaultPosix(sig: i32, info: *const posix.siginfo_t, ctx_ptr: ?*anyopaque) callconv(.C) noreturn {
176 // TODO: use alarm() here to prevent infinite loops176 // TODO: use alarm() here to prevent infinite loops
177 PanicSwitch.preDispatch();177 PanicSwitch.preDispatch();
178178
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 }
224214
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 }
231218
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 => {},
715682
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;
66
7const C = @This();7const C = @This();
8const build_options = @import("build_options");8const build_options = @import("build_options");
9const Module = @import("../Module.zig");9const Zcu = @import("../Module.zig");
10const Module = @import("../Package/Module.zig");
10const InternPool = @import("../InternPool.zig");11const InternPool = @import("../InternPool.zig");
11const Alignment = InternPool.Alignment;12const Alignment = InternPool.Alignment;
12const Compilation = @import("../Compilation.zig");13const 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 iterate70 /// 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 = .{},
7475
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 {
177178
178pub fn updateFunc(179pub 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;
186187
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 }
232240
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}
251251
252fn updateAnonDecl(self: *C, module: *Module, i: usize) !void {252fn 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];
255255
...@@ -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.code276 .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);
285288
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 };
296299
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}
306307
307pub fn updateDecl(self: *C, module: *Module, decl_index: InternPool.DeclIndex) !void {308pub 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();
310311
311 const gpa = self.base.comp.gpa;312 const gpa = self.base.comp.gpa;
312313
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();
323325
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 }
347353
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}
364364
365pub fn updateDeclLineNumber(self: *C, module: *Module, decl_index: InternPool.DeclIndex) !void {365pub 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-generating366 // 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}
372372
...@@ -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
399399
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.?;
403403
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 }
410410
411 // This code path happens exclusively with -ofmt=c. The flush logic for411 // 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.
413413
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);
416419
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();
419422
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 }
435438
...@@ -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
438441
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);
442446
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, {});
452456
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 }
456460
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 }
464469
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);
470475
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 }
474479
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 }
479484
...@@ -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}
505510
506const Flush = struct {511const 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) = .{},
510515
511 lazy_ctypes: codegen.CType.Store = .{},516 lazy_ctype_pool: codegen.CType.Pool,
512 lazy_fns: LazyFns = .{},517 lazy_fns: LazyFns = .{},
513518
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};
539545
...@@ -543,91 +549,62 @@ const FlushDeclError = error{...@@ -543,91 +549,62 @@ const FlushDeclError = error{
543549
544fn flushCTypes(550fn 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;
552559
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);
556563 defer global_from_decl_map.clearRetainingCapacity();
557 var global_ctypes = f.ctypes.promote(gpa);
558 defer f.ctypes.demote(global_ctypes);
559564
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();
563568
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)
571576 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}
629606
630fn flushErrDecls(self: *C, ctypes: *codegen.CType.Store) FlushDeclError!void {607fn 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;
632609
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 }
659640
...@@ -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}
667646
668fn flushLazyFn(647fn 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 }
703689
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}
711695
712fn flushLazyFns(self: *C, f: *Flush, lazy_fns: codegen.LazyFnMap) FlushDeclError!void {696fn 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()));
715706
...@@ -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}
724715
725fn flushDeclBlock(716fn 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}
742735
743pub fn flushEmitH(module: *Module) !void {736pub fn flushEmitH(zcu: *Zcu) !void {
744 const tracy = trace(@src());737 const tracy = trace(@src());
745 defer tracy.end();738 defer tracy.end();
746739
747 const emit_h = module.emit_h orelse return;740 const emit_h = zcu.emit_h orelse return;
748741
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();
753746
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 }
773766
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 possibly769 // 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 {
785778
786pub fn updateExports(779pub 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);
12291229
...@@ -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 };
13461346
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);
13491349
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));
14291429
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);
14321432
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 }
40574057
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().?);
212212
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 before214 // 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}
319319
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 }
336336
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}
6969
src/link/MachO.zig+1-1
...@@ -2060,7 +2060,7 @@ fn calcSectionSizes(self: *MachO) !void {...@@ -2060,7 +2060,7 @@ fn calcSectionSizes(self: *MachO) !void {
20602060
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 };
3342
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 }
4049
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 }
7970
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 the3545 // 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 and3547 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 }
35543550
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),
360359
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 {
609608
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 }
614614
...@@ -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 }
903903
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 }
915920
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 }
10701075
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 }
10861092
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);
6060
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 }
6464
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.alignment203 info.flags.alignment
204 else204 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});
207207
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 }
869869
...@@ -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 {
966969
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 },
975978
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);
11611164
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 equal1532 // 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 }
15331538
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 }
15371546
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 }
30173026
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 }
30273036
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_restrict130#define zig_restrict
131#endif131#endif
132132
133#if __STDC_VERSION__ >= 201112L133#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_VER135#elif _MSC_VER
138#define zig_align(alignment) __declspec(align(alignment))136#define zig_under_align(alignment) __declspec(align(alignment))
139#else137#else
140#define zig_align zig_align_unavailable138#define zig_under_align zig_align_unavailable
141#endif139#endif
142140
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#else143#else
148#define zig_align zig_align_unavailable144#define zig_align(alignment) zig_under_align(alignment)
149#endif145#endif
150146
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#endif161#endif
166162
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_VER166#elif _MSC_VER
170#define zig_linksection(name, def, ...) __pragma(section(name, __VA_ARGS__)) __declspec(allocate(name)) def167#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#else169#else
172#define zig_linksection(name, def, ...) zig_linksection_unavailable170#define zig_linksection(name) zig_linksection_unavailable
171#define zig_linksection_fn zig_linksection
173#endif172#endif
174173
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;
628627
629 // Originally reported at https://github.com/ziglang/zig/issues/14904628 // Originally reported at https://github.com/ziglang/zig/issues/14904
630629
...@@ -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 @@
1const expect = @import("std").testing.expect;1const expect = @import("std").testing.expect;
2const builtin = @import("builtin");2const builtin = @import("builtin");
33
4test "@fieldParentPtr non-first field" {4test "@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; // TODO6 a: bool = true,
7 b: f32 = 3.14,
8 c: struct { u8 } = .{42},
9 d: i32 = 12345,
10 };
711
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}
11136
12test "@fieldParentPtr first field" {137test "@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; // TODO139 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 }
15206
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}
19269
20const Foo = struct {270test "@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 };
26276
27const 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 }
33307
34fn 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 }
36338
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}
41370
42fn testParentFieldPtrFirst(a: *const bool) !void {371test "@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 }
44408
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}
49471
50test "@fieldParentPtr untagged union" {472test "@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; // TODO474 a: f32 = 3.14,
53 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO475 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
573test "@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 }
54646
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}
58709
59const Bar = union(enum) {710test "@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
847test "@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 }
65967
66const 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 };
67978
68fn 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 }
70989
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
1008test "@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
1112test "@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
1216test "@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}
751319
76test "@fieldParentPtr tagged union" {1320test "@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; // TODO1322 a: bool,
79 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1323 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 }
801420
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}
841452
85const BarTagged = union(enum) {1453test "@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 }
911491
92const 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 }
931522
94fn 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 }
961553
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}
1011585
102test "@fieldParentPtr extern union" {1586test "@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; // TODO1588 a: bool,
105 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1589 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
1719test "@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 }
1061821
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}
1101853
111const BarExtern = extern union {1854test "@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};
1171857
118const bar_extern = BarExtern{ .c = 42 };1858 const C = union(enum) {
1859 a: u0,
1860 b: i0,
1861 };
1191862
120fn 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 }
1221893
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}
227227
228test "fieldParentPtr of anon struct" {228test "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}
238238
239test "offsetOf tuple" {239test "offsetOf tuple" {
test/behavior/vector.zig+4
...@@ -1176,18 +1176,22 @@ test "@shlWithOverflow" {...@@ -1176,18 +1176,22 @@ test "@shlWithOverflow" {
1176test "alignment of vectors" {1176test "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};
4export fn foo(a: *i32) *Foo {4export fn foo(a: *i32) *Foo {
5 return @fieldParentPtr(Foo, "a", a);5 return @fieldParentPtr("a", a);
6}6}
77
8// error8// error
9// backend=stage29// backend=stage2
10// target=native10// 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 here13// :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{
99
10comptime {10comptime {
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}
1515
...@@ -17,4 +17,4 @@ comptime {...@@ -17,4 +17,4 @@ comptime {
17// backend=stage217// backend=stage2
18// target=native18// target=native
19//19//
20// :12:55: error: pointer value not based on parent struct20// :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};
99
10comptime {10comptime {
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}
1414
...@@ -16,5 +16,5 @@ comptime {...@@ -16,5 +16,5 @@ comptime {
16// backend=stage216// backend=stage2
17// target=native17// 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 here20// :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 @@
1const Foo = extern struct {1const Foo = extern struct {
2 a: i32,2 a: i32,
3};3};
4export fn foo(a: i32) *Foo {4export fn foo(a: i32) *const Foo {
5 return @fieldParentPtr(Foo, "a", a);5 return @fieldParentPtr("a", a);
6}6}
77
8// error8// error
9// backend=stage29// backend=stage2
10// target=native10// 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 @@
1const Foo = i32;
2export 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 @@
1const Foo = i32;
2export 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}
7pub export fn entry2() void {7pub export fn entry2() void {
8 @fieldParentPtr(T, "a", undefined);8 @as(*T, @fieldParentPtr("a", undefined));
9}9}
1010
11// error11// error
...@@ -13,4 +13,4 @@ pub export fn entry2() void {...@@ -13,4 +13,4 @@ pub export fn entry2() void {
13// target=native13// target=native
14//14//
15// :5:5: error: no offset available for comptime field15// :5:5: error: no offset available for comptime field
16// :8:5: error: cannot get @fieldParentPtr of a comptime field16// :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=stage28// backend=stage2
9// target=native9// target=native
10//10//
11// :3:23: error: cast increases pointer alignment11// :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 alignment14// :3:23: note: use @alignCast to assert pointer alignment
test/cases/compile_errors/invalid_bit_pointer.zig created+13
...@@ -0,0 +1,13 @@
1comptime {
2 _ = *align(1:32:4) u8;
3}
4comptime {
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 alignment19// :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 alignment22// :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=stage28// backend=stage2
9// target=native9// target=native
10//10//
11// :3:21: error: cast discards const qualifier11// :3:21: error: @ptrCast discards const qualifier
12// :3:21: note: use @constCast to discard const qualifier12// :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}";
8787
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);
9090
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");
9292
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 code1167 // 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 everywhere1172
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 linux1179
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 darwin1185
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):
354def InstIndex_SummaryProvider(value, _=None):354def InstIndex_SummaryProvider(value, _=None):
355 return 'instructions[%d]' % value.unsigned355 return 'instructions[%d]' % value.unsigned
356356
357class Module_Decl__Module_Decl_Index_SynthProvider:357class zig_DeclIndex_SynthProvider:
358 def __init__(self, value, _=None): self.value = value358 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 ip427 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 ip431 if ip: return ip
...@@ -617,7 +617,7 @@ type_tag_handlers = {...@@ -617,7 +617,7 @@ type_tag_handlers = {
617617
618def value_Value_str_lit(payload):618def 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: break621 if mod: break
622 else: return622 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)