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
564564 "${CMAKE_SOURCE_DIR}/src/clang_options_data.zig"
565565 "${CMAKE_SOURCE_DIR}/src/codegen.zig"
566566 "${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"
568568 "${CMAKE_SOURCE_DIR}/src/codegen/llvm.zig"
569569 "${CMAKE_SOURCE_DIR}/src/codegen/llvm/bindings.zig"
570570 "${CMAKE_SOURCE_DIR}/src/glibc.zig"
build.zig+1-3
......@@ -16,9 +16,7 @@ pub fn build(b: *std.Build) !void {
1616 const only_c = b.option(bool, "only-c", "Translate the Zig compiler to C code, with only the C backend enabled") orelse false;
1717 const target = t: {
1818 var default_target: std.zig.CrossTarget = .{};
19 if (only_c) {
20 default_target.ofmt = .c;
21 }
19 default_target.ofmt = b.option(std.Target.ObjectFormat, "ofmt", "Object format to target") orelse if (only_c) .c else null;
2220 break :t b.standardTargetOptions(.{ .default_target = default_target });
2321 };
2422
doc/langref.html.in+2-3
......@@ -3107,7 +3107,7 @@ test "struct namespaced variable" {
31073107// struct field order is determined by the compiler for optimal performance.
31083108// however, you can still calculate a struct base pointer given a field pointer:
31093109fn setYBasedOnX(x: *f32, y: f32) void {
3110 const point = @fieldParentPtr(Point, "x", x);
3110 const point: *Point = @fieldParentPtr("x", x);
31113111 point.y = y;
31123112}
31133113test "field parent pointer" {
......@@ -8757,8 +8757,7 @@ test "decl access by string" {
87578757 {#header_close#}
87588758
87598759 {#header_open|@fieldParentPtr#}
8760 <pre>{#syntax#}@fieldParentPtr(comptime ParentType: type, comptime field_name: []const u8,
8761 field_ptr: *T) *ParentType{#endsyntax#}</pre>
8760 <pre>{#syntax#}@fieldParentPtr(comptime field_name: []const u8, field_ptr: *T) anytype{#endsyntax#}</pre>
87628761 <p>
87638762 Given a pointer to a field, returns the base pointer of a struct.
87648763 </p>
lib/compiler/aro/aro/pragmas/gcc.zig+6-6
......@@ -37,18 +37,18 @@ const Directive = enum {
3737};
3838
3939fn beforePreprocess(pragma: *Pragma, comp: *Compilation) void {
40 var self = @fieldParentPtr(GCC, "pragma", pragma);
40 var self: *GCC = @fieldParentPtr("pragma", pragma);
4141 self.original_options = comp.diagnostics.options;
4242}
4343
4444fn beforeParse(pragma: *Pragma, comp: *Compilation) void {
45 var self = @fieldParentPtr(GCC, "pragma", pragma);
45 var self: *GCC = @fieldParentPtr("pragma", pragma);
4646 comp.diagnostics.options = self.original_options;
4747 self.options_stack.items.len = 0;
4848}
4949
5050fn afterParse(pragma: *Pragma, comp: *Compilation) void {
51 var self = @fieldParentPtr(GCC, "pragma", pragma);
51 var self: *GCC = @fieldParentPtr("pragma", pragma);
5252 comp.diagnostics.options = self.original_options;
5353 self.options_stack.items.len = 0;
5454}
......@@ -60,7 +60,7 @@ pub fn init(allocator: mem.Allocator) !*Pragma {
6060}
6161
6262fn deinit(pragma: *Pragma, comp: *Compilation) void {
63 var self = @fieldParentPtr(GCC, "pragma", pragma);
63 var self: *GCC = @fieldParentPtr("pragma", pragma);
6464 self.options_stack.deinit(comp.gpa);
6565 comp.gpa.destroy(self);
6666}
......@@ -108,7 +108,7 @@ fn diagnosticHandler(self: *GCC, pp: *Preprocessor, start_idx: TokenIndex) Pragm
108108}
109109
110110fn 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);
112112 const directive_tok = pp.tokens.get(start_idx + 1);
113113 if (directive_tok.id == .nl) return;
114114
......@@ -174,7 +174,7 @@ fn preprocessorHandler(pragma: *Pragma, pp: *Preprocessor, start_idx: TokenIndex
174174}
175175
176176fn 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);
178178 const directive_tok = p.pp.tokens.get(start_idx + 1);
179179 if (directive_tok.id == .nl) return;
180180 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 {
2222}
2323
2424fn deinit(pragma: *Pragma, comp: *Compilation) void {
25 const self = @fieldParentPtr(Message, "pragma", pragma);
25 const self: *Message = @fieldParentPtr("pragma", pragma);
2626 comp.gpa.destroy(self);
2727}
2828
lib/compiler/aro/aro/pragmas/once.zig+3-3
......@@ -27,18 +27,18 @@ pub fn init(allocator: mem.Allocator) !*Pragma {
2727}
2828
2929fn afterParse(pragma: *Pragma, _: *Compilation) void {
30 var self = @fieldParentPtr(Once, "pragma", pragma);
30 var self: *Once = @fieldParentPtr("pragma", pragma);
3131 self.pragma_once.clearRetainingCapacity();
3232}
3333
3434fn deinit(pragma: *Pragma, comp: *Compilation) void {
35 var self = @fieldParentPtr(Once, "pragma", pragma);
35 var self: *Once = @fieldParentPtr("pragma", pragma);
3636 self.pragma_once.deinit();
3737 comp.gpa.destroy(self);
3838}
3939
4040fn 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);
4242 const name_tok = pp.tokens.get(start_idx);
4343 const next = pp.tokens.get(start_idx + 1);
4444 if (next.id != .nl) {
lib/compiler/aro/aro/pragmas/pack.zig+2-2
......@@ -24,13 +24,13 @@ pub fn init(allocator: mem.Allocator) !*Pragma {
2424}
2525
2626fn deinit(pragma: *Pragma, comp: *Compilation) void {
27 var self = @fieldParentPtr(Pack, "pragma", pragma);
27 var self: *Pack = @fieldParentPtr("pragma", pragma);
2828 self.stack.deinit(comp.gpa);
2929 comp.gpa.destroy(self);
3030}
3131
3232fn 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);
3434 var idx = start_idx + 1;
3535 const l_paren = p.pp.tokens.get(idx);
3636 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 {
1616
1717pub fn deinit(obj: *Object) void {
1818 switch (obj.format) {
19 .elf => @fieldParentPtr(Elf, "obj", obj).deinit(),
19 .elf => @as(*Elf, @fieldParentPtr("obj", obj)).deinit(),
2020 else => unreachable,
2121 }
2222}
......@@ -32,7 +32,7 @@ pub const Section = union(enum) {
3232
3333pub fn getSection(obj: *Object, section: Section) !*std.ArrayList(u8) {
3434 switch (obj.format) {
35 .elf => return @fieldParentPtr(Elf, "obj", obj).getSection(section),
35 .elf => return @as(*Elf, @fieldParentPtr("obj", obj)).getSection(section),
3636 else => unreachable,
3737 }
3838}
......@@ -53,21 +53,21 @@ pub fn declareSymbol(
5353 size: u64,
5454) ![]const u8 {
5555 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),
5757 else => unreachable,
5858 }
5959}
6060
6161pub fn addRelocation(obj: *Object, name: []const u8, section: Section, address: u64, addend: i64) !void {
6262 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),
6464 else => unreachable,
6565 }
6666}
6767
6868pub fn finish(obj: *Object, file: std.fs.File) !void {
6969 switch (obj.format) {
70 .elf => return @fieldParentPtr(Elf, "obj", obj).finish(file),
70 .elf => return @as(*Elf, @fieldParentPtr("obj", obj)).finish(file),
7171 else => unreachable,
7272 }
7373}
lib/compiler/aro_translate_c.zig+10-10
......@@ -1098,13 +1098,13 @@ pub fn ScopeExtra(comptime ScopeExtraContext: type, comptime ScopeExtraType: typ
10981098 }
10991099 };
11001100
1101 pub fn findBlockScope(inner: *ScopeExtraScope, c: *ScopeExtraContext) !*ScopeExtraScope.Block {
1101 pub fn findBlockScope(inner: *ScopeExtraScope, c: *ScopeExtraContext) !*Block {
11021102 var scope = inner;
11031103 while (true) {
11041104 switch (scope.id) {
11051105 .root => unreachable,
1106 .block => return @fieldParentPtr(Block, "base", scope),
1107 .condition => return @fieldParentPtr(Condition, "base", scope).getBlockScope(c),
1106 .block => return @fieldParentPtr("base", scope),
1107 .condition => return @as(*Condition, @fieldParentPtr("base", scope)).getBlockScope(c),
11081108 else => scope = scope.parent.?,
11091109 }
11101110 }
......@@ -1116,7 +1116,7 @@ pub fn ScopeExtra(comptime ScopeExtraContext: type, comptime ScopeExtraType: typ
11161116 switch (scope.id) {
11171117 .root => unreachable,
11181118 .block => {
1119 const block = @fieldParentPtr(Block, "base", scope);
1119 const block: *Block = @fieldParentPtr("base", scope);
11201120 if (block.return_type) |ty| return ty;
11211121 scope = scope.parent.?;
11221122 },
......@@ -1128,15 +1128,15 @@ pub fn ScopeExtra(comptime ScopeExtraContext: type, comptime ScopeExtraType: typ
11281128 pub fn getAlias(scope: *ScopeExtraScope, name: []const u8) []const u8 {
11291129 return switch (scope.id) {
11301130 .root => return name,
1131 .block => @fieldParentPtr(Block, "base", scope).getAlias(name),
1131 .block => @as(*Block, @fieldParentPtr("base", scope)).getAlias(name),
11321132 .loop, .do_loop, .condition => scope.parent.?.getAlias(name),
11331133 };
11341134 }
11351135
11361136 pub fn contains(scope: *ScopeExtraScope, name: []const u8) bool {
11371137 return switch (scope.id) {
1138 .root => @fieldParentPtr(Root, "base", scope).contains(name),
1139 .block => @fieldParentPtr(Block, "base", scope).contains(name),
1138 .root => @as(*Root, @fieldParentPtr("base", scope)).contains(name),
1139 .block => @as(*Block, @fieldParentPtr("base", scope)).contains(name),
11401140 .loop, .do_loop, .condition => scope.parent.?.contains(name),
11411141 };
11421142 }
......@@ -1158,11 +1158,11 @@ pub fn ScopeExtra(comptime ScopeExtraContext: type, comptime ScopeExtraType: typ
11581158 while (true) {
11591159 switch (scope.id) {
11601160 .root => {
1161 const root = @fieldParentPtr(Root, "base", scope);
1161 const root: *Root = @fieldParentPtr("base", scope);
11621162 return root.nodes.append(node);
11631163 },
11641164 .block => {
1165 const block = @fieldParentPtr(Block, "base", scope);
1165 const block: *Block = @fieldParentPtr("base", scope);
11661166 return block.statements.append(node);
11671167 },
11681168 else => scope = scope.parent.?,
......@@ -1184,7 +1184,7 @@ pub fn ScopeExtra(comptime ScopeExtraContext: type, comptime ScopeExtraType: typ
11841184 switch (scope.id) {
11851185 .root => return,
11861186 .block => {
1187 const block = @fieldParentPtr(Block, "base", scope);
1187 const block: *Block = @fieldParentPtr("base", scope);
11881188 if (block.variable_discards.get(name)) |discard| {
11891189 discard.data.should_skip = true;
11901190 return;
lib/compiler/aro_translate_c/ast.zig+8-8
......@@ -409,7 +409,7 @@ pub const Node = extern union {
409409 return null;
410410
411411 if (self.ptr_otherwise.tag == t)
412 return @fieldParentPtr(t.Type(), "base", self.ptr_otherwise);
412 return @alignCast(@fieldParentPtr("base", self.ptr_otherwise));
413413
414414 return null;
415415 }
......@@ -1220,7 +1220,7 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
12201220 });
12211221 },
12221222 .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;
12241224 if (node.tag() == .pub_var_simple) _ = try c.addToken(.keyword_pub, "pub");
12251225 const const_tok = try c.addToken(.keyword_const, "const");
12261226 _ = try c.addIdentifier(payload.name);
......@@ -1293,7 +1293,7 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
12931293 },
12941294 .var_decl => return renderVar(c, node),
12951295 .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;
12971297 if (node.tag() == .alias) _ = try c.addToken(.keyword_pub, "pub");
12981298 const mut_tok = if (node.tag() == .alias)
12991299 try c.addToken(.keyword_const, "const")
......@@ -1492,7 +1492,7 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
14921492 });
14931493 },
14941494 .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
14971497 const asterisk = if (node.tag() == .single_pointer)
14981498 try c.addToken(.asterisk, "*")
......@@ -2085,7 +2085,7 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
20852085}
20862086
20872087fn 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;
20892089 if (payload.layout == .@"packed")
20902090 _ = try c.addToken(.keyword_packed, "packed")
20912091 else if (payload.layout == .@"extern")
......@@ -2487,7 +2487,7 @@ fn renderNodeGrouped(c: *Context, node: Node) !NodeIndex {
24872487}
24882488
24892489fn 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;
24912491 return c.addNode(.{
24922492 .tag = tag,
24932493 .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
24992499}
25002500
25012501fn 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;
25032503 const lhs = try renderNodeGrouped(c, payload.lhs);
25042504 return c.addNode(.{
25052505 .tag = tag,
......@@ -2512,7 +2512,7 @@ fn renderBinOpGrouped(c: *Context, node: Node, tag: std.zig.Ast.Node.Tag, tok_ta
25122512}
25132513
25142514fn 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;
25162516 const lhs = try renderNode(c, payload.lhs);
25172517 return c.addNode(.{
25182518 .tag = tag,
lib/compiler/resinator/ast.zig+85-88
......@@ -19,7 +19,7 @@ pub const Tree = struct {
1919 }
2020
2121 pub fn root(self: *Tree) *Node.Root {
22 return @fieldParentPtr(Node.Root, "base", self.node);
22 return @alignCast(@fieldParentPtr("base", self.node));
2323 }
2424
2525 pub fn dump(self: *Tree, writer: anytype) @TypeOf(writer).Error!void {
......@@ -174,7 +174,7 @@ pub const Node = struct {
174174
175175 pub fn cast(base: *Node, comptime id: Id) ?*id.Type() {
176176 if (base.id == id) {
177 return @fieldParentPtr(id.Type(), "base", base);
177 return @alignCast(@fieldParentPtr("base", base));
178178 }
179179 return null;
180180 }
......@@ -461,7 +461,7 @@ pub const Node = struct {
461461 pub fn isNumberExpression(node: *const Node) bool {
462462 switch (node.id) {
463463 .literal => {
464 const literal = @fieldParentPtr(Node.Literal, "base", node);
464 const literal: *const Node.Literal = @alignCast(@fieldParentPtr("base", node));
465465 return switch (literal.token.id) {
466466 .number => true,
467467 else => false,
......@@ -475,7 +475,7 @@ pub const Node = struct {
475475 pub fn isStringLiteral(node: *const Node) bool {
476476 switch (node.id) {
477477 .literal => {
478 const literal = @fieldParentPtr(Node.Literal, "base", node);
478 const literal: *const Node.Literal = @alignCast(@fieldParentPtr("base", node));
479479 return switch (literal.token.id) {
480480 .quoted_ascii_string, .quoted_wide_string => true,
481481 else => false,
......@@ -489,105 +489,103 @@ pub const Node = struct {
489489 switch (node.id) {
490490 .root => unreachable,
491491 .resource_external => {
492 const casted = @fieldParentPtr(Node.ResourceExternal, "base", node);
492 const casted: *const Node.ResourceExternal = @alignCast(@fieldParentPtr("base", node));
493493 return casted.id;
494494 },
495495 .resource_raw_data => {
496 const casted = @fieldParentPtr(Node.ResourceRawData, "base", node);
496 const casted: *const Node.ResourceRawData = @alignCast(@fieldParentPtr("base", node));
497497 return casted.id;
498498 },
499499 .literal => {
500 const casted = @fieldParentPtr(Node.Literal, "base", node);
500 const casted: *const Node.Literal = @alignCast(@fieldParentPtr("base", node));
501501 return casted.token;
502502 },
503503 .binary_expression => {
504 const casted = @fieldParentPtr(Node.BinaryExpression, "base", node);
504 const casted: *const Node.BinaryExpression = @alignCast(@fieldParentPtr("base", node));
505505 return casted.left.getFirstToken();
506506 },
507507 .grouped_expression => {
508 const casted = @fieldParentPtr(Node.GroupedExpression, "base", node);
508 const casted: *const Node.GroupedExpression = @alignCast(@fieldParentPtr("base", node));
509509 return casted.open_token;
510510 },
511511 .not_expression => {
512 const casted = @fieldParentPtr(Node.NotExpression, "base", node);
512 const casted: *const Node.NotExpression = @alignCast(@fieldParentPtr("base", node));
513513 return casted.not_token;
514514 },
515515 .accelerators => {
516 const casted = @fieldParentPtr(Node.Accelerators, "base", node);
516 const casted: *const Node.Accelerators = @alignCast(@fieldParentPtr("base", node));
517517 return casted.id;
518518 },
519519 .accelerator => {
520 const casted = @fieldParentPtr(Node.Accelerator, "base", node);
520 const casted: *const Node.Accelerator = @alignCast(@fieldParentPtr("base", node));
521521 return casted.event.getFirstToken();
522522 },
523523 .dialog => {
524 const casted = @fieldParentPtr(Node.Dialog, "base", node);
524 const casted: *const Node.Dialog = @alignCast(@fieldParentPtr("base", node));
525525 return casted.id;
526526 },
527527 .control_statement => {
528 const casted = @fieldParentPtr(Node.ControlStatement, "base", node);
528 const casted: *const Node.ControlStatement = @alignCast(@fieldParentPtr("base", node));
529529 return casted.type;
530530 },
531531 .toolbar => {
532 const casted = @fieldParentPtr(Node.Toolbar, "base", node);
532 const casted: *const Node.Toolbar = @alignCast(@fieldParentPtr("base", node));
533533 return casted.id;
534534 },
535535 .menu => {
536 const casted = @fieldParentPtr(Node.Menu, "base", node);
536 const casted: *const Node.Menu = @alignCast(@fieldParentPtr("base", node));
537537 return casted.id;
538538 },
539539 inline .menu_item, .menu_item_separator, .menu_item_ex => |menu_item_type| {
540 const node_type = menu_item_type.Type();
541 const casted = @fieldParentPtr(node_type, "base", node);
540 const casted: *const menu_item_type.Type() = @alignCast(@fieldParentPtr("base", node));
542541 return casted.menuitem;
543542 },
544543 inline .popup, .popup_ex => |popup_type| {
545 const node_type = popup_type.Type();
546 const casted = @fieldParentPtr(node_type, "base", node);
544 const casted: *const popup_type.Type() = @alignCast(@fieldParentPtr("base", node));
547545 return casted.popup;
548546 },
549547 .version_info => {
550 const casted = @fieldParentPtr(Node.VersionInfo, "base", node);
548 const casted: *const Node.VersionInfo = @alignCast(@fieldParentPtr("base", node));
551549 return casted.id;
552550 },
553551 .version_statement => {
554 const casted = @fieldParentPtr(Node.VersionStatement, "base", node);
552 const casted: *const Node.VersionStatement = @alignCast(@fieldParentPtr("base", node));
555553 return casted.type;
556554 },
557555 .block => {
558 const casted = @fieldParentPtr(Node.Block, "base", node);
556 const casted: *const Node.Block = @alignCast(@fieldParentPtr("base", node));
559557 return casted.identifier;
560558 },
561559 .block_value => {
562 const casted = @fieldParentPtr(Node.BlockValue, "base", node);
560 const casted: *const Node.BlockValue = @alignCast(@fieldParentPtr("base", node));
563561 return casted.identifier;
564562 },
565563 .block_value_value => {
566 const casted = @fieldParentPtr(Node.BlockValueValue, "base", node);
564 const casted: *const Node.BlockValueValue = @alignCast(@fieldParentPtr("base", node));
567565 return casted.expression.getFirstToken();
568566 },
569567 .string_table => {
570 const casted = @fieldParentPtr(Node.StringTable, "base", node);
568 const casted: *const Node.StringTable = @alignCast(@fieldParentPtr("base", node));
571569 return casted.type;
572570 },
573571 .string_table_string => {
574 const casted = @fieldParentPtr(Node.StringTableString, "base", node);
572 const casted: *const Node.StringTableString = @alignCast(@fieldParentPtr("base", node));
575573 return casted.id.getFirstToken();
576574 },
577575 .language_statement => {
578 const casted = @fieldParentPtr(Node.LanguageStatement, "base", node);
576 const casted: *const Node.LanguageStatement = @alignCast(@fieldParentPtr("base", node));
579577 return casted.language_token;
580578 },
581579 .font_statement => {
582 const casted = @fieldParentPtr(Node.FontStatement, "base", node);
580 const casted: *const Node.FontStatement = @alignCast(@fieldParentPtr("base", node));
583581 return casted.identifier;
584582 },
585583 .simple_statement => {
586 const casted = @fieldParentPtr(Node.SimpleStatement, "base", node);
584 const casted: *const Node.SimpleStatement = @alignCast(@fieldParentPtr("base", node));
587585 return casted.identifier;
588586 },
589587 .invalid => {
590 const casted = @fieldParentPtr(Node.Invalid, "base", node);
588 const casted: *const Node.Invalid = @alignCast(@fieldParentPtr("base", node));
591589 return casted.context[0];
592590 },
593591 }
......@@ -597,44 +595,44 @@ pub const Node = struct {
597595 switch (node.id) {
598596 .root => unreachable,
599597 .resource_external => {
600 const casted = @fieldParentPtr(Node.ResourceExternal, "base", node);
598 const casted: *const Node.ResourceExternal = @alignCast(@fieldParentPtr("base", node));
601599 return casted.filename.getLastToken();
602600 },
603601 .resource_raw_data => {
604 const casted = @fieldParentPtr(Node.ResourceRawData, "base", node);
602 const casted: *const Node.ResourceRawData = @alignCast(@fieldParentPtr("base", node));
605603 return casted.end_token;
606604 },
607605 .literal => {
608 const casted = @fieldParentPtr(Node.Literal, "base", node);
606 const casted: *const Node.Literal = @alignCast(@fieldParentPtr("base", node));
609607 return casted.token;
610608 },
611609 .binary_expression => {
612 const casted = @fieldParentPtr(Node.BinaryExpression, "base", node);
610 const casted: *const Node.BinaryExpression = @alignCast(@fieldParentPtr("base", node));
613611 return casted.right.getLastToken();
614612 },
615613 .grouped_expression => {
616 const casted = @fieldParentPtr(Node.GroupedExpression, "base", node);
614 const casted: *const Node.GroupedExpression = @alignCast(@fieldParentPtr("base", node));
617615 return casted.close_token;
618616 },
619617 .not_expression => {
620 const casted = @fieldParentPtr(Node.NotExpression, "base", node);
618 const casted: *const Node.NotExpression = @alignCast(@fieldParentPtr("base", node));
621619 return casted.number_token;
622620 },
623621 .accelerators => {
624 const casted = @fieldParentPtr(Node.Accelerators, "base", node);
622 const casted: *const Node.Accelerators = @alignCast(@fieldParentPtr("base", node));
625623 return casted.end_token;
626624 },
627625 .accelerator => {
628 const casted = @fieldParentPtr(Node.Accelerator, "base", node);
626 const casted: *const Node.Accelerator = @alignCast(@fieldParentPtr("base", node));
629627 if (casted.type_and_options.len > 0) return casted.type_and_options[casted.type_and_options.len - 1];
630628 return casted.idvalue.getLastToken();
631629 },
632630 .dialog => {
633 const casted = @fieldParentPtr(Node.Dialog, "base", node);
631 const casted: *const Node.Dialog = @alignCast(@fieldParentPtr("base", node));
634632 return casted.end_token;
635633 },
636634 .control_statement => {
637 const casted = @fieldParentPtr(Node.ControlStatement, "base", node);
635 const casted: *const Node.ControlStatement = @alignCast(@fieldParentPtr("base", node));
638636 if (casted.extra_data_end) |token| return token;
639637 if (casted.help_id) |help_id_node| return help_id_node.getLastToken();
640638 if (casted.exstyle) |exstyle_node| return exstyle_node.getLastToken();
......@@ -647,80 +645,79 @@ pub const Node = struct {
647645 return casted.height.getLastToken();
648646 },
649647 .toolbar => {
650 const casted = @fieldParentPtr(Node.Toolbar, "base", node);
648 const casted: *const Node.Toolbar = @alignCast(@fieldParentPtr("base", node));
651649 return casted.end_token;
652650 },
653651 .menu => {
654 const casted = @fieldParentPtr(Node.Menu, "base", node);
652 const casted: *const Node.Menu = @alignCast(@fieldParentPtr("base", node));
655653 return casted.end_token;
656654 },
657655 .menu_item => {
658 const casted = @fieldParentPtr(Node.MenuItem, "base", node);
656 const casted: *const Node.MenuItem = @alignCast(@fieldParentPtr("base", node));
659657 if (casted.option_list.len > 0) return casted.option_list[casted.option_list.len - 1];
660658 return casted.result.getLastToken();
661659 },
662660 .menu_item_separator => {
663 const casted = @fieldParentPtr(Node.MenuItemSeparator, "base", node);
661 const casted: *const Node.MenuItemSeparator = @alignCast(@fieldParentPtr("base", node));
664662 return casted.separator;
665663 },
666664 .menu_item_ex => {
667 const casted = @fieldParentPtr(Node.MenuItemEx, "base", node);
665 const casted: *const Node.MenuItemEx = @alignCast(@fieldParentPtr("base", node));
668666 if (casted.state) |state_node| return state_node.getLastToken();
669667 if (casted.type) |type_node| return type_node.getLastToken();
670668 if (casted.id) |id_node| return id_node.getLastToken();
671669 return casted.text;
672670 },
673671 inline .popup, .popup_ex => |popup_type| {
674 const node_type = popup_type.Type();
675 const casted = @fieldParentPtr(node_type, "base", node);
672 const casted: *const popup_type.Type() = @alignCast(@fieldParentPtr("base", node));
676673 return casted.end_token;
677674 },
678675 .version_info => {
679 const casted = @fieldParentPtr(Node.VersionInfo, "base", node);
676 const casted: *const Node.VersionInfo = @alignCast(@fieldParentPtr("base", node));
680677 return casted.end_token;
681678 },
682679 .version_statement => {
683 const casted = @fieldParentPtr(Node.VersionStatement, "base", node);
680 const casted: *const Node.VersionStatement = @alignCast(@fieldParentPtr("base", node));
684681 return casted.parts[casted.parts.len - 1].getLastToken();
685682 },
686683 .block => {
687 const casted = @fieldParentPtr(Node.Block, "base", node);
684 const casted: *const Node.Block = @alignCast(@fieldParentPtr("base", node));
688685 return casted.end_token;
689686 },
690687 .block_value => {
691 const casted = @fieldParentPtr(Node.BlockValue, "base", node);
688 const casted: *const Node.BlockValue = @alignCast(@fieldParentPtr("base", node));
692689 if (casted.values.len > 0) return casted.values[casted.values.len - 1].getLastToken();
693690 return casted.key;
694691 },
695692 .block_value_value => {
696 const casted = @fieldParentPtr(Node.BlockValueValue, "base", node);
693 const casted: *const Node.BlockValueValue = @alignCast(@fieldParentPtr("base", node));
697694 return casted.expression.getLastToken();
698695 },
699696 .string_table => {
700 const casted = @fieldParentPtr(Node.StringTable, "base", node);
697 const casted: *const Node.StringTable = @alignCast(@fieldParentPtr("base", node));
701698 return casted.end_token;
702699 },
703700 .string_table_string => {
704 const casted = @fieldParentPtr(Node.StringTableString, "base", node);
701 const casted: *const Node.StringTableString = @alignCast(@fieldParentPtr("base", node));
705702 return casted.string;
706703 },
707704 .language_statement => {
708 const casted = @fieldParentPtr(Node.LanguageStatement, "base", node);
705 const casted: *const Node.LanguageStatement = @alignCast(@fieldParentPtr("base", node));
709706 return casted.sublanguage_id.getLastToken();
710707 },
711708 .font_statement => {
712 const casted = @fieldParentPtr(Node.FontStatement, "base", node);
709 const casted: *const Node.FontStatement = @alignCast(@fieldParentPtr("base", node));
713710 if (casted.char_set) |char_set_node| return char_set_node.getLastToken();
714711 if (casted.italic) |italic_node| return italic_node.getLastToken();
715712 if (casted.weight) |weight_node| return weight_node.getLastToken();
716713 return casted.typeface;
717714 },
718715 .simple_statement => {
719 const casted = @fieldParentPtr(Node.SimpleStatement, "base", node);
716 const casted: *const Node.SimpleStatement = @alignCast(@fieldParentPtr("base", node));
720717 return casted.value.getLastToken();
721718 },
722719 .invalid => {
723 const casted = @fieldParentPtr(Node.Invalid, "base", node);
720 const casted: *const Node.Invalid = @alignCast(@fieldParentPtr("base", node));
724721 return casted.context[casted.context.len - 1];
725722 },
726723 }
......@@ -737,31 +734,31 @@ pub const Node = struct {
737734 switch (node.id) {
738735 .root => {
739736 try writer.writeAll("\n");
740 const root = @fieldParentPtr(Node.Root, "base", node);
737 const root: *Node.Root = @alignCast(@fieldParentPtr("base", node));
741738 for (root.body) |body_node| {
742739 try body_node.dump(tree, writer, indent + 1);
743740 }
744741 },
745742 .resource_external => {
746 const resource = @fieldParentPtr(Node.ResourceExternal, "base", node);
743 const resource: *Node.ResourceExternal = @alignCast(@fieldParentPtr("base", node));
747744 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 });
748745 try resource.filename.dump(tree, writer, indent + 1);
749746 },
750747 .resource_raw_data => {
751 const resource = @fieldParentPtr(Node.ResourceRawData, "base", node);
748 const resource: *Node.ResourceRawData = @alignCast(@fieldParentPtr("base", node));
752749 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 });
753750 for (resource.raw_data) |data_expression| {
754751 try data_expression.dump(tree, writer, indent + 1);
755752 }
756753 },
757754 .literal => {
758 const literal = @fieldParentPtr(Node.Literal, "base", node);
755 const literal: *Node.Literal = @alignCast(@fieldParentPtr("base", node));
759756 try writer.writeAll(" ");
760757 try writer.writeAll(literal.token.slice(tree.source));
761758 try writer.writeAll("\n");
762759 },
763760 .binary_expression => {
764 const binary = @fieldParentPtr(Node.BinaryExpression, "base", node);
761 const binary: *Node.BinaryExpression = @alignCast(@fieldParentPtr("base", node));
765762 try writer.writeAll(" ");
766763 try writer.writeAll(binary.operator.slice(tree.source));
767764 try writer.writeAll("\n");
......@@ -769,7 +766,7 @@ pub const Node = struct {
769766 try binary.right.dump(tree, writer, indent + 1);
770767 },
771768 .grouped_expression => {
772 const grouped = @fieldParentPtr(Node.GroupedExpression, "base", node);
769 const grouped: *Node.GroupedExpression = @alignCast(@fieldParentPtr("base", node));
773770 try writer.writeAll("\n");
774771 try writer.writeByteNTimes(' ', indent);
775772 try writer.writeAll(grouped.open_token.slice(tree.source));
......@@ -780,7 +777,7 @@ pub const Node = struct {
780777 try writer.writeAll("\n");
781778 },
782779 .not_expression => {
783 const not = @fieldParentPtr(Node.NotExpression, "base", node);
780 const not: *Node.NotExpression = @alignCast(@fieldParentPtr("base", node));
784781 try writer.writeAll(" ");
785782 try writer.writeAll(not.not_token.slice(tree.source));
786783 try writer.writeAll(" ");
......@@ -788,7 +785,7 @@ pub const Node = struct {
788785 try writer.writeAll("\n");
789786 },
790787 .accelerators => {
791 const accelerators = @fieldParentPtr(Node.Accelerators, "base", node);
788 const accelerators: *Node.Accelerators = @alignCast(@fieldParentPtr("base", node));
792789 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 });
793790 for (accelerators.optional_statements) |statement| {
794791 try statement.dump(tree, writer, indent + 1);
......@@ -804,7 +801,7 @@ pub const Node = struct {
804801 try writer.writeAll("\n");
805802 },
806803 .accelerator => {
807 const accelerator = @fieldParentPtr(Node.Accelerator, "base", node);
804 const accelerator: *Node.Accelerator = @alignCast(@fieldParentPtr("base", node));
808805 for (accelerator.type_and_options, 0..) |option, i| {
809806 if (i != 0) try writer.writeAll(",");
810807 try writer.writeByte(' ');
......@@ -815,7 +812,7 @@ pub const Node = struct {
815812 try accelerator.idvalue.dump(tree, writer, indent + 1);
816813 },
817814 .dialog => {
818 const dialog = @fieldParentPtr(Node.Dialog, "base", node);
815 const dialog: *Node.Dialog = @alignCast(@fieldParentPtr("base", node));
819816 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 });
820817 inline for (.{ "x", "y", "width", "height" }) |arg| {
821818 try writer.writeByteNTimes(' ', indent + 1);
......@@ -841,7 +838,7 @@ pub const Node = struct {
841838 try writer.writeAll("\n");
842839 },
843840 .control_statement => {
844 const control = @fieldParentPtr(Node.ControlStatement, "base", node);
841 const control: *Node.ControlStatement = @alignCast(@fieldParentPtr("base", node));
845842 try writer.print(" {s}", .{control.type.slice(tree.source)});
846843 if (control.text) |text| {
847844 try writer.print(" text: {s}", .{text.slice(tree.source)});
......@@ -877,7 +874,7 @@ pub const Node = struct {
877874 }
878875 },
879876 .toolbar => {
880 const toolbar = @fieldParentPtr(Node.Toolbar, "base", node);
877 const toolbar: *Node.Toolbar = @alignCast(@fieldParentPtr("base", node));
881878 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 });
882879 inline for (.{ "button_width", "button_height" }) |arg| {
883880 try writer.writeByteNTimes(' ', indent + 1);
......@@ -895,7 +892,7 @@ pub const Node = struct {
895892 try writer.writeAll("\n");
896893 },
897894 .menu => {
898 const menu = @fieldParentPtr(Node.Menu, "base", node);
895 const menu: *Node.Menu = @alignCast(@fieldParentPtr("base", node));
899896 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 });
900897 for (menu.optional_statements) |statement| {
901898 try statement.dump(tree, writer, indent + 1);
......@@ -916,16 +913,16 @@ pub const Node = struct {
916913 try writer.writeAll("\n");
917914 },
918915 .menu_item => {
919 const menu_item = @fieldParentPtr(Node.MenuItem, "base", node);
916 const menu_item: *Node.MenuItem = @alignCast(@fieldParentPtr("base", node));
920917 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 });
921918 try menu_item.result.dump(tree, writer, indent + 1);
922919 },
923920 .menu_item_separator => {
924 const menu_item = @fieldParentPtr(Node.MenuItemSeparator, "base", node);
921 const menu_item: *Node.MenuItemSeparator = @alignCast(@fieldParentPtr("base", node));
925922 try writer.print(" {s} {s}\n", .{ menu_item.menuitem.slice(tree.source), menu_item.separator.slice(tree.source) });
926923 },
927924 .menu_item_ex => {
928 const menu_item = @fieldParentPtr(Node.MenuItemEx, "base", node);
925 const menu_item: *Node.MenuItemEx = @alignCast(@fieldParentPtr("base", node));
929926 try writer.print(" {s} {s}\n", .{ menu_item.menuitem.slice(tree.source), menu_item.text.slice(tree.source) });
930927 inline for (.{ "id", "type", "state" }) |arg| {
931928 if (@field(menu_item, arg)) |val_node| {
......@@ -936,7 +933,7 @@ pub const Node = struct {
936933 }
937934 },
938935 .popup => {
939 const popup = @fieldParentPtr(Node.Popup, "base", node);
936 const popup: *Node.Popup = @alignCast(@fieldParentPtr("base", node));
940937 try writer.print(" {s} {s} [{d} options]\n", .{ popup.popup.slice(tree.source), popup.text.slice(tree.source), popup.option_list.len });
941938 try writer.writeByteNTimes(' ', indent);
942939 try writer.writeAll(popup.begin_token.slice(tree.source));
......@@ -949,7 +946,7 @@ pub const Node = struct {
949946 try writer.writeAll("\n");
950947 },
951948 .popup_ex => {
952 const popup = @fieldParentPtr(Node.PopupEx, "base", node);
949 const popup: *Node.PopupEx = @alignCast(@fieldParentPtr("base", node));
953950 try writer.print(" {s} {s}\n", .{ popup.popup.slice(tree.source), popup.text.slice(tree.source) });
954951 inline for (.{ "id", "type", "state", "help_id" }) |arg| {
955952 if (@field(popup, arg)) |val_node| {
......@@ -969,7 +966,7 @@ pub const Node = struct {
969966 try writer.writeAll("\n");
970967 },
971968 .version_info => {
972 const version_info = @fieldParentPtr(Node.VersionInfo, "base", node);
969 const version_info: *Node.VersionInfo = @alignCast(@fieldParentPtr("base", node));
973970 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 });
974971 for (version_info.fixed_info) |fixed_info| {
975972 try fixed_info.dump(tree, writer, indent + 1);
......@@ -985,14 +982,14 @@ pub const Node = struct {
985982 try writer.writeAll("\n");
986983 },
987984 .version_statement => {
988 const version_statement = @fieldParentPtr(Node.VersionStatement, "base", node);
985 const version_statement: *Node.VersionStatement = @alignCast(@fieldParentPtr("base", node));
989986 try writer.print(" {s}\n", .{version_statement.type.slice(tree.source)});
990987 for (version_statement.parts) |part| {
991988 try part.dump(tree, writer, indent + 1);
992989 }
993990 },
994991 .block => {
995 const block = @fieldParentPtr(Node.Block, "base", node);
992 const block: *Node.Block = @alignCast(@fieldParentPtr("base", node));
996993 try writer.print(" {s} {s}\n", .{ block.identifier.slice(tree.source), block.key.slice(tree.source) });
997994 for (block.values) |value| {
998995 try value.dump(tree, writer, indent + 1);
......@@ -1008,14 +1005,14 @@ pub const Node = struct {
10081005 try writer.writeAll("\n");
10091006 },
10101007 .block_value => {
1011 const block_value = @fieldParentPtr(Node.BlockValue, "base", node);
1008 const block_value: *Node.BlockValue = @alignCast(@fieldParentPtr("base", node));
10121009 try writer.print(" {s} {s}\n", .{ block_value.identifier.slice(tree.source), block_value.key.slice(tree.source) });
10131010 for (block_value.values) |value| {
10141011 try value.dump(tree, writer, indent + 1);
10151012 }
10161013 },
10171014 .block_value_value => {
1018 const block_value = @fieldParentPtr(Node.BlockValueValue, "base", node);
1015 const block_value: *Node.BlockValueValue = @alignCast(@fieldParentPtr("base", node));
10191016 if (block_value.trailing_comma) {
10201017 try writer.writeAll(" ,");
10211018 }
......@@ -1023,7 +1020,7 @@ pub const Node = struct {
10231020 try block_value.expression.dump(tree, writer, indent + 1);
10241021 },
10251022 .string_table => {
1026 const string_table = @fieldParentPtr(Node.StringTable, "base", node);
1023 const string_table: *Node.StringTable = @alignCast(@fieldParentPtr("base", node));
10271024 try writer.print(" {s} [{d} common_resource_attributes]\n", .{ string_table.type.slice(tree.source), string_table.common_resource_attributes.len });
10281025 for (string_table.optional_statements) |statement| {
10291026 try statement.dump(tree, writer, indent + 1);
......@@ -1040,19 +1037,19 @@ pub const Node = struct {
10401037 },
10411038 .string_table_string => {
10421039 try writer.writeAll("\n");
1043 const string = @fieldParentPtr(Node.StringTableString, "base", node);
1040 const string: *Node.StringTableString = @alignCast(@fieldParentPtr("base", node));
10441041 try string.id.dump(tree, writer, indent + 1);
10451042 try writer.writeByteNTimes(' ', indent + 1);
10461043 try writer.print("{s}\n", .{string.string.slice(tree.source)});
10471044 },
10481045 .language_statement => {
1049 const language = @fieldParentPtr(Node.LanguageStatement, "base", node);
1046 const language: *Node.LanguageStatement = @alignCast(@fieldParentPtr("base", node));
10501047 try writer.print(" {s}\n", .{language.language_token.slice(tree.source)});
10511048 try language.primary_language_id.dump(tree, writer, indent + 1);
10521049 try language.sublanguage_id.dump(tree, writer, indent + 1);
10531050 },
10541051 .font_statement => {
1055 const font = @fieldParentPtr(Node.FontStatement, "base", node);
1052 const font: *Node.FontStatement = @alignCast(@fieldParentPtr("base", node));
10561053 try writer.print(" {s} typeface: {s}\n", .{ font.identifier.slice(tree.source), font.typeface.slice(tree.source) });
10571054 try writer.writeByteNTimes(' ', indent + 1);
10581055 try writer.writeAll("point_size:\n");
......@@ -1066,12 +1063,12 @@ pub const Node = struct {
10661063 }
10671064 },
10681065 .simple_statement => {
1069 const statement = @fieldParentPtr(Node.SimpleStatement, "base", node);
1066 const statement: *Node.SimpleStatement = @alignCast(@fieldParentPtr("base", node));
10701067 try writer.print(" {s}\n", .{statement.identifier.slice(tree.source)});
10711068 try statement.value.dump(tree, writer, indent + 1);
10721069 },
10731070 .invalid => {
1074 const invalid = @fieldParentPtr(Node.Invalid, "base", node);
1071 const invalid: *Node.Invalid = @alignCast(@fieldParentPtr("base", node));
10751072 try writer.print(" context.len: {}\n", .{invalid.context.len});
10761073 for (invalid.context) |context_token| {
10771074 try writer.writeByteNTimes(' ', indent + 1);
lib/compiler/resinator/compile.zig+33-33
......@@ -229,34 +229,34 @@ pub const Compiler = struct {
229229 pub fn writeNode(self: *Compiler, node: *Node, writer: anytype) !void {
230230 switch (node.id) {
231231 .root => unreachable, // writeRoot should be called directly instead
232 .resource_external => try self.writeResourceExternal(@fieldParentPtr(Node.ResourceExternal, "base", node), writer),
233 .resource_raw_data => try self.writeResourceRawData(@fieldParentPtr(Node.ResourceRawData, "base", node), writer),
232 .resource_external => try self.writeResourceExternal(@alignCast(@fieldParentPtr("base", node)), writer),
233 .resource_raw_data => try self.writeResourceRawData(@alignCast(@fieldParentPtr("base", node)), writer),
234234 .literal => unreachable, // this is context dependent and should be handled by its parent
235235 .binary_expression => unreachable,
236236 .grouped_expression => unreachable,
237237 .not_expression => unreachable,
238238 .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),
240240 .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),
242242 .control_statement => unreachable,
243 .toolbar => try self.writeToolbar(@fieldParentPtr(Node.Toolbar, "base", node), writer),
244 .menu => try self.writeMenu(@fieldParentPtr(Node.Menu, "base", node), writer),
243 .toolbar => try self.writeToolbar(@alignCast(@fieldParentPtr("base", node)), writer),
244 .menu => try self.writeMenu(@alignCast(@fieldParentPtr("base", node)), writer),
245245 .menu_item => unreachable,
246246 .menu_item_separator => unreachable,
247247 .menu_item_ex => unreachable,
248248 .popup => unreachable,
249249 .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),
251251 .version_statement => unreachable,
252252 .block => unreachable,
253253 .block_value => unreachable,
254254 .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))),
256256 .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))),
258258 .font_statement => unreachable,
259 .simple_statement => self.writeTopLevelSimpleStatement(@fieldParentPtr(Node.SimpleStatement, "base", node)),
259 .simple_statement => self.writeTopLevelSimpleStatement(@alignCast(@fieldParentPtr("base", node))),
260260 }
261261 }
262262
......@@ -1289,7 +1289,7 @@ pub const Compiler = struct {
12891289 return evaluateNumberExpression(node, self.source, self.input_code_pages).asWord();
12901290 } else {
12911291 std.debug.assert(node.isStringLiteral());
1292 const literal = @fieldParentPtr(Node.Literal, "base", node);
1292 const literal: *Node.Literal = @alignCast(@fieldParentPtr("base", node));
12931293 const bytes = SourceBytes{
12941294 .slice = literal.token.slice(self.source),
12951295 .code_page = self.input_code_pages.getForToken(literal.token),
......@@ -1342,7 +1342,7 @@ pub const Compiler = struct {
13421342 /// the writer within this function could return error.NoSpaceLeft
13431343 pub fn writeAcceleratorsData(self: *Compiler, node: *Node.Accelerators, data_writer: anytype) !void {
13441344 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));
13461346 var modifiers = res.AcceleratorModifiers{};
13471347 for (accelerator.type_and_options) |type_or_option| {
13481348 const modifier = rc.AcceleratorTypeAndOptions.map.get(type_or_option.slice(self.source)).?;
......@@ -1426,7 +1426,7 @@ pub const Compiler = struct {
14261426 for (node.optional_statements) |optional_statement| {
14271427 switch (optional_statement.id) {
14281428 .simple_statement => {
1429 const simple_statement = @fieldParentPtr(Node.SimpleStatement, "base", optional_statement);
1429 const simple_statement: *Node.SimpleStatement = @alignCast(@fieldParentPtr("base", optional_statement));
14301430 const statement_identifier = simple_statement.identifier;
14311431 const statement_type = rc.OptionalStatements.dialog_map.get(statement_identifier.slice(self.source)) orelse continue;
14321432 switch (statement_type) {
......@@ -1440,7 +1440,7 @@ pub const Compiler = struct {
14401440 },
14411441 .caption => {
14421442 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));
14441444 optional_statement_values.caption = literal_node.token;
14451445 },
14461446 .class => {
......@@ -1466,7 +1466,7 @@ pub const Compiler = struct {
14661466 optional_statement_values.class = NameOrOrdinal{ .ordinal = class_ordinal.asWord() };
14671467 } else {
14681468 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));
14701470 const parsed = try self.parseQuotedStringAsWideString(literal_node.token);
14711471 optional_statement_values.class = NameOrOrdinal{ .name = parsed };
14721472 }
......@@ -1492,7 +1492,7 @@ pub const Compiler = struct {
14921492 }
14931493
14941494 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
14971497 const token_slice = literal_node.token.slice(self.source);
14981498 const bytes = SourceBytes{
......@@ -1542,7 +1542,7 @@ pub const Compiler = struct {
15421542 }
15431543 },
15441544 .font_statement => {
1545 const font = @fieldParentPtr(Node.FontStatement, "base", optional_statement);
1545 const font: *Node.FontStatement = @alignCast(@fieldParentPtr("base", optional_statement));
15461546 if (optional_statement_values.font != null) {
15471547 optional_statement_values.font.?.node = font;
15481548 } else {
......@@ -1581,7 +1581,7 @@ pub const Compiler = struct {
15811581 // Multiple CLASS parameters are specified and any of them are treated as a number, then
15821582 // the last CLASS is always treated as a number no matter what
15831583 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));
15851585 const ordinal_value = res.ForcedOrdinal.fromUtf16Le(optional_statement_values.class.?.name);
15861586
15871587 try self.addErrorDetails(.{
......@@ -1611,7 +1611,7 @@ pub const Compiler = struct {
16111611 // 2. Multiple MENU parameters are specified and any of them are treated as a number, then
16121612 // the last MENU is always treated as a number no matter what
16131613 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));
16151615 const token_slice = literal_node.token.slice(self.source);
16161616 const bytes = SourceBytes{
16171617 .slice = token_slice,
......@@ -1658,7 +1658,7 @@ pub const Compiler = struct {
16581658 // between resinator and the Win32 RC compiler, we only emit a hint instead of
16591659 // a warning.
16601660 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));
16621662 try self.addErrorDetails(.{
16631663 .err = .dialog_menu_id_was_uppercased,
16641664 .type = .hint,
......@@ -1704,7 +1704,7 @@ pub const Compiler = struct {
17041704 defer controls_by_id.deinit();
17051705
17061706 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
17091709 self.writeDialogControl(
17101710 control,
......@@ -1940,7 +1940,7 @@ pub const Compiler = struct {
19401940 // And then write out the ordinal using a proper a NameOrOrdinal encoding.
19411941 try ordinal.write(data_writer);
19421942 } 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));
19441944 const parsed = try self.parseQuotedStringAsWideString(literal_node.token);
19451945 defer self.allocator.free(parsed);
19461946 if (rc.ControlClass.fromWideString(parsed)) |control_class| {
......@@ -1955,7 +1955,7 @@ pub const Compiler = struct {
19551955 try name.write(data_writer);
19561956 }
19571957 } else {
1958 const literal_node = @fieldParentPtr(Node.Literal, "base", class_node);
1958 const literal_node: *Node.Literal = @alignCast(@fieldParentPtr("base", class_node));
19591959 const literal_slice = literal_node.token.slice(self.source);
19601960 // This succeeding is guaranteed by the parser
19611961 const control_class = rc.ControlClass.map.get(literal_slice) orelse unreachable;
......@@ -2178,7 +2178,7 @@ pub const Compiler = struct {
21782178 try writer.writeInt(u16, 0, .little); // null-terminated UTF-16 text
21792179 },
21802180 .menu_item => {
2181 const menu_item = @fieldParentPtr(Node.MenuItem, "base", node);
2181 const menu_item: *Node.MenuItem = @alignCast(@fieldParentPtr("base", node));
21822182 var flags = res.MenuItemFlags{};
21832183 for (menu_item.option_list) |option_token| {
21842184 // This failing would be a bug in the parser
......@@ -2196,7 +2196,7 @@ pub const Compiler = struct {
21962196 try writer.writeAll(std.mem.sliceAsBytes(text[0 .. text.len + 1]));
21972197 },
21982198 .popup => {
2199 const popup = @fieldParentPtr(Node.Popup, "base", node);
2199 const popup: *Node.Popup = @alignCast(@fieldParentPtr("base", node));
22002200 var flags = res.MenuItemFlags{ .value = res.MF.POPUP };
22012201 for (popup.option_list) |option_token| {
22022202 // This failing would be a bug in the parser
......@@ -2216,7 +2216,7 @@ pub const Compiler = struct {
22162216 }
22172217 },
22182218 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
22212221 if (menu_item.type) |flags| {
22222222 const value = evaluateNumberExpression(flags, self.source, self.input_code_pages);
......@@ -2295,7 +2295,7 @@ pub const Compiler = struct {
22952295 for (node.fixed_info) |fixed_info| {
22962296 switch (fixed_info.id) {
22972297 .version_statement => {
2298 const version_statement = @fieldParentPtr(Node.VersionStatement, "base", fixed_info);
2298 const version_statement: *Node.VersionStatement = @alignCast(@fieldParentPtr("base", fixed_info));
22992299 const version_type = rc.VersionInfo.map.get(version_statement.type.slice(self.source)).?;
23002300
23012301 // Ensure that all parts are cleared for each version, to properly account for
......@@ -2345,7 +2345,7 @@ pub const Compiler = struct {
23452345 }
23462346 },
23472347 .simple_statement => {
2348 const statement = @fieldParentPtr(Node.SimpleStatement, "base", fixed_info);
2348 const statement: *Node.SimpleStatement = @alignCast(@fieldParentPtr("base", fixed_info));
23492349 const statement_type = rc.VersionInfo.map.get(statement.identifier.slice(self.source)).?;
23502350 const value = evaluateNumberExpression(statement.value, self.source, self.input_code_pages);
23512351 switch (statement_type) {
......@@ -2416,7 +2416,7 @@ pub const Compiler = struct {
24162416
24172417 switch (node.id) {
24182418 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));
24202420 const parsed_key = try self.parseQuotedStringAsWideString(block_or_value.key);
24212421 defer self.allocator.free(parsed_key);
24222422
......@@ -2506,7 +2506,7 @@ pub const Compiler = struct {
25062506 const language = getLanguageFromOptionalStatements(node.optional_statements, self.source, self.input_code_pages) orelse self.state.language;
25072507
25082508 for (node.strings) |string_node| {
2509 const string = @fieldParentPtr(Node.StringTableString, "base", string_node);
2509 const string: *Node.StringTableString = @alignCast(@fieldParentPtr("base", string_node));
25102510 const string_id_data = try self.evaluateDataExpression(string.id);
25112511 const string_id = string_id_data.number.asWord();
25122512
......@@ -2795,11 +2795,11 @@ pub const Compiler = struct {
27952795 fn applyToOptionalStatements(language: *res.Language, version: *u32, characteristics: *u32, statements: []*Node, source: []const u8, code_page_lookup: *const CodePageLookup) void {
27962796 for (statements) |node| switch (node.id) {
27972797 .language_statement => {
2798 const language_statement = @fieldParentPtr(Node.LanguageStatement, "base", node);
2798 const language_statement: *Node.LanguageStatement = @alignCast(@fieldParentPtr("base", node));
27992799 language.* = languageFromLanguageStatement(language_statement, source, code_page_lookup);
28002800 },
28012801 .simple_statement => {
2802 const simple_statement = @fieldParentPtr(Node.SimpleStatement, "base", node);
2802 const simple_statement: *Node.SimpleStatement = @alignCast(@fieldParentPtr("base", node));
28032803 const statement_type = rc.OptionalStatements.map.get(simple_statement.identifier.slice(source)) orelse continue;
28042804 const result = Compiler.evaluateNumberExpression(simple_statement.value, source, code_page_lookup);
28052805 switch (statement_type) {
......@@ -2824,7 +2824,7 @@ pub const Compiler = struct {
28242824 pub fn getLanguageFromOptionalStatements(statements: []*Node, source: []const u8, code_page_lookup: *const CodePageLookup) ?res.Language {
28252825 for (statements) |node| switch (node.id) {
28262826 .language_statement => {
2827 const language_statement = @fieldParentPtr(Node.LanguageStatement, "base", node);
2827 const language_statement: *Node.LanguageStatement = @alignCast(@fieldParentPtr("base", node));
28282828 return languageFromLanguageStatement(language_statement, source, code_page_lookup);
28292829 },
28302830 else => continue,
lib/compiler/resinator/parse.zig+1-1
......@@ -889,7 +889,7 @@ pub const Parser = struct {
889889 if (control == .control) {
890890 class = try self.parseExpression(.{});
891891 if (class.?.id == .literal) {
892 const class_literal = @fieldParentPtr(Node.Literal, "base", class.?);
892 const class_literal: *Node.Literal = @alignCast(@fieldParentPtr("base", class.?));
893893 const is_invalid_control_class = class_literal.token.id == .literal and !rc.ControlClass.map.has(class_literal.token.slice(self.lexer.buffer));
894894 if (is_invalid_control_class) {
895895 return self.addErrorDetailsAndFail(.{
lib/docs/wasm/Walk.zig+6-6
......@@ -48,7 +48,7 @@ pub const File = struct {
4848 pub fn field_count(file: *const File, node: Ast.Node.Index) u32 {
4949 const scope = file.scopes.get(node) orelse return 0;
5050 if (scope.tag != .namespace) return 0;
51 const namespace = @fieldParentPtr(Scope.Namespace, "base", scope);
51 const namespace: *Scope.Namespace = @alignCast(@fieldParentPtr("base", scope));
5252 return namespace.field_count;
5353 }
5454
......@@ -439,11 +439,11 @@ pub const Scope = struct {
439439 while (true) switch (it.tag) {
440440 .top => unreachable,
441441 .local => {
442 const local = @fieldParentPtr(Local, "base", it);
442 const local: *Local = @alignCast(@fieldParentPtr("base", it));
443443 it = local.parent;
444444 },
445445 .namespace => {
446 const namespace = @fieldParentPtr(Namespace, "base", it);
446 const namespace: *Namespace = @alignCast(@fieldParentPtr("base", it));
447447 return namespace.decl_index;
448448 },
449449 };
......@@ -453,7 +453,7 @@ pub const Scope = struct {
453453 switch (scope.tag) {
454454 .top, .local => return null,
455455 .namespace => {
456 const namespace = @fieldParentPtr(Namespace, "base", scope);
456 const namespace: *Namespace = @alignCast(@fieldParentPtr("base", scope));
457457 return namespace.names.get(name);
458458 },
459459 }
......@@ -465,7 +465,7 @@ pub const Scope = struct {
465465 while (true) switch (it.tag) {
466466 .top => break,
467467 .local => {
468 const local = @fieldParentPtr(Local, "base", it);
468 const local: *Local = @alignCast(@fieldParentPtr("base", it));
469469 const name_token = main_tokens[local.var_node] + 1;
470470 const ident_name = ast.tokenSlice(name_token);
471471 if (std.mem.eql(u8, ident_name, name)) {
......@@ -474,7 +474,7 @@ pub const Scope = struct {
474474 it = local.parent;
475475 },
476476 .namespace => {
477 const namespace = @fieldParentPtr(Namespace, "base", it);
477 const namespace: *Namespace = @alignCast(@fieldParentPtr("base", it));
478478 if (namespace.names.get(name)) |node| {
479479 return node;
480480 }
lib/std/Build.zig+2-2
......@@ -1062,8 +1062,8 @@ pub fn getUninstallStep(self: *Build) *Step {
10621062
10631063fn makeUninstall(uninstall_step: *Step, prog_node: *std.Progress.Node) anyerror!void {
10641064 _ = prog_node;
1065 const uninstall_tls = @fieldParentPtr(TopLevelStep, "step", uninstall_step);
1066 const self = @fieldParentPtr(Build, "uninstall_tls", uninstall_tls);
1065 const uninstall_tls: *TopLevelStep = @fieldParentPtr("step", uninstall_step);
1066 const self: *Build = @fieldParentPtr("uninstall_tls", uninstall_tls);
10671067
10681068 for (self.installed_files.items) |installed_file| {
10691069 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 {
231231
232232pub fn cast(step: *Step, comptime T: type) ?*T {
233233 if (step.id == T.base_id) {
234 return @fieldParentPtr(T, "step", step);
234 return @fieldParentPtr("step", step);
235235 }
236236 return null;
237237}
lib/std/Build/Step/CheckFile.zig+1-1
......@@ -49,7 +49,7 @@ pub fn setName(self: *CheckFile, name: []const u8) void {
4949fn make(step: *Step, prog_node: *std.Progress.Node) !void {
5050 _ = prog_node;
5151 const b = step.owner;
52 const self = @fieldParentPtr(CheckFile, "step", step);
52 const self: *CheckFile = @fieldParentPtr("step", step);
5353
5454 const src_path = self.source.getPath(b);
5555 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 {
530530 _ = prog_node;
531531 const b = step.owner;
532532 const gpa = b.allocator;
533 const self = @fieldParentPtr(CheckObject, "step", step);
533 const self: *CheckObject = @fieldParentPtr("step", step);
534534
535535 const src_path = self.source.getPath(b);
536536 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
918918fn make(step: *Step, prog_node: *std.Progress.Node) !void {
919919 const b = step.owner;
920920 const arena = b.allocator;
921 const self = @fieldParentPtr(Compile, "step", step);
921 const self: *Compile = @fieldParentPtr("step", step);
922922
923923 var zig_args = ArrayList([]const u8).init(arena);
924924 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)
167167fn make(step: *Step, prog_node: *std.Progress.Node) !void {
168168 _ = prog_node;
169169 const b = step.owner;
170 const self = @fieldParentPtr(ConfigHeader, "step", step);
170 const self: *ConfigHeader = @fieldParentPtr("step", step);
171171 const gpa = b.allocator;
172172 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 {
4747
4848 const b = step.owner;
4949 const arena = b.allocator;
50 const self = @fieldParentPtr(Fmt, "step", step);
50 const self: *Fmt = @fieldParentPtr("step", step);
5151
5252 var argv: std.ArrayListUnmanaged([]const u8) = .{};
5353 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
121121
122122fn make(step: *Step, prog_node: *std.Progress.Node) !void {
123123 _ = prog_node;
124 const self = @fieldParentPtr(InstallArtifact, "step", step);
124 const self: *InstallArtifact = @fieldParentPtr("step", step);
125125 const dest_builder = step.owner;
126126 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 {
6363
6464fn make(step: *Step, prog_node: *std.Progress.Node) !void {
6565 _ = prog_node;
66 const self = @fieldParentPtr(InstallDirStep, "step", step);
66 const self: *InstallDirStep = @fieldParentPtr("step", step);
6767 const dest_builder = self.dest_builder;
6868 const arena = dest_builder.allocator;
6969 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(
4343fn make(step: *Step, prog_node: *std.Progress.Node) !void {
4444 _ = prog_node;
4545 const src_builder = step.owner;
46 const self = @fieldParentPtr(InstallFile, "step", step);
46 const self: *InstallFile = @fieldParentPtr("step", step);
4747 const dest_builder = self.dest_builder;
4848 const full_src_path = self.source.getPath2(src_builder, step);
4949 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 {
9292
9393fn make(step: *Step, prog_node: *std.Progress.Node) !void {
9494 const b = step.owner;
95 const self = @fieldParentPtr(ObjCopy, "step", step);
95 const self: *ObjCopy = @fieldParentPtr("step", step);
9696
9797 var man = b.graph.cache.obtain();
9898 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 {
415415 _ = prog_node;
416416
417417 const b = step.owner;
418 const self = @fieldParentPtr(Options, "step", step);
418 const self: *Options = @fieldParentPtr("step", step);
419419
420420 for (self.args.items) |item| {
421421 self.addOption(
lib/std/Build/Step/RemoveDir.zig+1-1
......@@ -28,7 +28,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
2828 _ = prog_node;
2929
3030 const b = step.owner;
31 const self = @fieldParentPtr(RemoveDir, "step", step);
31 const self: *RemoveDir = @fieldParentPtr("step", step);
3232
3333 b.build_root.handle.deleteTree(self.dir_path) catch |err| {
3434 if (b.build_root.path) |base| {
lib/std/Build/Step/Run.zig+1-1
......@@ -497,7 +497,7 @@ const IndexedOutput = struct {
497497fn make(step: *Step, prog_node: *std.Progress.Node) !void {
498498 const b = step.owner;
499499 const arena = b.allocator;
500 const self = @fieldParentPtr(Run, "step", step);
500 const self: *Run = @fieldParentPtr("step", step);
501501 const has_side_effects = self.hasSideEffects();
502502
503503 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 {
118118
119119fn make(step: *Step, prog_node: *std.Progress.Node) !void {
120120 const b = step.owner;
121 const self = @fieldParentPtr(TranslateC, "step", step);
121 const self: *TranslateC = @fieldParentPtr("step", step);
122122
123123 var argv_list = std.ArrayList([]const u8).init(b.allocator);
124124 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 {
141141fn make(step: *Step, prog_node: *std.Progress.Node) !void {
142142 _ = prog_node;
143143 const b = step.owner;
144 const wf = @fieldParentPtr(WriteFile, "step", step);
144 const wf: *WriteFile = @fieldParentPtr("step", step);
145145
146146 // Writing to source files is kind of an extra capability of this
147147 // 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 {
644644 };
645645
646646 // 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);
648648 const tail = head.tail orelse unreachable;
649649
650650 // Push the waiter to the tail by replacing it and linking to the previous tail.
......@@ -656,7 +656,7 @@ const PosixImpl = struct {
656656 fn remove(treap: *Treap, address: usize, max_waiters: usize) WaitList {
657657 // Find the wait queue associated with this address and get the head/tail if any.
658658 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;
660660 const queue_tail = if (queue_head) |head| head.tail else null;
661661
662662 // 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 {
699699 };
700700
701701 // 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);
703703 const tail = head.tail orelse unreachable;
704704
705705 // 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 {
8888 run_node: RunQueue.Node = .{ .data = .{ .runFn = runFn } },
8989
9090 fn runFn(runnable: *Runnable) void {
91 const run_node = @fieldParentPtr(RunQueue.Node, "data", runnable);
92 const closure = @fieldParentPtr(@This(), "run_node", run_node);
91 const run_node: *RunQueue.Node = @fieldParentPtr("data", runnable);
92 const closure: *@This() = @fieldParentPtr("run_node", run_node);
9393 @call(.auto, func, closure.arguments);
9494
9595 // 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 {
11501150
11511151/// Renamed from `sigaction` to `Sigaction` to avoid conflict with function name.
11521152pub const Sigaction = extern struct {
1153 pub const handler_fn = *align(1) const fn (c_int) callconv(.C) void;
1154 pub const sigaction_fn = *const fn (c_int, *const siginfo_t, ?*anyopaque) callconv(.C) void;
1153 pub const handler_fn = *align(1) const fn (i32) callconv(.C) void;
1154 pub const sigaction_fn = *const fn (i32, *const siginfo_t, ?*anyopaque) callconv(.C) void;
11551155
11561156 handler: extern union {
11571157 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 };
690690pub const sig_atomic_t = c_int;
691691
692692pub const Sigaction = extern struct {
693 pub const handler_fn = *align(1) const fn (c_int) callconv(.C) void;
694 pub const sigaction_fn = *const fn (c_int, *const siginfo_t, ?*anyopaque) callconv(.C) void;
693 pub const handler_fn = *align(1) const fn (i32) callconv(.C) void;
694 pub const sigaction_fn = *const fn (i32, *const siginfo_t, ?*anyopaque) callconv(.C) void;
695695
696696 /// signal handler
697697 handler: extern union {
......@@ -702,7 +702,7 @@ pub const Sigaction = extern struct {
702702 mask: sigset_t,
703703};
704704
705pub const sig_t = *const fn (c_int) callconv(.C) void;
705pub const sig_t = *const fn (i32) callconv(.C) void;
706706
707707pub const SOCK = struct {
708708 pub const STREAM = 1;
lib/std/c/freebsd.zig+2-2
......@@ -1171,8 +1171,8 @@ const NSIG = 32;
11711171
11721172/// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall.
11731173pub const Sigaction = extern struct {
1174 pub const handler_fn = *align(1) const fn (c_int) callconv(.C) void;
1175 pub const sigaction_fn = *const fn (c_int, *const siginfo_t, ?*anyopaque) callconv(.C) void;
1174 pub const handler_fn = *align(1) const fn (i32) callconv(.C) void;
1175 pub const sigaction_fn = *const fn (i32, *const siginfo_t, ?*anyopaque) callconv(.C) void;
11761176
11771177 /// signal handler
11781178 handler: extern union {
lib/std/c/haiku.zig+1-1
......@@ -501,7 +501,7 @@ pub const siginfo_t = extern struct {
501501/// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall.
502502pub const Sigaction = extern struct {
503503 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
506506 /// signal handler
507507 handler: extern union {
lib/std/c/netbsd.zig+2-2
......@@ -864,8 +864,8 @@ pub const SIG = struct {
864864
865865/// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall.
866866pub const Sigaction = extern struct {
867 pub const handler_fn = *align(1) const fn (c_int) callconv(.C) void;
868 pub const sigaction_fn = *const fn (c_int, *const siginfo_t, ?*anyopaque) callconv(.C) void;
867 pub const handler_fn = *align(1) const fn (i32) callconv(.C) void;
868 pub const sigaction_fn = *const fn (i32, *const siginfo_t, ?*anyopaque) callconv(.C) void;
869869
870870 /// signal handler
871871 handler: extern union {
lib/std/c/openbsd.zig+2-2
......@@ -842,8 +842,8 @@ pub const SIG = struct {
842842
843843/// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall.
844844pub const Sigaction = extern struct {
845 pub const handler_fn = *align(1) const fn (c_int) callconv(.C) void;
846 pub const sigaction_fn = *const fn (c_int, *const siginfo_t, ?*anyopaque) callconv(.C) void;
845 pub const handler_fn = *align(1) const fn (i32) callconv(.C) void;
846 pub const sigaction_fn = *const fn (i32, *const siginfo_t, ?*anyopaque) callconv(.C) void;
847847
848848 /// signal handler
849849 handler: extern union {
lib/std/c/solaris.zig+2-2
......@@ -874,8 +874,8 @@ pub const SIG = struct {
874874
875875/// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall.
876876pub const Sigaction = extern struct {
877 pub const handler_fn = *align(1) const fn (c_int) callconv(.C) void;
878 pub const sigaction_fn = *const fn (c_int, *const siginfo_t, ?*anyopaque) callconv(.C) void;
877 pub const handler_fn = *align(1) const fn (i32) callconv(.C) void;
878 pub const sigaction_fn = *const fn (i32, *const siginfo_t, ?*anyopaque) callconv(.C) void;
879879
880880 /// signal options
881881 flags: c_uint,
lib/std/debug.zig+1-1
......@@ -2570,7 +2570,7 @@ fn resetSegfaultHandler() void {
25702570 updateSegfaultHandler(&act) catch {};
25712571}
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 {
25742574 // Reset to the default handler so that if a segfault happens in this handler it will crash
25752575 // the process. Also when this handler returns, the original instruction will be repeated
25762576 // 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 {
108108 pool.mutex.lock();
109109 defer pool.mutex.unlock();
110110
111 const node = @fieldParentPtr(Node, "data", connection);
111 const node: *Node = @fieldParentPtr("data", connection);
112112
113113 pool.used.remove(node);
114114
lib/std/os/emscripten.zig+2-2
......@@ -695,8 +695,8 @@ pub const SIG = struct {
695695};
696696
697697pub const Sigaction = extern struct {
698 pub const handler_fn = *align(1) const fn (c_int) callconv(.C) void;
699 pub const sigaction_fn = *const fn (c_int, *const siginfo_t, ?*anyopaque) callconv(.C) void;
698 pub const handler_fn = *align(1) const fn (i32) callconv(.C) void;
699 pub const sigaction_fn = *const fn (i32, *const siginfo_t, ?*anyopaque) callconv(.C) void;
700700
701701 handler: extern union {
702702 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
43014301pub const app_mask: sigset_t = [2]u32{ 0xfffffffc, 0x7fffffff } ++ [_]u32{0xffffffff} ** 30;
43024302
43034303const 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;
43054305 const restorer = *const fn () callconv(.C) void;
43064306};
43074307
......@@ -4328,8 +4328,8 @@ pub const k_sigaction = switch (native_arch) {
43284328
43294329/// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall.
43304330pub const Sigaction = extern struct {
4331 pub const handler_fn = *align(1) const fn (c_int) callconv(.C) void;
4332 pub const sigaction_fn = *const fn (c_int, *const siginfo_t, ?*anyopaque) callconv(.C) void;
4331 pub const handler_fn = *align(1) const fn (i32) callconv(.C) void;
4332 pub const sigaction_fn = *const fn (i32, *const siginfo_t, ?*anyopaque) callconv(.C) void;
43334333
43344334 handler: extern union {
43354335 handler: ?handler_fn,
lib/std/os/plan9.zig+2-2
......@@ -186,8 +186,8 @@ pub const empty_sigset = 0;
186186pub const siginfo_t = c_long;
187187// TODO plan9 doesn't have sigaction_fn. Sigaction is not a union, but we incude it here to be compatible.
188188pub const Sigaction = extern struct {
189 pub const handler_fn = *const fn (c_int) callconv(.C) void;
190 pub const sigaction_fn = *const fn (c_int, *const siginfo_t, ?*anyopaque) callconv(.C) void;
189 pub const handler_fn = *const fn (i32) callconv(.C) void;
190 pub const sigaction_fn = *const fn (i32, *const siginfo_t, ?*anyopaque) callconv(.C) void;
191191
192192 handler: extern union {
193193 handler: ?handler_fn,
lib/std/start.zig+1-1
......@@ -597,4 +597,4 @@ fn maybeIgnoreSigpipe() void {
597597 }
598598}
599599
600fn noopSigHandler(_: c_int) callconv(.C) void {}
600fn noopSigHandler(_: i32) callconv(.C) void {}
lib/std/zig.zig+1
......@@ -1021,4 +1021,5 @@ test {
10211021 _ = string_literal;
10221022 _ = system;
10231023 _ = target;
1024 _ = c_translation;
10241025}
lib/std/zig/AstGen.zig+65-36
......@@ -316,8 +316,7 @@ const ResultInfo = struct {
316316 };
317317
318318 /// Find the result type for a cast builtin given the result location.
319 /// If the location does not have a known result type, emits an error on
320 /// the given node.
319 /// If the location does not have a known result type, returns `null`.
321320 fn resultType(rl: Loc, gz: *GenZir, node: Ast.Node.Index) !?Zir.Inst.Ref {
322321 return switch (rl) {
323322 .discard, .none, .ref, .inferred_ptr, .destructure => null,
......@@ -330,6 +329,9 @@ const ResultInfo = struct {
330329 };
331330 }
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.
333335 fn resultTypeForCast(rl: Loc, gz: *GenZir, node: Ast.Node.Index, builtin_name: []const u8) !Zir.Inst.Ref {
334336 const astgen = gz.astgen;
335337 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
27862788 .atomic_load,
27872789 .atomic_rmw,
27882790 .mul_add,
2789 .field_parent_ptr,
27902791 .max,
27912792 .min,
27922793 .c_import,
......@@ -8853,6 +8854,7 @@ fn ptrCast(
88538854 const node_datas = tree.nodes.items(.data);
88548855 const node_tags = tree.nodes.items(.tag);
88558856
8857 const FlagsInt = @typeInfo(Zir.Inst.FullPtrCastFlags).Struct.backing_integer.?;
88568858 var flags: Zir.Inst.FullPtrCastFlags = .{};
88578859
88588860 // Note that all pointer cast builtins have one parameter, so we only need
......@@ -8870,36 +8872,62 @@ fn ptrCast(
88708872 }
88718873
88728874 if (node_datas[node].lhs == 0) break; // 0 args
8873 if (node_datas[node].rhs != 0) break; // 2 args
88748875
88758876 const builtin_token = main_tokens[node];
88768877 const builtin_name = tree.tokenSlice(builtin_token);
88778878 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) {
8881 else => break,
8882 inline .ptr_cast,
8883 .align_cast,
8884 .addrspace_cast,
8885 .const_cast,
8886 .volatile_cast,
8887 => |tag| {
8888 if (@field(flags, @tagName(tag))) {
8889 return astgen.failNode(node, "redundant {s}", .{builtin_name});
8890 }
8891 @field(flags, @tagName(tag)) = true;
8892 },
8898 node = node_datas[node].lhs;
8899 } else {
8900 // 2 args
8901 if (info.param_count != 2) break;
8902
8903 switch (info.tag) {
8904 else => break,
8905 .field_parent_ptr => {
8906 if (flags.ptr_cast) break;
8907
8908 const flags_int: FlagsInt = @bitCast(flags);
8909 const cursor = maybeAdvanceSourceCursorToMainToken(gz, root_node);
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 }
88938923 }
8894
8895 node = node_datas[node].lhs;
88968924 }
88978925
8898 const flags_i: u5 = @bitCast(flags);
8899 assert(flags_i != 0);
8926 const flags_int: FlagsInt = @bitCast(flags);
8927 assert(flags_int != 0);
89008928
89018929 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))) {
89038931 // Special case: simpler representation
89048932 return typeCast(gz, scope, ri, root_node, node, .ptr_cast, "@ptrCast");
89058933 }
......@@ -8908,12 +8936,12 @@ fn ptrCast(
89088936 .const_cast = true,
89098937 .volatile_cast = true,
89108938 };
8911 if ((flags_i & ~@as(u5, @bitCast(no_result_ty_flags))) == 0) {
8939 if ((flags_int & ~@as(FlagsInt, @bitCast(no_result_ty_flags))) == 0) {
89128940 // Result type not needed
89138941 const cursor = maybeAdvanceSourceCursorToMainToken(gz, root_node);
89148942 const operand = try expr(gz, scope, .{ .rl = .none }, node);
89158943 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{
89178945 .node = gz.nodeIndexToRelative(root_node),
89188946 .operand = operand,
89198947 });
......@@ -8926,7 +8954,7 @@ fn ptrCast(
89268954 const result_type = try ri.rl.resultTypeForCast(gz, root_node, flags.needResultTypeBuiltinName());
89278955 const operand = try expr(gz, scope, .{ .rl = .none }, node);
89288956 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{
89308958 .node = gz.nodeIndexToRelative(root_node),
89318959 .lhs = result_type,
89328960 .rhs = operand,
......@@ -9379,7 +9407,7 @@ fn builtinCall(
93799407 try emitDbgNode(gz, node);
93809408
93819409 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),
93839411 .rhs = try expr(gz, scope, .{ .rl = .none }, params[0]),
93849412 .node = gz.nodeIndexToRelative(node),
93859413 });
......@@ -9452,7 +9480,7 @@ fn builtinCall(
94529480 },
94539481
94549482 .splat => {
9455 const result_type = try ri.rl.resultTypeForCast(gz, node, "@splat");
9483 const result_type = try ri.rl.resultTypeForCast(gz, node, builtin_name);
94569484 const elem_type = try gz.addUnNode(.vector_elem_type, result_type, node);
94579485 const scalar = try expr(gz, scope, .{ .rl = .{ .ty = elem_type } }, params[0]);
94589486 const result = try gz.addPlNode(.splat, node, Zir.Inst.Bin{
......@@ -9537,12 +9565,13 @@ fn builtinCall(
95379565 return rvalue(gz, ri, result, node);
95389566 },
95399567 .field_parent_ptr => {
9540 const parent_type = try typeExpr(gz, scope, params[0]);
9541 const field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }, params[1]);
9542 const result = try gz.addPlNode(.field_parent_ptr, node, Zir.Inst.FieldParentPtr{
9543 .parent_type = parent_type,
9568 const parent_ptr_type = try ri.rl.resultTypeForCast(gz, node, builtin_name);
9569 const field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }, params[0]);
9570 const result = try gz.addExtendedPayloadSmall(.field_parent_ptr, 0, Zir.Inst.FieldParentPtr{
9571 .src_node = gz.nodeIndexToRelative(node),
9572 .parent_ptr_type = parent_ptr_type,
95449573 .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]),
95469575 });
95479576 return rvalue(gz, ri, result, node);
95489577 },
......@@ -11686,20 +11715,20 @@ const Scope = struct {
1168611715 fn cast(base: *Scope, comptime T: type) ?*T {
1168711716 if (T == Defer) {
1168811717 switch (base.tag) {
11689 .defer_normal, .defer_error => return @fieldParentPtr(T, "base", base),
11718 .defer_normal, .defer_error => return @alignCast(@fieldParentPtr("base", base)),
1169011719 else => return null,
1169111720 }
1169211721 }
1169311722 if (T == Namespace) {
1169411723 switch (base.tag) {
11695 .namespace => return @fieldParentPtr(T, "base", base),
11724 .namespace => return @alignCast(@fieldParentPtr("base", base)),
1169611725 else => return null,
1169711726 }
1169811727 }
1169911728 if (base.tag != T.base_tag)
1170011729 return null;
1170111730
11702 return @fieldParentPtr(T, "base", base);
11731 return @alignCast(@fieldParentPtr("base", base));
1170311732 }
1170411733
1170511734 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.
911911 .work_item_id,
912912 .work_group_size,
913913 .work_group_id,
914 .field_parent_ptr,
914915 => {
915916 _ = try astrl.expr(args[0], block, ResultInfo.type_only);
916917 return false;
......@@ -976,7 +977,6 @@ fn builtinCall(astrl: *AstRlAnnotate, block: ?*Block, ri: ResultInfo, node: Ast.
976977 },
977978 .bit_offset_of,
978979 .offset_of,
979 .field_parent_ptr,
980980 .has_decl,
981981 .has_field,
982982 .field,
lib/std/zig/BuiltinFn.zig+1-1
......@@ -504,7 +504,7 @@ pub const list = list: {
504504 "@fieldParentPtr",
505505 .{
506506 .tag = .field_parent_ptr,
507 .param_count = 3,
507 .param_count = 2,
508508 },
509509 },
510510 .{
lib/std/zig/Zir.zig+12-7
......@@ -940,9 +940,6 @@ pub const Inst = struct {
940940 /// The addend communicates the type of the builtin.
941941 /// The mulends need to be coerced to the same type.
942942 mul_add,
943 /// Implements the `@fieldParentPtr` builtin.
944 /// Uses the `pl_node` union field with payload `FieldParentPtr`.
945 field_parent_ptr,
946943 /// Implements the `@memcpy` builtin.
947944 /// Uses the `pl_node` union field with payload `Bin`.
948945 memcpy,
......@@ -1230,7 +1227,6 @@ pub const Inst = struct {
12301227 .atomic_store,
12311228 .mul_add,
12321229 .builtin_call,
1233 .field_parent_ptr,
12341230 .max,
12351231 .memcpy,
12361232 .memset,
......@@ -1522,7 +1518,6 @@ pub const Inst = struct {
15221518 .atomic_rmw,
15231519 .mul_add,
15241520 .builtin_call,
1525 .field_parent_ptr,
15261521 .max,
15271522 .min,
15281523 .c_import,
......@@ -1794,7 +1789,6 @@ pub const Inst = struct {
17941789 .atomic_store = .pl_node,
17951790 .mul_add = .pl_node,
17961791 .builtin_call = .pl_node,
1797 .field_parent_ptr = .pl_node,
17981792 .max = .pl_node,
17991793 .memcpy = .pl_node,
18001794 .memset = .pl_node,
......@@ -2064,6 +2058,12 @@ pub const Inst = struct {
20642058 /// with a specific value. For instance, this is used for the capture of an `errdefer`.
20652059 /// This should never appear in a body.
20662060 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
20682068 pub const InstData = struct {
20692069 opcode: Extended,
......@@ -3363,9 +3363,14 @@ pub const Inst = struct {
33633363 };
33643364
33653365 pub const FieldParentPtr = struct {
3366 parent_type: Ref,
3366 src_node: i32,
3367 parent_ptr_type: Ref,
33673368 field_name: Ref,
33683369 field_ptr: Ref,
3370
3371 pub fn src(self: FieldParentPtr) LazySrcLoc {
3372 return LazySrcLoc.nodeOffset(self.src_node);
3373 }
33693374 };
33703375
33713376 pub const Shuffle = struct {
lib/std/zig/c_translation.zig+1-1
......@@ -414,7 +414,7 @@ pub const Macros = struct {
414414 }
415415
416416 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);
418418 }
419419
420420 /// 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;
130130#define zig_restrict
131131#endif
132132
133#if __STDC_VERSION__ >= 201112L
134#define zig_align(alignment) _Alignas(alignment)
135#elif zig_has_attribute(aligned)
136#define zig_align(alignment) __attribute__((aligned(alignment)))
133#if zig_has_attribute(aligned)
134#define zig_under_align(alignment) __attribute__((aligned(alignment)))
137135#elif _MSC_VER
138#define zig_align(alignment) __declspec(align(alignment))
136#define zig_under_align(alignment) __declspec(align(alignment))
139137#else
140#define zig_align zig_align_unavailable
138#define zig_under_align zig_align_unavailable
141139#endif
142140
143#if zig_has_attribute(aligned)
144#define zig_under_align(alignment) __attribute__((aligned(alignment)))
145#elif _MSC_VER
146#define zig_under_align(alignment) zig_align(alignment)
141#if __STDC_VERSION__ >= 201112L
142#define zig_align(alignment) _Alignas(alignment)
147143#else
148#define zig_align zig_align_unavailable
144#define zig_align(alignment) zig_under_align(alignment)
149145#endif
150146
151147#if zig_has_attribute(aligned)
......@@ -165,11 +161,14 @@ typedef char bool;
165161#endif
166162
167163#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
169166#elif _MSC_VER
170#define zig_linksection(name, def, ...) __pragma(section(name, __VA_ARGS__)) __declspec(allocate(name)) def
167#define zig_linksection(name) __pragma(section(name, read, write)) __declspec(allocate(name))
168#define zig_linksection_fn(name) __pragma(section(name, read, execute)) __declspec(code_seg(name))
171169#else
172#define zig_linksection(name, def, ...) zig_linksection_unavailable
170#define zig_linksection(name) zig_linksection_unavailable
171#define zig_linksection_fn zig_linksection
173172#endif
174173
175174#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
34513451
34523452 var dg: c_codegen.DeclGen = .{
34533453 .gpa = gpa,
3454 .module = module,
3454 .zcu = module,
3455 .mod = module.namespacePtr(decl.src_namespace).file_scope.mod,
34553456 .error_msg = null,
34563457 .pass = .{ .decl = decl_index },
34573458 .is_naked_fn = false,
34583459 .fwd_decl = fwd_decl.toManaged(gpa),
3459 .ctypes = .{},
3460 .ctype_pool = c_codegen.CType.Pool.empty,
3461 .scratch = .{},
34603462 .anon_decl_deps = .{},
34613463 .aligned_anon_decls = .{},
34623464 };
34633465 defer {
3464 dg.ctypes.deinit(gpa);
3465 dg.fwd_decl.deinit();
3466 fwd_decl.* = dg.fwd_decl.moveToUnmanaged();
3467 fwd_decl.shrinkAndFree(gpa, fwd_decl.items.len);
3468 dg.ctype_pool.deinit(gpa);
3469 dg.scratch.deinit(gpa);
34663470 }
3471 try dg.ctype_pool.init(gpa);
34673472
34683473 c_codegen.genHeader(&dg) catch |err| switch (err) {
34693474 error.AnalysisFail => {
......@@ -3472,9 +3477,6 @@ fn processOneJob(comp: *Compilation, job: Job, prog_node: *std.Progress.Node) !v
34723477 },
34733478 else => |e| return e,
34743479 };
3475
3476 fwd_decl.* = dg.fwd_decl.moveToUnmanaged();
3477 fwd_decl.shrinkAndFree(gpa, fwd_decl.items.len);
34783480 },
34793481 }
34803482 },
src/InternPool.zig+35-35
......@@ -712,7 +712,7 @@ pub const Key = union(enum) {
712712 pub fn fieldName(
713713 self: AnonStructType,
714714 ip: *const InternPool,
715 index: u32,
715 index: usize,
716716 ) OptionalNullTerminatedString {
717717 if (self.names.len == 0)
718718 return .none;
......@@ -3879,20 +3879,13 @@ pub const Alignment = enum(u6) {
38793879 none = std.math.maxInt(u6),
38803880 _,
38813881
3882 pub fn toByteUnitsOptional(a: Alignment) ?u64 {
3882 pub fn toByteUnits(a: Alignment) ?u64 {
38833883 return switch (a) {
38843884 .none => null,
38853885 else => @as(u64, 1) << @intFromEnum(a),
38863886 };
38873887 }
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
38963889 pub fn fromByteUnits(n: u64) Alignment {
38973890 if (n == 0) return .none;
38983891 assert(std.math.isPowerOfTwo(n));
......@@ -5170,48 +5163,55 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
51705163 .ptr => |ptr| {
51715164 const ptr_type = ip.indexToKey(ptr.ty).ptr_type;
51725165 assert(ptr_type.flags.size != .Slice);
5173 switch (ptr.addr) {
5174 .decl => |decl| ip.items.appendAssumeCapacity(.{
5166 ip.items.appendAssumeCapacity(switch (ptr.addr) {
5167 .decl => |decl| .{
51755168 .tag = .ptr_decl,
51765169 .data = try ip.addExtra(gpa, PtrDecl{
51775170 .ty = ptr.ty,
51785171 .decl = decl,
51795172 }),
5180 }),
5181 .comptime_alloc => |alloc_index| ip.items.appendAssumeCapacity(.{
5173 },
5174 .comptime_alloc => |alloc_index| .{
51825175 .tag = .ptr_comptime_alloc,
51835176 .data = try ip.addExtra(gpa, PtrComptimeAlloc{
51845177 .ty = ptr.ty,
51855178 .index = alloc_index,
51865179 }),
5187 }),
5188 .anon_decl => |anon_decl| ip.items.appendAssumeCapacity(
5189 if (ptrsHaveSameAlignment(ip, ptr.ty, ptr_type, anon_decl.orig_ty)) .{
5180 },
5181 .anon_decl => |anon_decl| if (ptrsHaveSameAlignment(ip, ptr.ty, ptr_type, anon_decl.orig_ty)) item: {
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 .{
51905190 .tag = .ptr_anon_decl,
51915191 .data = try ip.addExtra(gpa, PtrAnonDecl{
51925192 .ty = ptr.ty,
51935193 .val = anon_decl.val,
51945194 }),
5195 } else .{
5196 .tag = .ptr_anon_decl_aligned,
5197 .data = try ip.addExtra(gpa, PtrAnonDeclAligned{
5198 .ty = ptr.ty,
5199 .val = anon_decl.val,
5200 .orig_ty = anon_decl.orig_ty,
5201 }),
5202 },
5203 ),
5204 .comptime_field => |field_val| {
5195 };
5196 } else .{
5197 .tag = .ptr_anon_decl_aligned,
5198 .data = try ip.addExtra(gpa, PtrAnonDeclAligned{
5199 .ty = ptr.ty,
5200 .val = anon_decl.val,
5201 .orig_ty = anon_decl.orig_ty,
5202 }),
5203 },
5204 .comptime_field => |field_val| item: {
52055205 assert(field_val != .none);
5206 ip.items.appendAssumeCapacity(.{
5206 break :item .{
52075207 .tag = .ptr_comptime_field,
52085208 .data = try ip.addExtra(gpa, PtrComptimeField{
52095209 .ty = ptr.ty,
52105210 .field_val = field_val,
52115211 }),
5212 });
5212 };
52135213 },
5214 .int, .eu_payload, .opt_payload => |base| {
5214 .int, .eu_payload, .opt_payload => |base| item: {
52155215 switch (ptr.addr) {
52165216 .int => assert(ip.typeOf(base) == .usize_type),
52175217 .eu_payload => assert(ip.indexToKey(
......@@ -5222,7 +5222,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
52225222 ) == .opt_type),
52235223 else => unreachable,
52245224 }
5225 ip.items.appendAssumeCapacity(.{
5225 break :item .{
52265226 .tag = switch (ptr.addr) {
52275227 .int => .ptr_int,
52285228 .eu_payload => .ptr_eu_payload,
......@@ -5233,9 +5233,9 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
52335233 .ty = ptr.ty,
52345234 .base = base,
52355235 }),
5236 });
5236 };
52375237 },
5238 .elem, .field => |base_index| {
5238 .elem, .field => |base_index| item: {
52395239 const base_ptr_type = ip.indexToKey(ip.typeOf(base_index.base)).ptr_type;
52405240 switch (ptr.addr) {
52415241 .elem => assert(base_ptr_type.flags.size == .Many),
......@@ -5272,7 +5272,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
52725272 } });
52735273 assert(!(try ip.map.getOrPutAdapted(gpa, key, adapter)).found_existing);
52745274 try ip.items.ensureUnusedCapacity(gpa, 1);
5275 ip.items.appendAssumeCapacity(.{
5275 break :item .{
52765276 .tag = switch (ptr.addr) {
52775277 .elem => .ptr_elem,
52785278 .field => .ptr_field,
......@@ -5283,9 +5283,9 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
52835283 .base = base_index.base,
52845284 .index = index_index,
52855285 }),
5286 });
5286 };
52875287 },
5288 }
5288 });
52895289 },
52905290
52915291 .opt => |opt| {
src/Module.zig+3-3
......@@ -299,7 +299,7 @@ const ValueArena = struct {
299299 /// and must live until the matching call to release().
300300 pub fn acquire(self: *ValueArena, child_allocator: Allocator, out_arena_allocator: *std.heap.ArenaAllocator) Allocator {
301301 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();
303303 }
304304
305305 out_arena_allocator.* = self.state.promote(child_allocator);
......@@ -309,7 +309,7 @@ const ValueArena = struct {
309309
310310 /// Releases the allocator acquired by `acquire. `arena_allocator` must match the one passed to `acquire`.
311311 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) {
313313 self.state = self.state_acquired.?.*;
314314 self.state_acquired = null;
315315 }
......@@ -5846,7 +5846,7 @@ pub fn intBitsForValue(mod: *Module, val: Value, sign: bool) u16 {
58465846 return @as(u16, @intCast(big.bitCountTwosComp()));
58475847 },
58485848 .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);
58505850 },
58515851 .lazy_size => |lazy_ty| {
58525852 return Type.smallestUnsignedBits(Type.fromInterned(lazy_ty).abiSize(mod)) + @intFromBool(sign);
src/Sema.zig+180-118
......@@ -1131,7 +1131,6 @@ fn analyzeBodyInner(
11311131 .atomic_rmw => try sema.zirAtomicRmw(block, inst),
11321132 .mul_add => try sema.zirMulAdd(block, inst),
11331133 .builtin_call => try sema.zirBuiltinCall(block, inst),
1134 .field_parent_ptr => try sema.zirFieldParentPtr(block, inst),
11351134 .@"resume" => try sema.zirResume(block, inst),
11361135 .@"await" => try sema.zirAwait(block, inst),
11371136 .for_len => try sema.zirForLen(block, inst),
......@@ -1296,6 +1295,7 @@ fn analyzeBodyInner(
12961295 continue;
12971296 },
12981297 .value_placeholder => unreachable, // never appears in a body
1298 .field_parent_ptr => try sema.zirFieldParentPtr(block, extended),
12991299 };
13001300 },
13011301
......@@ -6508,7 +6508,7 @@ fn zirSetAlignStack(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Inst
65086508 const alignment = try sema.resolveAlign(block, operand_src, extra.operand);
65096509 if (alignment.order(Alignment.fromNonzeroByteUnits(256)).compare(.gt)) {
65106510 return sema.fail(block, src, "attempt to @setAlignStack({d}); maximum is 256", .{
6511 alignment.toByteUnitsOptional().?,
6511 alignment.toByteUnits().?,
65126512 });
65136513 }
65146514
......@@ -17699,19 +17699,20 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1769917699 .ty = new_decl_ty.toIntern(),
1770017700 .storage = .{ .elems = param_vals },
1770117701 } });
17702 const ptr_ty = (try sema.ptrType(.{
17702 const slice_ty = (try sema.ptrType(.{
1770317703 .child = param_info_ty.toIntern(),
1770417704 .flags = .{
1770517705 .size = .Slice,
1770617706 .is_const = true,
1770717707 },
1770817708 })).toIntern();
17709 const manyptr_ty = Type.fromInterned(slice_ty).slicePtrFieldType(mod).toIntern();
1770917710 break :v try mod.intern(.{ .slice = .{
17710 .ty = ptr_ty,
17711 .ty = slice_ty,
1771117712 .ptr = try mod.intern(.{ .ptr = .{
17712 .ty = Type.fromInterned(ptr_ty).slicePtrFieldType(mod).toIntern(),
17713 .ty = manyptr_ty,
1771317714 .addr = .{ .anon_decl = .{
17714 .orig_ty = ptr_ty,
17715 .orig_ty = manyptr_ty,
1771517716 .val = new_decl_val,
1771617717 } },
1771717718 } }),
......@@ -17804,7 +17805,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1780417805 },
1780517806 .Pointer => {
1780617807 const info = ty.ptrInfo(mod);
17807 const alignment = if (info.flags.alignment.toByteUnitsOptional()) |alignment|
17808 const alignment = if (info.flags.alignment.toByteUnits()) |alignment|
1780817809 try mod.intValue(Type.comptime_int, alignment)
1780917810 else
1781017811 try Type.fromInterned(info.child).lazyAbiAlignment(mod);
......@@ -18031,12 +18032,13 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1803118032 .ty = array_errors_ty.toIntern(),
1803218033 .storage = .{ .elems = vals },
1803318034 } });
18035 const manyptr_errors_ty = slice_errors_ty.slicePtrFieldType(mod).toIntern();
1803418036 break :v try mod.intern(.{ .slice = .{
1803518037 .ty = slice_errors_ty.toIntern(),
1803618038 .ptr = try mod.intern(.{ .ptr = .{
18037 .ty = slice_errors_ty.slicePtrFieldType(mod).toIntern(),
18039 .ty = manyptr_errors_ty,
1803818040 .addr = .{ .anon_decl = .{
18039 .orig_ty = slice_errors_ty.toIntern(),
18041 .orig_ty = manyptr_errors_ty,
1804018042 .val = new_decl_val,
1804118043 } },
1804218044 } }),
......@@ -18155,20 +18157,21 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1815518157 .ty = fields_array_ty.toIntern(),
1815618158 .storage = .{ .elems = enum_field_vals },
1815718159 } });
18158 const ptr_ty = (try sema.ptrType(.{
18160 const slice_ty = (try sema.ptrType(.{
1815918161 .child = enum_field_ty.toIntern(),
1816018162 .flags = .{
1816118163 .size = .Slice,
1816218164 .is_const = true,
1816318165 },
1816418166 })).toIntern();
18167 const manyptr_ty = Type.fromInterned(slice_ty).slicePtrFieldType(mod).toIntern();
1816518168 break :v try mod.intern(.{ .slice = .{
18166 .ty = ptr_ty,
18169 .ty = slice_ty,
1816718170 .ptr = try mod.intern(.{ .ptr = .{
18168 .ty = Type.fromInterned(ptr_ty).slicePtrFieldType(mod).toIntern(),
18171 .ty = manyptr_ty,
1816918172 .addr = .{ .anon_decl = .{
1817018173 .val = new_decl_val,
18171 .orig_ty = ptr_ty,
18174 .orig_ty = manyptr_ty,
1817218175 } },
1817318176 } }),
1817418177 .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
1827918282 // type: type,
1828018283 field_ty,
1828118284 // 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(),
1828318286 };
1828418287 field_val.* = try mod.intern(.{ .aggregate = .{
1828518288 .ty = union_field_ty.toIntern(),
......@@ -18296,19 +18299,20 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1829618299 .ty = array_fields_ty.toIntern(),
1829718300 .storage = .{ .elems = union_field_vals },
1829818301 } });
18299 const ptr_ty = (try sema.ptrType(.{
18302 const slice_ty = (try sema.ptrType(.{
1830018303 .child = union_field_ty.toIntern(),
1830118304 .flags = .{
1830218305 .size = .Slice,
1830318306 .is_const = true,
1830418307 },
1830518308 })).toIntern();
18309 const manyptr_ty = Type.fromInterned(slice_ty).slicePtrFieldType(mod).toIntern();
1830618310 break :v try mod.intern(.{ .slice = .{
18307 .ty = ptr_ty,
18311 .ty = slice_ty,
1830818312 .ptr = try mod.intern(.{ .ptr = .{
18309 .ty = Type.fromInterned(ptr_ty).slicePtrFieldType(mod).toIntern(),
18313 .ty = manyptr_ty,
1831018314 .addr = .{ .anon_decl = .{
18311 .orig_ty = ptr_ty,
18315 .orig_ty = manyptr_ty,
1831218316 .val = new_decl_val,
1831318317 } },
1831418318 } }),
......@@ -18436,7 +18440,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1843618440 // is_comptime: bool,
1843718441 Value.makeBool(is_comptime).toIntern(),
1843818442 // 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(),
1844018444 };
1844118445 struct_field_val.* = try mod.intern(.{ .aggregate = .{
1844218446 .ty = struct_field_ty.toIntern(),
......@@ -18505,7 +18509,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1850518509 // is_comptime: bool,
1850618510 Value.makeBool(field_is_comptime).toIntern(),
1850718511 // 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(),
1850918513 };
1851018514 field_val.* = try mod.intern(.{ .aggregate = .{
1851118515 .ty = struct_field_ty.toIntern(),
......@@ -18523,19 +18527,20 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1852318527 .ty = array_fields_ty.toIntern(),
1852418528 .storage = .{ .elems = struct_field_vals },
1852518529 } });
18526 const ptr_ty = (try sema.ptrType(.{
18530 const slice_ty = (try sema.ptrType(.{
1852718531 .child = struct_field_ty.toIntern(),
1852818532 .flags = .{
1852918533 .size = .Slice,
1853018534 .is_const = true,
1853118535 },
1853218536 })).toIntern();
18537 const manyptr_ty = Type.fromInterned(slice_ty).slicePtrFieldType(mod).toIntern();
1853318538 break :v try mod.intern(.{ .slice = .{
18534 .ty = ptr_ty,
18539 .ty = slice_ty,
1853518540 .ptr = try mod.intern(.{ .ptr = .{
18536 .ty = Type.fromInterned(ptr_ty).slicePtrFieldType(mod).toIntern(),
18541 .ty = manyptr_ty,
1853718542 .addr = .{ .anon_decl = .{
18538 .orig_ty = ptr_ty,
18543 .orig_ty = manyptr_ty,
1853918544 .val = new_decl_val,
1854018545 } },
1854118546 } }),
......@@ -18661,19 +18666,20 @@ fn typeInfoDecls(
1866118666 .ty = array_decl_ty.toIntern(),
1866218667 .storage = .{ .elems = decl_vals.items },
1866318668 } });
18664 const ptr_ty = (try sema.ptrType(.{
18669 const slice_ty = (try sema.ptrType(.{
1866518670 .child = declaration_ty.toIntern(),
1866618671 .flags = .{
1866718672 .size = .Slice,
1866818673 .is_const = true,
1866918674 },
1867018675 })).toIntern();
18676 const manyptr_ty = Type.fromInterned(slice_ty).slicePtrFieldType(mod).toIntern();
1867118677 return try mod.intern(.{ .slice = .{
18672 .ty = ptr_ty,
18678 .ty = slice_ty,
1867318679 .ptr = try mod.intern(.{ .ptr = .{
18674 .ty = Type.fromInterned(ptr_ty).slicePtrFieldType(mod).toIntern(),
18680 .ty = manyptr_ty,
1867518681 .addr = .{ .anon_decl = .{
18676 .orig_ty = ptr_ty,
18682 .orig_ty = manyptr_ty,
1867718683 .val = new_decl_val,
1867818684 } },
1867918685 } }),
......@@ -19803,8 +19809,18 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
1980319809 break :blk @intCast(host_size);
1980419810 } else 0;
1980519811
19806 if (host_size != 0 and bit_offset >= host_size * 8) {
19807 return sema.fail(block, bitoffset_src, "bit offset starts after end of host integer", .{});
19812 if (host_size != 0) {
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 }
1980819824 }
1980919825
1981019826 if (elem_ty.zigTypeTag(mod) == .Fn) {
......@@ -22552,7 +22568,7 @@ fn zirPtrFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
2255222568 try sema.addSafetyCheck(block, src, is_non_zero, .cast_to_null);
2255322569 }
2255422570 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;
2255622572 const align_minus_1 = Air.internedToRef((try mod.intValue(Type.usize, align_bytes_minus_1)).toIntern());
2255722573 const remainder = try block.addBinOp(.bit_and, operand_coerced, align_minus_1);
2255822574 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!
2257222588 try sema.addSafetyCheck(block, src, is_non_zero, .cast_to_null);
2257322589 }
2257422590 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;
2257622592 const align_minus_1 = Air.internedToRef((try mod.intValue(Type.usize, align_bytes_minus_1)).toIntern());
2257722593 const remainder = try block.addBinOp(.bit_and, elem_coerced, align_minus_1);
2257822594 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
2274122757}
2274222758
2274322759fn zirPtrCastFull(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref {
22744 const flags: Zir.Inst.FullPtrCastFlags = @bitCast(@as(
22745 @typeInfo(Zir.Inst.FullPtrCastFlags).Struct.backing_integer.?,
22746 @truncate(extended.small),
22747 ));
22760 const FlagsInt = @typeInfo(Zir.Inst.FullPtrCastFlags).Struct.backing_integer.?;
22761 const flags: Zir.Inst.FullPtrCastFlags = @bitCast(@as(FlagsInt, @truncate(extended.small)));
2274822762 const extra = sema.code.extraData(Zir.Inst.BinNode, extended.operand).data;
2274922763 const src = LazySrcLoc.nodeOffset(extra.node);
2275022764 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
2275722771 operand,
2275822772 operand_src,
2275922773 dest_ty,
22774 flags.needResultTypeBuiltinName(),
2276022775 );
2276122776}
2276222777
......@@ -22775,6 +22790,7 @@ fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
2277522790 operand,
2277622791 operand_src,
2277722792 dest_ty,
22793 "@ptrCast",
2277822794 );
2277922795}
2278022796
......@@ -22786,6 +22802,7 @@ fn ptrCastFull(
2278622802 operand: Air.Inst.Ref,
2278722803 operand_src: LazySrcLoc,
2278822804 dest_ty: Type,
22805 operation: []const u8,
2278922806) CompileError!Air.Inst.Ref {
2279022807 const mod = sema.mod;
2279122808 const operand_ty = sema.typeOf(operand);
......@@ -22818,7 +22835,7 @@ fn ptrCastFull(
2281822835 };
2281922836 const dest_elem_size = Type.fromInterned(dest_info.child).abiSize(mod);
2282022837 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});
2282222839 }
2282322840 }
2282422841
......@@ -22967,13 +22984,13 @@ fn ptrCastFull(
2296722984 if (!flags.align_cast) {
2296822985 if (dest_align.compare(.gt, src_align)) {
2296922986 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});
2297122988 errdefer msg.destroy(sema.gpa);
2297222989 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,
2297422991 });
2297522992 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,
2297722994 });
2297822995 try sema.errNote(block, src, msg, "use @alignCast to assert pointer alignment", .{});
2297922996 break :msg msg;
......@@ -22984,7 +23001,7 @@ fn ptrCastFull(
2298423001 if (!flags.addrspace_cast) {
2298523002 if (src_info.flags.address_space != dest_info.flags.address_space) {
2298623003 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});
2298823005 errdefer msg.destroy(sema.gpa);
2298923006 try sema.errNote(block, operand_src, msg, "'{}' has address space '{s}'", .{
2299023007 operand_ty.fmt(mod), @tagName(src_info.flags.address_space),
......@@ -23014,7 +23031,7 @@ fn ptrCastFull(
2301423031 if (!flags.const_cast) {
2301523032 if (src_info.flags.is_const and !dest_info.flags.is_const) {
2301623033 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});
2301823035 errdefer msg.destroy(sema.gpa);
2301923036 try sema.errNote(block, src, msg, "use @constCast to discard const qualifier", .{});
2302023037 break :msg msg;
......@@ -23025,7 +23042,7 @@ fn ptrCastFull(
2302523042 if (!flags.volatile_cast) {
2302623043 if (src_info.flags.is_volatile and !dest_info.flags.is_volatile) {
2302723044 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});
2302923046 errdefer msg.destroy(sema.gpa);
2303023047 try sema.errNote(block, src, msg, "use @volatileCast to discard volatile qualifier", .{});
2303123048 break :msg msg;
......@@ -23067,7 +23084,7 @@ fn ptrCastFull(
2306723084 if (!dest_align.check(addr)) {
2306823085 return sema.fail(block, operand_src, "pointer address 0x{X} is not aligned to {d} bytes", .{
2306923086 addr,
23070 dest_align.toByteUnitsOptional().?,
23087 dest_align.toByteUnits().?,
2307123088 });
2307223089 }
2307323090 }
......@@ -23110,7 +23127,7 @@ fn ptrCastFull(
2311023127 dest_align.compare(.gt, src_align) and
2311123128 try sema.typeHasRuntimeBits(Type.fromInterned(dest_info.child)))
2311223129 {
23113 const align_bytes_minus_1 = dest_align.toByteUnitsOptional().? - 1;
23130 const align_bytes_minus_1 = dest_align.toByteUnits().? - 1;
2311423131 const align_minus_1 = Air.internedToRef((try mod.intValue(Type.usize, align_bytes_minus_1)).toIntern());
2311523132 const ptr_int = try block.addUnOp(.int_from_ptr, ptr);
2311623133 const remainder = try block.addBinOp(.bit_and, ptr_int, align_minus_1);
......@@ -23171,10 +23188,8 @@ fn ptrCastFull(
2317123188
2317223189fn zirPtrCastNoDest(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref {
2317323190 const mod = sema.mod;
23174 const flags: Zir.Inst.FullPtrCastFlags = @bitCast(@as(
23175 @typeInfo(Zir.Inst.FullPtrCastFlags).Struct.backing_integer.?,
23176 @truncate(extended.small),
23177 ));
23191 const FlagsInt = @typeInfo(Zir.Inst.FullPtrCastFlags).Struct.backing_integer.?;
23192 const flags: Zir.Inst.FullPtrCastFlags = @bitCast(@as(FlagsInt, @truncate(extended.small)));
2317823193 const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data;
2317923194 const src = LazySrcLoc.nodeOffset(extra.node);
2318023195 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
2484324858 );
2484424859}
2484524860
24846fn zirFieldParentPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) 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);
24861fn zirFieldParentPtr(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref {
2486024862 const mod = sema.mod;
2486124863 const ip = &mod.intern_pool;
2486224864
24863 if (parent_ty.zigTypeTag(mod) != .Struct and parent_ty.zigTypeTag(mod) != .Union) {
24864 return sema.fail(block, ty_src, "expected struct or union type, found '{}'", .{parent_ty.fmt(sema.mod)});
24865 const extra = sema.code.extraData(Zir.Inst.FieldParentPtr, extended.operand).data;
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)}),
2486524883 }
2486624884 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 });
2486824889 const field_index = switch (parent_ty.zigTypeTag(mod)) {
2486924890 .Struct => blk: {
2487024891 if (parent_ty.isTuple(mod)) {
2487124892 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", .{});
2487324894 }
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);
2487524896 } 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);
2487724898 }
2487824899 },
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),
2488024901 else => unreachable,
2488124902 };
24882
2488324903 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", .{});
2488524905 }
2488624906
24887 try sema.checkPtrOperand(block, ptr_src, field_ptr_ty);
24888 const field_ptr_ty_info = field_ptr_ty.ptrInfo(mod);
24907 const field_ptr = try sema.resolveInst(extra.field_ptr);
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 = .{
24891 .child = parent_ty.structFieldType(field_index, mod).toIntern(),
24912 var actual_parent_ptr_info: InternPool.Key.PtrType = .{
24913 .child = parent_ty.toIntern(),
2489224914 .flags = .{
24893 .address_space = field_ptr_ty_info.flags.address_space,
24894 .is_const = field_ptr_ty_info.flags.is_const,
24915 .alignment = try parent_ptr_ty.ptrAlignmentAdvanced(mod, sema),
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,
2489524920 },
24921 .packed_offset = parent_ptr_info.packed_offset,
2489624922 };
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") {
24899 return sema.fail(block, src, "TODO handle packed structs/unions with @fieldParentPtr", .{});
24900 } else {
24901 ptr_ty_data.flags.alignment = blk: {
24902 if (mod.typeToStruct(parent_ty)) |struct_type| {
24903 break :blk struct_type.fieldAlign(ip, field_index);
24904 } else if (mod.typeToUnion(parent_ty)) |union_obj| {
24905 break :blk union_obj.fieldAlign(ip, field_index);
24906 } else {
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);
24948 actual_parent_ptr_info.packed_offset = .{ .bit_offset = 0, .host_size = 0 };
24949 actual_field_ptr_info.packed_offset = .{ .bit_offset = 0, .host_size = 0 };
24950 },
24951 .@"extern" => {
24952 const field_offset = parent_ty.structFieldOffset(field_index, mod);
24953 actual_parent_ptr_info.flags.alignment = actual_field_ptr_info.flags.alignment.minStrict(if (field_offset > 0)
24954 Alignment.fromLog2Units(@ctz(field_offset))
24955 else
24956 actual_field_ptr_info.flags.alignment);
2491424957
24915 ptr_ty_data.child = parent_ty.toIntern();
24916 const result_ptr = try sema.ptrType(ptr_ty_data);
24958 actual_parent_ptr_info.packed_offset = .{ .bit_offset = 0, .host_size = 0 };
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: {
2491924977 const field = switch (ip.indexToKey(field_ptr_val.toIntern())) {
2492024978 .ptr => |ptr| switch (ptr.addr) {
2492124979 .field => |field| field,
2492224980 else => null,
2492324981 },
2492424982 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
2492724985 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 '{}'", .{
2492924987 field_name.fmt(ip), field_index, field.index, parent_ty.fmt(sema.mod),
2493024988 });
2493124989 }
24932 return Air.internedToRef(field.base);
24933 }
24934
24935 try sema.requireRuntimeBlock(block, src, ptr_src);
24936 try sema.queueFullTypeResolution(result_ptr);
24937 return block.addInst(.{
24938 .tag = .field_parent_ptr,
24939 .data = .{ .ty_pl = .{
24940 .ty = Air.internedToRef(result_ptr.toIntern()),
24941 .payload = try block.sema.addExtra(Air.FieldParentPtr{
24942 .field_ptr = casted_field_ptr,
24943 .field_index = @intCast(field_index),
24944 }),
24945 } },
24946 });
24990 break :result try sema.coerce(block, actual_parent_ptr_ty, Air.internedToRef(field.base), inst_src);
24991 } else result: {
24992 try sema.requireRuntimeBlock(block, inst_src, field_ptr_src);
24993 try sema.queueFullTypeResolution(parent_ty);
24994 break :result try block.addInst(.{
24995 .tag = .field_parent_ptr,
24996 .data = .{ .ty_pl = .{
24997 .ty = Air.internedToRef(actual_parent_ptr_ty.toIntern()),
24998 .payload = try block.sema.addExtra(Air.FieldParentPtr{
24999 .field_ptr = casted_field_ptr,
25000 .field_index = @intCast(field_index),
25001 }),
25002 } },
25003 });
25004 };
25005 return sema.ptrCastFull(block, flags, inst_src, result, inst_src, parent_ptr_ty, "@fieldParentPtr");
2494725006}
2494825007
2494925008fn zirMinMax(
......@@ -27837,7 +27896,7 @@ fn structFieldPtrByIndex(
2783727896 const elem_size_bits = Type.fromInterned(ptr_ty_data.child).bitSize(mod);
2783827897 if (elem_size_bytes * 8 == elem_size_bits) {
2783927898 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().?));
2784127900 assert(new_align != .none);
2784227901 ptr_ty_data.flags.alignment = new_align;
2784327902 ptr_ty_data.packed_offset = .{ .host_size = 0, .bit_offset = 0 };
......@@ -29132,7 +29191,7 @@ fn coerceExtra(
2913229191 .addr = .{ .int = if (dest_info.flags.alignment != .none)
2913329192 (try mod.intValue(
2913429193 Type.usize,
29135 dest_info.flags.alignment.toByteUnitsOptional().?,
29194 dest_info.flags.alignment.toByteUnits().?,
2913629195 )).toIntern()
2913729196 else
2913829197 try mod.intern_pool.getCoercedInts(
......@@ -29800,7 +29859,7 @@ const InMemoryCoercionResult = union(enum) {
2980029859 },
2980129860 .ptr_alignment => |pair| {
2980229861 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,
2980429863 });
2980529864 break;
2980629865 },
......@@ -36066,7 +36125,7 @@ fn resolveUnionLayout(sema: *Sema, ty: Type) CompileError!void {
3606636125 // alignment is greater.
3606736126 var size: u64 = 0;
3606836127 var padding: u32 = 0;
36069 if (tag_align.compare(.gte, max_align)) {
36128 if (tag_align.order(max_align).compare(.gte)) {
3607036129 // {Tag, Payload}
3607136130 size += tag_size;
3607236131 size = max_align.forward(size);
......@@ -36077,7 +36136,10 @@ fn resolveUnionLayout(sema: *Sema, ty: Type) CompileError!void {
3607736136 } else {
3607836137 // {Payload, Tag}
3607936138 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);
3608136143 size += tag_size;
3608236144 const prev_size = size;
3608336145 size = max_align.forward(size);
src/Value.zig+8-8
......@@ -176,7 +176,7 @@ pub fn toBigIntAdvanced(
176176 if (opt_sema) |sema| try sema.resolveTypeLayout(Type.fromInterned(ty));
177177 const x = switch (int.storage) {
178178 else => unreachable,
179 .lazy_align => Type.fromInterned(ty).abiAlignment(mod).toByteUnits(0),
179 .lazy_align => Type.fromInterned(ty).abiAlignment(mod).toByteUnits() orelse 0,
180180 .lazy_size => Type.fromInterned(ty).abiSize(mod),
181181 };
182182 return BigIntMutable.init(&space.limbs, x).toConst();
......@@ -237,9 +237,9 @@ pub fn getUnsignedIntAdvanced(val: Value, mod: *Module, opt_sema: ?*Sema) !?u64
237237 .u64 => |x| x,
238238 .i64 => |x| std.math.cast(u64, x),
239239 .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
241241 else
242 Type.fromInterned(ty).abiAlignment(mod).toByteUnits(0),
242 Type.fromInterned(ty).abiAlignment(mod).toByteUnits() orelse 0,
243243 .lazy_size => |ty| if (opt_sema) |sema|
244244 (try Type.fromInterned(ty).abiSizeAdvanced(mod, .{ .sema = sema })).scalar
245245 else
......@@ -289,7 +289,7 @@ pub fn toSignedInt(val: Value, mod: *Module) i64 {
289289 .big_int => |big_int| big_int.to(i64) catch unreachable,
290290 .i64 => |x| x,
291291 .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),
293293 .lazy_size => |ty| @intCast(Type.fromInterned(ty).abiSize(mod)),
294294 },
295295 else => unreachable,
......@@ -497,7 +497,7 @@ pub fn writeToPackedMemory(
497497 inline .u64, .i64 => |int| std.mem.writeVarPackedInt(buffer, bit_offset, bits, int, endian),
498498 .big_int => |bigint| bigint.writePackedTwosComplement(buffer, bit_offset, bits, endian),
499499 .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;
501501 std.mem.writeVarPackedInt(buffer, bit_offset, bits, num, endian);
502502 },
503503 .lazy_size => |lazy_size| {
......@@ -890,7 +890,7 @@ pub fn toFloat(val: Value, comptime T: type, mod: *Module) T {
890890 }
891891 return @floatFromInt(x);
892892 },
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),
894894 .lazy_size => |ty| @floatFromInt(Type.fromInterned(ty).abiSize(mod)),
895895 },
896896 .float => |float| switch (float.storage) {
......@@ -1529,9 +1529,9 @@ pub fn floatFromIntScalar(val: Value, float_ty: Type, mod: *Module, opt_sema: ?*
15291529 },
15301530 inline .u64, .i64 => |x| floatFromIntInner(x, float_ty, mod),
15311531 .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);
15331533 } 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);
15351535 },
15361536 .lazy_size => |ty| if (opt_sema) |sema| {
15371537 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 {
12961296 // subtract it from the current stack pointer
12971297 try prologue.append(.{ .tag = .i32_sub, .data = .{ .tag = {} } });
12981298 // 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 } });
13001300 // Bitwise-and the value to get the new stack pointer to ensure the pointers are aligned with the abi alignment
13011301 try prologue.append(.{ .tag = .i32_and, .data = .{ .tag = {} } });
13021302 // 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 {
21072107 });
21082108 try func.addMemArg(Mir.Inst.Tag.fromOpcode(opcode), .{
21092109 .offset = operand.offset(),
2110 .alignment = @intCast(scalar_type.abiAlignment(mod).toByteUnitsOptional().?),
2110 .alignment = @intCast(scalar_type.abiAlignment(mod).toByteUnits().?),
21112111 });
21122112 },
21132113 else => try func.emitWValue(operand),
......@@ -2384,7 +2384,7 @@ fn store(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerE
23842384 try func.mir_extra.appendSlice(func.gpa, &[_]u32{
23852385 std.wasm.simdOpcode(.v128_store),
23862386 offset + lhs.offset(),
2387 @intCast(ty.abiAlignment(mod).toByteUnits(0)),
2387 @intCast(ty.abiAlignment(mod).toByteUnits() orelse 0),
23882388 });
23892389 return func.addInst(.{ .tag = .simd_prefix, .data = .{ .payload = extra_index } });
23902390 },
......@@ -2440,7 +2440,7 @@ fn store(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerE
24402440 Mir.Inst.Tag.fromOpcode(opcode),
24412441 .{
24422442 .offset = offset + lhs.offset(),
2443 .alignment = @intCast(ty.abiAlignment(mod).toByteUnitsOptional().?),
2443 .alignment = @intCast(ty.abiAlignment(mod).toByteUnits().?),
24442444 },
24452445 );
24462446}
......@@ -2500,7 +2500,7 @@ fn load(func: *CodeGen, operand: WValue, ty: Type, offset: u32) InnerError!WValu
25002500 try func.mir_extra.appendSlice(func.gpa, &[_]u32{
25012501 std.wasm.simdOpcode(.v128_load),
25022502 offset + operand.offset(),
2503 @intCast(ty.abiAlignment(mod).toByteUnitsOptional().?),
2503 @intCast(ty.abiAlignment(mod).toByteUnits().?),
25042504 });
25052505 try func.addInst(.{ .tag = .simd_prefix, .data = .{ .payload = extra_index } });
25062506 return WValue{ .stack = {} };
......@@ -2518,7 +2518,7 @@ fn load(func: *CodeGen, operand: WValue, ty: Type, offset: u32) InnerError!WValu
25182518 Mir.Inst.Tag.fromOpcode(opcode),
25192519 .{
25202520 .offset = offset + operand.offset(),
2521 .alignment = @intCast(ty.abiAlignment(mod).toByteUnitsOptional().?),
2521 .alignment = @intCast(ty.abiAlignment(mod).toByteUnits().?),
25222522 },
25232523 );
25242524
......@@ -3456,7 +3456,7 @@ fn intStorageAsI32(storage: InternPool.Key.Int.Storage, mod: *Module) i32 {
34563456 .i64 => |x| @as(i32, @intCast(x)),
34573457 .u64 => |x| @as(i32, @bitCast(@as(u32, @intCast(x)))),
34583458 .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)))),
34603460 .lazy_size => |ty| @as(i32, @bitCast(@as(u32, @intCast(Type.fromInterned(ty).abiSize(mod))))),
34613461 };
34623462}
......@@ -4204,7 +4204,7 @@ fn airIsErr(func: *CodeGen, inst: Air.Inst.Index, opcode: wasm.Opcode) InnerErro
42044204 if (pl_ty.hasRuntimeBitsIgnoreComptime(mod)) {
42054205 try func.addMemArg(.i32_load16_u, .{
42064206 .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().?),
42084208 });
42094209 }
42104210
......@@ -5141,7 +5141,7 @@ fn airSplat(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
51415141 try func.mir_extra.appendSlice(func.gpa, &[_]u32{
51425142 opcode,
51435143 operand.offset(),
5144 @intCast(elem_ty.abiAlignment(mod).toByteUnitsOptional().?),
5144 @intCast(elem_ty.abiAlignment(mod).toByteUnits().?),
51455145 });
51465146 try func.addInst(.{ .tag = .simd_prefix, .data = .{ .payload = extra_index } });
51475147 try func.addLabel(.local_set, result.local.value);
......@@ -6552,7 +6552,7 @@ fn lowerTry(
65526552 const err_offset = @as(u32, @intCast(errUnionErrorOffset(pl_ty, mod)));
65536553 try func.addMemArg(.i32_load16_u, .{
65546554 .offset = err_union.offset() + err_offset,
6555 .alignment = @intCast(Type.anyerror.abiAlignment(mod).toByteUnitsOptional().?),
6555 .alignment = @intCast(Type.anyerror.abiAlignment(mod).toByteUnits().?),
65566556 });
65576557 }
65586558 try func.addTag(.i32_eqz);
......@@ -7499,7 +7499,7 @@ fn airCmpxchg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
74997499 else => |size| return func.fail("TODO: implement `@cmpxchg` for types with abi size '{d}'", .{size}),
75007500 }, .{
75017501 .offset = ptr_operand.offset(),
7502 .alignment = @intCast(ty.abiAlignment(mod).toByteUnitsOptional().?),
7502 .alignment = @intCast(ty.abiAlignment(mod).toByteUnits().?),
75037503 });
75047504 try func.addLabel(.local_tee, val_local.local.value);
75057505 _ = try func.cmp(.stack, expected_val, ty, .eq);
......@@ -7561,7 +7561,7 @@ fn airAtomicLoad(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
75617561 try func.emitWValue(ptr);
75627562 try func.addAtomicMemArg(tag, .{
75637563 .offset = ptr.offset(),
7564 .alignment = @intCast(ty.abiAlignment(mod).toByteUnitsOptional().?),
7564 .alignment = @intCast(ty.abiAlignment(mod).toByteUnits().?),
75657565 });
75667566 } else {
75677567 _ = try func.load(ptr, ty, 0);
......@@ -7622,7 +7622,7 @@ fn airAtomicRmw(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
76227622 },
76237623 .{
76247624 .offset = ptr.offset(),
7625 .alignment = @intCast(ty.abiAlignment(mod).toByteUnitsOptional().?),
7625 .alignment = @intCast(ty.abiAlignment(mod).toByteUnits().?),
76267626 },
76277627 );
76287628 const select_res = try func.allocLocal(ty);
......@@ -7682,7 +7682,7 @@ fn airAtomicRmw(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
76827682 };
76837683 try func.addAtomicMemArg(tag, .{
76847684 .offset = ptr.offset(),
7685 .alignment = @intCast(ty.abiAlignment(mod).toByteUnitsOptional().?),
7685 .alignment = @intCast(ty.abiAlignment(mod).toByteUnits().?),
76867686 });
76877687 const result = try WValue.toLocal(.stack, func, ty);
76887688 return func.finishAir(inst, result, &.{ pl_op.operand, extra.operand });
......@@ -7781,7 +7781,7 @@ fn airAtomicStore(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
77817781 try func.lowerToStack(operand);
77827782 try func.addAtomicMemArg(tag, .{
77837783 .offset = ptr.offset(),
7784 .alignment = @intCast(ty.abiAlignment(mod).toByteUnitsOptional().?),
7784 .alignment = @intCast(ty.abiAlignment(mod).toByteUnits().?),
77857785 });
77867786 } else {
77877787 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
79207920 const mod = self.bin_file.comp.module.?;
79217921 const ptr_field_ty = self.typeOfIndex(inst);
79227922 const ptr_container_ty = self.typeOf(operand);
7923 const ptr_container_ty_info = ptr_container_ty.ptrInfo(mod);
79247923 const container_ty = ptr_container_ty.childType(mod);
79257924
7926 const field_offset: i32 = if (mod.typeToPackedStruct(container_ty)) |struct_obj|
7927 if (ptr_field_ty.ptrInfo(mod).packed_offset.host_size == 0)
7928 @divExact(mod.structPackedFieldBitOffset(struct_obj, index) +
7929 ptr_container_ty_info.packed_offset.bit_offset, 8)
7930 else
7931 0
7932 else
7933 @intCast(container_ty.structFieldOffset(index, mod));
7925 const field_off: i32 = switch (container_ty.containerLayout(mod)) {
7926 .auto, .@"extern" => @intCast(container_ty.structFieldOffset(index, mod)),
7927 .@"packed" => @divExact(@as(i32, ptr_container_ty.ptrInfo(mod).packed_offset.bit_offset) +
7928 (if (mod.typeToStruct(container_ty)) |struct_obj| mod.structPackedFieldBitOffset(struct_obj, index) else 0) -
7929 ptr_field_ty.ptrInfo(mod).packed_offset.bit_offset, 8),
7930 };
79347931
79357932 const src_mcv = try self.resolveInst(operand);
79367933 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
79387935 .register, .register_offset => self.reuseOperand(inst, operand, 0, src_mcv),
79397936 else => false,
79407937 }) 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);
79427939}
79437940
79447941fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
......@@ -7958,11 +7955,8 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
79587955
79597956 const src_mcv = try self.resolveInst(operand);
79607957 const field_off: u32 = switch (container_ty.containerLayout(mod)) {
7961 .auto, .@"extern" => @intCast(container_ty.structFieldOffset(index, mod) * 8),
7962 .@"packed" => if (mod.typeToStruct(container_ty)) |struct_type|
7963 mod.structPackedFieldBitOffset(struct_type, index)
7964 else
7965 0,
7958 .auto, .@"extern" => @intCast(container_ty.structFieldOffset(extra.field_index, mod) * 8),
7959 .@"packed" => if (mod.typeToStruct(container_ty)) |struct_obj| mod.structPackedFieldBitOffset(struct_obj, extra.field_index) else 0,
79667960 };
79677961
79687962 switch (src_mcv) {
......@@ -8239,7 +8233,12 @@ fn airFieldParentPtr(self: *Self, inst: Air.Inst.Index) !void {
82398233
82408234 const inst_ty = self.typeOfIndex(inst);
82418235 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
82448243 const src_mcv = try self.resolveInst(extra.field_ptr);
82458244 const dst_mcv = if (src_mcv.isRegisterOffset() and
......@@ -8247,7 +8246,7 @@ fn airFieldParentPtr(self: *Self, inst: Air.Inst.Index) !void {
82478246 src_mcv
82488247 else
82498248 try self.copyToRegisterWithInstTracking(inst, inst_ty, src_mcv);
8250 const result = dst_mcv.offset(-field_offset);
8249 const result = dst_mcv.offset(-field_off);
82518250 return self.finishAir(inst, result, .{ extra.field_ptr, .none, .none });
82528251}
82538252
......@@ -17950,7 +17949,7 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {
1795017949 .Struct => {
1795117950 const frame_index = try self.allocFrameIndex(FrameAlloc.initSpill(result_ty, mod));
1795217951 if (result_ty.containerLayout(mod) == .@"packed") {
17953 const struct_type = mod.typeToStruct(result_ty).?;
17952 const struct_obj = mod.typeToStruct(result_ty).?;
1795417953 try self.genInlineMemset(
1795517954 .{ .lea_frame = .{ .index = frame_index } },
1795617955 .{ .immediate = 0 },
......@@ -17971,7 +17970,7 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {
1797117970 }
1797217971 const elem_abi_size: u32 = @intCast(elem_ty.abiSize(mod));
1797317972 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);
1797517974 const elem_byte_off: i32 = @intCast(elem_off / elem_abi_bits * elem_abi_size);
1797617975 const elem_bit_off = elem_off % elem_abi_bits;
1797717976 const elem_mcv = try self.resolveInst(elem);
......@@ -18959,7 +18958,7 @@ fn resolveCallingConventionValues(
1895918958
1896018959 const param_size: u31 = @intCast(ty.abiSize(mod));
1896118960 const param_align: u31 =
18962 @intCast(@max(ty.abiAlignment(mod).toByteUnitsOptional().?, 8));
18961 @intCast(@max(ty.abiAlignment(mod).toByteUnits().?, 8));
1896318962 result.stack_byte_count =
1896418963 mem.alignForward(u31, result.stack_byte_count, param_align);
1896518964 arg.* = .{ .load_frame = .{
......@@ -19003,7 +19002,7 @@ fn resolveCallingConventionValues(
1900319002 continue;
1900419003 }
1900519004 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().?);
1900719006 result.stack_byte_count =
1900819007 mem.alignForward(u31, result.stack_byte_count, param_align);
1900919008 arg.* = .{ .load_frame = .{
......@@ -19096,7 +19095,7 @@ fn splitType(self: *Self, ty: Type) ![2]Type {
1909619095 .integer => switch (part_i) {
1909719096 0 => Type.u64,
1909819097 1 => part: {
19099 const elem_size = ty.abiAlignment(mod).minStrict(.@"8").toByteUnitsOptional().?;
19098 const elem_size = ty.abiAlignment(mod).minStrict(.@"8").toByteUnits().?;
1910019099 const elem_ty = try mod.intType(.unsigned, @intCast(elem_size * 8));
1910119100 break :part switch (@divExact(ty.abiSize(mod) - 8, elem_size)) {
1910219101 1 => elem_ty,
src/arch/x86_64/Encoding.zig+2-3
......@@ -848,9 +848,8 @@ const mnemonic_to_encodings_map = init: {
848848 const final_storage = data_storage;
849849 var final_map: [mnemonic_count][]const Data = .{&.{}} ** mnemonic_count;
850850 storage_i = 0;
851 for (&final_map, mnemonic_map) |*value, wip_value| {
852 value.ptr = final_storage[storage_i..].ptr;
853 value.len = wip_value.len;
851 for (&final_map, mnemonic_map) |*final_value, value| {
852 final_value.* = final_storage[storage_i..][0..value.len];
854853 storage_i += value.len;
855854 }
856855 break :init final_map;
src/codegen.zig+3-3
......@@ -548,7 +548,7 @@ pub fn generateSymbol(
548548 }
549549
550550 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
553553 const padding = math.cast(
554554 usize,
......@@ -893,12 +893,12 @@ fn genDeclRef(
893893 // TODO this feels clunky. Perhaps we should check for it in `genTypedValue`?
894894 if (ty.castPtrToFn(zcu)) |fn_ty| {
895895 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().? });
897897 }
898898 } else if (ty.zigTypeTag(zcu) == .Pointer) {
899899 const elem_ty = ty.elemType2(zcu);
900900 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().? });
902902 }
903903 }
904904
src/codegen/c.zig+1907-1884
......@@ -5,12 +5,13 @@ const mem = std.mem;
55const log = std.log.scoped(.c);
66
77const link = @import("../link.zig");
8const Module = @import("../Module.zig");
8const Zcu = @import("../Module.zig");
9const Module = @import("../Package/Module.zig");
910const Compilation = @import("../Compilation.zig");
1011const Value = @import("../Value.zig");
1112const Type = @import("../type.zig").Type;
1213const C = link.File.C;
13const Decl = Module.Decl;
14const Decl = Zcu.Decl;
1415const trace = @import("../tracy.zig").trace;
1516const LazySrcLoc = std.zig.LazySrcLoc;
1617const Air = @import("../Air.zig");
......@@ -21,7 +22,7 @@ const Alignment = InternPool.Alignment;
2122const BigIntLimb = std.math.big.Limb;
2223const BigInt = std.math.big.int;
2324
24pub const CType = @import("c/type.zig").CType;
25pub const CType = @import("c/Type.zig");
2526
2627pub const CValue = union(enum) {
2728 none: void,
......@@ -30,7 +31,7 @@ pub const CValue = union(enum) {
3031 /// Address of a local.
3132 local_ref: LocalIndex,
3233 /// A constant instruction, to be rendered inline.
33 constant: InternPool.Index,
34 constant: Value,
3435 /// Index into the parameters
3536 arg: usize,
3637 /// The array field of a parameter
......@@ -61,7 +62,7 @@ pub const LazyFnKey = union(enum) {
6162 never_inline: InternPool.DeclIndex,
6263};
6364pub const LazyFnValue = struct {
64 fn_name: []const u8,
65 fn_name: CType.String,
6566 data: Data,
6667
6768 pub const Data = union {
......@@ -72,18 +73,20 @@ pub const LazyFnValue = struct {
7273};
7374pub const LazyFnMap = std.AutoArrayHashMapUnmanaged(LazyFnKey, LazyFnValue);
7475
75const LoopDepth = u16;
7676const Local = struct {
77 cty_idx: CType.Index,
78 alignas: CType.AlignAs,
77 ctype: CType,
78 flags: packed struct(u32) {
79 alignas: CType.AlignAs,
80 _: u20 = undefined,
81 },
7982
8083 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 };
8285 }
8386};
8487
8588const LocalIndex = u16;
86const LocalType = struct { cty_idx: CType.Index, alignas: CType.AlignAs };
89const LocalType = struct { ctype: CType, alignas: CType.AlignAs };
8790const LocalsList = std.AutoArrayHashMapUnmanaged(LocalIndex, void);
8891const LocalsMap = std.AutoArrayHashMapUnmanaged(LocalType, LocalsList);
8992
......@@ -190,6 +193,7 @@ const reserved_idents = std.ComptimeStringMap(void, .{
190193 .{ "switch", {} },
191194 .{ "thread_local", {} },
192195 .{ "typedef", {} },
196 .{ "typeof", {} },
193197 .{ "uint16_t", {} },
194198 .{ "uint32_t", {} },
195199 .{ "uint64_t", {} },
......@@ -300,30 +304,32 @@ pub const Function = struct {
300304 const gop = try f.value_map.getOrPut(ref);
301305 if (gop.found_existing) return gop.value_ptr.*;
302306
303 const mod = f.object.dg.module;
304 const val = (try f.air.value(ref, mod)).?;
307 const zcu = f.object.dg.zcu;
308 const val = (try f.air.value(ref, zcu)).?;
305309 const ty = f.typeOf(ref);
306310
307 const result: CValue = if (lowersToArray(ty, mod)) result: {
311 const result: CValue = if (lowersToArray(ty, zcu)) result: {
308312 const writer = f.object.codeHeaderWriter();
309 const alignment: Alignment = .none;
310 const decl_c_value = try f.allocLocalValue(ty, alignment);
313 const decl_c_value = try f.allocLocalValue(.{
314 .ctype = try f.ctypeFromType(ty, .complete),
315 .alignas = CType.AlignAs.fromAbiAlignment(ty.abiAlignment(zcu)),
316 });
311317 const gpa = f.object.dg.gpa;
312318 try f.allocs.put(gpa, decl_c_value.new_local, false);
313319 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);
315321 try writer.writeAll(" = ");
316 try f.object.dg.renderValue(writer, ty, val, .StaticInitializer);
322 try f.object.dg.renderValue(writer, val, .StaticInitializer);
317323 try writer.writeAll(";\n ");
318324 break :result decl_c_value;
319 } else .{ .constant = val.toIntern() };
325 } else .{ .constant = val };
320326
321327 gop.value_ptr.* = result;
322328 return result;
323329 }
324330
325331 fn wantSafety(f: *Function) bool {
326 return switch (f.object.dg.module.optimizeMode()) {
332 return switch (f.object.dg.zcu.optimizeMode()) {
327333 .Debug, .ReleaseSafe => true,
328334 .ReleaseFast, .ReleaseSmall => false,
329335 };
......@@ -332,159 +338,174 @@ pub const Function = struct {
332338 /// Skips the reuse logic. This function should be used for any persistent allocation, i.e.
333339 /// those which go into `allocs`. This function does not add the resulting local into `allocs`;
334340 /// that responsibility lies with the caller.
335 fn allocLocalValue(f: *Function, ty: Type, alignment: Alignment) !CValue {
336 const mod = f.object.dg.module;
337 const gpa = f.object.dg.gpa;
338 try f.locals.append(gpa, .{
339 .cty_idx = try f.typeToIndex(ty, .complete),
340 .alignas = CType.AlignAs.init(alignment, ty.abiAlignment(mod)),
341 fn allocLocalValue(f: *Function, local_type: LocalType) !CValue {
342 try f.locals.ensureUnusedCapacity(f.object.dg.gpa, 1);
343 defer f.locals.appendAssumeCapacity(.{
344 .ctype = local_type.ctype,
345 .flags = .{ .alignas = local_type.alignas },
341346 });
342 return .{ .new_local = @intCast(f.locals.items.len - 1) };
347 return .{ .new_local = @intCast(f.locals.items.len) };
343348 }
344349
345350 fn allocLocal(f: *Function, inst: ?Air.Inst.Index, ty: Type) !CValue {
346 const result = try f.allocAlignedLocal(ty, .{}, .none);
347 if (inst) |i| {
348 log.debug("%{d}: allocating t{d}", .{ i, result.new_local });
349 } else {
350 log.debug("allocating t{d}", .{result.new_local});
351 }
352 return result;
351 return f.allocAlignedLocal(inst, .{
352 .ctype = try f.ctypeFromType(ty, .complete),
353 .alignas = CType.AlignAs.fromAbiAlignment(ty.abiAlignment(f.object.dg.zcu)),
354 });
353355 }
354356
355357 /// Only allocates the local; does not print anything. Will attempt to re-use locals, so should
356358 /// not be used for persistent locals (i.e. those in `allocs`).
357 fn allocAlignedLocal(f: *Function, ty: Type, _: CQualifiers, alignment: Alignment) !CValue {
358 const mod = f.object.dg.module;
359 if (f.free_locals_map.getPtr(.{
360 .cty_idx = try f.typeToIndex(ty, .complete),
361 .alignas = CType.AlignAs.init(alignment, ty.abiAlignment(mod)),
362 })) |locals_list| {
363 if (locals_list.popOrNull()) |local_entry| {
364 return .{ .new_local = local_entry.key };
359 fn allocAlignedLocal(f: *Function, inst: ?Air.Inst.Index, local_type: LocalType) !CValue {
360 const result: CValue = result: {
361 if (f.free_locals_map.getPtr(local_type)) |locals_list| {
362 if (locals_list.popOrNull()) |local_entry| {
363 break :result .{ .new_local = local_entry.key };
364 }
365365 }
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});
366372 }
367
368 return try f.allocLocalValue(ty, alignment);
373 return result;
369374 }
370375
371376 fn writeCValue(f: *Function, w: anytype, c_value: CValue, location: ValueRenderLocation) !void {
372377 switch (c_value) {
373 .constant => |val| try f.object.dg.renderValue(
374 w,
375 Type.fromInterned(f.object.dg.module.intern_pool.typeOf(val)),
376 Value.fromInterned(val),
377 location,
378 ),
379 .undef => |ty| try f.object.dg.renderValue(w, ty, Value.undef, location),
378 .none => unreachable,
379 .new_local, .local => |i| try w.print("t{d}", .{i}),
380 .local_ref => |i| {
381 const local = &f.locals.items[i];
382 if (local.flags.alignas.abiOrder().compare(.lt)) {
383 const gpa = f.object.dg.gpa;
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),
380405 else => try f.object.dg.writeCValue(w, c_value),
381406 }
382407 }
383408
384409 fn writeCValueDeref(f: *Function, w: anytype, c_value: CValue) !void {
385410 switch (c_value) {
386 .constant => |val| {
411 .none => unreachable,
412 .new_local, .local, .constant => {
387413 try w.writeAll("(*");
388 try f.object.dg.renderValue(
389 w,
390 Type.fromInterned(f.object.dg.module.intern_pool.typeOf(val)),
391 Value.fromInterned(val),
392 .Other,
393 );
414 try f.writeCValue(w, c_value, .Other);
415 try w.writeByte(')');
416 },
417 .local_ref => |i| try w.print("t{d}", .{i}),
418 .arg => |i| try w.print("(*a{d})", .{i}),
419 .arg_array => |i| {
420 try w.writeAll("(*");
421 try f.writeCValueMember(w, .{ .arg = i }, .{ .identifier = "array" });
394422 try w.writeByte(')');
395423 },
396424 else => try f.object.dg.writeCValueDeref(w, c_value),
397425 }
398426 }
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 {
401434 switch (c_value) {
402 .constant => |val| {
403 try f.object.dg.renderValue(
404 w,
405 Type.fromInterned(f.object.dg.module.intern_pool.typeOf(val)),
406 Value.fromInterned(val),
407 .Other,
408 );
409 try w.writeByte('.');
410 try f.writeCValue(w, member, .Other);
435 .new_local, .local, .local_ref, .constant, .arg, .arg_array => {
436 try f.writeCValue(writer, c_value, .Other);
437 try writer.writeByte('.');
438 try f.writeCValue(writer, member, .Other);
411439 },
412 else => try f.object.dg.writeCValueMember(w, c_value, member),
440 else => return f.object.dg.writeCValueMember(writer, c_value, member),
413441 }
414442 }
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 {
417445 switch (c_value) {
418 .constant => |val| {
419 try w.writeByte('(');
420 try f.object.dg.renderValue(
421 w,
422 Type.fromInterned(f.object.dg.module.intern_pool.typeOf(val)),
423 Value.fromInterned(val),
424 .Other,
425 );
426 try w.writeAll(")->");
427 try f.writeCValue(w, member, .Other);
446 .new_local, .local, .arg, .arg_array => {
447 try f.writeCValue(writer, c_value, .Other);
448 try writer.writeAll("->");
449 },
450 .constant => {
451 try writer.writeByte('(');
452 try f.writeCValue(writer, c_value, .Other);
453 try writer.writeAll(")->");
428454 },
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),
430460 }
461 try f.writeCValue(writer, member, .Other);
431462 }
432463
433464 fn fail(f: *Function, comptime format: []const u8, args: anytype) error{ AnalysisFail, OutOfMemory } {
434465 return f.object.dg.fail(format, args);
435466 }
436467
437 fn indexToCType(f: *Function, idx: CType.Index) CType {
438 return f.object.dg.indexToCType(idx);
468 fn ctypeFromType(f: *Function, ty: Type, kind: CType.Kind) !CType {
469 return f.object.dg.ctypeFromType(ty, kind);
439470 }
440471
441 fn typeToIndex(f: *Function, ty: Type, kind: CType.Kind) !CType.Index {
442 return f.object.dg.typeToIndex(ty, kind);
472 fn byteSize(f: *Function, ctype: CType) u64 {
473 return f.object.dg.byteSize(ctype);
443474 }
444475
445 fn typeToCType(f: *Function, ty: Type, kind: CType.Kind) !CType {
446 return f.object.dg.typeToCType(ty, kind);
476 fn renderType(f: *Function, w: anytype, ctype: Type) !void {
477 return f.object.dg.renderType(w, ctype);
447478 }
448479
449 fn byteSize(f: *Function, cty: CType) u64 {
450 return f.object.dg.byteSize(cty);
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);
480 fn renderCType(f: *Function, w: anytype, ctype: CType) !void {
481 return f.object.dg.renderCType(w, ctype);
459482 }
460483
461484 fn renderIntCast(f: *Function, w: anytype, dest_ty: Type, src: CValue, v: Vectorize, src_ty: Type, location: ValueRenderLocation) !void {
462485 return f.object.dg.renderIntCast(w, dest_ty, .{ .c_value = .{ .f = f, .value = src, .v = v } }, src_ty, location);
463486 }
464487
465 fn fmtIntLiteral(f: *Function, ty: Type, val: Value) !std.fmt.Formatter(formatIntLiteral) {
466 return f.object.dg.fmtIntLiteral(ty, val, .Other);
488 fn fmtIntLiteral(f: *Function, val: Value) !std.fmt.Formatter(formatIntLiteral) {
489 return f.object.dg.fmtIntLiteral(val, .Other);
467490 }
468491
469492 fn getLazyFnName(f: *Function, key: LazyFnKey, data: LazyFnValue.Data) ![]const u8 {
470493 const gpa = f.object.dg.gpa;
494 const zcu = f.object.dg.zcu;
495 const ctype_pool = &f.object.dg.ctype_pool;
496
471497 const gop = try f.lazy_fns.getOrPut(gpa, key);
472498 if (!gop.found_existing) {
473499 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
480501 gop.value_ptr.* = .{
481502 .fn_name = switch (key) {
482503 .tag_name,
483504 .never_tail,
484505 .never_inline,
485 => |owner_decl| try std.fmt.allocPrint(arena, "zig_{s}_{}__{d}", .{
506 => |owner_decl| try ctype_pool.fmt(gpa, "zig_{s}_{}__{d}", .{
486507 @tagName(key),
487 fmtIdent(mod.intern_pool.stringToSlice(mod.declPtr(owner_decl).name)),
508 fmtIdent(zcu.intern_pool.stringToSlice(zcu.declPtr(owner_decl).name)),
488509 @intFromEnum(owner_decl),
489510 }),
490511 },
......@@ -495,7 +516,7 @@ pub const Function = struct {
495516 },
496517 };
497518 }
498 return gop.value_ptr.fn_name;
519 return gop.value_ptr.fn_name.slice(ctype_pool);
499520 }
500521
501522 pub fn deinit(f: *Function) void {
......@@ -506,21 +527,20 @@ pub const Function = struct {
506527 f.blocks.deinit(gpa);
507528 f.value_map.deinit();
508529 f.lazy_fns.deinit(gpa);
509 f.object.dg.ctypes.deinit(gpa);
510530 }
511531
512532 fn typeOf(f: *Function, inst: Air.Inst.Ref) Type {
513 const mod = f.object.dg.module;
514 return f.air.typeOf(inst, &mod.intern_pool);
533 const zcu = f.object.dg.zcu;
534 return f.air.typeOf(inst, &zcu.intern_pool);
515535 }
516536
517537 fn typeOfIndex(f: *Function, inst: Air.Inst.Index) Type {
518 const mod = f.object.dg.module;
519 return f.air.typeOfIndex(inst, &mod.intern_pool);
538 const zcu = f.object.dg.zcu;
539 return f.air.typeOfIndex(inst, &zcu.intern_pool);
520540 }
521541};
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`.
524544/// It is not available when generating .h file.
525545pub const Object = struct {
526546 dg: DeclGen,
......@@ -542,13 +562,15 @@ pub const Object = struct {
542562/// This data is available both when outputting .c code and when outputting an .h file.
543563pub const DeclGen = struct {
544564 gpa: mem.Allocator,
545 module: *Module,
565 zcu: *Zcu,
566 mod: *Module,
546567 pass: Pass,
547568 is_naked_fn: bool,
548569 /// This is a borrowed reference from `link.C`.
549570 fwd_decl: std.ArrayList(u8),
550 error_msg: ?*Module.ErrorMsg,
551 ctypes: CType.Store,
571 error_msg: ?*Zcu.ErrorMsg,
572 ctype_pool: CType.Pool,
573 scratch: std.ArrayListUnmanaged(u32),
552574 /// Keeps track of anonymous decls that need to be rendered before this
553575 /// (named) Decl in the output C code.
554576 anon_decl_deps: std.AutoArrayHashMapUnmanaged(InternPool.Index, C.DeclBlock),
......@@ -566,75 +588,71 @@ pub const DeclGen = struct {
566588
567589 fn fail(dg: *DeclGen, comptime format: []const u8, args: anytype) error{ AnalysisFail, OutOfMemory } {
568590 @setCold(true);
569 const mod = dg.module;
591 const zcu = dg.zcu;
570592 const decl_index = dg.pass.decl;
571 const decl = mod.declPtr(decl_index);
572 const src_loc = decl.srcLoc(mod);
573 dg.error_msg = try Module.ErrorMsg.create(dg.gpa, src_loc, format, args);
593 const decl = zcu.declPtr(decl_index);
594 const src_loc = decl.srcLoc(zcu);
595 dg.error_msg = try Zcu.ErrorMsg.create(dg.gpa, src_loc, format, args);
574596 return error.AnalysisFail;
575597 }
576598
577599 fn renderAnonDeclValue(
578600 dg: *DeclGen,
579601 writer: anytype,
580 ty: Type,
581602 ptr_val: Value,
582603 anon_decl: InternPool.Key.Ptr.Addr.AnonDecl,
583604 location: ValueRenderLocation,
584605 ) error{ OutOfMemory, AnalysisFail }!void {
585 const mod = dg.module;
586 const ip = &mod.intern_pool;
587 const decl_val = anon_decl.val;
588 const decl_ty = Type.fromInterned(ip.typeOf(decl_val));
606 const zcu = dg.zcu;
607 const ip = &zcu.intern_pool;
608 const ctype_pool = &dg.ctype_pool;
609 const decl_val = Value.fromInterned(anon_decl.val);
610 const decl_ty = decl_val.typeOf(zcu);
589611
590612 // 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)) {
592 return dg.writeCValue(writer, .{ .undef = ty });
613 const ptr_ty = ptr_val.typeOf(zcu);
614 if (ptr_ty.isPtrAtRuntime(zcu) and !decl_ty.isFnOrHasRuntimeBits(zcu)) {
615 return dg.writeCValue(writer, .{ .undef = ptr_ty });
593616 }
594617
595618 // Chase function values in order to be able to reference the original function.
596 if (Value.fromInterned(decl_val).getFunction(mod)) |func| {
597 _ = func;
598 _ = ptr_val;
599 _ = 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 }
619 if (decl_val.getFunction(zcu)) |func|
620 return dg.renderDeclValue(writer, ptr_val, func.owner_decl, location);
621 if (decl_val.getExternFunc(zcu)) |extern_func|
622 return dg.renderDeclValue(writer, ptr_val, extern_func.decl, location);
608623
609 assert(Value.fromInterned(decl_val).getVariable(mod) == null);
624 assert(decl_val.getVariable(zcu) == null);
610625
611626 // We shouldn't cast C function pointers as this is UB (when you call
612627 // them). The analysis until now should ensure that the C function
613628 // pointers are compatible. If they are not, then there is a bug
614629 // 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);
616 if (need_typecast) {
630 const elem_ctype = (try dg.ctypeFromType(ptr_ty, .complete)).info(ctype_pool).pointer.elem_ctype;
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) {
617635 try writer.writeAll("((");
618 try dg.renderType(writer, ty);
636 try dg.renderType(writer, ptr_ty);
619637 try writer.writeByte(')');
620638 }
621639 try writer.writeByte('&');
622640 try renderAnonDeclName(writer, decl_val);
623 if (need_typecast) try writer.writeByte(')');
641 if (need_cast) try writer.writeByte(')');
624642
625643 // Indicate that the anon decl should be rendered to the output so that
626644 // our reference above is not undefined.
627645 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);
629647 if (!gop.found_existing) gop.value_ptr.* = .{};
630648
631649 // Only insert an alignment entry if the alignment is greater than ABI
632650 // alignment. If there is already an entry, keep the greater alignment.
633651 const explicit_alignment = ptr_type.flags.alignment;
634652 if (explicit_alignment != .none) {
635 const abi_alignment = Type.fromInterned(ptr_type.child).abiAlignment(mod);
636 if (explicit_alignment.compareStrict(.gt, abi_alignment)) {
637 const aligned_gop = try dg.aligned_anon_decls.getOrPut(dg.gpa, decl_val);
653 const abi_alignment = Type.fromInterned(ptr_type.child).abiAlignment(zcu);
654 if (explicit_alignment.order(abi_alignment).compare(.gt)) {
655 const aligned_gop = try dg.aligned_anon_decls.getOrPut(dg.gpa, anon_decl.val);
638656 aligned_gop.value_ptr.* = if (aligned_gop.found_existing)
639657 aligned_gop.value_ptr.maxStrict(explicit_alignment)
640658 else
......@@ -646,41 +664,46 @@ pub const DeclGen = struct {
646664 fn renderDeclValue(
647665 dg: *DeclGen,
648666 writer: anytype,
649 ty: Type,
650667 val: Value,
651668 decl_index: InternPool.DeclIndex,
652669 location: ValueRenderLocation,
653670 ) error{ OutOfMemory, AnalysisFail }!void {
654 const mod = dg.module;
655 const decl = mod.declPtr(decl_index);
671 const zcu = dg.zcu;
672 const ctype_pool = &dg.ctype_pool;
673 const decl = zcu.declPtr(decl_index);
656674 assert(decl.has_tv);
657675
658676 // 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)) {
660680 return dg.writeCValue(writer, .{ .undef = ty });
661681 }
662682
663683 // 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)
665 return dg.renderDeclValue(writer, ty, val, func.owner_decl, location);
666 if (decl.val.getExternFunc(mod)) |extern_func| if (extern_func.decl != decl_index)
667 return dg.renderDeclValue(writer, ty, val, extern_func.decl, location);
684 if (decl.val.getFunction(zcu)) |func| if (func.owner_decl != decl_index)
685 return dg.renderDeclValue(writer, val, func.owner_decl, location);
686 if (decl.val.getExternFunc(zcu)) |extern_func| if (extern_func.decl != decl_index)
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
671691 // We shouldn't cast C function pointers as this is UB (when you call
672692 // them). The analysis until now should ensure that the C function
673693 // pointers are compatible. If they are not, then there is a bug
674694 // 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);
676 if (need_typecast) {
695 const elem_ctype = (try dg.ctypeFromType(ty, .complete)).info(ctype_pool).pointer.elem_ctype;
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) {
677700 try writer.writeAll("((");
678701 try dg.renderType(writer, ty);
679702 try writer.writeByte(')');
680703 }
681704 try writer.writeByte('&');
682705 try dg.renderDeclName(writer, decl_index, 0);
683 if (need_typecast) try writer.writeByte(')');
706 if (need_cast) try writer.writeByte(')');
684707 }
685708
686709 /// Renders a "parent" pointer by recursing to the root decl/variable
......@@ -691,33 +714,34 @@ pub const DeclGen = struct {
691714 ptr_val: InternPool.Index,
692715 location: ValueRenderLocation,
693716 ) error{ OutOfMemory, AnalysisFail }!void {
694 const mod = dg.module;
695 const ptr_ty = Type.fromInterned(mod.intern_pool.typeOf(ptr_val));
696 const ptr_cty = try dg.typeToIndex(ptr_ty, .complete);
697 const ptr = mod.intern_pool.indexToKey(ptr_val).ptr;
717 const zcu = dg.zcu;
718 const ip = &zcu.intern_pool;
719 const ptr_ty = Type.fromInterned(ip.typeOf(ptr_val));
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;
698723 switch (ptr.addr) {
699 .decl => |d| try dg.renderDeclValue(writer, ptr_ty, Value.fromInterned(ptr_val), d, location),
700 .anon_decl => |anon_decl| try dg.renderAnonDeclValue(writer, ptr_ty, Value.fromInterned(ptr_val), anon_decl, location),
724 .decl => |d| try dg.renderDeclValue(writer, Value.fromInterned(ptr_val), d, location),
725 .anon_decl => |anon_decl| try dg.renderAnonDeclValue(writer, Value.fromInterned(ptr_val), anon_decl, location),
701726 .int => |int| {
702727 try writer.writeByte('(');
703 try dg.renderCType(writer, ptr_cty);
704 try writer.print("){x}", .{try dg.fmtIntLiteral(Type.usize, Value.fromInterned(int), .Other)});
728 try dg.renderCType(writer, ptr_ctype);
729 try writer.print("){x}", .{try dg.fmtIntLiteral(Value.fromInterned(int), .Other)});
705730 },
706731 .eu_payload, .opt_payload => |base| {
707 const ptr_base_ty = Type.fromInterned(mod.intern_pool.typeOf(base));
708 const base_ty = ptr_base_ty.childType(mod);
732 const ptr_base_ty = Type.fromInterned(ip.typeOf(base));
733 const base_ty = ptr_base_ty.childType(zcu);
709734 // Ensure complete type definition is visible before accessing fields.
710 _ = try dg.typeToIndex(base_ty, .complete);
735 _ = try dg.ctypeFromType(base_ty, .complete);
711736 const payload_ty = switch (ptr.addr) {
712 .eu_payload => base_ty.errorUnionPayload(mod),
713 .opt_payload => base_ty.optionalChild(mod),
737 .eu_payload => base_ty.errorUnionPayload(zcu),
738 .opt_payload => base_ty.optionalChild(zcu),
714739 else => unreachable,
715740 };
716 const ptr_payload_ty = try mod.adjustPtrTypeChild(ptr_base_ty, payload_ty);
717 const ptr_payload_cty = try dg.typeToIndex(ptr_payload_ty, .complete);
718 if (ptr_cty != ptr_payload_cty) {
741 const payload_ctype = try dg.ctypeFromType(payload_ty, .forward);
742 if (!ptr_child_ctype.eql(payload_ctype)) {
719743 try writer.writeByte('(');
720 try dg.renderCType(writer, ptr_cty);
744 try dg.renderCType(writer, ptr_ctype);
721745 try writer.writeByte(')');
722746 }
723747 try writer.writeAll("&(");
......@@ -725,70 +749,90 @@ pub const DeclGen = struct {
725749 try writer.writeAll(")->payload");
726750 },
727751 .elem => |elem| {
728 const ptr_base_ty = Type.fromInterned(mod.intern_pool.typeOf(elem.base));
729 const elem_ty = ptr_base_ty.elemType2(mod);
730 const ptr_elem_ty = try mod.adjustPtrTypeChild(ptr_base_ty, elem_ty);
731 const ptr_elem_cty = try dg.typeToIndex(ptr_elem_ty, .complete);
732 if (ptr_cty != ptr_elem_cty) {
752 const ptr_base_ty = Type.fromInterned(ip.typeOf(elem.base));
753 const elem_ty = ptr_base_ty.elemType2(zcu);
754 const elem_ctype = try dg.ctypeFromType(elem_ty, .forward);
755 if (!ptr_child_ctype.eql(elem_ctype)) {
733756 try writer.writeByte('(');
734 try dg.renderCType(writer, ptr_cty);
757 try dg.renderCType(writer, ptr_ctype);
735758 try writer.writeByte(')');
736759 }
737760 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)
739762 try writer.writeByte('*');
740763 try dg.renderParentPtr(writer, elem.base, location);
741764 try writer.print(")[{d}]", .{elem.index});
742765 },
743766 .field => |field| {
744 const ptr_base_ty = Type.fromInterned(mod.intern_pool.typeOf(field.base));
745 const base_ty = ptr_base_ty.childType(mod);
746 // Ensure complete type definition is visible before accessing fields.
747 _ = try dg.typeToIndex(base_ty, .complete);
748 const field_ty = switch (mod.intern_pool.indexToKey(base_ty.toIntern())) {
749 .anon_struct_type, .struct_type, .union_type => base_ty.structFieldType(@as(usize, @intCast(field.index)), mod),
750 .ptr_type => |ptr_type| switch (ptr_type.flags.size) {
751 .One, .Many, .C => unreachable,
752 .Slice => switch (field.index) {
753 Value.slice_ptr_index => base_ty.slicePtrFieldType(mod),
754 Value.slice_len_index => Type.usize,
755 else => unreachable,
756 },
767 const ptr_base_ty = Type.fromInterned(ip.typeOf(field.base));
768 const base_ty = ptr_base_ty.childType(zcu);
769 // Ensure complete type definition is available before accessing fields.
770 _ = try dg.ctypeFromType(base_ty, .complete);
771 switch (fieldLocation(ptr_base_ty, ptr_ty, @as(u32, @intCast(field.index)), zcu)) {
772 .begin => {
773 const ptr_base_ctype = try dg.ctypeFromType(ptr_base_ty, .complete);
774 if (!ptr_ctype.eql(ptr_base_ctype)) {
775 try writer.writeByte('(');
776 try dg.renderCType(writer, ptr_ctype);
777 try writer.writeByte(')');
778 }
779 try dg.renderParentPtr(writer, field.base, location);
757780 },
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),
769781 .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 }
770803 try writer.writeAll("&(");
771804 try dg.renderParentPtr(writer, field.base, location);
772805 try writer.writeAll(")->");
773806 try dg.writeCValue(writer, name);
774807 },
775808 .byte_offset => |byte_offset| {
776 const u8_ptr_ty = try mod.adjustPtrTypeChild(ptr_ty, Type.u8);
777 const byte_offset_val = try mod.intValue(Type.usize, byte_offset);
809 const u8_ptr_ty = try zcu.adjustPtrTypeChild(ptr_ty, Type.u8);
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 }
779817 try writer.writeAll("((");
780 try dg.renderType(writer, u8_ptr_ty);
818 try dg.renderCType(writer, u8_ptr_ctype);
781819 try writer.writeByte(')');
782820 try dg.renderParentPtr(writer, field.base, location);
783821 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),
785823 });
786824 },
787825 .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 }
788832 try writer.writeAll("((");
789833 try dg.renderParentPtr(writer, field.base, location);
790834 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),
792836 });
793837 },
794838 }
......@@ -800,215 +844,21 @@ pub const DeclGen = struct {
800844 fn renderValue(
801845 dg: *DeclGen,
802846 writer: anytype,
803 ty: Type,
804847 val: Value,
805848 location: ValueRenderLocation,
806849 ) error{ OutOfMemory, AnalysisFail }!void {
807 const mod = dg.module;
808 const ip = &mod.intern_pool;
850 const zcu = dg.zcu;
851 const ip = &zcu.intern_pool;
852 const target = &dg.mod.resolved_target.result;
809853
810 const target = mod.getTarget();
811854 const initializer_type: ValueRenderLocation = switch (location) {
812855 .StaticInitializer => .StaticInitializer,
813856 else => .Initializer,
814857 };
815858
816 const safety_on = switch (mod.optimizeMode()) {
817 .Debug, .ReleaseSafe => true,
818 .ReleaseFast, .ReleaseSmall => false,
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)) {
859 const ty = val.typeOf(zcu);
860 if (val.isUndefDeep(zcu)) return dg.renderUndefValue(writer, ty, location);
861 switch (ip.indexToKey(val.toIntern())) {
1012862 // types, not values
1013863 .int_type,
1014864 .ptr_type,
......@@ -1050,26 +900,28 @@ pub const DeclGen = struct {
1050900 .empty_enum_value,
1051901 => unreachable, // non-runtime values
1052902 .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)}),
1054904 .lazy_align, .lazy_size => {
1055905 try writer.writeAll("((");
1056906 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 )});
1058911 },
1059912 },
1060913 .err => |err| try writer.print("zig_error_{}", .{
1061914 fmtIdent(ip.stringToSlice(err.name)),
1062915 }),
1063916 .error_union => |error_union| {
1064 const payload_ty = ty.errorUnionPayload(mod);
1065 const error_ty = ty.errorUnionSet(mod);
1066 const err_int_ty = try mod.errorIntType();
1067 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
917 const payload_ty = ty.errorUnionPayload(zcu);
918 const error_ty = ty.errorUnionSet(zcu);
919 const err_int_ty = try zcu.errorIntType();
920 if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) {
1068921 switch (error_union.val) {
1069922 .err_name => |err_name| return dg.renderValue(
1070923 writer,
1071 error_ty,
1072 Value.fromInterned((try mod.intern(.{ .err = .{
924 Value.fromInterned((try zcu.intern(.{ .err = .{
1073925 .ty = error_ty.toIntern(),
1074926 .name = err_name,
1075927 } }))),
......@@ -1077,8 +929,7 @@ pub const DeclGen = struct {
1077929 ),
1078930 .payload => return dg.renderValue(
1079931 writer,
1080 err_int_ty,
1081 try mod.intValue(err_int_ty, 0),
932 try zcu.intValue(err_int_ty, 0),
1082933 location,
1083934 ),
1084935 }
......@@ -1093,9 +944,8 @@ pub const DeclGen = struct {
1093944 try writer.writeAll("{ .payload = ");
1094945 try dg.renderValue(
1095946 writer,
1096 payload_ty,
1097947 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(),
1099949 .payload => |payload| payload,
1100950 }),
1101951 initializer_type,
......@@ -1104,8 +954,7 @@ pub const DeclGen = struct {
1104954 switch (error_union.val) {
1105955 .err_name => |err_name| try dg.renderValue(
1106956 writer,
1107 error_ty,
1108 Value.fromInterned((try mod.intern(.{ .err = .{
957 Value.fromInterned((try zcu.intern(.{ .err = .{
1109958 .ty = error_ty.toIntern(),
1110959 .name = err_name,
1111960 } }))),
......@@ -1113,24 +962,23 @@ pub const DeclGen = struct {
1113962 ),
1114963 .payload => try dg.renderValue(
1115964 writer,
1116 err_int_ty,
1117 try mod.intValue(err_int_ty, 0),
965 try zcu.intValue(err_int_ty, 0),
1118966 location,
1119967 ),
1120968 }
1121969 try writer.writeAll(" }");
1122970 },
1123 .enum_tag => {
1124 const enum_tag = ip.indexToKey(val.ip_index).enum_tag;
1125 const int_tag_ty = ip.typeOf(enum_tag.int);
1126 try dg.renderValue(writer, Type.fromInterned(int_tag_ty), Value.fromInterned(enum_tag.int), location);
1127 },
971 .enum_tag => |enum_tag| try dg.renderValue(
972 writer,
973 Value.fromInterned(enum_tag.int),
974 location,
975 ),
1128976 .float => {
1129 const bits = ty.floatBits(target);
1130 const f128_val = val.toFloat(f128, mod);
977 const bits = ty.floatBits(target.*);
978 const f128_val = val.toFloat(f128, zcu);
1131979
1132980 // 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
1135983 assert(bits <= 128);
1136984 var repr_val_limbs: [BigInt.calcTwosCompLimbCount(128)]BigIntLimb = undefined;
......@@ -1141,26 +989,24 @@ pub const DeclGen = struct {
1141989 };
1142990
1143991 switch (bits) {
1144 16 => repr_val_big.set(@as(u16, @bitCast(val.toFloat(f16, mod)))),
1145 32 => repr_val_big.set(@as(u32, @bitCast(val.toFloat(f32, mod)))),
1146 64 => repr_val_big.set(@as(u64, @bitCast(val.toFloat(f64, mod)))),
1147 80 => repr_val_big.set(@as(u80, @bitCast(val.toFloat(f80, mod)))),
992 16 => repr_val_big.set(@as(u16, @bitCast(val.toFloat(f16, zcu)))),
993 32 => repr_val_big.set(@as(u32, @bitCast(val.toFloat(f32, zcu)))),
994 64 => repr_val_big.set(@as(u64, @bitCast(val.toFloat(f64, zcu)))),
995 80 => repr_val_big.set(@as(u80, @bitCast(val.toFloat(f80, zcu)))),
1148996 128 => repr_val_big.set(@as(u128, @bitCast(f128_val))),
1149997 else => unreachable,
1150998 }
1151999
1152 const repr_val = try mod.intValue_big(repr_ty, repr_val_big.toConst());
1153
11541000 var empty = true;
11551001 if (std.math.isFinite(f128_val)) {
11561002 try writer.writeAll("zig_make_");
11571003 try dg.renderTypeForBuiltinFnName(writer, ty);
11581004 try writer.writeByte('(');
11591005 switch (bits) {
1160 16 => try writer.print("{x}", .{val.toFloat(f16, mod)}),
1161 32 => try writer.print("{x}", .{val.toFloat(f32, mod)}),
1162 64 => try writer.print("{x}", .{val.toFloat(f64, mod)}),
1163 80 => try writer.print("{x}", .{val.toFloat(f80, mod)}),
1006 16 => try writer.print("{x}", .{val.toFloat(f16, zcu)}),
1007 32 => try writer.print("{x}", .{val.toFloat(f32, zcu)}),
1008 64 => try writer.print("{x}", .{val.toFloat(f64, zcu)}),
1009 80 => try writer.print("{x}", .{val.toFloat(f80, zcu)}),
11641010 128 => try writer.print("{x}", .{f128_val}),
11651011 else => unreachable,
11661012 }
......@@ -1200,17 +1046,20 @@ pub const DeclGen = struct {
12001046 if (std.math.isNan(f128_val)) switch (bits) {
12011047 // We only actually need to pass the significand, but it will get
12021048 // properly masked anyway, so just pass the whole value.
1203 16 => try writer.print("\"0x{x}\"", .{@as(u16, @bitCast(val.toFloat(f16, mod)))}),
1204 32 => try writer.print("\"0x{x}\"", .{@as(u32, @bitCast(val.toFloat(f32, mod)))}),
1205 64 => try writer.print("\"0x{x}\"", .{@as(u64, @bitCast(val.toFloat(f64, mod)))}),
1206 80 => try writer.print("\"0x{x}\"", .{@as(u80, @bitCast(val.toFloat(f80, mod)))}),
1049 16 => try writer.print("\"0x{x}\"", .{@as(u16, @bitCast(val.toFloat(f16, zcu)))}),
1050 32 => try writer.print("\"0x{x}\"", .{@as(u32, @bitCast(val.toFloat(f32, zcu)))}),
1051 64 => try writer.print("\"0x{x}\"", .{@as(u64, @bitCast(val.toFloat(f64, zcu)))}),
1052 80 => try writer.print("\"0x{x}\"", .{@as(u80, @bitCast(val.toFloat(f80, zcu)))}),
12071053 128 => try writer.print("\"0x{x}\"", .{@as(u128, @bitCast(f128_val))}),
12081054 else => unreachable,
12091055 };
12101056 try writer.writeAll(", ");
12111057 empty = false;
12121058 }
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 )});
12141063 if (!empty) try writer.writeByte(')');
12151064 },
12161065 .slice => |slice| {
......@@ -1220,42 +1069,39 @@ pub const DeclGen = struct {
12201069 try writer.writeByte(')');
12211070 }
12221071 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);
12241073 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);
12261075 try writer.writeByte('}');
12271076 },
12281077 .ptr => |ptr| switch (ptr.addr) {
1229 .decl => |d| try dg.renderDeclValue(writer, ty, val, d, location),
1230 .anon_decl => |decl_val| try dg.renderAnonDeclValue(writer, ty, val, decl_val, location),
1078 .decl => |d| try dg.renderDeclValue(writer, val, d, location),
1079 .anon_decl => |decl_val| try dg.renderAnonDeclValue(writer, val, decl_val, location),
12311080 .int => |int| {
12321081 try writer.writeAll("((");
12331082 try dg.renderType(writer, ty);
1234 try writer.print("){x})", .{
1235 try dg.fmtIntLiteral(Type.usize, Value.fromInterned(int), location),
1236 });
1083 try writer.print("){x})", .{try dg.fmtIntLiteral(Value.fromInterned(int), location)});
12371084 },
12381085 .eu_payload,
12391086 .opt_payload,
12401087 .elem,
12411088 .field,
1242 => try dg.renderParentPtr(writer, val.ip_index, location),
1089 => try dg.renderParentPtr(writer, val.toIntern(), location),
12431090 .comptime_field, .comptime_alloc => unreachable,
12441091 },
12451092 .opt => |opt| {
1246 const payload_ty = ty.optionalChild(mod);
1093 const payload_ty = ty.optionalChild(zcu);
12471094
12481095 const is_null_val = Value.makeBool(opt.val == .none);
1249 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod))
1250 return dg.renderValue(writer, Type.bool, is_null_val, location);
1096 if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu))
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(
12531100 writer,
1254 payload_ty,
12551101 switch (opt.val) {
1256 .none => switch (payload_ty.zigTypeTag(mod)) {
1257 .ErrorSet => try mod.intValue(try mod.errorIntType(), 0),
1258 .Pointer => try mod.getCoerced(val, payload_ty),
1102 .none => switch (payload_ty.zigTypeTag(zcu)) {
1103 .ErrorSet => try zcu.intValue(try zcu.errorIntType(), 0),
1104 .Pointer => try zcu.getCoerced(val, payload_ty),
12591105 else => unreachable,
12601106 },
12611107 else => |payload| Value.fromInterned(payload),
......@@ -1270,15 +1116,19 @@ pub const DeclGen = struct {
12701116 }
12711117
12721118 try writer.writeAll("{ .payload = ");
1273 try dg.renderValue(writer, payload_ty, Value.fromInterned(switch (opt.val) {
1274 .none => try mod.intern(.{ .undef = payload_ty.ip_index }),
1275 else => |payload| payload,
1276 }), initializer_type);
1119 switch (opt.val) {
1120 .none => try dg.renderUndefValue(writer, payload_ty, initializer_type),
1121 else => |payload| try dg.renderValue(
1122 writer,
1123 Value.fromInterned(payload),
1124 initializer_type,
1125 ),
1126 }
12771127 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);
12791129 try writer.writeAll(" }");
12801130 },
1281 .aggregate => switch (ip.indexToKey(ty.ip_index)) {
1131 .aggregate => switch (ip.indexToKey(ty.toIntern())) {
12821132 .array_type, .vector_type => {
12831133 if (location == .FunctionArgument) {
12841134 try writer.writeByte('(');
......@@ -1287,21 +1137,21 @@ pub const DeclGen = struct {
12871137 }
12881138 // Fall back to generic implementation.
12891139
1290 const ai = ty.arrayInfo(mod);
1291 if (ai.elem_type.eql(Type.u8, mod)) {
1292 var literal = stringLiteral(writer, ty.arrayLenIncludingSentinel(mod));
1140 const ai = ty.arrayInfo(zcu);
1141 if (ai.elem_type.eql(Type.u8, zcu)) {
1142 var literal = stringLiteral(writer, ty.arrayLenIncludingSentinel(zcu));
12931143 try literal.start();
12941144 var index: usize = 0;
12951145 while (index < ai.len) : (index += 1) {
1296 const elem_val = try val.elemValue(mod, index);
1297 const elem_val_u8: u8 = if (elem_val.isUndef(mod))
1146 const elem_val = try val.elemValue(zcu, index);
1147 const elem_val_u8: u8 = if (elem_val.isUndef(zcu))
12981148 undefPattern(u8)
12991149 else
1300 @intCast(elem_val.toUnsignedInt(mod));
1150 @intCast(elem_val.toUnsignedInt(zcu));
13011151 try literal.writeChar(elem_val_u8);
13021152 }
13031153 if (ai.sentinel) |s| {
1304 const s_u8: u8 = @intCast(s.toUnsignedInt(mod));
1154 const s_u8: u8 = @intCast(s.toUnsignedInt(zcu));
13051155 if (s_u8 != 0) try literal.writeChar(s_u8);
13061156 }
13071157 try literal.end();
......@@ -1310,12 +1160,12 @@ pub const DeclGen = struct {
13101160 var index: usize = 0;
13111161 while (index < ai.len) : (index += 1) {
13121162 if (index != 0) try writer.writeByte(',');
1313 const elem_val = try val.elemValue(mod, index);
1314 try dg.renderValue(writer, ai.elem_type, elem_val, initializer_type);
1163 const elem_val = try val.elemValue(zcu, index);
1164 try dg.renderValue(writer, elem_val, initializer_type);
13151165 }
13161166 if (ai.sentinel) |s| {
13171167 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);
13191169 }
13201170 try writer.writeByte('}');
13211171 }
......@@ -1333,27 +1183,29 @@ pub const DeclGen = struct {
13331183 const comptime_val = tuple.values.get(ip)[field_index];
13341184 if (comptime_val != .none) continue;
13351185 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
13381188 if (!empty) try writer.writeByte(',');
13391189
1340 const field_val = Value.fromInterned(switch (ip.indexToKey(val.ip_index).aggregate.storage) {
1341 .bytes => |bytes| try ip.get(mod.gpa, .{ .int = .{
1342 .ty = field_ty.toIntern(),
1343 .storage = .{ .u64 = bytes[field_index] },
1344 } }),
1345 .elems => |elems| elems[field_index],
1346 .repeated_elem => |elem| elem,
1347 });
1348 try dg.renderValue(writer, field_ty, field_val, initializer_type);
1190 const field_val = Value.fromInterned(
1191 switch (ip.indexToKey(val.toIntern()).aggregate.storage) {
1192 .bytes => |bytes| try ip.get(zcu.gpa, .{ .int = .{
1193 .ty = field_ty.toIntern(),
1194 .storage = .{ .u64 = bytes[field_index] },
1195 } }),
1196 .elems => |elems| elems[field_index],
1197 .repeated_elem => |elem| elem,
1198 },
1199 );
1200 try dg.renderValue(writer, field_val, initializer_type);
13491201
13501202 empty = false;
13511203 }
13521204 try writer.writeByte('}');
13531205 },
13541206 .struct_type => {
1355 const struct_type = ip.loadStructType(ty.toIntern());
1356 switch (struct_type.layout) {
1207 const loaded_struct = ip.loadStructType(ty.toIntern());
1208 switch (loaded_struct.layout) {
13571209 .auto, .@"extern" => {
13581210 if (!location.isInitializer()) {
13591211 try writer.writeByte('(');
......@@ -1362,47 +1214,46 @@ pub const DeclGen = struct {
13621214 }
13631215
13641216 try writer.writeByte('{');
1365 var empty = true;
1366 for (0..struct_type.field_types.len) |field_index| {
1367 const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[field_index]);
1368 if (struct_type.fieldIsComptime(ip, field_index)) continue;
1369 if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
1370
1371 if (!empty) try writer.writeByte(',');
1372 const field_val = switch (ip.indexToKey(val.ip_index).aggregate.storage) {
1373 .bytes => |bytes| try ip.get(mod.gpa, .{ .int = .{
1217 var field_it = loaded_struct.iterateRuntimeOrder(ip);
1218 var need_comma = false;
1219 while (field_it.next()) |field_index| {
1220 const field_ty = Type.fromInterned(loaded_struct.field_types.get(ip)[field_index]);
1221 if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue;
1222
1223 if (need_comma) try writer.writeByte(',');
1224 need_comma = true;
1225 const field_val = switch (ip.indexToKey(val.toIntern()).aggregate.storage) {
1226 .bytes => |bytes| try ip.get(zcu.gpa, .{ .int = .{
13741227 .ty = field_ty.toIntern(),
13751228 .storage = .{ .u64 = bytes[field_index] },
13761229 } }),
13771230 .elems => |elems| elems[field_index],
13781231 .repeated_elem => |elem| elem,
13791232 };
1380 try dg.renderValue(writer, field_ty, Value.fromInterned(field_val), initializer_type);
1381
1382 empty = false;
1233 try dg.renderValue(writer, Value.fromInterned(field_val), initializer_type);
13831234 }
13841235 try writer.writeByte('}');
13851236 },
13861237 .@"packed" => {
1387 const int_info = ty.intInfo(mod);
1238 const int_info = ty.intInfo(zcu);
13881239
13891240 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
13921243 var bit_offset: u64 = 0;
13931244 var eff_num_fields: usize = 0;
13941245
1395 for (0..struct_type.field_types.len) |field_index| {
1396 const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[field_index]);
1397 if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
1246 for (0..loaded_struct.field_types.len) |field_index| {
1247 const field_ty = Type.fromInterned(loaded_struct.field_types.get(ip)[field_index]);
1248 if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue;
13981249 eff_num_fields += 1;
13991250 }
14001251
14011252 if (eff_num_fields == 0) {
14021253 try writer.writeByte('(');
1403 try dg.renderValue(writer, ty, Value.undef, initializer_type);
1254 try dg.renderUndefValue(writer, ty, initializer_type);
14041255 try writer.writeByte(')');
1405 } else if (ty.bitSize(mod) > 64) {
1256 } else if (ty.bitSize(zcu) > 64) {
14061257 // zig_or_u128(zig_or_u128(zig_shl_u128(a, a_off), zig_shl_u128(b, b_off)), zig_shl_u128(c, c_off))
14071258 var num_or = eff_num_fields - 1;
14081259 while (num_or > 0) : (num_or -= 1) {
......@@ -1413,12 +1264,12 @@ pub const DeclGen = struct {
14131264
14141265 var eff_index: usize = 0;
14151266 var needs_closing_paren = false;
1416 for (0..struct_type.field_types.len) |field_index| {
1417 const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[field_index]);
1418 if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
1267 for (0..loaded_struct.field_types.len) |field_index| {
1268 const field_ty = Type.fromInterned(loaded_struct.field_types.get(ip)[field_index]);
1269 if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue;
14191270
1420 const field_val = switch (ip.indexToKey(val.ip_index).aggregate.storage) {
1421 .bytes => |bytes| try ip.get(mod.gpa, .{ .int = .{
1271 const field_val = switch (ip.indexToKey(val.toIntern()).aggregate.storage) {
1272 .bytes => |bytes| try ip.get(zcu.gpa, .{ .int = .{
14221273 .ty = field_ty.toIntern(),
14231274 .storage = .{ .u64 = bytes[field_index] },
14241275 } }),
......@@ -1432,8 +1283,7 @@ pub const DeclGen = struct {
14321283 try writer.writeByte('(');
14331284 try dg.renderIntCast(writer, ty, cast_context, field_ty, .FunctionArgument);
14341285 try writer.writeAll(", ");
1435 const bit_offset_val = try mod.intValue(bit_offset_ty, bit_offset);
1436 try dg.renderValue(writer, bit_offset_ty, bit_offset_val, .FunctionArgument);
1286 try dg.renderValue(writer, try zcu.intValue(bit_offset_ty, bit_offset), .FunctionArgument);
14371287 try writer.writeByte(')');
14381288 } else {
14391289 try dg.renderIntCast(writer, ty, cast_context, field_ty, .FunctionArgument);
......@@ -1442,7 +1292,7 @@ pub const DeclGen = struct {
14421292 if (needs_closing_paren) try writer.writeByte(')');
14431293 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);
14461296 needs_closing_paren = true;
14471297 eff_index += 1;
14481298 }
......@@ -1450,17 +1300,17 @@ pub const DeclGen = struct {
14501300 try writer.writeByte('(');
14511301 // a << a_off | b << b_off | c << c_off
14521302 var empty = true;
1453 for (0..struct_type.field_types.len) |field_index| {
1454 const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[field_index]);
1455 if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
1303 for (0..loaded_struct.field_types.len) |field_index| {
1304 const field_ty = Type.fromInterned(loaded_struct.field_types.get(ip)[field_index]);
1305 if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue;
14561306
14571307 if (!empty) try writer.writeAll(" | ");
14581308 try writer.writeByte('(');
14591309 try dg.renderType(writer, ty);
14601310 try writer.writeByte(')');
14611311
1462 const field_val = switch (ip.indexToKey(val.ip_index).aggregate.storage) {
1463 .bytes => |bytes| try ip.get(mod.gpa, .{ .int = .{
1312 const field_val = switch (ip.indexToKey(val.toIntern()).aggregate.storage) {
1313 .bytes => |bytes| try ip.get(zcu.gpa, .{ .int = .{
14641314 .ty = field_ty.toIntern(),
14651315 .storage = .{ .u64 = bytes[field_index] },
14661316 } }),
......@@ -1469,15 +1319,14 @@ pub const DeclGen = struct {
14691319 };
14701320
14711321 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);
14731323 try writer.writeAll(" << ");
1474 const bit_offset_val = try mod.intValue(bit_offset_ty, bit_offset);
1475 try dg.renderValue(writer, bit_offset_ty, bit_offset_val, .FunctionArgument);
1324 try dg.renderValue(writer, try zcu.intValue(bit_offset_ty, bit_offset), .FunctionArgument);
14761325 } else {
1477 try dg.renderValue(writer, field_ty, Value.fromInterned(field_val), .Other);
1326 try dg.renderValue(writer, Value.fromInterned(field_val), .Other);
14781327 }
14791328
1480 bit_offset += field_ty.bitSize(mod);
1329 bit_offset += field_ty.bitSize(zcu);
14811330 empty = false;
14821331 }
14831332 try writer.writeByte(')');
......@@ -1488,30 +1337,30 @@ pub const DeclGen = struct {
14881337 else => unreachable,
14891338 },
14901339 .un => |un| {
1491 const union_obj = mod.typeToUnion(ty).?;
1340 const loaded_union = ip.loadUnionType(ty.toIntern());
14921341 if (un.tag == .none) {
1493 const backing_ty = try ty.unionBackingType(mod);
1494 switch (union_obj.getLayout(ip)) {
1342 const backing_ty = try ty.unionBackingType(zcu);
1343 switch (loaded_union.getLayout(ip)) {
14951344 .@"packed" => {
14961345 if (!location.isInitializer()) {
14971346 try writer.writeByte('(');
14981347 try dg.renderType(writer, backing_ty);
14991348 try writer.writeByte(')');
15001349 }
1501 try dg.renderValue(writer, backing_ty, Value.fromInterned(un.val), initializer_type);
1350 try dg.renderValue(writer, Value.fromInterned(un.val), initializer_type);
15021351 },
15031352 .@"extern" => {
15041353 if (location == .StaticInitializer) {
15051354 return dg.fail("TODO: C backend: implement extern union backing type rendering in static initializers", .{});
15061355 }
15071356
1508 const ptr_ty = try mod.singleConstPtrType(ty);
1357 const ptr_ty = try zcu.singleConstPtrType(ty);
15091358 try writer.writeAll("*((");
15101359 try dg.renderType(writer, ptr_ty);
15111360 try writer.writeAll(")(");
15121361 try dg.renderType(writer, backing_ty);
15131362 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);
15151364 try writer.writeAll("})");
15161365 },
15171366 else => unreachable,
......@@ -1523,21 +1372,21 @@ pub const DeclGen = struct {
15231372 try writer.writeByte(')');
15241373 }
15251374
1526 const field_index = mod.unionTagFieldIndex(union_obj, Value.fromInterned(un.tag)).?;
1527 const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[field_index]);
1528 const field_name = union_obj.loadTagType(ip).names.get(ip)[field_index];
1529 if (union_obj.getLayout(ip) == .@"packed") {
1530 if (field_ty.hasRuntimeBits(mod)) {
1531 if (field_ty.isPtrAtRuntime(mod)) {
1375 const field_index = zcu.unionTagFieldIndex(loaded_union, Value.fromInterned(un.tag)).?;
1376 const field_ty = Type.fromInterned(loaded_union.field_types.get(ip)[field_index]);
1377 const field_name = loaded_union.loadTagType(ip).names.get(ip)[field_index];
1378 if (loaded_union.getLayout(ip) == .@"packed") {
1379 if (field_ty.hasRuntimeBits(zcu)) {
1380 if (field_ty.isPtrAtRuntime(zcu)) {
15321381 try writer.writeByte('(');
15331382 try dg.renderType(writer, ty);
15341383 try writer.writeByte(')');
1535 } else if (field_ty.zigTypeTag(mod) == .Float) {
1384 } else if (field_ty.zigTypeTag(zcu) == .Float) {
15361385 try writer.writeByte('(');
15371386 try dg.renderType(writer, ty);
15381387 try writer.writeByte(')');
15391388 }
1540 try dg.renderValue(writer, field_ty, Value.fromInterned(un.val), initializer_type);
1389 try dg.renderValue(writer, Value.fromInterned(un.val), initializer_type);
15411390 } else {
15421391 try writer.writeAll("0");
15431392 }
......@@ -1545,33 +1394,291 @@ pub const DeclGen = struct {
15451394 }
15461395
15471396 try writer.writeByte('{');
1548 if (ty.unionTagTypeSafety(mod)) |tag_ty| {
1549 const layout = mod.getUnionLayout(union_obj);
1397 if (ty.unionTagTypeSafety(zcu)) |_| {
1398 const layout = zcu.getUnionLayout(loaded_union);
15501399 if (layout.tag_size != 0) {
15511400 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);
15531402 }
1554 if (ty.unionHasAllZeroBitFieldTypes(mod)) return try writer.writeByte('}');
1403 if (ty.unionHasAllZeroBitFieldTypes(zcu)) return try writer.writeByte('}');
15551404 if (layout.tag_size != 0) try writer.writeByte(',');
15561405 try writer.writeAll(" .payload = {");
15571406 }
1558 if (field_ty.hasRuntimeBits(mod)) {
1407 if (field_ty.hasRuntimeBits(zcu)) {
15591408 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);
15611410 try writer.writeByte(' ');
1562 } else for (0..union_obj.field_types.len) |this_field_index| {
1563 const this_field_ty = Type.fromInterned(union_obj.field_types.get(ip)[this_field_index]);
1564 if (!this_field_ty.hasRuntimeBits(mod)) continue;
1565 try dg.renderValue(writer, this_field_ty, Value.undef, initializer_type);
1411 } else for (0..loaded_union.field_types.len) |this_field_index| {
1412 const this_field_ty = Type.fromInterned(loaded_union.field_types.get(ip)[this_field_index]);
1413 if (!this_field_ty.hasRuntimeBits(zcu)) continue;
1414 try dg.renderUndefValue(writer, this_field_ty, initializer_type);
15661415 break;
15671416 }
1568 if (ty.unionTagTypeSafety(mod)) |_| try writer.writeByte('}');
1417 if (ty.unionTagTypeSafety(zcu)) |_| try writer.writeByte('}');
15691418 try writer.writeByte('}');
15701419 }
15711420 },
15721421 }
15731422 }
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
15751682 fn renderFunctionSignature(
15761683 dg: *DeclGen,
15771684 w: anytype,
......@@ -1582,15 +1689,14 @@ pub const DeclGen = struct {
15821689 ident: []const u8,
15831690 },
15841691 ) !void {
1585 const store = &dg.ctypes.set;
1586 const mod = dg.module;
1587 const ip = &mod.intern_pool;
1692 const zcu = dg.zcu;
1693 const ip = &zcu.intern_pool;
15881694
1589 const fn_decl = mod.declPtr(fn_decl_index);
1590 const fn_ty = fn_decl.typeOf(mod);
1591 const fn_cty_idx = try dg.typeToIndex(fn_ty, kind);
1695 const fn_decl = zcu.declPtr(fn_decl_index);
1696 const fn_ty = fn_decl.typeOf(zcu);
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).?;
15941700 if (fn_info.cc == .Naked) {
15951701 switch (kind) {
15961702 .forward => try w.writeAll("zig_naked_decl "),
......@@ -1598,11 +1704,11 @@ pub const DeclGen = struct {
15981704 else => unreachable,
15991705 }
16001706 }
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)
16021708 try w.writeAll("zig_cold ");
16031709 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
16071713 if (toCallingConvention(fn_info.cc)) |call_conv| {
16081714 try w.print("{}zig_callconv({s})", .{ trailing, call_conv });
......@@ -1611,7 +1717,7 @@ pub const DeclGen = struct {
16111717
16121718 switch (kind) {
16131719 .forward => {},
1614 .complete => if (fn_decl.alignment.toByteUnitsOptional()) |a| {
1720 .complete => if (fn_decl.alignment.toByteUnits()) |a| {
16151721 try w.print("{}zig_align_fn({})", .{ trailing, a });
16161722 trailing = .maybe_space;
16171723 },
......@@ -1628,10 +1734,10 @@ pub const DeclGen = struct {
16281734
16291735 try renderTypeSuffix(
16301736 dg.pass,
1631 store.*,
1632 mod,
1737 &dg.ctype_pool,
1738 zcu,
16331739 w,
1634 fn_cty_idx,
1740 fn_ctype,
16351741 .suffix,
16361742 CQualifiers.init(.{ .@"const" = switch (kind) {
16371743 .forward => false,
......@@ -1642,16 +1748,16 @@ pub const DeclGen = struct {
16421748
16431749 switch (kind) {
16441750 .forward => {
1645 if (fn_decl.alignment.toByteUnitsOptional()) |a| {
1751 if (fn_decl.alignment.toByteUnits()) |a| {
16461752 try w.print(" zig_align_fn({})", .{a});
16471753 }
16481754 switch (name) {
16491755 .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);
16511757 const external_name = ip.stringToSlice(
16521758 if (maybe_exports) |exports|
16531759 exports.items[export_index].opts.name
1654 else if (fn_decl.isExtern(mod))
1760 else if (fn_decl.isExtern(zcu))
16551761 fn_decl.name
16561762 else
16571763 break :mangled,
......@@ -1689,20 +1795,13 @@ pub const DeclGen = struct {
16891795 }
16901796 }
16911797
1692 fn indexToCType(dg: *DeclGen, idx: CType.Index) CType {
1693 return dg.ctypes.indexToCType(idx);
1798 fn ctypeFromType(dg: *DeclGen, ty: Type, kind: CType.Kind) !CType {
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);
16941801 }
16951802
1696 fn typeToIndex(dg: *DeclGen, ty: Type, kind: CType.Kind) !CType.Index {
1697 return dg.ctypes.typeToIndex(dg.gpa, ty, dg.module, kind);
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());
1803 fn byteSize(dg: *DeclGen, ctype: CType) u64 {
1804 return ctype.byteSize(&dg.ctype_pool, dg.mod);
17061805 }
17071806
17081807 /// Renders a type as a single identifier, generating intermediate typedefs
......@@ -1717,14 +1816,12 @@ pub const DeclGen = struct {
17171816 /// | `renderType` | "uint8_t *" | "uint8_t *[10]" |
17181817 ///
17191818 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));
17211820 }
17221821
1723 fn renderCType(dg: *DeclGen, w: anytype, idx: CType.Index) error{ OutOfMemory, AnalysisFail }!void {
1724 const store = &dg.ctypes.set;
1725 const mod = dg.module;
1726 _ = try renderTypePrefix(dg.pass, store.*, mod, w, idx, .suffix, .{});
1727 try renderTypeSuffix(dg.pass, store.*, mod, w, idx, .suffix, .{});
1822 fn renderCType(dg: *DeclGen, w: anytype, ctype: CType) error{ OutOfMemory, AnalysisFail }!void {
1823 _ = try renderTypePrefix(dg.pass, &dg.ctype_pool, dg.zcu, w, ctype, .suffix, .{});
1824 try renderTypeSuffix(dg.pass, &dg.ctype_pool, dg.zcu, w, ctype, .suffix, .{});
17281825 }
17291826
17301827 const IntCastContext = union(enum) {
......@@ -1737,15 +1834,13 @@ pub const DeclGen = struct {
17371834 value: Value,
17381835 },
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 {
17411838 switch (self.*) {
17421839 .c_value => |v| {
17431840 try v.f.writeCValue(w, v.value, location);
17441841 try v.v.elem(v.f, w);
17451842 },
1746 .value => |v| {
1747 try dg.renderValue(w, value_ty, v.value, location);
1748 },
1843 .value => |v| try dg.renderValue(w, v.value, location),
17491844 }
17501845 }
17511846 };
......@@ -1764,18 +1859,18 @@ pub const DeclGen = struct {
17641859 /// | > 64 bit integer | < 64 bit integer | zig_make_<dest_ty>(0, src)
17651860 /// | > 64 bit integer | > 64 bit integer | zig_make_<dest_ty>(zig_hi_<src_ty>(src), zig_lo_<src_ty>(src))
17661861 fn renderIntCast(dg: *DeclGen, w: anytype, dest_ty: Type, context: IntCastContext, src_ty: Type, location: ValueRenderLocation) !void {
1767 const mod = dg.module;
1768 const dest_bits = dest_ty.bitSize(mod);
1769 const dest_int_info = dest_ty.intInfo(mod);
1862 const zcu = dg.zcu;
1863 const dest_bits = dest_ty.bitSize(zcu);
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);
17721867 const src_eff_ty: Type = if (src_is_ptr) switch (dest_int_info.signedness) {
17731868 .unsigned => Type.usize,
17741869 .signed => Type.isize,
17751870 } else src_ty;
17761871
1777 const src_bits = src_eff_ty.bitSize(mod);
1778 const src_int_info = if (src_eff_ty.isAbiInt(mod)) src_eff_ty.intInfo(mod) else null;
1872 const src_bits = src_eff_ty.bitSize(zcu);
1873 const src_int_info = if (src_eff_ty.isAbiInt(zcu)) src_eff_ty.intInfo(zcu) else null;
17791874 if (dest_bits <= 64 and src_bits <= 64) {
17801875 const needs_cast = src_int_info == null or
17811876 (toCIntBits(dest_int_info.bits) != toCIntBits(src_int_info.?.bits) or
......@@ -1791,7 +1886,7 @@ pub const DeclGen = struct {
17911886 try dg.renderType(w, src_eff_ty);
17921887 try w.writeByte(')');
17931888 }
1794 try context.writeValue(dg, w, src_ty, location);
1889 try context.writeValue(dg, w, location);
17951890 } else if (dest_bits <= 64 and src_bits > 64) {
17961891 assert(!src_is_ptr);
17971892 if (dest_bits < 64) {
......@@ -1802,7 +1897,7 @@ pub const DeclGen = struct {
18021897 try w.writeAll("zig_lo_");
18031898 try dg.renderTypeForBuiltinFnName(w, src_eff_ty);
18041899 try w.writeByte('(');
1805 try context.writeValue(dg, w, src_ty, .FunctionArgument);
1900 try context.writeValue(dg, w, .FunctionArgument);
18061901 try w.writeByte(')');
18071902 } else if (dest_bits > 64 and src_bits <= 64) {
18081903 try w.writeAll("zig_make_");
......@@ -1813,7 +1908,7 @@ pub const DeclGen = struct {
18131908 try dg.renderType(w, src_eff_ty);
18141909 try w.writeByte(')');
18151910 }
1816 try context.writeValue(dg, w, src_ty, .FunctionArgument);
1911 try context.writeValue(dg, w, .FunctionArgument);
18171912 try w.writeByte(')');
18181913 } else {
18191914 assert(!src_is_ptr);
......@@ -1822,11 +1917,11 @@ pub const DeclGen = struct {
18221917 try w.writeAll("(zig_hi_");
18231918 try dg.renderTypeForBuiltinFnName(w, src_eff_ty);
18241919 try w.writeByte('(');
1825 try context.writeValue(dg, w, src_ty, .FunctionArgument);
1920 try context.writeValue(dg, w, .FunctionArgument);
18261921 try w.writeAll("), zig_lo_");
18271922 try dg.renderTypeForBuiltinFnName(w, src_eff_ty);
18281923 try w.writeByte('(');
1829 try context.writeValue(dg, w, src_ty, .FunctionArgument);
1924 try context.writeValue(dg, w, .FunctionArgument);
18301925 try w.writeAll("))");
18311926 }
18321927 }
......@@ -1848,61 +1943,73 @@ pub const DeclGen = struct {
18481943 alignment: Alignment,
18491944 kind: CType.Kind,
18501945 ) error{ OutOfMemory, AnalysisFail }!void {
1851 const mod = dg.module;
1852 const alignas = CType.AlignAs.init(alignment, ty.abiAlignment(mod));
1853 try dg.renderCTypeAndName(w, try dg.typeToIndex(ty, kind), name, qualifiers, alignas);
1946 try dg.renderCTypeAndName(
1947 w,
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 );
18541956 }
18551957
18561958 fn renderCTypeAndName(
18571959 dg: *DeclGen,
18581960 w: anytype,
1859 cty_idx: CType.Index,
1961 ctype: CType,
18601962 name: CValue,
18611963 qualifiers: CQualifiers,
18621964 alignas: CType.AlignAs,
18631965 ) error{ OutOfMemory, AnalysisFail }!void {
1864 const store = &dg.ctypes.set;
1865 const mod = dg.module;
1866
18671966 switch (alignas.abiOrder()) {
18681967 .lt => try w.print("zig_under_align({}) ", .{alignas.toByteUnits()}),
18691968 .eq => {},
18701969 .gt => try w.print("zig_align({}) ", .{alignas.toByteUnits()}),
18711970 }
18721971
1873 const trailing = try renderTypePrefix(dg.pass, store.*, mod, w, cty_idx, .suffix, qualifiers);
1874 try w.print("{}", .{trailing});
1875 try dg.writeCValue(w, name);
1876 try renderTypeSuffix(dg.pass, store.*, mod, w, cty_idx, .suffix, .{});
1972 try w.print("{}", .{
1973 try renderTypePrefix(dg.pass, &dg.ctype_pool, dg.zcu, w, ctype, .suffix, qualifiers),
1974 });
1975 try dg.writeName(w, name);
1976 try renderTypeSuffix(dg.pass, &dg.ctype_pool, dg.zcu, w, ctype, .suffix, .{});
18771977 }
18781978
18791979 fn declIsGlobal(dg: *DeclGen, val: Value) bool {
1880 const mod = dg.module;
1881 return switch (mod.intern_pool.indexToKey(val.ip_index)) {
1882 .variable => |variable| mod.decl_exports.contains(variable.decl),
1980 const zcu = dg.zcu;
1981 return switch (zcu.intern_pool.indexToKey(val.toIntern())) {
1982 .variable => |variable| zcu.decl_exports.contains(variable.decl),
18831983 .extern_func => true,
1884 .func => |func| mod.decl_exports.contains(func.owner_decl),
1984 .func => |func| zcu.decl_exports.contains(func.owner_decl),
18851985 else => unreachable,
18861986 };
18871987 }
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
18891999 fn writeCValue(dg: *DeclGen, w: anytype, c_value: CValue) !void {
18902000 switch (c_value) {
1891 .none => unreachable,
1892 .local, .new_local => |i| return w.print("t{d}", .{i}),
1893 .local_ref => |i| return w.print("&t{d}", .{i}),
1894 .constant => |val| return renderAnonDeclName(w, val),
1895 .arg => |i| return w.print("a{d}", .{i}),
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),
2001 .none, .new_local, .local, .local_ref => unreachable,
2002 .constant => |val| try renderAnonDeclName(w, val),
2003 .arg, .arg_array => unreachable,
2004 .field => |i| try w.print("f{d}", .{i}),
2005 .decl => |decl| try dg.renderDeclName(w, decl, 0),
18992006 .decl_ref => |decl| {
19002007 try w.writeByte('&');
1901 return dg.renderDeclName(w, decl, 0);
2008 try dg.renderDeclName(w, decl, 0);
19022009 },
1903 .undef => |ty| return dg.renderValue(w, ty, Value.undef, .Other),
1904 .identifier => |ident| return w.print("{ }", .{fmtIdent(ident)}),
1905 .payload_identifier => |ident| return w.print("{ }.{ }", .{
2010 .undef => |ty| try dg.renderUndefValue(w, ty, .Other),
2011 .identifier => |ident| try w.print("{ }", .{fmtIdent(ident)}),
2012 .payload_identifier => |ident| try w.print("{ }.{ }", .{
19062013 fmtIdent("payload"),
19072014 fmtIdent(ident),
19082015 }),
......@@ -1911,26 +2018,17 @@ pub const DeclGen = struct {
19112018
19122019 fn writeCValueDeref(dg: *DeclGen, w: anytype, c_value: CValue) !void {
19132020 switch (c_value) {
1914 .none => unreachable,
1915 .local, .new_local => |i| return w.print("(*t{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}),
2021 .none, .new_local, .local, .local_ref, .constant, .arg, .arg_array => unreachable,
2022 .field => |i| try w.print("f{d}", .{i}),
19252023 .decl => |decl| {
19262024 try w.writeAll("(*");
19272025 try dg.renderDeclName(w, decl, 0);
1928 return w.writeByte(')');
2026 try w.writeByte(')');
19292027 },
1930 .decl_ref => |decl| return dg.renderDeclName(w, decl, 0),
2028 .decl_ref => |decl| try dg.renderDeclName(w, decl, 0),
19312029 .undef => unreachable,
1932 .identifier => |ident| return w.print("(*{ })", .{fmtIdent(ident)}),
1933 .payload_identifier => |ident| return w.print("(*{ }.{ })", .{
2030 .identifier => |ident| try w.print("(*{ })", .{fmtIdent(ident)}),
2031 .payload_identifier => |ident| try w.print("(*{ }.{ })", .{
19342032 fmtIdent("payload"),
19352033 fmtIdent(ident),
19362034 }),
......@@ -1950,12 +2048,12 @@ pub const DeclGen = struct {
19502048
19512049 fn writeCValueDerefMember(dg: *DeclGen, writer: anytype, c_value: CValue, member: CValue) !void {
19522050 switch (c_value) {
1953 .none, .constant, .field, .undef => unreachable,
1954 .new_local, .local, .arg, .arg_array, .decl, .identifier, .payload_identifier => {
2051 .none, .new_local, .local, .local_ref, .constant, .field, .undef, .arg, .arg_array => unreachable,
2052 .decl, .identifier, .payload_identifier => {
19552053 try dg.writeCValue(writer, c_value);
19562054 try writer.writeAll("->");
19572055 },
1958 .local_ref, .decl_ref => {
2056 .decl_ref => {
19592057 try dg.writeCValueDeref(writer, c_value);
19602058 try writer.writeByte('.');
19612059 },
......@@ -1969,11 +2067,12 @@ pub const DeclGen = struct {
19692067 variable: InternPool.Key.Variable,
19702068 fwd_kind: enum { tentative, final },
19712069 ) !void {
1972 const decl = dg.module.declPtr(decl_index);
2070 const zcu = dg.zcu;
2071 const decl = zcu.declPtr(decl_index);
19732072 const fwd = dg.fwdDeclWriter();
19742073 const is_global = variable.is_extern or dg.declIsGlobal(decl.val);
19752074 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);
19772076 const export_weak_linkage = if (maybe_exports) |exports|
19782077 exports.items[0].opts.linkage == .weak
19792078 else
......@@ -1982,14 +2081,14 @@ pub const DeclGen = struct {
19822081 if (variable.is_threadlocal) try fwd.writeAll("zig_threadlocal ");
19832082 try dg.renderTypeAndName(
19842083 fwd,
1985 decl.typeOf(dg.module),
2084 decl.typeOf(zcu),
19862085 .{ .decl = decl_index },
19872086 CQualifiers.init(.{ .@"const" = variable.is_const }),
19882087 decl.alignment,
19892088 .complete,
19902089 );
19912090 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|
19932092 exports.items[0].opts.name
19942093 else if (variable.is_extern)
19952094 decl.name
......@@ -2007,23 +2106,23 @@ pub const DeclGen = struct {
20072106 }
20082107
20092108 fn renderDeclName(dg: *DeclGen, writer: anytype, decl_index: InternPool.DeclIndex, export_index: u32) !void {
2010 const mod = dg.module;
2011 const decl = mod.declPtr(decl_index);
2109 const zcu = dg.zcu;
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| {
20142113 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)),
20162115 });
2017 } else if (decl.getExternDecl(mod).unwrap()) |extern_decl_index| {
2116 } else if (decl.getExternDecl(zcu).unwrap()) |extern_decl_index| {
20182117 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)),
20202119 });
20212120 } else {
20222121 // MSVC has a limit of 4095 character token length limit, and fmtIdent can (worst case),
20232122 // expand to 3x the length of its input, but let's cut it off at a much shorter limit.
20242123 var name: [100]u8 = undefined;
20252124 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) {
20272126 error.NoSpaceLeft => {},
20282127 };
20292128 try writer.print("{}__{d}", .{
......@@ -2033,77 +2132,71 @@ pub const DeclGen = struct {
20332132 }
20342133 }
20352134
2036 fn renderAnonDeclName(writer: anytype, anon_decl_val: InternPool.Index) !void {
2037 return writer.print("__anon_{d}", .{@intFromEnum(anon_decl_val)});
2135 fn renderAnonDeclName(writer: anytype, anon_decl_val: Value) !void {
2136 try writer.print("__anon_{d}", .{@intFromEnum(anon_decl_val.toIntern())});
20382137 }
20392138
20402139 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));
20422141 }
20432142
2044 fn renderCTypeForBuiltinFnName(dg: *DeclGen, writer: anytype, cty: CType) !void {
2045 switch (cty.tag()) {
2046 else => try writer.print("{c}{d}", .{
2047 if (cty.isBool())
2143 fn renderCTypeForBuiltinFnName(dg: *DeclGen, writer: anytype, ctype: CType) !void {
2144 switch (ctype.info(&dg.ctype_pool)) {
2145 else => |ctype_info| try writer.print("{c}{d}", .{
2146 if (ctype.isBool())
20482147 signAbbrev(.unsigned)
2049 else if (cty.isInteger())
2050 signAbbrev(cty.signedness(dg.module.getTarget()))
2051 else if (cty.isFloat())
2148 else if (ctype.isInteger())
2149 signAbbrev(ctype.signedness(dg.mod))
2150 else if (ctype.isFloat())
20522151 @as(u8, 'f')
2053 else if (cty.isPointer())
2152 else if (ctype_info == .pointer)
20542153 @as(u8, 'p')
20552154 else
2056 return dg.fail("TODO: CBE: implement renderTypeForBuiltinFnName for type {}", .{
2057 cty.tag(),
2058 }),
2059 if (cty.isFloat()) cty.floatActiveBits(dg.module.getTarget()) else dg.byteSize(cty) * 8,
2155 return dg.fail("TODO: CBE: implement renderTypeForBuiltinFnName for {s} type", .{@tagName(ctype_info)}),
2156 if (ctype.isFloat()) ctype.floatActiveBits(dg.mod) else dg.byteSize(ctype) * 8,
20602157 }),
20612158 .array => try writer.writeAll("big"),
20622159 }
20632160 }
20642161
20652162 fn renderBuiltinInfo(dg: *DeclGen, writer: anytype, ty: Type, info: BuiltinInfo) !void {
2066 const cty = try dg.typeToCType(ty, .complete);
2067 const is_big = cty.tag() == .array;
2068
2163 const ctype = try dg.ctypeFromType(ty, .complete);
2164 const is_big = ctype.info(&dg.ctype_pool) == .array;
20692165 switch (info) {
20702166 .none => if (!is_big) return,
20712167 .bits => {},
20722168 }
20732169
2074 const mod = dg.module;
2075 const int_info = if (ty.isAbiInt(mod)) ty.intInfo(mod) else std.builtin.Type.Int{
2170 const zcu = dg.zcu;
2171 const int_info = if (ty.isAbiInt(zcu)) ty.intInfo(zcu) else std.builtin.Type.Int{
20762172 .signedness = .unsigned,
2077 .bits = @as(u16, @intCast(ty.bitSize(mod))),
2173 .bits = @as(u16, @intCast(ty.bitSize(zcu))),
20782174 };
20792175
20802176 if (is_big) try writer.print(", {}", .{int_info.signedness == .signed});
2081
2082 const bits_ty = if (is_big) Type.u16 else Type.u8;
20832177 try writer.print(", {}", .{try dg.fmtIntLiteral(
2084 bits_ty,
2085 try mod.intValue(bits_ty, int_info.bits),
2178 try zcu.intValue(if (is_big) Type.u16 else Type.u8, int_info.bits),
20862179 .FunctionArgument,
20872180 )});
20882181 }
20892182
20902183 fn fmtIntLiteral(
20912184 dg: *DeclGen,
2092 ty: Type,
20932185 val: Value,
20942186 loc: ValueRenderLocation,
20952187 ) !std.fmt.Formatter(formatIntLiteral) {
2096 const mod = dg.module;
2188 const zcu = dg.zcu;
20972189 const kind: CType.Kind = switch (loc) {
20982190 .FunctionArgument => .parameter,
20992191 .Initializer, .Other => .complete,
21002192 .StaticInitializer => .global,
21012193 };
2194 const ty = val.typeOf(zcu);
21022195 return std.fmt.Formatter(formatIntLiteral){ .data = .{
21032196 .dg = dg,
2104 .int_info = ty.intInfo(mod),
2197 .int_info = ty.intInfo(zcu),
21052198 .kind = kind,
2106 .cty = try dg.typeToCType(ty, kind),
2199 .ctype = try dg.ctypeFromType(ty, kind),
21072200 .val = val,
21082201 } };
21092202 }
......@@ -2132,122 +2225,74 @@ const RenderCTypeTrailing = enum {
21322225 }
21332226 }
21342227};
2135fn renderTypeName(
2136 mod: *Module,
2228fn renderAlignedTypeName(w: anytype, ctype: CType) !void {
2229 try w.print("anon__aligned_{d}", .{@intFromEnum(ctype.index)});
2230}
2231fn renderFwdDeclTypeName(
2232 zcu: *Zcu,
21372233 w: anytype,
2138 idx: CType.Index,
2139 cty: CType,
2234 ctype: CType,
2235 fwd_decl: CType.Info.FwdDecl,
21402236 attributes: []const u8,
21412237) !void {
2142 switch (cty.tag()) {
2143 else => unreachable,
2144
2145 .fwd_anon_struct,
2146 .fwd_anon_union,
2147 => |tag| try w.print("{s} {s}anon__lazy_{d}", .{
2148 @tagName(tag)["fwd_anon_".len..],
2149 attributes,
2150 idx,
2238 try w.print("{s} {s}", .{ @tagName(fwd_decl.tag), attributes });
2239 switch (fwd_decl.name) {
2240 .anon => try w.print("anon__lazy_{d}", .{@intFromEnum(ctype.index)}),
2241 .owner_decl => |owner_decl| try w.print("{}__{d}", .{
2242 fmtIdent(zcu.intern_pool.stringToSlice(zcu.declPtr(owner_decl).name)),
2243 @intFromEnum(owner_decl),
21512244 }),
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 },
21642245 }
21652246}
21662247fn renderTypePrefix(
21672248 pass: DeclGen.Pass,
2168 store: CType.Store.Set,
2169 mod: *Module,
2249 ctype_pool: *const CType.Pool,
2250 zcu: *Zcu,
21702251 w: anytype,
2171 idx: CType.Index,
2252 ctype: CType,
21722253 parent_fix: CTypeFix,
21732254 qualifiers: CQualifiers,
21742255) @TypeOf(w).Error!RenderCTypeTrailing {
21752256 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);
2178 switch (cty.tag()) {
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(
2260 .pointer => |pointer_info| {
2261 try w.print("{}*", .{try renderTypePrefix(
22252262 pass,
2226 store,
2227 mod,
2263 ctype_pool,
2264 zcu,
22282265 w,
2229 child_idx,
2266 pointer_info.elem_ctype,
22302267 .prefix,
2231 CQualifiers.init(.{ .@"const" = switch (tag) {
2232 .pointer, .pointer_volatile => false,
2233 .pointer_const, .pointer_const_volatile => true,
2234 else => unreachable,
2235 }, .@"volatile" = switch (tag) {
2236 .pointer, .pointer_const => false,
2237 .pointer_volatile, .pointer_const_volatile => true,
2238 else => unreachable,
2239 } }),
2240 );
2241 try w.print("{}*", .{child_trailing});
2268 CQualifiers.init(.{
2269 .@"const" = pointer_info.@"const",
2270 .@"volatile" = pointer_info.@"volatile",
2271 }),
2272 )});
22422273 trailing = .no_space;
22432274 },
22442275
2245 .array,
2246 .vector,
2247 => {
2248 const child_idx = cty.cast(CType.Payload.Sequence).?.data.elem_type;
2249 const child_trailing =
2250 try renderTypePrefix(pass, store, mod, w, child_idx, .suffix, qualifiers);
2276 .aligned => switch (pass) {
2277 .decl => |decl_index| try w.print("decl__{d}_{d}", .{
2278 @intFromEnum(decl_index), @intFromEnum(ctype.index),
2279 }),
2280 .anon => |anon_decl| try w.print("anon__{d}_{d}", .{
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 );
22512296 switch (parent_fix) {
22522297 .prefix => {
22532298 try w.print("{}(", .{child_trailing});
......@@ -2257,56 +2302,46 @@ fn renderTypePrefix(
22572302 }
22582303 },
22592304
2260 .fwd_anon_struct,
2261 .fwd_anon_union,
2262 => switch (pass) {
2263 .decl => |decl_index| try w.print("decl__{d}_{d}", .{ @intFromEnum(decl_index), idx }),
2264 .anon => |anon_decl| try w.print("anon__{d}_{d}", .{ @intFromEnum(anon_decl), idx }),
2265 .flush => try renderTypeName(mod, w, idx, cty, ""),
2305 .fwd_decl => |fwd_decl_info| switch (fwd_decl_info.name) {
2306 .anon => switch (pass) {
2307 .decl => |decl_index| try w.print("decl__{d}_{d}", .{
2308 @intFromEnum(decl_index), @intFromEnum(ctype.index),
2309 }),
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, ""),
22662316 },
22672317
2268 .fwd_struct,
2269 .fwd_union,
2270 => try renderTypeName(mod, w, idx, cty, ""),
2271
2272 .unnamed_struct,
2273 .unnamed_union,
2274 .packed_unnamed_struct,
2275 .packed_unnamed_union,
2276 => |tag| {
2277 try w.print("{s} {s}", .{
2278 @tagName(tag)["unnamed_".len..],
2279 if (cty.isPacked()) "zig_packed(" else "",
2280 });
2281 try renderAggregateFields(mod, w, store, cty, 1);
2282 if (cty.isPacked()) try w.writeByte(')');
2318 .aggregate => |aggregate_info| switch (aggregate_info.name) {
2319 .anon => {
2320 try w.print("{s} {s}", .{
2321 @tagName(aggregate_info.tag),
2322 if (aggregate_info.@"packed") "zig_packed(" else "",
2323 });
2324 try renderFields(zcu, w, ctype_pool, aggregate_info, 1);
2325 if (aggregate_info.@"packed") try w.writeByte(')');
2326 },
2327 .fwd_decl => |fwd_decl| return renderTypePrefix(
2328 pass,
2329 ctype_pool,
2330 zcu,
2331 w,
2332 fwd_decl,
2333 parent_fix,
2334 qualifiers,
2335 ),
22832336 },
22842337
2285 .anon_struct,
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 => {
2338 .function => |function_info| {
23042339 const child_trailing = try renderTypePrefix(
23052340 pass,
2306 store,
2307 mod,
2341 ctype_pool,
2342 zcu,
23082343 w,
2309 cty.cast(CType.Payload.Function).?.data.return_type,
2344 function_info.return_ctype,
23102345 .suffix,
23112346 .{},
23122347 );
......@@ -2319,170 +2354,107 @@ fn renderTypePrefix(
23192354 }
23202355 },
23212356 }
2322
23232357 var qualifier_it = qualifiers.iterator();
23242358 while (qualifier_it.next()) |qualifier| {
23252359 try w.print("{}{s}", .{ trailing, @tagName(qualifier) });
23262360 trailing = .maybe_space;
23272361 }
2328
23292362 return trailing;
23302363}
23312364fn renderTypeSuffix(
23322365 pass: DeclGen.Pass,
2333 store: CType.Store.Set,
2334 mod: *Module,
2366 ctype_pool: *const CType.Pool,
2367 zcu: *Zcu,
23352368 w: anytype,
2336 idx: CType.Index,
2369 ctype: CType,
23372370 parent_fix: CTypeFix,
23382371 qualifiers: CQualifiers,
23392372) @TypeOf(w).Error!void {
2340 const cty = store.indexToCType(idx);
2341 switch (cty.tag()) {
2342 .void,
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(
2373 switch (ctype.info(ctype_pool)) {
2374 .basic, .aligned, .fwd_decl, .aggregate => {},
2375 .pointer => |pointer_info| try renderTypeSuffix(
23862376 pass,
2387 store,
2388 mod,
2377 ctype_pool,
2378 zcu,
23892379 w,
2390 cty.cast(CType.Payload.Child).?.data,
2380 pointer_info.elem_ctype,
23912381 .prefix,
23922382 .{},
23932383 ),
2394
2395 .array,
2396 .vector,
2397 => {
2384 .array, .vector => |sequence_info| {
23982385 switch (parent_fix) {
23992386 .prefix => try w.writeByte(')'),
24002387 .suffix => {},
24012388 }
24022389
2403 try w.print("[{}]", .{cty.cast(CType.Payload.Sequence).?.data.len});
2404 try renderTypeSuffix(
2405 pass,
2406 store,
2407 mod,
2408 w,
2409 cty.cast(CType.Payload.Sequence).?.data.elem_type,
2410 .suffix,
2411 .{},
2412 );
2390 try w.print("[{}]", .{sequence_info.len});
2391 try renderTypeSuffix(pass, ctype_pool, zcu, w, sequence_info.elem_ctype, .suffix, .{});
24132392 },
2414
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| {
2393 .function => |function_info| {
24342394 switch (parent_fix) {
24352395 .prefix => try w.writeByte(')'),
24362396 .suffix => {},
24372397 }
24382398
2439 const data = cty.cast(CType.Payload.Function).?.data;
2440
24412399 try w.writeByte('(');
24422400 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);
24442403 if (need_comma) try w.writeAll(", ");
24452404 need_comma = true;
24462405 const trailing =
2447 try renderTypePrefix(pass, store, mod, w, param_type, .suffix, qualifiers);
2448 if (qualifiers.contains(.@"const")) try w.print("{}a{d}", .{ trailing, param_i });
2449 try renderTypeSuffix(pass, store, mod, w, param_type, .suffix, .{});
2406 try renderTypePrefix(pass, ctype_pool, zcu, w, param_type, .suffix, qualifiers);
2407 if (qualifiers.contains(.@"const")) try w.print("{}a{d}", .{ trailing, param_index });
2408 try renderTypeSuffix(pass, ctype_pool, zcu, w, param_type, .suffix, .{});
24502409 }
2451 switch (tag) {
2452 .function => {},
2453 .varargs_function => {
2454 if (need_comma) try w.writeAll(", ");
2455 need_comma = true;
2456 try w.writeAll("...");
2457 },
2458 else => unreachable,
2410 if (function_info.varargs) {
2411 if (need_comma) try w.writeAll(", ");
2412 need_comma = true;
2413 try w.writeAll("...");
24592414 }
24602415 if (!need_comma) try w.writeAll("void");
24612416 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, .{});
24642419 },
24652420 }
24662421}
2467fn renderAggregateFields(
2468 mod: *Module,
2422fn renderFields(
2423 zcu: *Zcu,
24692424 writer: anytype,
2470 store: CType.Store.Set,
2471 cty: CType,
2425 ctype_pool: *const CType.Pool,
2426 aggregate_info: CType.Info.Aggregate,
24722427 indent: usize,
24732428) !void {
24742429 try writer.writeAll("{\n");
2475 const fields = cty.fields();
2476 for (fields) |field| {
2430 for (0..aggregate_info.fields.len) |field_index| {
2431 const field_info = aggregate_info.fields.at(field_index, ctype_pool);
24772432 try writer.writeByteNTimes(' ', indent + 1);
2478 switch (field.alignas.abiOrder()) {
2479 .lt => try writer.print("zig_under_align({}) ", .{field.alignas.toByteUnits()}),
2480 .eq => {},
2481 .gt => try writer.print("zig_align({}) ", .{field.alignas.toByteUnits()}),
2433 switch (field_info.alignas.abiOrder()) {
2434 .lt => {
2435 std.debug.assert(aggregate_info.@"packed");
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 },
24822446 }
2483 const trailing = try renderTypePrefix(.flush, store, mod, writer, field.type, .suffix, .{});
2484 try writer.print("{}{ }", .{ trailing, fmtIdent(mem.span(field.name)) });
2485 try renderTypeSuffix(.flush, store, mod, writer, field.type, .suffix, .{});
2447 const trailing = try renderTypePrefix(
2448 .flush,
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, .{});
24862458 try writer.writeAll(";\n");
24872459 }
24882460 try writer.writeByteNTimes(' ', indent);
......@@ -2490,106 +2462,112 @@ fn renderAggregateFields(
24902462}
24912463
24922464pub fn genTypeDecl(
2493 mod: *Module,
2465 zcu: *Zcu,
24942466 writer: anytype,
2495 global_store: CType.Store.Set,
2496 global_idx: CType.Index,
2467 global_ctype_pool: *const CType.Pool,
2468 global_ctype: CType,
24972469 pass: DeclGen.Pass,
2498 decl_store: CType.Store.Set,
2499 decl_idx: CType.Index,
2470 decl_ctype_pool: *const CType.Pool,
2471 decl_ctype: CType,
25002472 found_existing: bool,
25012473) !void {
2502 const global_cty = global_store.indexToCType(global_idx);
2503 switch (global_cty.tag()) {
2504 .fwd_anon_struct => if (pass != .flush) {
2505 try writer.writeAll("typedef ");
2506 _ = try renderTypePrefix(.flush, global_store, mod, writer, global_idx, .suffix, .{});
2507 try writer.writeByte(' ');
2508 _ = try renderTypePrefix(pass, decl_store, mod, writer, decl_idx, .suffix, .{});
2509 try writer.writeAll(";\n");
2510 },
2511
2512 .fwd_struct,
2513 .fwd_union,
2514 .anon_struct,
2515 .anon_union,
2516 .@"struct",
2517 .@"union",
2518 .packed_struct,
2519 .packed_union,
2520 => |tag| if (!found_existing) {
2521 switch (tag) {
2522 .fwd_struct,
2523 .fwd_union,
2524 => {
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 );
2474 switch (global_ctype.info(global_ctype_pool)) {
2475 .basic, .pointer, .array, .vector, .function => {},
2476 .aligned => |aligned_info| {
2477 if (!found_existing) {
2478 std.debug.assert(aligned_info.alignas.abiOrder().compare(.lt));
2479 try writer.print("typedef zig_under_align({d}) ", .{aligned_info.alignas.toByteUnits()});
2480 try writer.print("{}", .{try renderTypePrefix(
2481 .flush,
2482 global_ctype_pool,
2483 zcu,
2484 writer,
2485 aligned_info.ctype,
2486 .suffix,
2487 .{},
2488 )});
2489 try renderAlignedTypeName(writer, global_ctype);
2490 try renderTypeSuffix(.flush, global_ctype_pool, zcu, writer, aligned_info.ctype, .suffix, .{});
2491 try writer.writeAll(";\n");
2492 }
2493 switch (pass) {
2494 .decl, .anon => {
2495 try writer.writeAll("typedef ");
2496 _ = try renderTypePrefix(.flush, global_ctype_pool, zcu, writer, global_ctype, .suffix, .{});
25552497 try writer.writeByte(' ');
2556 try renderAggregateFields(mod, writer, global_store, global_cty, 0);
2557 if (global_cty.isPacked()) try writer.writeByte(')');
2498 _ = try renderTypePrefix(pass, decl_ctype_pool, zcu, writer, decl_ctype, .suffix, .{});
25582499 try writer.writeAll(";\n");
25592500 },
2560
2561 else => unreachable,
2501 .flush => {},
25622502 }
25632503 },
2564
2565 else => {},
2504 .fwd_decl => |fwd_decl_info| switch (fwd_decl_info.name) {
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 },
25662544 }
25672545}
25682546
2569pub fn genGlobalAsm(mod: *Module, writer: anytype) !void {
2570 for (mod.global_assembly.values()) |asm_source| {
2547pub fn genGlobalAsm(zcu: *Zcu, writer: anytype) !void {
2548 for (zcu.global_assembly.values()) |asm_source| {
25712549 try writer.print("__asm({s});\n", .{fmtStringLiteral(asm_source, null)});
25722550 }
25732551}
25742552
25752553pub fn genErrDecls(o: *Object) !void {
2576 const mod = o.dg.module;
2577 const ip = &mod.intern_pool;
2554 const zcu = o.dg.zcu;
2555 const ip = &zcu.intern_pool;
25782556 const writer = o.writer();
25792557
25802558 var max_name_len: usize = 0;
25812559 // 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) {
25832561 try writer.writeAll("enum {\n");
25842562 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| {
25862564 const name = ip.stringToSlice(name_nts);
25872565 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 = .{
25892567 .ty = .anyerror_type,
25902568 .name = name_nts,
25912569 } });
2592 try o.dg.renderValue(writer, Type.anyerror, Value.fromInterned(err_val), .Other);
2570 try o.dg.renderValue(writer, Value.fromInterned(err_val), .Other);
25932571 try writer.print(" = {d}u,\n", .{value});
25942572 }
25952573 o.indent_writer.popIndent();
......@@ -2601,44 +2579,56 @@ pub fn genErrDecls(o: *Object) !void {
26012579 defer o.dg.gpa.free(name_buf);
26022580
26032581 @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| {
26052583 const name = ip.stringToSlice(name_ip);
26062584 @memcpy(name_buf[name_prefix.len..][0..name.len], name);
26072585 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(.{
26102588 .len = name.len,
26112589 .child = .u8_type,
26122590 .sentinel = .zero_u8,
26132591 });
2614 const name_val = try mod.intern(.{ .aggregate = .{
2592 const name_val = try zcu.intern(.{ .aggregate = .{
26152593 .ty = name_ty.toIntern(),
26162594 .storage = .{ .bytes = name },
26172595 } });
26182596
26192597 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 );
26212606 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);
26232608 try writer.writeAll(";\n");
26242609 }
26252610
2626 const name_array_ty = try mod.arrayType(.{
2627 .len = mod.global_error_set.count(),
2611 const name_array_ty = try zcu.arrayType(.{
2612 .len = zcu.global_error_set.count(),
26282613 .child = .slice_const_u8_sentinel_0_type,
26292614 });
26302615
26312616 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 );
26332625 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| {
26352627 const name = ip.stringToSlice(name_nts);
26362628 if (value != 0) try writer.writeByte(',');
2637
2638 const len_val = try mod.intValue(Type.usize, name.len);
2639
26402629 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),
26422632 });
26432633 }
26442634 try writer.writeAll("};\n");
......@@ -2648,16 +2638,16 @@ fn genExports(o: *Object) !void {
26482638 const tracy = trace(@src());
26492639 defer tracy.end();
26502640
2651 const mod = o.dg.module;
2652 const ip = &mod.intern_pool;
2641 const zcu = o.dg.zcu;
2642 const ip = &zcu.intern_pool;
26532643 const decl_index = switch (o.dg.pass) {
26542644 .decl => |decl| decl,
26552645 .anon, .flush => return,
26562646 };
2657 const decl = mod.declPtr(decl_index);
2647 const decl = zcu.declPtr(decl_index);
26582648 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;
26612651 if (exports.items.len < 2) return;
26622652
26632653 const is_variable_const = switch (ip.indexToKey(decl.val.toIntern())) {
......@@ -2685,7 +2675,7 @@ fn genExports(o: *Object) !void {
26852675 const export_name = ip.stringToSlice(@"export".opts.name);
26862676 try o.dg.renderTypeAndName(
26872677 fwd,
2688 decl.typeOf(mod),
2678 decl.typeOf(zcu),
26892679 .{ .identifier = export_name },
26902680 CQualifiers.init(.{ .@"const" = is_variable_const }),
26912681 decl.alignment,
......@@ -2707,13 +2697,13 @@ fn genExports(o: *Object) !void {
27072697 }
27082698}
27092699
2710pub fn genLazyFn(o: *Object, lazy_fn: LazyFnMap.Entry) !void {
2711 const mod = o.dg.module;
2712 const ip = &mod.intern_pool;
2700pub fn genLazyFn(o: *Object, lazy_ctype_pool: *const CType.Pool, lazy_fn: LazyFnMap.Entry) !void {
2701 const zcu = o.dg.zcu;
2702 const ip = &zcu.intern_pool;
2703 const ctype_pool = &o.dg.ctype_pool;
27132704 const w = o.writer();
27142705 const key = lazy_fn.key_ptr.*;
27152706 const val = lazy_fn.value_ptr;
2716 const fn_name = val.fn_name;
27172707 switch (key) {
27182708 .tag_name => {
27192709 const enum_ty = val.data.tag_name;
......@@ -2723,52 +2713,51 @@ pub fn genLazyFn(o: *Object, lazy_fn: LazyFnMap.Entry) !void {
27232713 try w.writeAll("static ");
27242714 try o.dg.renderType(w, name_slice_ty);
27252715 try w.writeByte(' ');
2726 try w.writeAll(fn_name);
2716 try w.writeAll(val.fn_name.slice(lazy_ctype_pool));
27272717 try w.writeByte('(');
27282718 try o.dg.renderTypeAndName(w, enum_ty, .{ .identifier = "tag" }, Const, .none, .complete);
27292719 try w.writeAll(") {\n switch (tag) {\n");
2730 const tag_names = enum_ty.enumFields(mod);
2720 const tag_names = enum_ty.enumFields(zcu);
27312721 for (0..tag_names.len) |tag_index| {
27322722 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);
2736
2737 const name_ty = try mod.arrayType(.{
2725 const name_ty = try zcu.arrayType(.{
27382726 .len = tag_name.len,
27392727 .child = .u8_type,
27402728 .sentinel = .zero_u8,
27412729 });
2742 const name_val = try mod.intern(.{ .aggregate = .{
2730 const name_val = try zcu.intern(.{ .aggregate = .{
27432731 .ty = name_ty.toIntern(),
27442732 .storage = .{ .bytes = tag_name },
27452733 } });
2746 const len_val = try mod.intValue(Type.usize, tag_name.len);
27472734
27482735 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),
27502737 });
27512738 try o.dg.renderTypeAndName(w, name_ty, .{ .identifier = "name" }, Const, .none, .complete);
27522739 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);
27542741 try w.writeAll(";\n return (");
27552742 try o.dg.renderType(w, name_slice_ty);
27562743 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),
27582746 });
27592747
27602748 try w.writeAll(" }\n");
27612749 }
27622750 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);
27642752 try w.writeAll(") ");
27652753 _ = try airBreakpoint(w);
27662754 try w.writeAll("}\n");
27672755 },
27682756 .never_tail, .never_inline => |fn_decl_index| {
2769 const fn_decl = mod.declPtr(fn_decl_index);
2770 const fn_cty = try o.dg.typeToCType(fn_decl.typeOf(mod), .complete);
2771 const fn_info = fn_cty.cast(CType.Payload.Function).?.data;
2757 const fn_decl = zcu.declPtr(fn_decl_index);
2758 const fn_ctype = try o.dg.ctypeFromType(fn_decl.typeOf(zcu), .complete);
2759 const fn_info = fn_ctype.info(ctype_pool).function;
2760 const fn_name = val.fn_name.slice(lazy_ctype_pool);
27722761
27732762 const fwd_decl_writer = o.dg.fwdDeclWriter();
27742763 try fwd_decl_writer.print("static zig_{s} ", .{@tagName(key)});
......@@ -2781,11 +2770,13 @@ pub fn genLazyFn(o: *Object, lazy_fn: LazyFnMap.Entry) !void {
27812770 try fwd_decl_writer.writeAll(";\n");
27822771
27832772 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 });
27852776 try w.writeAll(" {\n return ");
27862777 try o.dg.renderDeclName(w, fn_decl_index, 0);
27872778 try w.writeByte('(');
2788 for (0..fn_info.param_types.len) |arg| {
2779 for (0..fn_info.param_ctypes.len) |arg| {
27892780 if (arg > 0) try w.writeAll(", ");
27902781 try o.dg.writeCValue(w, .{ .arg = arg });
27912782 }
......@@ -2799,10 +2790,10 @@ pub fn genFunc(f: *Function) !void {
27992790 defer tracy.end();
28002791
28012792 const o = &f.object;
2802 const mod = o.dg.module;
2793 const zcu = o.dg.zcu;
28032794 const gpa = o.dg.gpa;
28042795 const decl_index = o.dg.pass.decl;
2805 const decl = mod.declPtr(decl_index);
2796 const decl = zcu.declPtr(decl_index);
28062797
28072798 o.code_header = std.ArrayList(u8).init(gpa);
28082799 defer o.code_header.deinit();
......@@ -2811,7 +2802,7 @@ pub fn genFunc(f: *Function) !void {
28112802 const fwd_decl_writer = o.dg.fwdDeclWriter();
28122803 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|
28152806 if (exports.items[0].opts.linkage == .weak) try fwd_decl_writer.writeAll("zig_weak_linkage_fn ");
28162807 try o.dg.renderFunctionSignature(fwd_decl_writer, decl_index, .forward, .{ .export_index = 0 });
28172808 try fwd_decl_writer.writeAll(";\n");
......@@ -2819,6 +2810,8 @@ pub fn genFunc(f: *Function) !void {
28192810
28202811 try o.indent_writer.insertNewline();
28212812 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)});
28222815 try o.dg.renderFunctionSignature(o.writer(), decl_index, .complete, .{ .export_index = 0 });
28232816 try o.writer().writeByte(' ');
28242817
......@@ -2867,7 +2860,7 @@ pub fn genFunc(f: *Function) !void {
28672860 for (free_locals.values()) |list| {
28682861 for (list.keys()) |local_index| {
28692862 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);
28712864 try w.writeAll(";\n ");
28722865 }
28732866 }
......@@ -2884,43 +2877,41 @@ pub fn genDecl(o: *Object) !void {
28842877 const tracy = trace(@src());
28852878 defer tracy.end();
28862879
2887 const mod = o.dg.module;
2880 const zcu = o.dg.zcu;
28882881 const decl_index = o.dg.pass.decl;
2889 const decl = mod.declPtr(decl_index);
2890 const decl_val = decl.val;
2891 const decl_ty = decl_val.typeOf(mod);
2882 const decl = zcu.declPtr(decl_index);
2883 const decl_ty = decl.typeOf(zcu);
28922884
2893 if (!decl_ty.isFnOrHasRuntimeBitsIgnoreComptime(mod)) return;
2894 if (decl_val.getExternFunc(mod)) |_| {
2885 if (!decl_ty.isFnOrHasRuntimeBitsIgnoreComptime(zcu)) return;
2886 if (decl.val.getExternFunc(zcu)) |_| {
28952887 const fwd_decl_writer = o.dg.fwdDeclWriter();
28962888 try fwd_decl_writer.writeAll("zig_extern ");
28972889 try o.dg.renderFunctionSignature(fwd_decl_writer, decl_index, .forward, .{ .export_index = 0 });
28982890 try fwd_decl_writer.writeAll(";\n");
28992891 try genExports(o);
2900 } else if (decl_val.getVariable(mod)) |variable| {
2892 } else if (decl.val.getVariable(zcu)) |variable| {
29012893 try o.dg.renderFwdDecl(decl_index, variable, .final);
29022894 try genExports(o);
29032895
29042896 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);
29072899 const w = o.writer();
29082900 if (!is_global) try w.writeAll("static ");
29092901 if (variable.is_weak_linkage) try w.writeAll("zig_weak_linkage ");
29102902 if (variable.is_threadlocal) try w.writeAll("zig_threadlocal ");
2911 if (mod.intern_pool.stringToSliceUnwrap(decl.@"linksection")) |s|
2912 try w.print("zig_linksection(\"{s}\", ", .{s});
2903 if (zcu.intern_pool.stringToSliceUnwrap(decl.@"linksection")) |s|
2904 try w.print("zig_linksection({s}) ", .{fmtStringLiteral(s, null)});
29132905 const decl_c_value = .{ .decl = decl_index };
29142906 try o.dg.renderTypeAndName(w, decl_ty, decl_c_value, .{}, decl.alignment, .complete);
2915 if (decl.@"linksection" != .none) try w.writeAll(", read, write)");
29162907 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);
29182909 try w.writeByte(';');
29192910 try o.indent_writer.insertNewline();
29202911 } 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);
29222913 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");
29242915 }
29252916}
29262917
......@@ -2930,19 +2921,19 @@ pub fn genDeclValue(
29302921 is_global: bool,
29312922 decl_c_value: CValue,
29322923 alignment: Alignment,
2933 link_section: InternPool.OptionalNullTerminatedString,
2924 @"linksection": InternPool.OptionalNullTerminatedString,
29342925) !void {
2935 const mod = o.dg.module;
2926 const zcu = o.dg.zcu;
29362927 const fwd_decl_writer = o.dg.fwdDeclWriter();
29372928
2938 const ty = val.typeOf(mod);
2929 const ty = val.typeOf(zcu);
29392930
29402931 try fwd_decl_writer.writeAll(if (is_global) "zig_extern " else "static ");
29412932 try o.dg.renderTypeAndName(fwd_decl_writer, ty, decl_c_value, Const, alignment, .complete);
29422933 switch (o.dg.pass) {
29432934 .decl => |decl_index| {
2944 if (mod.decl_exports.get(decl_index)) |exports| {
2945 const export_name = mod.intern_pool.stringToSlice(exports.items[0].opts.name);
2935 if (zcu.decl_exports.get(decl_index)) |exports| {
2936 const export_name = zcu.intern_pool.stringToSlice(exports.items[0].opts.name);
29462937 if (isMangledIdent(export_name, true)) {
29472938 try fwd_decl_writer.print(" zig_mangled_final({ }, {s})", .{
29482939 fmtIdent(export_name), fmtStringLiteral(export_name, null),
......@@ -2958,13 +2949,11 @@ pub fn genDeclValue(
29582949
29592950 const w = o.writer();
29602951 if (!is_global) try w.writeAll("static ");
2961
2962 if (mod.intern_pool.stringToSliceUnwrap(link_section)) |s|
2963 try w.print("zig_linksection(\"{s}\", ", .{s});
2952 if (zcu.intern_pool.stringToSliceUnwrap(@"linksection")) |s|
2953 try w.print("zig_linksection({s}) ", .{fmtStringLiteral(s, null)});
29642954 try o.dg.renderTypeAndName(w, ty, decl_c_value, Const, alignment, .complete);
2965 if (link_section != .none) try w.writeAll(", read)");
29662955 try w.writeAll(" = ");
2967 try o.dg.renderValue(w, ty, val, .StaticInitializer);
2956 try o.dg.renderValue(w, val, .StaticInitializer);
29682957 try w.writeAll(";\n");
29692958}
29702959
......@@ -2972,12 +2961,12 @@ pub fn genHeader(dg: *DeclGen) error{ AnalysisFail, OutOfMemory }!void {
29722961 const tracy = trace(@src());
29732962 defer tracy.end();
29742963
2975 const mod = dg.module;
2964 const zcu = dg.zcu;
29762965 const decl_index = dg.pass.decl;
2977 const decl = mod.declPtr(decl_index);
2966 const decl = zcu.declPtr(decl_index);
29782967 const writer = dg.fwdDeclWriter();
29792968
2980 switch (decl.val.typeOf(mod).zigTypeTag(mod)) {
2969 switch (decl.typeOf(zcu).zigTypeTag(zcu)) {
29812970 .Fn => if (dg.declIsGlobal(decl.val)) {
29822971 try writer.writeAll("zig_extern ");
29832972 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
30603049}
30613050
30623051fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutOfMemory }!void {
3063 const mod = f.object.dg.module;
3064 const ip = &mod.intern_pool;
3052 const zcu = f.object.dg.zcu;
3053 const ip = &zcu.intern_pool;
30653054 const air_tags = f.air.instructions.items(.tag);
30663055
30673056 for (body) |inst| {
......@@ -3096,10 +3085,10 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail,
30963085 .div_trunc, .div_exact => try airBinOp(f, inst, "/", "div_trunc", .none),
30973086 .rem => blk: {
30983087 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);
31003089 // For binary operations @TypeOf(lhs)==@TypeOf(rhs),
31013090 // so we only check one.
3102 break :blk if (lhs_scalar_ty.isInt(mod))
3091 break :blk if (lhs_scalar_ty.isInt(zcu))
31033092 try airBinOp(f, inst, "%", "rem", .none)
31043093 else
31053094 try airBinFloatOp(f, inst, "fmod");
......@@ -3359,10 +3348,10 @@ fn airSliceField(f: *Function, inst: Air.Inst.Index, is_ptr: bool, field_name: [
33593348}
33603349
33613350fn airPtrElemVal(f: *Function, inst: Air.Inst.Index) !CValue {
3362 const mod = f.object.dg.module;
3351 const zcu = f.object.dg.zcu;
33633352 const inst_ty = f.typeOfIndex(inst);
33643353 const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
3365 if (!inst_ty.hasRuntimeBitsIgnoreComptime(mod)) {
3354 if (!inst_ty.hasRuntimeBitsIgnoreComptime(zcu)) {
33663355 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
33673356 return .none;
33683357 }
......@@ -3385,14 +3374,13 @@ fn airPtrElemVal(f: *Function, inst: Air.Inst.Index) !CValue {
33853374}
33863375
33873376fn airPtrElemPtr(f: *Function, inst: Air.Inst.Index) !CValue {
3388 const mod = f.object.dg.module;
3377 const zcu = f.object.dg.zcu;
33893378 const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
33903379 const bin_op = f.air.extraData(Air.Bin, ty_pl.payload).data;
33913380
33923381 const inst_ty = f.typeOfIndex(inst);
33933382 const ptr_ty = f.typeOf(bin_op.lhs);
3394 const elem_ty = ptr_ty.childType(mod);
3395 const elem_has_bits = elem_ty.hasRuntimeBitsIgnoreComptime(mod);
3383 const elem_has_bits = ptr_ty.elemType2(zcu).hasRuntimeBitsIgnoreComptime(zcu);
33963384
33973385 const ptr = try f.resolveInst(bin_op.lhs);
33983386 const index = try f.resolveInst(bin_op.rhs);
......@@ -3407,7 +3395,7 @@ fn airPtrElemPtr(f: *Function, inst: Air.Inst.Index) !CValue {
34073395 try f.renderType(writer, inst_ty);
34083396 try writer.writeByte(')');
34093397 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) {
34113399 // It's a pointer to an array, so we need to de-reference.
34123400 try f.writeCValueDeref(writer, ptr);
34133401 } else try f.writeCValue(writer, ptr, .Other);
......@@ -3421,10 +3409,10 @@ fn airPtrElemPtr(f: *Function, inst: Air.Inst.Index) !CValue {
34213409}
34223410
34233411fn airSliceElemVal(f: *Function, inst: Air.Inst.Index) !CValue {
3424 const mod = f.object.dg.module;
3412 const zcu = f.object.dg.zcu;
34253413 const inst_ty = f.typeOfIndex(inst);
34263414 const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
3427 if (!inst_ty.hasRuntimeBitsIgnoreComptime(mod)) {
3415 if (!inst_ty.hasRuntimeBitsIgnoreComptime(zcu)) {
34283416 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
34293417 return .none;
34303418 }
......@@ -3447,14 +3435,14 @@ fn airSliceElemVal(f: *Function, inst: Air.Inst.Index) !CValue {
34473435}
34483436
34493437fn airSliceElemPtr(f: *Function, inst: Air.Inst.Index) !CValue {
3450 const mod = f.object.dg.module;
3438 const zcu = f.object.dg.zcu;
34513439 const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
34523440 const bin_op = f.air.extraData(Air.Bin, ty_pl.payload).data;
34533441
34543442 const inst_ty = f.typeOfIndex(inst);
34553443 const slice_ty = f.typeOf(bin_op.lhs);
3456 const elem_ty = slice_ty.elemType2(mod);
3457 const elem_has_bits = elem_ty.hasRuntimeBitsIgnoreComptime(mod);
3444 const elem_ty = slice_ty.elemType2(zcu);
3445 const elem_has_bits = elem_ty.hasRuntimeBitsIgnoreComptime(zcu);
34583446
34593447 const slice = try f.resolveInst(bin_op.lhs);
34603448 const index = try f.resolveInst(bin_op.rhs);
......@@ -3477,10 +3465,10 @@ fn airSliceElemPtr(f: *Function, inst: Air.Inst.Index) !CValue {
34773465}
34783466
34793467fn airArrayElemVal(f: *Function, inst: Air.Inst.Index) !CValue {
3480 const mod = f.object.dg.module;
3468 const zcu = f.object.dg.zcu;
34813469 const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
34823470 const inst_ty = f.typeOfIndex(inst);
3483 if (!inst_ty.hasRuntimeBitsIgnoreComptime(mod)) {
3471 if (!inst_ty.hasRuntimeBitsIgnoreComptime(zcu)) {
34843472 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
34853473 return .none;
34863474 }
......@@ -3503,47 +3491,53 @@ fn airArrayElemVal(f: *Function, inst: Air.Inst.Index) !CValue {
35033491}
35043492
35053493fn airAlloc(f: *Function, inst: Air.Inst.Index) !CValue {
3506 const mod = f.object.dg.module;
3494 const zcu = f.object.dg.zcu;
35073495 const inst_ty = f.typeOfIndex(inst);
3508 const elem_type = inst_ty.childType(mod);
3509 if (!elem_type.isFnOrHasRuntimeBitsIgnoreComptime(mod)) return .{ .undef = inst_ty };
3510
3511 const local = try f.allocLocalValue(
3512 elem_type,
3513 inst_ty.ptrAlignment(mod),
3514 );
3496 const elem_ty = inst_ty.childType(zcu);
3497 if (!elem_ty.isFnOrHasRuntimeBitsIgnoreComptime(zcu)) return .{ .undef = inst_ty };
3498
3499 const local = try f.allocLocalValue(.{
3500 .ctype = try f.ctypeFromType(elem_ty, .complete),
3501 .alignas = CType.AlignAs.fromAlignment(.{
3502 .@"align" = inst_ty.ptrInfo(zcu).flags.alignment,
3503 .abi = elem_ty.abiAlignment(zcu),
3504 }),
3505 });
35153506 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;
35173508 try f.allocs.put(gpa, local.new_local, true);
35183509 return .{ .local_ref = local.new_local };
35193510}
35203511
35213512fn airRetPtr(f: *Function, inst: Air.Inst.Index) !CValue {
3522 const mod = f.object.dg.module;
3513 const zcu = f.object.dg.zcu;
35233514 const inst_ty = f.typeOfIndex(inst);
3524 const elem_ty = inst_ty.childType(mod);
3525 if (!elem_ty.isFnOrHasRuntimeBitsIgnoreComptime(mod)) return .{ .undef = inst_ty };
3526
3527 const local = try f.allocLocalValue(
3528 elem_ty,
3529 inst_ty.ptrAlignment(mod),
3530 );
3515 const elem_ty = inst_ty.childType(zcu);
3516 if (!elem_ty.isFnOrHasRuntimeBitsIgnoreComptime(zcu)) return .{ .undef = inst_ty };
3517
3518 const local = try f.allocLocalValue(.{
3519 .ctype = try f.ctypeFromType(elem_ty, .complete),
3520 .alignas = CType.AlignAs.fromAlignment(.{
3521 .@"align" = inst_ty.ptrInfo(zcu).flags.alignment,
3522 .abi = elem_ty.abiAlignment(zcu),
3523 }),
3524 });
35313525 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;
35333527 try f.allocs.put(gpa, local.new_local, true);
35343528 return .{ .local_ref = local.new_local };
35353529}
35363530
35373531fn airArg(f: *Function, inst: Air.Inst.Index) !CValue {
35383532 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
35413535 const i = f.next_arg_index;
35423536 f.next_arg_index += 1;
3543 const result: CValue = if (inst_cty != try f.typeToIndex(inst_ty, .complete))
3544 .{ .arg_array = i }
3537 const result: CValue = if (inst_ctype.eql(try f.ctypeFromType(inst_ty, .complete)))
3538 .{ .arg = i }
35453539 else
3546 .{ .arg = i };
3540 .{ .arg_array = i };
35473541
35483542 if (f.liveness.isUnused(inst)) {
35493543 const writer = f.object.writer();
......@@ -3559,15 +3553,15 @@ fn airArg(f: *Function, inst: Air.Inst.Index) !CValue {
35593553}
35603554
35613555fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue {
3562 const mod = f.object.dg.module;
3556 const zcu = f.object.dg.zcu;
35633557 const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
35643558
35653559 const ptr_ty = f.typeOf(ty_op.operand);
3566 const ptr_scalar_ty = ptr_ty.scalarType(mod);
3567 const ptr_info = ptr_scalar_ty.ptrInfo(mod);
3560 const ptr_scalar_ty = ptr_ty.scalarType(zcu);
3561 const ptr_info = ptr_scalar_ty.ptrInfo(zcu);
35683562 const src_ty = Type.fromInterned(ptr_info.child);
35693563
3570 if (!src_ty.hasRuntimeBitsIgnoreComptime(mod)) {
3564 if (!src_ty.hasRuntimeBitsIgnoreComptime(zcu)) {
35713565 try reap(f, inst, &.{ty_op.operand});
35723566 return .none;
35733567 }
......@@ -3577,10 +3571,10 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue {
35773571 try reap(f, inst, &.{ty_op.operand});
35783572
35793573 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)
35813575 else
35823576 true;
3583 const is_array = lowersToArray(src_ty, mod);
3577 const is_array = lowersToArray(src_ty, zcu);
35843578 const need_memcpy = !is_aligned or is_array;
35853579
35863580 const writer = f.object.writer();
......@@ -3600,12 +3594,12 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue {
36003594 try writer.writeAll("))");
36013595 } else if (ptr_info.packed_offset.host_size > 0 and ptr_info.flags.vector_index == .none) {
36023596 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));
3606 const bit_offset_val = try mod.intValue(bit_offset_ty, ptr_info.packed_offset.bit_offset);
3599 const bit_offset_ty = try zcu.intType(.unsigned, Type.smallestUnsignedBits(host_bits - 1));
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
36103604 try f.writeCValue(writer, local, .Other);
36113605 try v.elem(f, writer);
......@@ -3616,9 +3610,9 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue {
36163610 try writer.writeAll("((");
36173611 try f.renderType(writer, field_ty);
36183612 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;
36203614 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", .{});
36223616 try writer.writeAll("zig_lo_");
36233617 try f.object.dg.renderTypeForBuiltinFnName(writer, host_ty);
36243618 try writer.writeByte('(');
......@@ -3628,7 +3622,7 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue {
36283622 try writer.writeByte('(');
36293623 try f.writeCValueDeref(writer, operand);
36303624 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)});
36323626 if (cant_cast) try writer.writeByte(')');
36333627 try f.object.dg.renderBuiltinInfo(writer, field_ty, .bits);
36343628 try writer.writeByte(')');
......@@ -3646,24 +3640,27 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue {
36463640}
36473641
36483642fn 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;
36503644 const un_op = f.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
36513645 const writer = f.object.writer();
36523646 const op_inst = un_op.toIndex();
36533647 const op_ty = f.typeOf(un_op);
3654 const ret_ty = if (is_ptr) op_ty.childType(mod) else op_ty;
3655 const lowered_ret_ty = try lowerFnRetTy(ret_ty, mod);
3648 const ret_ty = if (is_ptr) op_ty.childType(zcu) else op_ty;
3649 const ret_ctype = try f.ctypeFromType(ret_ty, .parameter);
36563650
36573651 if (op_inst != null and f.air.instructions.items(.tag)[@intFromEnum(op_inst.?)] == .call_always_tail) {
36583652 try reap(f, inst, &.{un_op});
36593653 _ = try airCall(f, op_inst.?, .always_tail);
3660 } else if (lowered_ret_ty.hasRuntimeBitsIgnoreComptime(mod)) {
3654 } else if (ret_ctype.index != .void) {
36613655 const operand = try f.resolveInst(un_op);
36623656 try reap(f, inst, &.{un_op});
36633657 var deref = is_ptr;
3664 const is_array = lowersToArray(ret_ty, mod);
3658 const is_array = lowersToArray(ret_ty, zcu);
36653659 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 });
36673664 try writer.writeAll("memcpy(");
36683665 try f.writeCValueMember(writer, array_local, .{ .identifier = "array" });
36693666 try writer.writeAll(", ");
......@@ -3696,16 +3693,16 @@ fn airRet(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValue {
36963693}
36973694
36983695fn airIntCast(f: *Function, inst: Air.Inst.Index) !CValue {
3699 const mod = f.object.dg.module;
3696 const zcu = f.object.dg.zcu;
37003697 const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
37013698
37023699 const operand = try f.resolveInst(ty_op.operand);
37033700 try reap(f, inst, &.{ty_op.operand});
37043701
37053702 const inst_ty = f.typeOfIndex(inst);
3706 const inst_scalar_ty = inst_ty.scalarType(mod);
3703 const inst_scalar_ty = inst_ty.scalarType(zcu);
37073704 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
37103707 const writer = f.object.writer();
37113708 const local = try f.allocLocal(inst, inst_ty);
......@@ -3722,20 +3719,20 @@ fn airIntCast(f: *Function, inst: Air.Inst.Index) !CValue {
37223719}
37233720
37243721fn airTrunc(f: *Function, inst: Air.Inst.Index) !CValue {
3725 const mod = f.object.dg.module;
3722 const zcu = f.object.dg.zcu;
37263723 const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
37273724
37283725 const operand = try f.resolveInst(ty_op.operand);
37293726 try reap(f, inst, &.{ty_op.operand});
37303727 const inst_ty = f.typeOfIndex(inst);
3731 const inst_scalar_ty = inst_ty.scalarType(mod);
3732 const dest_int_info = inst_scalar_ty.intInfo(mod);
3728 const inst_scalar_ty = inst_ty.scalarType(zcu);
3729 const dest_int_info = inst_scalar_ty.intInfo(zcu);
37333730 const dest_bits = dest_int_info.bits;
37343731 const dest_c_bits = toCIntBits(dest_int_info.bits) orelse
37353732 return f.fail("TODO: C backend: implement integer types larger than 128 bits", .{});
37363733 const operand_ty = f.typeOf(ty_op.operand);
3737 const scalar_ty = operand_ty.scalarType(mod);
3738 const scalar_int_info = scalar_ty.intInfo(mod);
3734 const scalar_ty = operand_ty.scalarType(zcu);
3735 const scalar_int_info = scalar_ty.intInfo(zcu);
37393736
37403737 const writer = f.object.writer();
37413738 const local = try f.allocLocal(inst, inst_ty);
......@@ -3763,18 +3760,19 @@ fn airTrunc(f: *Function, inst: Air.Inst.Index) !CValue {
37633760 try v.elem(f, writer);
37643761 } else switch (dest_int_info.signedness) {
37653762 .unsigned => {
3766 const mask_val = try inst_scalar_ty.maxIntScalar(mod, scalar_ty);
37673763 try writer.writeAll("zig_and_");
37683764 try f.object.dg.renderTypeForBuiltinFnName(writer, scalar_ty);
37693765 try writer.writeByte('(');
37703766 try f.writeCValue(writer, operand, .FunctionArgument);
37713767 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 });
37733771 },
37743772 .signed => {
37753773 const c_bits = toCIntBits(scalar_int_info.bits) orelse
37763774 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
37793777 try writer.writeAll("zig_shr_");
37803778 try f.object.dg.renderTypeForBuiltinFnName(writer, scalar_ty);
......@@ -3792,9 +3790,9 @@ fn airTrunc(f: *Function, inst: Air.Inst.Index) !CValue {
37923790 try f.writeCValue(writer, operand, .FunctionArgument);
37933791 try v.elem(f, writer);
37943792 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)});
37963794 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)});
37983796 },
37993797 }
38003798
......@@ -3821,18 +3819,18 @@ fn airIntFromBool(f: *Function, inst: Air.Inst.Index) !CValue {
38213819}
38223820
38233821fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
3824 const mod = f.object.dg.module;
3822 const zcu = f.object.dg.zcu;
38253823 // *a = b;
38263824 const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
38273825
38283826 const ptr_ty = f.typeOf(bin_op.lhs);
3829 const ptr_scalar_ty = ptr_ty.scalarType(mod);
3830 const ptr_info = ptr_scalar_ty.ptrInfo(mod);
3827 const ptr_scalar_ty = ptr_ty.scalarType(zcu);
3828 const ptr_info = ptr_scalar_ty.ptrInfo(zcu);
38313829
38323830 const ptr_val = try f.resolveInst(bin_op.lhs);
38333831 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
38373835 if (val_is_undef) {
38383836 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 {
38483846 }
38493847
38503848 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)
38523850 else
38533851 true;
3854 const is_array = lowersToArray(Type.fromInterned(ptr_info.child), mod);
3852 const is_array = lowersToArray(Type.fromInterned(ptr_info.child), zcu);
38553853 const need_memcpy = !is_aligned or is_array;
38563854
38573855 const src_val = try f.resolveInst(bin_op.rhs);
......@@ -3863,7 +3861,7 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
38633861 if (need_memcpy) {
38643862 // For this memcpy to safely work we need the rhs to have the same
38653863 // 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
38683866 // If the source is a constant, writeCValue will emit a brace initialization
38693867 // so work around this by initializing into new local.
......@@ -3893,12 +3891,12 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
38933891 }
38943892 } else if (ptr_info.packed_offset.host_size > 0 and ptr_info.flags.vector_index == .none) {
38953893 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));
3899 const bit_offset_val = try mod.intValue(bit_offset_ty, ptr_info.packed_offset.bit_offset);
3896 const bit_offset_ty = try zcu.intType(.unsigned, Type.smallestUnsignedBits(host_bits - 1));
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
39033901 const ExpectedContents = [BigInt.Managed.default_capacity]BigIntLimb;
39043902 var stack align(@alignOf(ExpectedContents)) =
......@@ -3911,7 +3909,7 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
39113909 try mask.shiftLeft(&mask, ptr_info.packed_offset.bit_offset);
39123910 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
39163914 try f.writeCValueDeref(writer, ptr_val);
39173915 try v.elem(f, writer);
......@@ -3922,12 +3920,12 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
39223920 try writer.writeByte('(');
39233921 try f.writeCValueDeref(writer, ptr_val);
39243922 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)});
39263924 try f.object.dg.renderTypeForBuiltinFnName(writer, host_ty);
39273925 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;
39293927 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", .{});
39313929 try writer.writeAll("zig_make_");
39323930 try f.object.dg.renderTypeForBuiltinFnName(writer, host_ty);
39333931 try writer.writeAll("(0, ");
......@@ -3937,7 +3935,7 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
39373935 try writer.writeByte(')');
39383936 }
39393937
3940 if (src_ty.isPtrAtRuntime(mod)) {
3938 if (src_ty.isPtrAtRuntime(zcu)) {
39413939 try writer.writeByte('(');
39423940 try f.renderType(writer, Type.usize);
39433941 try writer.writeByte(')');
......@@ -3945,7 +3943,7 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
39453943 try f.writeCValue(writer, src_val, .Other);
39463944 try v.elem(f, writer);
39473945 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)});
39493947 } else {
39503948 try f.writeCValueDeref(writer, ptr_val);
39513949 try v.elem(f, writer);
......@@ -3960,7 +3958,7 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
39603958}
39613959
39623960fn 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;
39643962 const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
39653963 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:
39703968
39713969 const inst_ty = f.typeOfIndex(inst);
39723970 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
39753973 const w = f.object.writer();
39763974 const local = try f.allocLocal(inst, inst_ty);
......@@ -3998,11 +3996,11 @@ fn airOverflow(f: *Function, inst: Air.Inst.Index, operation: []const u8, info:
39983996}
39993997
40003998fn airNot(f: *Function, inst: Air.Inst.Index) !CValue {
4001 const mod = f.object.dg.module;
3999 const zcu = f.object.dg.zcu;
40024000 const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
40034001 const operand_ty = f.typeOf(ty_op.operand);
4004 const scalar_ty = operand_ty.scalarType(mod);
4005 if (scalar_ty.ip_index != .bool_type) return try airUnBuiltinCall(f, inst, "not", .bits);
4002 const scalar_ty = operand_ty.scalarType(zcu);
4003 if (scalar_ty.toIntern() != .bool_type) return try airUnBuiltinCall(f, inst, "not", .bits);
40064004
40074005 const op = try f.resolveInst(ty_op.operand);
40084006 try reap(f, inst, &.{ty_op.operand});
......@@ -4031,11 +4029,11 @@ fn airBinOp(
40314029 operation: []const u8,
40324030 info: BuiltinInfo,
40334031) !CValue {
4034 const mod = f.object.dg.module;
4032 const zcu = f.object.dg.zcu;
40354033 const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
40364034 const operand_ty = f.typeOf(bin_op.lhs);
4037 const scalar_ty = operand_ty.scalarType(mod);
4038 if ((scalar_ty.isInt(mod) and scalar_ty.bitSize(mod) > 64) or scalar_ty.isRuntimeFloat())
4035 const scalar_ty = operand_ty.scalarType(zcu);
4036 if ((scalar_ty.isInt(zcu) and scalar_ty.bitSize(zcu) > 64) or scalar_ty.isRuntimeFloat())
40394037 return try airBinBuiltinCall(f, inst, operation, info);
40404038
40414039 const lhs = try f.resolveInst(bin_op.lhs);
......@@ -4069,12 +4067,12 @@ fn airCmpOp(
40694067 data: anytype,
40704068 operator: std.math.CompareOperator,
40714069) !CValue {
4072 const mod = f.object.dg.module;
4070 const zcu = f.object.dg.zcu;
40734071 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);
4077 if (scalar_ty.isInt(mod) and scalar_bits > 64)
4074 const scalar_bits = scalar_ty.bitSize(zcu);
4075 if (scalar_ty.isInt(zcu) and scalar_bits > 64)
40784076 return airCmpBuiltinCall(
40794077 f,
40804078 inst,
......@@ -4092,7 +4090,7 @@ fn airCmpOp(
40924090 try reap(f, inst, &.{ data.lhs, data.rhs });
40934091
40944092 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);
40964094 const writer = f.object.writer();
40974095 const local = try f.allocLocal(inst, inst_ty);
40984096 const v = try Vectorize.start(f, inst, writer, lhs_ty);
......@@ -4117,12 +4115,12 @@ fn airEquality(
41174115 inst: Air.Inst.Index,
41184116 operator: std.math.CompareOperator,
41194117) !CValue {
4120 const mod = f.object.dg.module;
4118 const zcu = f.object.dg.zcu;
41214119 const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
41224120
41234121 const operand_ty = f.typeOf(bin_op.lhs);
4124 const operand_bits = operand_ty.bitSize(mod);
4125 if (operand_ty.isInt(mod) and operand_bits > 64)
4122 const operand_bits = operand_ty.bitSize(zcu);
4123 if (operand_ty.isInt(zcu) and operand_bits > 64)
41264124 return airCmpBuiltinCall(
41274125 f,
41284126 inst,
......@@ -4145,7 +4143,7 @@ fn airEquality(
41454143 try f.writeCValue(writer, local, .Other);
41464144 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)) {
41494147 try f.writeCValueMember(writer, lhs, .{ .identifier = "is_null" });
41504148 try writer.writeAll(" || ");
41514149 try f.writeCValueMember(writer, rhs, .{ .identifier = "is_null" });
......@@ -4184,7 +4182,7 @@ fn airCmpLtErrorsLen(f: *Function, inst: Air.Inst.Index) !CValue {
41844182}
41854183
41864184fn airPtrAddSub(f: *Function, inst: Air.Inst.Index, operator: u8) !CValue {
4187 const mod = f.object.dg.module;
4185 const zcu = f.object.dg.zcu;
41884186 const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
41894187 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 {
41934191 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
41944192
41954193 const inst_ty = f.typeOfIndex(inst);
4196 const inst_scalar_ty = inst_ty.scalarType(mod);
4197 const elem_ty = inst_scalar_ty.elemType2(mod);
4194 const inst_scalar_ty = inst_ty.scalarType(zcu);
4195 const elem_ty = inst_scalar_ty.elemType2(zcu);
41984196
41994197 const local = try f.allocLocal(inst, inst_ty);
42004198 const writer = f.object.writer();
......@@ -4203,7 +4201,7 @@ fn airPtrAddSub(f: *Function, inst: Air.Inst.Index, operator: u8) !CValue {
42034201 try v.elem(f, writer);
42044202 try writer.writeAll(" = ");
42054203
4206 if (elem_ty.hasRuntimeBitsIgnoreComptime(mod)) {
4204 if (elem_ty.hasRuntimeBitsIgnoreComptime(zcu)) {
42074205 // We must convert to and from integer types to prevent UB if the operation
42084206 // results in a NULL pointer, or if LHS is NULL. The operation is only UB
42094207 // if the result is NULL and then dereferenced.
......@@ -4232,13 +4230,13 @@ fn airPtrAddSub(f: *Function, inst: Air.Inst.Index, operator: u8) !CValue {
42324230}
42334231
42344232fn 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;
42364234 const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
42374235
42384236 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)
42424240 return try airBinBuiltinCall(f, inst, operation[1..], .none);
42434241 if (inst_scalar_ty.isRuntimeFloat())
42444242 return try airBinFloatOp(f, inst, operation);
......@@ -4274,7 +4272,7 @@ fn airMinMax(f: *Function, inst: Air.Inst.Index, operator: u8, operation: []cons
42744272}
42754273
42764274fn airSlice(f: *Function, inst: Air.Inst.Index) !CValue {
4277 const mod = f.object.dg.module;
4275 const zcu = f.object.dg.zcu;
42784276 const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
42794277 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 {
42834281 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
42844282
42854283 const inst_ty = f.typeOfIndex(inst);
4286 const ptr_ty = inst_ty.slicePtrFieldType(mod);
4284 const ptr_ty = inst_ty.slicePtrFieldType(zcu);
42874285
42884286 const writer = f.object.writer();
42894287 const local = try f.allocLocal(inst, inst_ty);
......@@ -4291,9 +4289,6 @@ fn airSlice(f: *Function, inst: Air.Inst.Index) !CValue {
42914289 const a = try Assignment.start(f, writer, ptr_ty);
42924290 try f.writeCValueMember(writer, local, .{ .identifier = "ptr" });
42934291 try a.assign(f, writer);
4294 try writer.writeByte('(');
4295 try f.renderType(writer, ptr_ty);
4296 try writer.writeByte(')');
42974292 try f.writeCValue(writer, ptr, .Other);
42984293 try a.end(f, writer);
42994294 }
......@@ -4301,7 +4296,7 @@ fn airSlice(f: *Function, inst: Air.Inst.Index) !CValue {
43014296 const a = try Assignment.start(f, writer, Type.usize);
43024297 try f.writeCValueMember(writer, local, .{ .identifier = "len" });
43034298 try a.assign(f, writer);
4304 try f.writeCValue(writer, len, .Other);
4299 try f.writeCValue(writer, len, .Initializer);
43054300 try a.end(f, writer);
43064301 }
43074302 return local;
......@@ -4312,7 +4307,7 @@ fn airCall(
43124307 inst: Air.Inst.Index,
43134308 modifier: std.builtin.CallModifier,
43144309) !CValue {
4315 const mod = f.object.dg.module;
4310 const zcu = f.object.dg.zcu;
43164311 // Not even allowed to call panic in a naked function.
43174312 if (f.object.dg.is_naked_fn) return .none;
43184313
......@@ -4327,22 +4322,23 @@ fn airCall(
43274322 defer gpa.free(resolved_args);
43284323 for (resolved_args, args) |*resolved_arg, arg| {
43294324 const arg_ty = f.typeOf(arg);
4330 const arg_cty = try f.typeToIndex(arg_ty, .parameter);
4331 if (f.indexToCType(arg_cty).tag() == .void) {
4325 const arg_ctype = try f.ctypeFromType(arg_ty, .parameter);
4326 if (arg_ctype.index == .void) {
43324327 resolved_arg.* = .none;
43334328 continue;
43344329 }
43354330 resolved_arg.* = try f.resolveInst(arg);
4336 if (arg_cty != try f.typeToIndex(arg_ty, .complete)) {
4337 const lowered_arg_ty = try lowerFnRetTy(arg_ty, mod);
4338
4339 const array_local = try f.allocLocal(inst, lowered_arg_ty);
4331 if (!arg_ctype.eql(try f.ctypeFromType(arg_ty, .complete))) {
4332 const array_local = try f.allocAlignedLocal(inst, .{
4333 .ctype = arg_ctype,
4334 .alignas = CType.AlignAs.fromAbiAlignment(arg_ty.abiAlignment(zcu)),
4335 });
43404336 try writer.writeAll("memcpy(");
43414337 try f.writeCValueMember(writer, array_local, .{ .identifier = "array" });
43424338 try writer.writeAll(", ");
43434339 try f.writeCValue(writer, resolved_arg.*, .FunctionArgument);
43444340 try writer.writeAll(", sizeof(");
4345 try f.renderType(writer, lowered_arg_ty);
4341 try f.renderCType(writer, arg_ctype);
43464342 try writer.writeAll("));\n");
43474343 resolved_arg.* = array_local;
43484344 }
......@@ -4357,28 +4353,33 @@ fn airCall(
43574353 }
43584354
43594355 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)) {
43614357 .Fn => callee_ty,
4362 .Pointer => callee_ty.childType(mod),
4358 .Pointer => callee_ty.childType(zcu),
43634359 else => unreachable,
4364 };
4365
4366 const ret_ty = fn_ty.fnReturnType(mod);
4367 const lowered_ret_ty = try lowerFnRetTy(ret_ty, mod);
4360 }).?;
4361 const ret_ty = Type.fromInterned(fn_info.return_type);
4362 const ret_ctype: CType = if (ret_ty.isNoReturn(zcu))
4363 .{ .index = .void }
4364 else
4365 try f.ctypeFromType(ret_ty, .parameter);
43684366
43694367 const result_local = result: {
43704368 if (modifier == .always_tail) {
43714369 try writer.writeAll("zig_always_tail return ");
43724370 break :result .none;
4373 } else if (!lowered_ret_ty.hasRuntimeBitsIgnoreComptime(mod)) {
4371 } else if (ret_ctype.index == .void) {
43744372 break :result .none;
43754373 } else if (f.liveness.isUnused(inst)) {
43764374 try writer.writeByte('(');
4377 try f.renderType(writer, Type.void);
4375 try f.renderCType(writer, .{ .index = .void });
43784376 try writer.writeByte(')');
43794377 break :result .none;
43804378 } 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 });
43824383 try f.writeCValue(writer, local, .Other);
43834384 try writer.writeAll(" = ");
43844385 break :result local;
......@@ -4388,8 +4389,8 @@ fn airCall(
43884389 callee: {
43894390 known: {
43904391 const fn_decl = fn_decl: {
4391 const callee_val = (try f.air.value(pl_op.operand, mod)) orelse break :known;
4392 break :fn_decl switch (mod.intern_pool.indexToKey(callee_val.ip_index)) {
4392 const callee_val = (try f.air.value(pl_op.operand, zcu)) orelse break :known;
4393 break :fn_decl switch (zcu.intern_pool.indexToKey(callee_val.toIntern())) {
43934394 .extern_func => |extern_func| extern_func.decl,
43944395 .func => |func| func.owner_decl,
43954396 .ptr => |ptr| switch (ptr.addr) {
......@@ -4420,18 +4421,21 @@ fn airCall(
44204421 }
44214422
44224423 try writer.writeByte('(');
4423 var args_written: usize = 0;
4424 var need_comma = false;
44244425 for (resolved_args) |resolved_arg| {
44254426 if (resolved_arg == .none) continue;
4426 if (args_written != 0) try writer.writeAll(", ");
4427 if (need_comma) try writer.writeAll(", ");
4428 need_comma = true;
44274429 try f.writeCValue(writer, resolved_arg, .FunctionArgument);
4428 if (resolved_arg == .new_local) try freeLocal(f, inst, resolved_arg.new_local, null);
4429 args_written += 1;
4430 switch (resolved_arg) {
4431 .new_local => |local| try freeLocal(f, inst, local, null),
4432 else => {},
4433 }
44304434 }
44314435 try writer.writeAll(");\n");
44324436
44334437 const result = result: {
4434 if (result_local == .none or !lowersToArray(ret_ty, mod))
4438 if (result_local == .none or !lowersToArray(ret_ty, zcu))
44354439 break :result result_local;
44364440
44374441 const array_local = try f.allocLocal(inst, ret_ty);
......@@ -4465,22 +4469,22 @@ fn airDbgStmt(f: *Function, inst: Air.Inst.Index) !CValue {
44654469}
44664470
44674471fn airDbgInlineBlock(f: *Function, inst: Air.Inst.Index) !CValue {
4468 const mod = f.object.dg.module;
4472 const zcu = f.object.dg.zcu;
44694473 const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
44704474 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);
44724476 const writer = f.object.writer();
44734477 try writer.writeAll("/* ");
4474 try owner_decl.renderFullyQualifiedName(mod, writer);
4478 try owner_decl.renderFullyQualifiedName(zcu, writer);
44754479 try writer.writeAll(" */ ");
44764480 return lowerBlock(f, inst, @ptrCast(f.air.extra[extra.end..][0..extra.data.body_len]));
44774481}
44784482
44794483fn airDbgVar(f: *Function, inst: Air.Inst.Index) !CValue {
4480 const mod = f.object.dg.module;
4484 const zcu = f.object.dg.zcu;
44814485 const pl_op = f.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
44824486 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;
44844488 if (!operand_is_undef) _ = try f.resolveInst(pl_op.operand);
44854489
44864490 try reap(f, inst, &.{pl_op.operand});
......@@ -4496,7 +4500,7 @@ fn airBlock(f: *Function, inst: Air.Inst.Index) !CValue {
44964500}
44974501
44984502fn 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;
45004504 const liveness_block = f.liveness.getBlock(inst);
45014505
45024506 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)
45044508 const writer = f.object.writer();
45054509
45064510 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))
45084512 try f.allocLocal(inst, inst_ty)
45094513 else
45104514 .none;
......@@ -4526,7 +4530,7 @@ fn lowerBlock(f: *Function, inst: Air.Inst.Index, body: []const Air.Inst.Index)
45264530 try f.object.indent_writer.insertNewline();
45274531
45284532 // 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)) {
45304534 // label must be followed by an expression, include an empty one.
45314535 try writer.print("zig_block_{d}:;\n", .{block_id});
45324536 }
......@@ -4543,11 +4547,11 @@ fn airTry(f: *Function, inst: Air.Inst.Index) !CValue {
45434547}
45444548
45454549fn airTryPtr(f: *Function, inst: Air.Inst.Index) !CValue {
4546 const mod = f.object.dg.module;
4550 const zcu = f.object.dg.zcu;
45474551 const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
45484552 const extra = f.air.extraData(Air.TryPtr, ty_pl.payload);
45494553 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);
45514555 return lowerTry(f, inst, extra.data.ptr, body, err_union_ty, true);
45524556}
45534557
......@@ -4559,15 +4563,15 @@ fn lowerTry(
45594563 err_union_ty: Type,
45604564 is_ptr: bool,
45614565) !CValue {
4562 const mod = f.object.dg.module;
4566 const zcu = f.object.dg.zcu;
45634567 const err_union = try f.resolveInst(operand);
45644568 const inst_ty = f.typeOfIndex(inst);
45654569 const liveness_condbr = f.liveness.getCondBr(inst);
45664570 const writer = f.object.writer();
4567 const payload_ty = err_union_ty.errorUnionPayload(mod);
4568 const payload_has_bits = payload_ty.hasRuntimeBitsIgnoreComptime(mod);
4571 const payload_ty = err_union_ty.errorUnionPayload(zcu);
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)) {
45714575 try writer.writeAll("if (");
45724576 if (!payload_has_bits) {
45734577 if (is_ptr)
......@@ -4661,7 +4665,7 @@ const LocalResult = struct {
46614665 need_free: bool,
46624666
46634667 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
46664670 if (lr.need_free) {
46674671 // Move the freshly allocated local to be owned by this instruction,
......@@ -4673,7 +4677,7 @@ const LocalResult = struct {
46734677 try lr.free(f);
46744678 const writer = f.object.writer();
46754679 try f.writeCValue(writer, local, .Other);
4676 if (dest_ty.isAbiInt(mod)) {
4680 if (dest_ty.isAbiInt(zcu)) {
46774681 try writer.writeAll(" = ");
46784682 } else {
46794683 try writer.writeAll(" = (");
......@@ -4693,13 +4697,14 @@ const LocalResult = struct {
46934697};
46944698
46954699fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !LocalResult {
4696 const mod = f.object.dg.module;
4697 const target = mod.getTarget();
4700 const zcu = f.object.dg.zcu;
4701 const target = &f.object.dg.mod.resolved_target.result;
4702 const ctype_pool = &f.object.dg.ctype_pool;
46984703 const writer = f.object.writer();
46994704
4700 if (operand_ty.isAbiInt(mod) and dest_ty.isAbiInt(mod)) {
4701 const src_info = dest_ty.intInfo(mod);
4702 const dest_info = operand_ty.intInfo(mod);
4705 if (operand_ty.isAbiInt(zcu) and dest_ty.isAbiInt(zcu)) {
4706 const src_info = dest_ty.intInfo(zcu);
4707 const dest_info = operand_ty.intInfo(zcu);
47034708 if (src_info.signedness == dest_info.signedness and
47044709 src_info.bits == dest_info.bits)
47054710 {
......@@ -4710,7 +4715,7 @@ fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !Loca
47104715 }
47114716 }
47124717
4713 if (dest_ty.isPtrAtRuntime(mod) and operand_ty.isPtrAtRuntime(mod)) {
4718 if (dest_ty.isPtrAtRuntime(zcu) and operand_ty.isPtrAtRuntime(zcu)) {
47144719 const local = try f.allocLocal(null, dest_ty);
47154720 try f.writeCValue(writer, local, .Other);
47164721 try writer.writeAll(" = (");
......@@ -4727,7 +4732,7 @@ fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !Loca
47274732 const operand_lval = if (operand == .constant) blk: {
47284733 const operand_local = try f.allocLocal(null, operand_ty);
47294734 try f.writeCValue(writer, operand_local, .Other);
4730 if (operand_ty.isAbiInt(mod)) {
4735 if (operand_ty.isAbiInt(zcu)) {
47314736 try writer.writeAll(" = ");
47324737 } else {
47334738 try writer.writeAll(" = (");
......@@ -4747,55 +4752,60 @@ fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !Loca
47474752 try writer.writeAll(", sizeof(");
47484753 try f.renderType(
47494754 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,
47514756 );
47524757 try writer.writeAll("));\n");
47534758
47544759 // Ensure padding bits have the expected value.
4755 if (dest_ty.isAbiInt(mod)) {
4756 const dest_cty = try f.typeToCType(dest_ty, .complete);
4757 const dest_info = dest_ty.intInfo(mod);
4760 if (dest_ty.isAbiInt(zcu)) {
4761 const dest_ctype = try f.ctypeFromType(dest_ty, .complete);
4762 const dest_info = dest_ty.intInfo(zcu);
47584763 var bits: u16 = dest_info.bits;
4759 var wrap_cty: ?CType = null;
4764 var wrap_ctype: ?CType = null;
47604765 var need_bitcasts = false;
47614766
47624767 try f.writeCValue(writer, local, .Other);
4763 if (dest_cty.castTag(.array)) |pl| {
4764 try writer.print("[{d}]", .{switch (target.cpu.arch.endian()) {
4765 .little => pl.data.len - 1,
4766 .big => 0,
4767 }});
4768 const elem_cty = f.indexToCType(pl.data.elem_type);
4769 wrap_cty = elem_cty.toSignedness(dest_info.signedness);
4770 need_bitcasts = wrap_cty.?.tag() == .zig_i128;
4771 bits -= 1;
4772 bits %= @as(u16, @intCast(f.byteSize(elem_cty) * 8));
4773 bits += 1;
4768 switch (dest_ctype.info(ctype_pool)) {
4769 else => {},
4770 .array => |array_info| {
4771 try writer.print("[{d}]", .{switch (target.cpu.arch.endian()) {
4772 .little => array_info.len - 1,
4773 .big => 0,
4774 }});
4775 wrap_ctype = array_info.elem_ctype.toSignedness(dest_info.signedness);
4776 need_bitcasts = wrap_ctype.?.index == .zig_i128;
4777 bits -= 1;
4778 bits %= @as(u16, @intCast(f.byteSize(array_info.elem_ctype) * 8));
4779 bits += 1;
4780 },
47744781 }
47754782 try writer.writeAll(" = ");
47764783 if (need_bitcasts) {
47774784 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());
47794786 try writer.writeByte('(');
47804787 }
47814788 try writer.writeAll("zig_wrap_");
4782 const info_ty = try mod.intType(dest_info.signedness, bits);
4783 if (wrap_cty) |cty|
4784 try f.object.dg.renderCTypeForBuiltinFnName(writer, cty)
4789 const info_ty = try zcu.intType(dest_info.signedness, bits);
4790 if (wrap_ctype) |ctype|
4791 try f.object.dg.renderCTypeForBuiltinFnName(writer, ctype)
47854792 else
47864793 try f.object.dg.renderTypeForBuiltinFnName(writer, info_ty);
47874794 try writer.writeByte('(');
47884795 if (need_bitcasts) {
47894796 try writer.writeAll("zig_bitCast_");
4790 try f.object.dg.renderCTypeForBuiltinFnName(writer, wrap_cty.?);
4797 try f.object.dg.renderCTypeForBuiltinFnName(writer, wrap_ctype.?);
47914798 try writer.writeByte('(');
47924799 }
47934800 try f.writeCValue(writer, local, .Other);
4794 if (dest_cty.castTag(.array)) |pl| {
4795 try writer.print("[{d}]", .{switch (target.cpu.arch.endian()) {
4796 .little => pl.data.len - 1,
4797 .big => 0,
4798 }});
4801 switch (dest_ctype.info(ctype_pool)) {
4802 else => {},
4803 .array => |array_info| try writer.print("[{d}]", .{
4804 switch (target.cpu.arch.endian()) {
4805 .little => array_info.len - 1,
4806 .big => 0,
4807 },
4808 }),
47994809 }
48004810 if (need_bitcasts) try writer.writeByte(')');
48014811 try f.object.dg.renderBuiltinInfo(writer, info_ty, .bits);
......@@ -4912,7 +4922,7 @@ fn airCondBr(f: *Function, inst: Air.Inst.Index) !CValue {
49124922}
49134923
49144924fn airSwitchBr(f: *Function, inst: Air.Inst.Index) !CValue {
4915 const mod = f.object.dg.module;
4925 const zcu = f.object.dg.zcu;
49164926 const pl_op = f.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
49174927 const condition = try f.resolveInst(pl_op.operand);
49184928 try reap(f, inst, &.{pl_op.operand});
......@@ -4921,11 +4931,11 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index) !CValue {
49214931 const writer = f.object.writer();
49224932
49234933 try writer.writeAll("switch (");
4924 if (condition_ty.zigTypeTag(mod) == .Bool) {
4934 if (condition_ty.zigTypeTag(zcu) == .Bool) {
49254935 try writer.writeByte('(');
49264936 try f.renderType(writer, Type.u1);
49274937 try writer.writeByte(')');
4928 } else if (condition_ty.isPtrAtRuntime(mod)) {
4938 } else if (condition_ty.isPtrAtRuntime(zcu)) {
49294939 try writer.writeByte('(');
49304940 try f.renderType(writer, Type.usize);
49314941 try writer.writeByte(')');
......@@ -4952,12 +4962,12 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index) !CValue {
49524962 for (items) |item| {
49534963 try f.object.indent_writer.insertNewline();
49544964 try writer.writeAll("case ");
4955 if (condition_ty.isPtrAtRuntime(mod)) {
4965 if (condition_ty.isPtrAtRuntime(zcu)) {
49564966 try writer.writeByte('(');
49574967 try f.renderType(writer, Type.usize);
49584968 try writer.writeByte(')');
49594969 }
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);
49614971 try writer.writeByte(':');
49624972 }
49634973 try writer.writeByte(' ');
......@@ -4994,13 +5004,13 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index) !CValue {
49945004}
49955005
49965006fn 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;
49985008 return switch (constraint[0]) {
49995009 '{' => true,
50005010 'i', 'r' => false,
50015011 'I' => !target.cpu.arch.isArmOrThumb(),
50025012 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())) {
50045014 .ptr => |ptr| switch (ptr.addr) {
50055015 .decl => false,
50065016 else => true,
......@@ -5013,7 +5023,7 @@ fn asmInputNeedsLocal(f: *Function, constraint: []const u8, value: CValue) bool
50135023}
50145024
50155025fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
5016 const mod = f.object.dg.module;
5026 const zcu = f.object.dg.zcu;
50175027 const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
50185028 const extra = f.air.extraData(Air.Asm, ty_pl.payload);
50195029 const is_volatile = @as(u1, @truncate(extra.data.flags >> 31)) != 0;
......@@ -5028,15 +5038,18 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
50285038 const result = result: {
50295039 const writer = f.object.writer();
50305040 const inst_ty = f.typeOfIndex(inst);
5031 const local = if (inst_ty.hasRuntimeBitsIgnoreComptime(mod)) local: {
5032 const local = try f.allocLocal(inst, inst_ty);
5041 const inst_local = if (inst_ty.hasRuntimeBitsIgnoreComptime(zcu)) local: {
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 });
50335046 if (f.wantSafety()) {
5034 try f.writeCValue(writer, local, .Other);
5047 try f.writeCValue(writer, inst_local, .Other);
50355048 try writer.writeAll(" = ");
50365049 try f.writeCValue(writer, .{ .undef = inst_ty }, .Other);
50375050 try writer.writeAll(";\n");
50385051 }
5039 break :local local;
5052 break :local inst_local;
50405053 } else .none;
50415054
50425055 const locals_begin = @as(LocalIndex, @intCast(f.locals.items.len));
......@@ -5057,12 +5070,14 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
50575070
50585071 const is_reg = constraint[1] == '{';
50595072 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);
50615074 try writer.writeAll("register ");
5062 const alignment: Alignment = .none;
5063 const local_value = try f.allocLocalValue(output_ty, alignment);
5064 try f.allocs.put(gpa, local_value.new_local, false);
5065 try f.object.dg.renderTypeAndName(writer, output_ty, local_value, .{}, alignment, .complete);
5075 const output_local = try f.allocLocalValue(.{
5076 .ctype = try f.ctypeFromType(output_ty, .complete),
5077 .alignas = CType.AlignAs.fromAbiAlignment(output_ty.abiAlignment(zcu)),
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);
50665081 try writer.writeAll(" __asm(\"");
50675082 try writer.writeAll(constraint["={".len .. constraint.len - "}".len]);
50685083 try writer.writeAll("\")");
......@@ -5092,10 +5107,12 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
50925107 if (asmInputNeedsLocal(f, constraint, input_val)) {
50935108 const input_ty = f.typeOf(input);
50945109 if (is_reg) try writer.writeAll("register ");
5095 const alignment: Alignment = .none;
5096 const local_value = try f.allocLocalValue(input_ty, alignment);
5097 try f.allocs.put(gpa, local_value.new_local, false);
5098 try f.object.dg.renderTypeAndName(writer, input_ty, local_value, Const, alignment, .complete);
5110 const input_local = try f.allocLocalValue(.{
5111 .ctype = try f.ctypeFromType(input_ty, .complete),
5112 .alignas = CType.AlignAs.fromAbiAlignment(input_ty.abiAlignment(zcu)),
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);
50995116 if (is_reg) {
51005117 try writer.writeAll(" __asm(\"");
51015118 try writer.writeAll(constraint["{".len .. constraint.len - "}".len]);
......@@ -5188,7 +5205,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
51885205 try f.writeCValue(writer, .{ .local = locals_index }, .Other);
51895206 locals_index += 1;
51905207 } else if (output == .none) {
5191 try f.writeCValue(writer, local, .FunctionArgument);
5208 try f.writeCValue(writer, inst_local, .FunctionArgument);
51925209 } else {
51935210 try f.writeCValueDeref(writer, try f.resolveInst(output));
51945211 }
......@@ -5244,7 +5261,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
52445261 const is_reg = constraint[1] == '{';
52455262 if (is_reg) {
52465263 try f.writeCValueDeref(writer, if (output == .none)
5247 .{ .local_ref = local.new_local }
5264 .{ .local_ref = inst_local.new_local }
52485265 else
52495266 try f.resolveInst(output));
52505267 try writer.writeAll(" = ");
......@@ -5254,7 +5271,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
52545271 }
52555272 }
52565273
5257 break :result if (f.liveness.isUnused(inst)) .none else local;
5274 break :result if (f.liveness.isUnused(inst)) .none else inst_local;
52585275 };
52595276
52605277 var bt = iterateBigTomb(f, inst);
......@@ -5275,7 +5292,7 @@ fn airIsNull(
52755292 operator: []const u8,
52765293 is_ptr: bool,
52775294) !CValue {
5278 const mod = f.object.dg.module;
5295 const zcu = f.object.dg.zcu;
52795296 const un_op = f.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
52805297
52815298 const writer = f.object.writer();
......@@ -5292,22 +5309,22 @@ fn airIsNull(
52925309 }
52935310
52945311 const operand_ty = f.typeOf(un_op);
5295 const optional_ty = if (is_ptr) operand_ty.childType(mod) else operand_ty;
5296 const payload_ty = optional_ty.optionalChild(mod);
5297 const err_int_ty = try mod.errorIntType();
5312 const optional_ty = if (is_ptr) operand_ty.childType(zcu) else operand_ty;
5313 const payload_ty = optional_ty.optionalChild(zcu);
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))
53005317 Value.true
5301 else if (optional_ty.isPtrLikeOptional(mod))
5318 else if (optional_ty.isPtrLikeOptional(zcu))
53025319 // operand is a regular pointer, test `operand !=/== NULL`
5303 try mod.getCoerced(Value.null, optional_ty)
5304 else if (payload_ty.zigTypeTag(mod) == .ErrorSet)
5305 try mod.intValue(err_int_ty, 0)
5306 else if (payload_ty.isSlice(mod) and optional_ty.optionalReprIsPayload(mod)) rhs: {
5320 try zcu.getCoerced(Value.null, optional_ty)
5321 else if (payload_ty.zigTypeTag(zcu) == .ErrorSet)
5322 try zcu.intValue(err_int_ty, 0)
5323 else if (payload_ty.isSlice(zcu) and optional_ty.optionalReprIsPayload(zcu)) rhs: {
53075324 try writer.writeAll(".ptr");
5308 const slice_ptr_ty = payload_ty.slicePtrFieldType(mod);
5309 const opt_slice_ptr_ty = try mod.optionalType(slice_ptr_ty.toIntern());
5310 break :rhs try mod.nullValue(opt_slice_ptr_ty);
5325 const slice_ptr_ty = payload_ty.slicePtrFieldType(zcu);
5326 const opt_slice_ptr_ty = try zcu.optionalType(slice_ptr_ty.toIntern());
5327 break :rhs try zcu.nullValue(opt_slice_ptr_ty);
53115328 } else rhs: {
53125329 try writer.writeAll(".is_null");
53135330 break :rhs Value.true;
......@@ -5315,22 +5332,22 @@ fn airIsNull(
53155332 try writer.writeByte(' ');
53165333 try writer.writeAll(operator);
53175334 try writer.writeByte(' ');
5318 try f.object.dg.renderValue(writer, rhs.typeOf(mod), rhs, .Other);
5335 try f.object.dg.renderValue(writer, rhs, .Other);
53195336 try writer.writeAll(";\n");
53205337 return local;
53215338}
53225339
53235340fn airOptionalPayload(f: *Function, inst: Air.Inst.Index) !CValue {
5324 const mod = f.object.dg.module;
5341 const zcu = f.object.dg.zcu;
53255342 const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
53265343
53275344 const operand = try f.resolveInst(ty_op.operand);
53285345 try reap(f, inst, &.{ty_op.operand});
53295346 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)) {
53345351 return .none;
53355352 }
53365353
......@@ -5338,7 +5355,7 @@ fn airOptionalPayload(f: *Function, inst: Air.Inst.Index) !CValue {
53385355 const writer = f.object.writer();
53395356 const local = try f.allocLocal(inst, inst_ty);
53405357
5341 if (opt_ty.optionalReprIsPayload(mod)) {
5358 if (opt_ty.optionalReprIsPayload(zcu)) {
53425359 try f.writeCValue(writer, local, .Other);
53435360 try writer.writeAll(" = ");
53445361 try f.writeCValue(writer, operand, .Other);
......@@ -5355,24 +5372,24 @@ fn airOptionalPayload(f: *Function, inst: Air.Inst.Index) !CValue {
53555372}
53565373
53575374fn airOptionalPayloadPtr(f: *Function, inst: Air.Inst.Index) !CValue {
5358 const mod = f.object.dg.module;
5375 const zcu = f.object.dg.zcu;
53595376 const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
53605377
53615378 const writer = f.object.writer();
53625379 const operand = try f.resolveInst(ty_op.operand);
53635380 try reap(f, inst, &.{ty_op.operand});
53645381 const ptr_ty = f.typeOf(ty_op.operand);
5365 const opt_ty = ptr_ty.childType(mod);
5382 const opt_ty = ptr_ty.childType(zcu);
53665383 const inst_ty = f.typeOfIndex(inst);
53675384
5368 if (!inst_ty.childType(mod).hasRuntimeBitsIgnoreComptime(mod)) {
5385 if (!inst_ty.childType(zcu).hasRuntimeBitsIgnoreComptime(zcu)) {
53695386 return .{ .undef = inst_ty };
53705387 }
53715388
53725389 const local = try f.allocLocal(inst, inst_ty);
53735390 try f.writeCValue(writer, local, .Other);
53745391
5375 if (opt_ty.optionalReprIsPayload(mod)) {
5392 if (opt_ty.optionalReprIsPayload(zcu)) {
53765393 // the operand is just a regular pointer, no need to do anything special.
53775394 // *?*T -> **T and ?*T -> *T are **T -> **T and *T -> *T in C
53785395 try writer.writeAll(" = ");
......@@ -5386,18 +5403,18 @@ fn airOptionalPayloadPtr(f: *Function, inst: Air.Inst.Index) !CValue {
53865403}
53875404
53885405fn airOptionalPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue {
5389 const mod = f.object.dg.module;
5406 const zcu = f.object.dg.zcu;
53905407 const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
53915408 const writer = f.object.writer();
53925409 const operand = try f.resolveInst(ty_op.operand);
53935410 try reap(f, inst, &.{ty_op.operand});
53945411 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
53985415 const inst_ty = f.typeOfIndex(inst);
53995416
5400 if (opt_ty.optionalReprIsPayload(mod)) {
5417 if (opt_ty.optionalReprIsPayload(zcu)) {
54015418 if (f.liveness.isUnused(inst)) {
54025419 return .none;
54035420 }
......@@ -5412,7 +5429,7 @@ fn airOptionalPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue {
54125429 } else {
54135430 try f.writeCValueDeref(writer, operand);
54145431 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);
54165433 try writer.writeAll(";\n");
54175434
54185435 if (f.liveness.isUnused(inst)) {
......@@ -5432,67 +5449,82 @@ fn fieldLocation(
54325449 container_ptr_ty: Type,
54335450 field_ptr_ty: Type,
54345451 field_index: u32,
5435 mod: *Module,
5452 zcu: *Zcu,
54365453) union(enum) {
54375454 begin: void,
54385455 field: CValue,
54395456 byte_offset: u32,
54405457 end: void,
54415458} {
5442 const ip = &mod.intern_pool;
5443 const container_ty = container_ptr_ty.childType(mod);
5444 return switch (container_ty.zigTypeTag(mod)) {
5445 .Struct => blk: {
5446 if (mod.typeToPackedStruct(container_ty)) |struct_type| {
5447 if (field_ptr_ty.ptrInfo(mod).packed_offset.host_size == 0)
5448 break :blk .{ .byte_offset = @divExact(mod.structPackedFieldBitOffset(struct_type, field_index) + container_ptr_ty.ptrInfo(mod).packed_offset.bit_offset, 8) }
5459 const ip = &zcu.intern_pool;
5460 const container_ty = Type.fromInterned(ip.indexToKey(container_ptr_ty.toIntern()).ptr_type.child);
5461 switch (ip.indexToKey(container_ty.toIntern())) {
5462 .struct_type => {
5463 const loaded_struct = ip.loadStructType(container_ty.toIntern());
5464 switch (loaded_struct.layout) {
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) }
54495483 else
5450 break :blk .begin;
5484 .begin,
54515485 }
5452
5453 for (field_index..container_ty.structFieldCount(mod)) |next_field_index_usize| {
5454 const next_field_index: u32 = @intCast(next_field_index_usize);
5455 if (container_ty.structFieldIsComptime(next_field_index, mod)) continue;
5456 const field_ty = container_ty.structFieldType(next_field_index, mod);
5457 if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
5458
5459 break :blk .{ .field = if (container_ty.isSimpleTuple(mod))
5460 .{ .field = next_field_index }
5486 },
5487 .anon_struct_type => |anon_struct_info| {
5488 for (field_index..anon_struct_info.types.len) |next_field_index| {
5489 if (anon_struct_info.values.get(ip)[next_field_index] != .none) continue;
5490 const field_type = Type.fromInterned(anon_struct_info.types.get(ip)[next_field_index]);
5491 if (!field_type.hasRuntimeBitsIgnoreComptime(zcu)) continue;
5492 return .{ .field = if (anon_struct_info.fieldName(ip, next_field_index).unwrap()) |field_name|
5493 .{ .identifier = ip.stringToSlice(field_name) }
54615494 else
5462 .{ .identifier = ip.stringToSlice(container_ty.legacyStructFieldName(next_field_index, mod)) } };
5495 .{ .field = next_field_index } };
54635496 }
5464 break :blk if (container_ty.hasRuntimeBitsIgnoreComptime(mod)) .end else .begin;
5497 return if (container_ty.hasRuntimeBitsIgnoreComptime(zcu)) .end else .begin;
54655498 },
5466 .Union => {
5467 const union_obj = mod.typeToUnion(container_ty).?;
5468 return switch (union_obj.getLayout(ip)) {
5499 .union_type => {
5500 const loaded_union = ip.loadUnionType(container_ty.toIntern());
5501 switch (loaded_union.getLayout(ip)) {
54695502 .auto, .@"extern" => {
5470 const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[field_index]);
5471 if (!field_ty.hasRuntimeBitsIgnoreComptime(mod))
5472 return if (container_ty.unionTagTypeSafety(mod) != null and
5473 !container_ty.unionHasAllZeroBitFieldTypes(mod))
5503 const field_ty = Type.fromInterned(loaded_union.field_types.get(ip)[field_index]);
5504 if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu))
5505 return if (loaded_union.hasTag(ip) and !container_ty.unionHasAllZeroBitFieldTypes(zcu))
54745506 .{ .field = .{ .identifier = "payload" } }
54755507 else
54765508 .begin;
5477 const field_name = union_obj.loadTagType(ip).names.get(ip)[field_index];
5478 return .{ .field = if (container_ty.unionTagTypeSafety(mod)) |_|
5509 const field_name = loaded_union.loadTagType(ip).names.get(ip)[field_index];
5510 return .{ .field = if (loaded_union.hasTag(ip))
54795511 .{ .payload_identifier = ip.stringToSlice(field_name) }
54805512 else
54815513 .{ .identifier = ip.stringToSlice(field_name) } };
54825514 },
5483 .@"packed" => .begin,
5484 };
5515 .@"packed" => return .begin,
5516 }
54855517 },
5486 .Pointer => switch (container_ty.ptrSize(mod)) {
5518 .ptr_type => |ptr_info| switch (ptr_info.flags.size) {
5519 .One, .Many, .C => unreachable,
54875520 .Slice => switch (field_index) {
5488 0 => .{ .field = .{ .identifier = "ptr" } },
5489 1 => .{ .field = .{ .identifier = "len" } },
5521 0 => return .{ .field = .{ .identifier = "ptr" } },
5522 1 => return .{ .field = .{ .identifier = "len" } },
54905523 else => unreachable,
54915524 },
5492 .One, .Many, .C => unreachable,
54935525 },
54945526 else => unreachable,
5495 };
5527 }
54965528}
54975529
54985530fn airStructFieldPtr(f: *Function, inst: Air.Inst.Index) !CValue {
......@@ -5515,12 +5547,12 @@ fn airStructFieldPtrIndex(f: *Function, inst: Air.Inst.Index, index: u8) !CValue
55155547}
55165548
55175549fn airFieldParentPtr(f: *Function, inst: Air.Inst.Index) !CValue {
5518 const mod = f.object.dg.module;
5550 const zcu = f.object.dg.zcu;
55195551 const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
55205552 const extra = f.air.extraData(Air.FieldParentPtr, ty_pl.payload).data;
55215553
55225554 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
55255557 const field_ptr_ty = f.typeOf(extra.field_ptr);
55265558 const field_ptr_val = try f.resolveInst(extra.field_ptr);
......@@ -5533,10 +5565,10 @@ fn airFieldParentPtr(f: *Function, inst: Air.Inst.Index) !CValue {
55335565 try f.renderType(writer, container_ptr_ty);
55345566 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)) {
55375569 .begin => try f.writeCValue(writer, field_ptr_val, .Initializer),
55385570 .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
55415573 try writer.writeAll("((");
55425574 try f.renderType(writer, u8_ptr_ty);
......@@ -5549,19 +5581,19 @@ fn airFieldParentPtr(f: *Function, inst: Air.Inst.Index) !CValue {
55495581 try writer.writeAll("))");
55505582 },
55515583 .byte_offset => |byte_offset| {
5552 const u8_ptr_ty = try mod.adjustPtrTypeChild(field_ptr_ty, Type.u8);
5553
5554 const byte_offset_val = try mod.intValue(Type.usize, byte_offset);
5584 const u8_ptr_ty = try zcu.adjustPtrTypeChild(field_ptr_ty, Type.u8);
55555585
55565586 try writer.writeAll("((");
55575587 try f.renderType(writer, u8_ptr_ty);
55585588 try writer.writeByte(')');
55595589 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 });
55615593 },
55625594 .end => {
55635595 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))});
55655597 },
55665598 }
55675599
......@@ -5576,12 +5608,12 @@ fn fieldPtr(
55765608 container_ptr_val: CValue,
55775609 field_index: u32,
55785610) !CValue {
5579 const mod = f.object.dg.module;
5580 const container_ty = container_ptr_ty.childType(mod);
5611 const zcu = f.object.dg.zcu;
5612 const container_ty = container_ptr_ty.childType(zcu);
55815613 const field_ptr_ty = f.typeOfIndex(inst);
55825614
55835615 // Ensure complete type definition is visible before accessing fields.
5584 _ = try f.typeToIndex(container_ty, .complete);
5616 _ = try f.ctypeFromType(container_ty, .complete);
55855617
55865618 const writer = f.object.writer();
55875619 const local = try f.allocLocal(inst, field_ptr_ty);
......@@ -5590,27 +5622,27 @@ fn fieldPtr(
55905622 try f.renderType(writer, field_ptr_ty);
55915623 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)) {
55945626 .begin => try f.writeCValue(writer, container_ptr_val, .Initializer),
55955627 .field => |field| {
55965628 try writer.writeByte('&');
55975629 try f.writeCValueDerefMember(writer, container_ptr_val, field);
55985630 },
55995631 .byte_offset => |byte_offset| {
5600 const u8_ptr_ty = try mod.adjustPtrTypeChild(field_ptr_ty, Type.u8);
5601
5602 const byte_offset_val = try mod.intValue(Type.usize, byte_offset);
5632 const u8_ptr_ty = try zcu.adjustPtrTypeChild(field_ptr_ty, Type.u8);
56035633
56045634 try writer.writeAll("((");
56055635 try f.renderType(writer, u8_ptr_ty);
56065636 try writer.writeByte(')');
56075637 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 });
56095641 },
56105642 .end => {
56115643 try writer.writeByte('(');
56125644 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))});
56145646 },
56155647 }
56165648
......@@ -5619,13 +5651,13 @@ fn fieldPtr(
56195651}
56205652
56215653fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {
5622 const mod = f.object.dg.module;
5623 const ip = &mod.intern_pool;
5654 const zcu = f.object.dg.zcu;
5655 const ip = &zcu.intern_pool;
56245656 const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
56255657 const extra = f.air.extraData(Air.StructField, ty_pl.payload).data;
56265658
56275659 const inst_ty = f.typeOfIndex(inst);
5628 if (!inst_ty.hasRuntimeBitsIgnoreComptime(mod)) {
5660 if (!inst_ty.hasRuntimeBitsIgnoreComptime(zcu)) {
56295661 try reap(f, inst, &.{extra.struct_operand});
56305662 return .none;
56315663 }
......@@ -5636,110 +5668,109 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {
56365668 const writer = f.object.writer();
56375669
56385670 // 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)) {
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);
5684 const bit_offset_ty = try zcu.intType(.unsigned, Type.smallestUnsignedBits(int_info.bits - 1));
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);
5654 const bit_offset_val = try mod.intValue(bit_offset_ty, bit_offset);
5688 const field_int_signedness = if (inst_ty.isAbiInt(zcu))
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))
5657 inst_ty.intInfo(mod).signedness
5658 else
5659 .unsigned;
5660 const field_int_ty = try mod.intType(field_int_signedness, @as(u16, @intCast(inst_ty.bitSize(mod))));
5661
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);
5694 const temp_local = try f.allocLocal(inst, field_int_ty);
5695 try f.writeCValue(writer, temp_local, .Other);
5696 try writer.writeAll(" = zig_wrap_");
5697 try f.object.dg.renderTypeForBuiltinFnName(writer, field_int_ty);
5698 try writer.writeAll("((");
5699 try f.renderType(writer, field_int_ty);
56855700 try writer.writeByte(')');
5686 }
5687 if (cant_cast) try writer.writeByte(')');
5688 try f.object.dg.renderBuiltinInfo(writer, field_int_ty, .bits);
5689 try writer.writeAll(");\n");
5690 if (inst_ty.eql(field_int_ty, f.object.dg.module)) return temp_local;
5691
5692 const local = try f.allocLocal(inst, inst_ty);
5693 try writer.writeAll("memcpy(");
5694 try f.writeCValue(writer, .{ .local_ref = local.new_local }, .FunctionArgument);
5695 try writer.writeAll(", ");
5696 try f.writeCValue(writer, .{ .local_ref = temp_local.new_local }, .FunctionArgument);
5697 try writer.writeAll(", sizeof(");
5698 try f.renderType(writer, inst_ty);
5699 try writer.writeAll("));\n");
5700 try freeLocal(f, inst, temp_local.new_local, null);
5701 return local;
5702 },
5703 },
5701 const cant_cast = int_info.bits > 64;
5702 if (cant_cast) {
5703 if (field_int_ty.bitSize(zcu) > 64) return f.fail("TODO: C backend: implement casting between types > 64 bits", .{});
5704 try writer.writeAll("zig_lo_");
5705 try f.object.dg.renderTypeForBuiltinFnName(writer, struct_ty);
5706 try writer.writeByte('(');
5707 }
5708 if (bit_offset > 0) {
5709 try writer.writeAll("zig_shr_");
5710 try f.object.dg.renderTypeForBuiltinFnName(writer, struct_ty);
5711 try writer.writeByte('(');
5712 }
5713 try f.writeCValue(writer, struct_byval, .Other);
5714 if (bit_offset > 0) try writer.print(", {})", .{
5715 try f.fmtIntLiteral(try zcu.intValue(bit_offset_ty, bit_offset)),
5716 });
5717 if (cant_cast) try writer.writeByte(')');
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)
5706 .{ .field = extra.field_index }
5722 const local = try f.allocLocal(inst, inst_ty);
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) }
57075737 else
5708 .{ .identifier = ip.stringToSlice(struct_ty.legacyStructFieldName(extra.field_index, mod)) },
5709
5738 .{ .field = extra.field_index },
57105739 .union_type => field_name: {
5711 const union_obj = ip.loadUnionType(struct_ty.toIntern());
5712 if (union_obj.flagsPtr(ip).layout == .@"packed") {
5713 const operand_lval = if (struct_byval == .constant) blk: {
5714 const operand_local = try f.allocLocal(inst, struct_ty);
5715 try f.writeCValue(writer, operand_local, .Other);
5716 try writer.writeAll(" = ");
5717 try f.writeCValue(writer, struct_byval, .Initializer);
5718 try writer.writeAll(";\n");
5719 break :blk operand_local;
5720 } else struct_byval;
5721
5722 const local = try f.allocLocal(inst, inst_ty);
5723 try writer.writeAll("memcpy(&");
5724 try f.writeCValue(writer, local, .Other);
5725 try writer.writeAll(", &");
5726 try f.writeCValue(writer, operand_lval, .Other);
5727 try writer.writeAll(", sizeof(");
5728 try f.renderType(writer, inst_ty);
5729 try writer.writeAll("));\n");
5730
5731 if (struct_byval == .constant) {
5732 try freeLocal(f, inst, operand_lval.new_local, null);
5733 }
5740 const loaded_union = ip.loadUnionType(struct_ty.toIntern());
5741 switch (loaded_union.getLayout(ip)) {
5742 .auto, .@"extern" => {
5743 const name = loaded_union.loadTagType(ip).names.get(ip)[extra.field_index];
5744 break :field_name if (loaded_union.hasTag(ip))
5745 .{ .payload_identifier = ip.stringToSlice(name) }
5746 else
5747 .{ .identifier = ip.stringToSlice(name) };
5748 },
5749 .@"packed" => {
5750 const operand_lval = if (struct_byval == .constant) blk: {
5751 const operand_local = try f.allocLocal(inst, struct_ty);
5752 try f.writeCValue(writer, operand_local, .Other);
5753 try writer.writeAll(" = ");
5754 try f.writeCValue(writer, struct_byval, .Initializer);
5755 try writer.writeAll(";\n");
5756 break :blk operand_local;
5757 } else struct_byval;
5758
5759 const local = try f.allocLocal(inst, inst_ty);
5760 try writer.writeAll("memcpy(&");
5761 try f.writeCValue(writer, local, .Other);
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;
5736 } else {
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 };
5772 return local;
5773 },
57435774 }
57445775 },
57455776 else => unreachable,
......@@ -5757,7 +5788,7 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {
57575788/// *(E!T) -> E
57585789/// Note that the result is never a pointer.
57595790fn airUnwrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue {
5760 const mod = f.object.dg.module;
5791 const zcu = f.object.dg.zcu;
57615792 const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
57625793
57635794 const inst_ty = f.typeOfIndex(inst);
......@@ -5765,13 +5796,13 @@ fn airUnwrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue {
57655796 const operand_ty = f.typeOf(ty_op.operand);
57665797 try reap(f, inst, &.{ty_op.operand});
57675798
5768 const operand_is_ptr = operand_ty.zigTypeTag(mod) == .Pointer;
5769 const error_union_ty = if (operand_is_ptr) operand_ty.childType(mod) else operand_ty;
5770 const error_ty = error_union_ty.errorUnionSet(mod);
5771 const payload_ty = error_union_ty.errorUnionPayload(mod);
5799 const operand_is_ptr = operand_ty.zigTypeTag(zcu) == .Pointer;
5800 const error_union_ty = if (operand_is_ptr) operand_ty.childType(zcu) else operand_ty;
5801 const error_ty = error_union_ty.errorUnionSet(zcu);
5802 const payload_ty = error_union_ty.errorUnionPayload(zcu);
57725803 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) {
57755806 // The store will be 'x = x'; elide it.
57765807 return local;
57775808 }
......@@ -5780,35 +5811,32 @@ fn airUnwrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue {
57805811 try f.writeCValue(writer, local, .Other);
57815812 try writer.writeAll(" = ");
57825813
5783 if (!payload_ty.hasRuntimeBits(mod)) {
5784 try f.writeCValue(writer, operand, .Other);
5785 } else {
5786 if (!error_ty.errorSetIsEmpty(mod))
5787 if (operand_is_ptr)
5788 try f.writeCValueDerefMember(writer, operand, .{ .identifier = "error" })
5789 else
5790 try f.writeCValueMember(writer, operand, .{ .identifier = "error" })
5791 else {
5792 const err_int_ty = try mod.errorIntType();
5793 try f.object.dg.renderValue(writer, err_int_ty, try mod.intValue(err_int_ty, 0), .Initializer);
5794 }
5795 }
5814 if (!payload_ty.hasRuntimeBits(zcu))
5815 try f.writeCValue(writer, operand, .Other)
5816 else if (error_ty.errorSetIsEmpty(zcu))
5817 try writer.print("{}", .{
5818 try f.fmtIntLiteral(try zcu.intValue(try zcu.errorIntType(), 0)),
5819 })
5820 else if (operand_is_ptr)
5821 try f.writeCValueDerefMember(writer, operand, .{ .identifier = "error" })
5822 else
5823 try f.writeCValueMember(writer, operand, .{ .identifier = "error" });
57965824 try writer.writeAll(";\n");
57975825 return local;
57985826}
57995827
58005828fn 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;
58025830 const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
58035831
58045832 const inst_ty = f.typeOfIndex(inst);
58055833 const operand = try f.resolveInst(ty_op.operand);
58065834 try reap(f, inst, &.{ty_op.operand});
58075835 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
58105838 const writer = f.object.writer();
5811 if (!error_union_ty.errorUnionPayload(mod).hasRuntimeBits(mod)) {
5839 if (!error_union_ty.errorUnionPayload(zcu).hasRuntimeBits(zcu)) {
58125840 if (!is_ptr) return .none;
58135841
58145842 const local = try f.allocLocal(inst, inst_ty);
......@@ -5834,11 +5862,11 @@ fn airUnwrapErrUnionPay(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValu
58345862}
58355863
58365864fn airWrapOptional(f: *Function, inst: Air.Inst.Index) !CValue {
5837 const mod = f.object.dg.module;
5865 const zcu = f.object.dg.zcu;
58385866 const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
58395867
58405868 const inst_ty = f.typeOfIndex(inst);
5841 const repr_is_payload = inst_ty.optionalReprIsPayload(mod);
5869 const repr_is_payload = inst_ty.optionalReprIsPayload(zcu);
58425870 const payload_ty = f.typeOf(ty_op.operand);
58435871 const payload = try f.resolveInst(ty_op.operand);
58445872 try reap(f, inst, &.{ty_op.operand});
......@@ -5859,20 +5887,20 @@ fn airWrapOptional(f: *Function, inst: Air.Inst.Index) !CValue {
58595887 const a = try Assignment.start(f, writer, Type.bool);
58605888 try f.writeCValueMember(writer, local, .{ .identifier = "is_null" });
58615889 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);
58635891 try a.end(f, writer);
58645892 }
58655893 return local;
58665894}
58675895
58685896fn airWrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue {
5869 const mod = f.object.dg.module;
5897 const zcu = f.object.dg.zcu;
58705898 const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
58715899
58725900 const inst_ty = f.typeOfIndex(inst);
5873 const payload_ty = inst_ty.errorUnionPayload(mod);
5874 const repr_is_err = !payload_ty.hasRuntimeBitsIgnoreComptime(mod);
5875 const err_ty = inst_ty.errorUnionSet(mod);
5901 const payload_ty = inst_ty.errorUnionPayload(zcu);
5902 const repr_is_err = !payload_ty.hasRuntimeBitsIgnoreComptime(zcu);
5903 const err_ty = inst_ty.errorUnionSet(zcu);
58765904 const err = try f.resolveInst(ty_op.operand);
58775905 try reap(f, inst, &.{ty_op.operand});
58785906
......@@ -5888,7 +5916,7 @@ fn airWrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue {
58885916 const a = try Assignment.start(f, writer, payload_ty);
58895917 try f.writeCValueMember(writer, local, .{ .identifier = "payload" });
58905918 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);
58925920 try a.end(f, writer);
58935921 }
58945922 {
......@@ -5905,29 +5933,25 @@ fn airWrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue {
59055933}
59065934
59075935fn airErrUnionPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue {
5908 const mod = f.object.dg.module;
5936 const zcu = f.object.dg.zcu;
59095937 const writer = f.object.writer();
59105938 const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
59115939 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);
5915 const err_int_ty = try mod.errorIntType();
5942 const payload_ty = error_union_ty.errorUnionPayload(zcu);
5943 const err_int_ty = try zcu.errorIntType();
5944 const no_err = try zcu.intValue(err_int_ty, 0);
59165945
59175946 // First, set the non-error value.
5918 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
5947 if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) {
59195948 try f.writeCValueDeref(writer, operand);
5920 try writer.writeAll(" = ");
5921 try f.object.dg.renderValue(writer, err_int_ty, try mod.intValue(err_int_ty, 0), .Other);
5922 try writer.writeAll(";\n ");
5923
5949 try writer.print(" = {};\n", .{try f.fmtIntLiteral(no_err)});
59245950 return operand;
59255951 }
59265952 try reap(f, inst, &.{ty_op.operand});
59275953 try f.writeCValueDeref(writer, operand);
5928 try writer.writeAll(".error = ");
5929 try f.object.dg.renderValue(writer, err_int_ty, try mod.intValue(err_int_ty, 0), .Other);
5930 try writer.writeAll(";\n");
5954 try writer.print(".error = {};\n", .{try f.fmtIntLiteral(no_err)});
59315955
59325956 // Then return the payload pointer (only if it is used)
59335957 if (f.liveness.isUnused(inst)) return .none;
......@@ -5956,14 +5980,14 @@ fn airSaveErrReturnTraceIndex(f: *Function, inst: Air.Inst.Index) !CValue {
59565980}
59575981
59585982fn airWrapErrUnionPay(f: *Function, inst: Air.Inst.Index) !CValue {
5959 const mod = f.object.dg.module;
5983 const zcu = f.object.dg.zcu;
59605984 const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
59615985
59625986 const inst_ty = f.typeOfIndex(inst);
5963 const payload_ty = inst_ty.errorUnionPayload(mod);
5987 const payload_ty = inst_ty.errorUnionPayload(zcu);
59645988 const payload = try f.resolveInst(ty_op.operand);
5965 const repr_is_err = !payload_ty.hasRuntimeBitsIgnoreComptime(mod);
5966 const err_ty = inst_ty.errorUnionSet(mod);
5989 const repr_is_err = !payload_ty.hasRuntimeBitsIgnoreComptime(zcu);
5990 const err_ty = inst_ty.errorUnionSet(zcu);
59675991 try reap(f, inst, &.{ty_op.operand});
59685992
59695993 const writer = f.object.writer();
......@@ -5982,15 +6006,14 @@ fn airWrapErrUnionPay(f: *Function, inst: Air.Inst.Index) !CValue {
59826006 else
59836007 try f.writeCValueMember(writer, local, .{ .identifier = "error" });
59846008 try a.assign(f, writer);
5985 const err_int_ty = try mod.errorIntType();
5986 try f.object.dg.renderValue(writer, err_int_ty, try mod.intValue(err_int_ty, 0), .Other);
6009 try f.object.dg.renderValue(writer, try zcu.intValue(try zcu.errorIntType(), 0), .Other);
59876010 try a.end(f, writer);
59886011 }
59896012 return local;
59906013}
59916014
59926015fn 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;
59946017 const un_op = f.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
59956018
59966019 const writer = f.object.writer();
......@@ -5998,16 +6021,16 @@ fn airIsErr(f: *Function, inst: Air.Inst.Index, is_ptr: bool, operator: []const
59986021 try reap(f, inst, &.{un_op});
59996022 const operand_ty = f.typeOf(un_op);
60006023 const local = try f.allocLocal(inst, Type.bool);
6001 const err_union_ty = if (is_ptr) operand_ty.childType(mod) else operand_ty;
6002 const payload_ty = err_union_ty.errorUnionPayload(mod);
6003 const error_ty = err_union_ty.errorUnionSet(mod);
6024 const err_union_ty = if (is_ptr) operand_ty.childType(zcu) else operand_ty;
6025 const payload_ty = err_union_ty.errorUnionPayload(zcu);
6026 const error_ty = err_union_ty.errorUnionSet(zcu);
60046027
6028 const a = try Assignment.start(f, writer, Type.bool);
60056029 try f.writeCValue(writer, local, .Other);
6006 try writer.writeAll(" = ");
6007
6008 const err_int_ty = try mod.errorIntType();
6009 if (!error_ty.errorSetIsEmpty(mod))
6010 if (payload_ty.hasRuntimeBits(mod))
6030 try a.assign(f, writer);
6031 const err_int_ty = try zcu.errorIntType();
6032 if (!error_ty.errorSetIsEmpty(zcu))
6033 if (payload_ty.hasRuntimeBits(zcu))
60116034 if (is_ptr)
60126035 try f.writeCValueDerefMember(writer, operand, .{ .identifier = "error" })
60136036 else
......@@ -6015,63 +6038,85 @@ fn airIsErr(f: *Function, inst: Air.Inst.Index, is_ptr: bool, operator: []const
60156038 else
60166039 try f.writeCValue(writer, operand, .Other)
60176040 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);
60196042 try writer.writeByte(' ');
60206043 try writer.writeAll(operator);
60216044 try writer.writeByte(' ');
6022 try f.object.dg.renderValue(writer, err_int_ty, try mod.intValue(err_int_ty, 0), .Other);
6023 try writer.writeAll(";\n");
6045 try f.object.dg.renderValue(writer, try zcu.intValue(err_int_ty, 0), .Other);
6046 try a.end(f, writer);
60246047 return local;
60256048}
60266049
60276050fn 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;
60296053 const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
60306054
60316055 const operand = try f.resolveInst(ty_op.operand);
60326056 try reap(f, inst, &.{ty_op.operand});
60336057 const inst_ty = f.typeOfIndex(inst);
6058 const ptr_ty = inst_ty.slicePtrFieldType(zcu);
60346059 const writer = f.object.writer();
60356060 const local = try f.allocLocal(inst, inst_ty);
6036 const array_ty = f.typeOf(ty_op.operand).childType(mod);
6037
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("; ");
6061 const operand_ty = f.typeOf(ty_op.operand);
6062 const array_ty = operand_ty.childType(zcu);
60506063
6051 const len_val = try mod.intValue(Type.usize, array_ty.arrayLen(mod));
6052 try f.writeCValueMember(writer, local, .{ .identifier = "len" });
6053 try writer.print(" = {};\n", .{try f.fmtIntLiteral(Type.usize, len_val)});
6064 {
6065 const a = try Assignment.start(f, writer, ptr_ty);
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
60556100 return local;
60566101}
60576102
60586103fn airFloatCast(f: *Function, inst: Air.Inst.Index) !CValue {
6059 const mod = f.object.dg.module;
6104 const zcu = f.object.dg.zcu;
60606105 const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
60616106
60626107 const inst_ty = f.typeOfIndex(inst);
6063 const inst_scalar_ty = inst_ty.scalarType(mod);
6108 const inst_scalar_ty = inst_ty.scalarType(zcu);
60646109 const operand = try f.resolveInst(ty_op.operand);
60656110 try reap(f, inst, &.{ty_op.operand});
60666111 const operand_ty = f.typeOf(ty_op.operand);
6067 const scalar_ty = operand_ty.scalarType(mod);
6068 const target = f.object.dg.module.getTarget();
6112 const scalar_ty = operand_ty.scalarType(zcu);
6113 const target = &f.object.dg.mod.resolved_target.result;
60696114 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"
6071 else if (inst_scalar_ty.isInt(mod) and scalar_ty.isRuntimeFloat())
6072 if (inst_scalar_ty.isSignedInt(mod)) "fix" else "fixuns"
6073 else if (inst_scalar_ty.isRuntimeFloat() and scalar_ty.isInt(mod))
6074 if (scalar_ty.isSignedInt(mod)) "float" else "floatun"
6115 if (inst_scalar_ty.floatBits(target.*) < scalar_ty.floatBits(target.*)) "trunc" else "extend"
6116 else if (inst_scalar_ty.isInt(zcu) and scalar_ty.isRuntimeFloat())
6117 if (inst_scalar_ty.isSignedInt(zcu)) "fix" else "fixuns"
6118 else if (inst_scalar_ty.isRuntimeFloat() and scalar_ty.isInt(zcu))
6119 if (scalar_ty.isSignedInt(zcu)) "float" else "floatun"
60756120 else
60766121 unreachable;
60776122
......@@ -6082,20 +6127,20 @@ fn airFloatCast(f: *Function, inst: Air.Inst.Index) !CValue {
60826127 try f.writeCValue(writer, local, .Other);
60836128 try v.elem(f, writer);
60846129 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()) {
60866131 try writer.writeAll("zig_wrap_");
60876132 try f.object.dg.renderTypeForBuiltinFnName(writer, inst_scalar_ty);
60886133 try writer.writeByte('(');
60896134 }
60906135 try writer.writeAll("zig_");
60916136 try writer.writeAll(operation);
6092 try writer.writeAll(compilerRtAbbrev(scalar_ty, mod));
6093 try writer.writeAll(compilerRtAbbrev(inst_scalar_ty, mod));
6137 try writer.writeAll(compilerRtAbbrev(scalar_ty, zcu, target.*));
6138 try writer.writeAll(compilerRtAbbrev(inst_scalar_ty, zcu, target.*));
60946139 try writer.writeByte('(');
60956140 try f.writeCValue(writer, operand, .FunctionArgument);
60966141 try v.elem(f, writer);
60976142 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()) {
60996144 try f.object.dg.renderBuiltinInfo(writer, inst_scalar_ty, .bits);
61006145 try writer.writeByte(')');
61016146 }
......@@ -6106,7 +6151,7 @@ fn airFloatCast(f: *Function, inst: Air.Inst.Index) !CValue {
61066151}
61076152
61086153fn airIntFromPtr(f: *Function, inst: Air.Inst.Index) !CValue {
6109 const mod = f.object.dg.module;
6154 const zcu = f.object.dg.zcu;
61106155 const un_op = f.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
61116156
61126157 const operand = try f.resolveInst(un_op);
......@@ -6120,7 +6165,7 @@ fn airIntFromPtr(f: *Function, inst: Air.Inst.Index) !CValue {
61206165 try writer.writeAll(" = (");
61216166 try f.renderType(writer, inst_ty);
61226167 try writer.writeByte(')');
6123 if (operand_ty.isSlice(mod)) {
6168 if (operand_ty.isSlice(zcu)) {
61246169 try f.writeCValueMember(writer, operand, .{ .identifier = "ptr" });
61256170 } else {
61266171 try f.writeCValue(writer, operand, .Other);
......@@ -6135,18 +6180,18 @@ fn airUnBuiltinCall(
61356180 operation: []const u8,
61366181 info: BuiltinInfo,
61376182) !CValue {
6138 const mod = f.object.dg.module;
6183 const zcu = f.object.dg.zcu;
61396184 const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
61406185
61416186 const operand = try f.resolveInst(ty_op.operand);
61426187 try reap(f, inst, &.{ty_op.operand});
61436188 const inst_ty = f.typeOfIndex(inst);
6144 const inst_scalar_ty = inst_ty.scalarType(mod);
6189 const inst_scalar_ty = inst_ty.scalarType(zcu);
61456190 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);
6149 const ref_ret = inst_scalar_cty.tag() == .array;
6193 const inst_scalar_ctype = try f.ctypeFromType(inst_scalar_ty, .complete);
6194 const ref_ret = inst_scalar_ctype.info(&f.object.dg.ctype_pool) == .array;
61506195
61516196 const writer = f.object.writer();
61526197 const local = try f.allocLocal(inst, inst_ty);
......@@ -6179,23 +6224,23 @@ fn airBinBuiltinCall(
61796224 operation: []const u8,
61806225 info: BuiltinInfo,
61816226) !CValue {
6182 const mod = f.object.dg.module;
6227 const zcu = f.object.dg.zcu;
61836228 const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
61846229
61856230 const operand_ty = f.typeOf(bin_op.lhs);
6186 const operand_cty = try f.typeToCType(operand_ty, .complete);
6187 const is_big = operand_cty.tag() == .array;
6231 const operand_ctype = try f.ctypeFromType(operand_ty, .complete);
6232 const is_big = operand_ctype.info(&f.object.dg.ctype_pool) == .array;
61886233
61896234 const lhs = try f.resolveInst(bin_op.lhs);
61906235 const rhs = try f.resolveInst(bin_op.rhs);
61916236 if (!is_big) try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
61926237
61936238 const inst_ty = f.typeOfIndex(inst);
6194 const inst_scalar_ty = inst_ty.scalarType(mod);
6195 const scalar_ty = operand_ty.scalarType(mod);
6239 const inst_scalar_ty = inst_ty.scalarType(zcu);
6240 const scalar_ty = operand_ty.scalarType(zcu);
61966241
6197 const inst_scalar_cty = try f.typeToCType(inst_scalar_ty, .complete);
6198 const ref_ret = inst_scalar_cty.tag() == .array;
6242 const inst_scalar_ctype = try f.ctypeFromType(inst_scalar_ty, .complete);
6243 const ref_ret = inst_scalar_ctype.info(&f.object.dg.ctype_pool) == .array;
61996244
62006245 const writer = f.object.writer();
62016246 const local = try f.allocLocal(inst, inst_ty);
......@@ -6234,18 +6279,18 @@ fn airCmpBuiltinCall(
62346279 operation: enum { cmp, operator },
62356280 info: BuiltinInfo,
62366281) !CValue {
6237 const mod = f.object.dg.module;
6282 const zcu = f.object.dg.zcu;
62386283 const lhs = try f.resolveInst(data.lhs);
62396284 const rhs = try f.resolveInst(data.rhs);
62406285 try reap(f, inst, &.{ data.lhs, data.rhs });
62416286
62426287 const inst_ty = f.typeOfIndex(inst);
6243 const inst_scalar_ty = inst_ty.scalarType(mod);
6288 const inst_scalar_ty = inst_ty.scalarType(zcu);
62446289 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);
6248 const ref_ret = inst_scalar_cty.tag() == .array;
6292 const inst_scalar_ctype = try f.ctypeFromType(inst_scalar_ty, .complete);
6293 const ref_ret = inst_scalar_ctype.info(&f.object.dg.ctype_pool) == .array;
62496294
62506295 const writer = f.object.writer();
62516296 const local = try f.allocLocal(inst, inst_ty);
......@@ -6275,7 +6320,7 @@ fn airCmpBuiltinCall(
62756320 try writer.writeByte(')');
62766321 if (!ref_ret) try writer.print("{s}{}", .{
62776322 compareOperatorC(operator),
6278 try f.fmtIntLiteral(Type.i32, try mod.intValue(Type.i32, 0)),
6323 try f.fmtIntLiteral(try zcu.intValue(Type.i32, 0)),
62796324 });
62806325 try writer.writeAll(";\n");
62816326 try v.end(f, inst, writer);
......@@ -6284,7 +6329,7 @@ fn airCmpBuiltinCall(
62846329}
62856330
62866331fn 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;
62886333 const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
62896334 const extra = f.air.extraData(Air.Cmpxchg, ty_pl.payload).data;
62906335 const inst_ty = f.typeOfIndex(inst);
......@@ -6292,19 +6337,19 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue
62926337 const expected_value = try f.resolveInst(extra.expected_value);
62936338 const new_value = try f.resolveInst(extra.new_value);
62946339 const ptr_ty = f.typeOf(extra.ptr);
6295 const ty = ptr_ty.childType(mod);
6340 const ty = ptr_ty.childType(zcu);
62966341
62976342 const writer = f.object.writer();
62986343 const new_value_mat = try Materialize.start(f, inst, writer, ty, new_value);
62996344 try reap(f, inst, &.{ extra.ptr, extra.expected_value, extra.new_value });
63006345
63016346 const repr_ty = if (ty.isRuntimeFloat())
6302 mod.intType(.unsigned, @as(u16, @intCast(ty.abiSize(mod) * 8))) catch unreachable
6347 zcu.intType(.unsigned, @as(u16, @intCast(ty.abiSize(zcu) * 8))) catch unreachable
63036348 else
63046349 ty;
63056350
63066351 const local = try f.allocLocal(inst, inst_ty);
6307 if (inst_ty.isPtrLikeOptional(mod)) {
6352 if (inst_ty.isPtrLikeOptional(zcu)) {
63086353 {
63096354 const a = try Assignment.start(f, writer, ty);
63106355 try f.writeCValue(writer, local, .Other);
......@@ -6317,7 +6362,7 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue
63176362 try writer.print("zig_cmpxchg_{s}((zig_atomic(", .{flavor});
63186363 try f.renderType(writer, ty);
63196364 try writer.writeByte(')');
6320 if (ptr_ty.isVolatilePtr(mod)) try writer.writeAll(" volatile");
6365 if (ptr_ty.isVolatilePtr(zcu)) try writer.writeAll(" volatile");
63216366 try writer.writeAll(" *)");
63226367 try f.writeCValue(writer, ptr, .Other);
63236368 try writer.writeAll(", ");
......@@ -6331,7 +6376,7 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue
63316376 try writer.writeAll(", ");
63326377 try f.object.dg.renderTypeForBuiltinFnName(writer, ty);
63336378 try writer.writeAll(", ");
6334 try f.object.dg.renderType(writer, repr_ty);
6379 try f.renderType(writer, repr_ty);
63356380 try writer.writeByte(')');
63366381 try writer.writeAll(") {\n");
63376382 f.object.indent_writer.pushIndent();
......@@ -6359,7 +6404,7 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue
63596404 try writer.print("zig_cmpxchg_{s}((zig_atomic(", .{flavor});
63606405 try f.renderType(writer, ty);
63616406 try writer.writeByte(')');
6362 if (ptr_ty.isVolatilePtr(mod)) try writer.writeAll(" volatile");
6407 if (ptr_ty.isVolatilePtr(zcu)) try writer.writeAll(" volatile");
63636408 try writer.writeAll(" *)");
63646409 try f.writeCValue(writer, ptr, .Other);
63656410 try writer.writeAll(", ");
......@@ -6373,7 +6418,7 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue
63736418 try writer.writeAll(", ");
63746419 try f.object.dg.renderTypeForBuiltinFnName(writer, ty);
63756420 try writer.writeAll(", ");
6376 try f.object.dg.renderType(writer, repr_ty);
6421 try f.renderType(writer, repr_ty);
63776422 try writer.writeByte(')');
63786423 try a.end(f, writer);
63796424 }
......@@ -6389,12 +6434,12 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue
63896434}
63906435
63916436fn airAtomicRmw(f: *Function, inst: Air.Inst.Index) !CValue {
6392 const mod = f.object.dg.module;
6437 const zcu = f.object.dg.zcu;
63936438 const pl_op = f.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
63946439 const extra = f.air.extraData(Air.AtomicRmw, pl_op.payload).data;
63956440 const inst_ty = f.typeOfIndex(inst);
63966441 const ptr_ty = f.typeOf(pl_op.operand);
6397 const ty = ptr_ty.childType(mod);
6442 const ty = ptr_ty.childType(zcu);
63986443 const ptr = try f.resolveInst(pl_op.operand);
63996444 const operand = try f.resolveInst(extra.operand);
64006445
......@@ -6402,10 +6447,10 @@ fn airAtomicRmw(f: *Function, inst: Air.Inst.Index) !CValue {
64026447 const operand_mat = try Materialize.start(f, inst, writer, ty, operand);
64036448 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));
64066451 const is_float = ty.isRuntimeFloat();
64076452 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
64106455 const local = try f.allocLocal(inst, inst_ty);
64116456 try writer.print("zig_atomicrmw_{s}", .{toAtomicRmwSuffix(extra.op())});
......@@ -6421,7 +6466,7 @@ fn airAtomicRmw(f: *Function, inst: Air.Inst.Index) !CValue {
64216466 if (use_atomic) try writer.writeAll("zig_atomic(");
64226467 try f.renderType(writer, ty);
64236468 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");
64256470 try writer.writeAll(" *)");
64266471 try f.writeCValue(writer, ptr, .Other);
64276472 try writer.writeAll(", ");
......@@ -6431,7 +6476,7 @@ fn airAtomicRmw(f: *Function, inst: Air.Inst.Index) !CValue {
64316476 try writer.writeAll(", ");
64326477 try f.object.dg.renderTypeForBuiltinFnName(writer, ty);
64336478 try writer.writeAll(", ");
6434 try f.object.dg.renderType(writer, repr_ty);
6479 try f.renderType(writer, repr_ty);
64356480 try writer.writeAll(");\n");
64366481 try operand_mat.end(f, inst);
64376482
......@@ -6444,15 +6489,15 @@ fn airAtomicRmw(f: *Function, inst: Air.Inst.Index) !CValue {
64446489}
64456490
64466491fn airAtomicLoad(f: *Function, inst: Air.Inst.Index) !CValue {
6447 const mod = f.object.dg.module;
6492 const zcu = f.object.dg.zcu;
64486493 const atomic_load = f.air.instructions.items(.data)[@intFromEnum(inst)].atomic_load;
64496494 const ptr = try f.resolveInst(atomic_load.ptr);
64506495 try reap(f, inst, &.{atomic_load.ptr});
64516496 const ptr_ty = f.typeOf(atomic_load.ptr);
6452 const ty = ptr_ty.childType(mod);
6497 const ty = ptr_ty.childType(zcu);
64536498
64546499 const repr_ty = if (ty.isRuntimeFloat())
6455 mod.intType(.unsigned, @as(u16, @intCast(ty.abiSize(mod) * 8))) catch unreachable
6500 zcu.intType(.unsigned, @as(u16, @intCast(ty.abiSize(zcu) * 8))) catch unreachable
64566501 else
64576502 ty;
64586503
......@@ -6465,7 +6510,7 @@ fn airAtomicLoad(f: *Function, inst: Air.Inst.Index) !CValue {
64656510 try writer.writeAll(", (zig_atomic(");
64666511 try f.renderType(writer, ty);
64676512 try writer.writeByte(')');
6468 if (ptr_ty.isVolatilePtr(mod)) try writer.writeAll(" volatile");
6513 if (ptr_ty.isVolatilePtr(zcu)) try writer.writeAll(" volatile");
64696514 try writer.writeAll(" *)");
64706515 try f.writeCValue(writer, ptr, .Other);
64716516 try writer.writeAll(", ");
......@@ -6473,17 +6518,17 @@ fn airAtomicLoad(f: *Function, inst: Air.Inst.Index) !CValue {
64736518 try writer.writeAll(", ");
64746519 try f.object.dg.renderTypeForBuiltinFnName(writer, ty);
64756520 try writer.writeAll(", ");
6476 try f.object.dg.renderType(writer, repr_ty);
6521 try f.renderType(writer, repr_ty);
64776522 try writer.writeAll(");\n");
64786523
64796524 return local;
64806525}
64816526
64826527fn 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;
64846529 const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
64856530 const ptr_ty = f.typeOf(bin_op.lhs);
6486 const ty = ptr_ty.childType(mod);
6531 const ty = ptr_ty.childType(zcu);
64876532 const ptr = try f.resolveInst(bin_op.lhs);
64886533 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
64926537 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
64936538
64946539 const repr_ty = if (ty.isRuntimeFloat())
6495 mod.intType(.unsigned, @as(u16, @intCast(ty.abiSize(mod) * 8))) catch unreachable
6540 zcu.intType(.unsigned, @as(u16, @intCast(ty.abiSize(zcu) * 8))) catch unreachable
64966541 else
64976542 ty;
64986543
64996544 try writer.writeAll("zig_atomic_store((zig_atomic(");
65006545 try f.renderType(writer, ty);
65016546 try writer.writeByte(')');
6502 if (ptr_ty.isVolatilePtr(mod)) try writer.writeAll(" volatile");
6547 if (ptr_ty.isVolatilePtr(zcu)) try writer.writeAll(" volatile");
65036548 try writer.writeAll(" *)");
65046549 try f.writeCValue(writer, ptr, .Other);
65056550 try writer.writeAll(", ");
......@@ -6507,7 +6552,7 @@ fn airAtomicStore(f: *Function, inst: Air.Inst.Index, order: [*:0]const u8) !CVa
65076552 try writer.print(", {s}, ", .{order});
65086553 try f.object.dg.renderTypeForBuiltinFnName(writer, ty);
65096554 try writer.writeAll(", ");
6510 try f.object.dg.renderType(writer, repr_ty);
6555 try f.renderType(writer, repr_ty);
65116556 try writer.writeAll(");\n");
65126557 try element_mat.end(f, inst);
65136558
......@@ -6515,8 +6560,8 @@ fn airAtomicStore(f: *Function, inst: Air.Inst.Index, order: [*:0]const u8) !CVa
65156560}
65166561
65176562fn writeSliceOrPtr(f: *Function, writer: anytype, ptr: CValue, ptr_ty: Type) !void {
6518 const mod = f.object.dg.module;
6519 if (ptr_ty.isSlice(mod)) {
6563 const zcu = f.object.dg.zcu;
6564 if (ptr_ty.isSlice(zcu)) {
65206565 try f.writeCValueMember(writer, ptr, .{ .identifier = "ptr" });
65216566 } else {
65226567 try f.writeCValue(writer, ptr, .FunctionArgument);
......@@ -6524,14 +6569,14 @@ fn writeSliceOrPtr(f: *Function, writer: anytype, ptr: CValue, ptr_ty: Type) !vo
65246569}
65256570
65266571fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
6527 const mod = f.object.dg.module;
6572 const zcu = f.object.dg.zcu;
65286573 const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
65296574 const dest_ty = f.typeOf(bin_op.lhs);
65306575 const dest_slice = try f.resolveInst(bin_op.lhs);
65316576 const value = try f.resolveInst(bin_op.rhs);
65326577 const elem_ty = f.typeOf(bin_op.rhs);
6533 const elem_abi_size = elem_ty.abiSize(mod);
6534 const val_is_undef = if (try f.air.value(bin_op.rhs, mod)) |val| val.isUndefDeep(mod) else false;
6578 const elem_abi_size = elem_ty.abiSize(zcu);
6579 const val_is_undef = if (try f.air.value(bin_op.rhs, zcu)) |val| val.isUndefDeep(zcu) else false;
65356580 const writer = f.object.writer();
65366581
65376582 if (val_is_undef) {
......@@ -6541,7 +6586,7 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
65416586 }
65426587
65436588 try writer.writeAll("memset(");
6544 switch (dest_ty.ptrSize(mod)) {
6589 switch (dest_ty.ptrSize(zcu)) {
65456590 .Slice => {
65466591 try f.writeCValueMember(writer, dest_slice, .{ .identifier = "ptr" });
65476592 try writer.writeAll(", 0xaa, ");
......@@ -6553,8 +6598,8 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
65536598 }
65546599 },
65556600 .One => {
6556 const array_ty = dest_ty.childType(mod);
6557 const len = array_ty.arrayLen(mod) * elem_abi_size;
6601 const array_ty = dest_ty.childType(zcu);
6602 const len = array_ty.arrayLen(zcu) * elem_abi_size;
65586603
65596604 try f.writeCValue(writer, dest_slice, .FunctionArgument);
65606605 try writer.print(", 0xaa, {d});\n", .{len});
......@@ -6565,12 +6610,12 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
65656610 return .none;
65666611 }
65676612
6568 if (elem_abi_size > 1 or dest_ty.isVolatilePtr(mod)) {
6613 if (elem_abi_size > 1 or dest_ty.isVolatilePtr(zcu)) {
65696614 // For the assignment in this loop, the array pointer needs to get
65706615 // casted to a regular pointer, otherwise an error like this occurs:
65716616 // error: array type 'uint32_t[20]' (aka 'unsigned int[20]') is not assignable
6572 const elem_ptr_ty = try mod.ptrType(.{
6573 .child = elem_ty.ip_index,
6617 const elem_ptr_ty = try zcu.ptrType(.{
6618 .child = elem_ty.toIntern(),
65746619 .flags = .{
65756620 .size = .C,
65766621 },
......@@ -6581,17 +6626,17 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
65816626 try writer.writeAll("for (");
65826627 try f.writeCValue(writer, index, .Other);
65836628 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);
65856630 try writer.writeAll("; ");
65866631 try f.writeCValue(writer, index, .Other);
65876632 try writer.writeAll(" != ");
6588 switch (dest_ty.ptrSize(mod)) {
6633 switch (dest_ty.ptrSize(zcu)) {
65896634 .Slice => {
65906635 try f.writeCValueMember(writer, dest_slice, .{ .identifier = "len" });
65916636 },
65926637 .One => {
6593 const array_ty = dest_ty.childType(mod);
6594 try writer.print("{d}", .{array_ty.arrayLen(mod)});
6638 const array_ty = dest_ty.childType(zcu);
6639 try writer.print("{d}", .{array_ty.arrayLen(zcu)});
65956640 },
65966641 .Many, .C => unreachable,
65976642 }
......@@ -6620,7 +6665,7 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
66206665 const bitcasted = try bitcast(f, Type.u8, value, elem_ty);
66216666
66226667 try writer.writeAll("memset(");
6623 switch (dest_ty.ptrSize(mod)) {
6668 switch (dest_ty.ptrSize(zcu)) {
66246669 .Slice => {
66256670 try f.writeCValueMember(writer, dest_slice, .{ .identifier = "ptr" });
66266671 try writer.writeAll(", ");
......@@ -6630,8 +6675,8 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
66306675 try writer.writeAll(");\n");
66316676 },
66326677 .One => {
6633 const array_ty = dest_ty.childType(mod);
6634 const len = array_ty.arrayLen(mod) * elem_abi_size;
6678 const array_ty = dest_ty.childType(zcu);
6679 const len = array_ty.arrayLen(zcu) * elem_abi_size;
66356680
66366681 try f.writeCValue(writer, dest_slice, .FunctionArgument);
66376682 try writer.writeAll(", ");
......@@ -6646,7 +6691,7 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
66466691}
66476692
66486693fn airMemcpy(f: *Function, inst: Air.Inst.Index) !CValue {
6649 const mod = f.object.dg.module;
6694 const zcu = f.object.dg.zcu;
66506695 const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
66516696 const dest_ptr = try f.resolveInst(bin_op.lhs);
66526697 const src_ptr = try f.resolveInst(bin_op.rhs);
......@@ -6659,42 +6704,32 @@ fn airMemcpy(f: *Function, inst: Air.Inst.Index) !CValue {
66596704 try writer.writeAll(", ");
66606705 try writeSliceOrPtr(f, writer, src_ptr, src_ty);
66616706 try writer.writeAll(", ");
6662 switch (dest_ty.ptrSize(mod)) {
6663 .Slice => {
6664 const elem_ty = dest_ty.childType(mod);
6665 const elem_abi_size = elem_ty.abiSize(mod);
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 },
6707 switch (dest_ty.ptrSize(zcu)) {
6708 .One => try writer.print("{}", .{
6709 try f.fmtIntLiteral(try zcu.intValue(Type.usize, dest_ty.childType(zcu).arrayLen(zcu))),
6710 }),
66806711 .Many, .C => unreachable,
6712 .Slice => try f.writeCValueMember(writer, dest_ptr, .{ .identifier = "len" }),
66816713 }
6714 try writer.writeAll(" * sizeof(");
6715 try f.renderType(writer, dest_ty.elemType2(zcu));
6716 try writer.writeAll("));\n");
66826717
66836718 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
66846719 return .none;
66856720}
66866721
66876722fn airSetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue {
6688 const mod = f.object.dg.module;
6723 const zcu = f.object.dg.zcu;
66896724 const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
66906725 const union_ptr = try f.resolveInst(bin_op.lhs);
66916726 const new_tag = try f.resolveInst(bin_op.rhs);
66926727 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
66936728
6694 const union_ty = f.typeOf(bin_op.lhs).childType(mod);
6695 const layout = union_ty.unionGetLayout(mod);
6729 const union_ty = f.typeOf(bin_op.lhs).childType(zcu);
6730 const layout = union_ty.unionGetLayout(zcu);
66966731 if (layout.tag_size == 0) return .none;
6697 const tag_ty = union_ty.unionTagTypeSafety(mod).?;
6732 const tag_ty = union_ty.unionTagTypeSafety(zcu).?;
66986733
66996734 const writer = f.object.writer();
67006735 const a = try Assignment.start(f, writer, tag_ty);
......@@ -6706,14 +6741,14 @@ fn airSetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue {
67066741}
67076742
67086743fn airGetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue {
6709 const mod = f.object.dg.module;
6744 const zcu = f.object.dg.zcu;
67106745 const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
67116746
67126747 const operand = try f.resolveInst(ty_op.operand);
67136748 try reap(f, inst, &.{ty_op.operand});
67146749
67156750 const union_ty = f.typeOf(ty_op.operand);
6716 const layout = union_ty.unionGetLayout(mod);
6751 const layout = union_ty.unionGetLayout(zcu);
67176752 if (layout.tag_size == 0) return .none;
67186753
67196754 const inst_ty = f.typeOfIndex(inst);
......@@ -6728,7 +6763,7 @@ fn airGetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue {
67286763}
67296764
67306765fn airTagName(f: *Function, inst: Air.Inst.Index) !CValue {
6731 const mod = f.object.dg.module;
6766 const zcu = f.object.dg.zcu;
67326767 const un_op = f.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
67336768
67346769 const inst_ty = f.typeOfIndex(inst);
......@@ -6740,7 +6775,7 @@ fn airTagName(f: *Function, inst: Air.Inst.Index) !CValue {
67406775 const local = try f.allocLocal(inst, inst_ty);
67416776 try f.writeCValue(writer, local, .Other);
67426777 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 }),
67446779 });
67456780 try f.writeCValue(writer, operand, .Other);
67466781 try writer.writeAll(");\n");
......@@ -6765,14 +6800,14 @@ fn airErrorName(f: *Function, inst: Air.Inst.Index) !CValue {
67656800}
67666801
67676802fn airSplat(f: *Function, inst: Air.Inst.Index) !CValue {
6768 const mod = f.object.dg.module;
6803 const zcu = f.object.dg.zcu;
67696804 const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
67706805
67716806 const operand = try f.resolveInst(ty_op.operand);
67726807 try reap(f, inst, &.{ty_op.operand});
67736808
67746809 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
67776812 const writer = f.object.writer();
67786813 const local = try f.allocLocal(inst, inst_ty);
......@@ -6820,7 +6855,7 @@ fn airSelect(f: *Function, inst: Air.Inst.Index) !CValue {
68206855}
68216856
68226857fn airShuffle(f: *Function, inst: Air.Inst.Index) !CValue {
6823 const mod = f.object.dg.module;
6858 const zcu = f.object.dg.zcu;
68246859 const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
68256860 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 {
68366871 for (0..extra.mask_len) |index| {
68376872 try f.writeCValue(writer, local, .Other);
68386873 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);
68406875 try writer.writeAll("] = ");
68416876
6842 const mask_elem = (try mask.elemValue(mod, index)).toSignedInt(mod);
6843 const src_val = try mod.intValue(Type.usize, @as(u64, @intCast(mask_elem ^ mask_elem >> 63)));
6877 const mask_elem = (try mask.elemValue(zcu, index)).toSignedInt(zcu);
6878 const src_val = try zcu.intValue(Type.usize, @as(u64, @intCast(mask_elem ^ mask_elem >> 63)));
68446879
68456880 try f.writeCValue(writer, if (mask_elem >= 0) lhs else rhs, .Other);
68466881 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);
68486883 try writer.writeAll("];\n");
68496884 }
68506885
......@@ -6852,7 +6887,7 @@ fn airShuffle(f: *Function, inst: Air.Inst.Index) !CValue {
68526887}
68536888
68546889fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue {
6855 const mod = f.object.dg.module;
6890 const zcu = f.object.dg.zcu;
68566891 const reduce = f.air.instructions.items(.data)[@intFromEnum(inst)].reduce;
68576892
68586893 const scalar_ty = f.typeOfIndex(inst);
......@@ -6861,7 +6896,7 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue {
68616896 const operand_ty = f.typeOf(reduce.operand);
68626897 const writer = f.object.writer();
68636898
6864 const use_operator = scalar_ty.bitSize(mod) <= 64;
6899 const use_operator = scalar_ty.bitSize(zcu) <= 64;
68656900 const op: union(enum) {
68666901 const Func = struct { operation: []const u8, info: BuiltinInfo = .none };
68676902 float_op: Func,
......@@ -6872,28 +6907,28 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue {
68726907 .And => if (use_operator) .{ .infix = " &= " } else .{ .builtin = .{ .operation = "and" } },
68736908 .Or => if (use_operator) .{ .infix = " |= " } else .{ .builtin = .{ .operation = "or" } },
68746909 .Xor => if (use_operator) .{ .infix = " ^= " } else .{ .builtin = .{ .operation = "xor" } },
6875 .Min => switch (scalar_ty.zigTypeTag(mod)) {
6910 .Min => switch (scalar_ty.zigTypeTag(zcu)) {
68766911 .Int => if (use_operator) .{ .ternary = " < " } else .{
68776912 .builtin = .{ .operation = "min" },
68786913 },
68796914 .Float => .{ .float_op = .{ .operation = "fmin" } },
68806915 else => unreachable,
68816916 },
6882 .Max => switch (scalar_ty.zigTypeTag(mod)) {
6917 .Max => switch (scalar_ty.zigTypeTag(zcu)) {
68836918 .Int => if (use_operator) .{ .ternary = " > " } else .{
68846919 .builtin = .{ .operation = "max" },
68856920 },
68866921 .Float => .{ .float_op = .{ .operation = "fmax" } },
68876922 else => unreachable,
68886923 },
6889 .Add => switch (scalar_ty.zigTypeTag(mod)) {
6924 .Add => switch (scalar_ty.zigTypeTag(zcu)) {
68906925 .Int => if (use_operator) .{ .infix = " += " } else .{
68916926 .builtin = .{ .operation = "addw", .info = .bits },
68926927 },
68936928 .Float => .{ .builtin = .{ .operation = "add" } },
68946929 else => unreachable,
68956930 },
6896 .Mul => switch (scalar_ty.zigTypeTag(mod)) {
6931 .Mul => switch (scalar_ty.zigTypeTag(zcu)) {
68976932 .Int => if (use_operator) .{ .infix = " *= " } else .{
68986933 .builtin = .{ .operation = "mulw", .info = .bits },
68996934 },
......@@ -6908,7 +6943,7 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue {
69086943 // Equivalent to:
69096944 // reduce: {
69106945 // var accum: T = init;
6911 // for (vec) : (elem) {
6946 // for (vec) |elem| {
69126947 // accum = func(accum, elem);
69136948 // }
69146949 // break :reduce accum;
......@@ -6918,40 +6953,40 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue {
69186953 try f.writeCValue(writer, accum, .Other);
69196954 try writer.writeAll(" = ");
69206955
6921 try f.object.dg.renderValue(writer, scalar_ty, switch (reduce.operation) {
6922 .Or, .Xor => switch (scalar_ty.zigTypeTag(mod)) {
6956 try f.object.dg.renderValue(writer, switch (reduce.operation) {
6957 .Or, .Xor => switch (scalar_ty.zigTypeTag(zcu)) {
69236958 .Bool => Value.false,
6924 .Int => try mod.intValue(scalar_ty, 0),
6959 .Int => try zcu.intValue(scalar_ty, 0),
69256960 else => unreachable,
69266961 },
6927 .And => switch (scalar_ty.zigTypeTag(mod)) {
6962 .And => switch (scalar_ty.zigTypeTag(zcu)) {
69286963 .Bool => Value.true,
6929 .Int => switch (scalar_ty.intInfo(mod).signedness) {
6930 .unsigned => try scalar_ty.maxIntScalar(mod, scalar_ty),
6931 .signed => try mod.intValue(scalar_ty, -1),
6964 .Int => switch (scalar_ty.intInfo(zcu).signedness) {
6965 .unsigned => try scalar_ty.maxIntScalar(zcu, scalar_ty),
6966 .signed => try zcu.intValue(scalar_ty, -1),
69326967 },
69336968 else => unreachable,
69346969 },
6935 .Add => switch (scalar_ty.zigTypeTag(mod)) {
6936 .Int => try mod.intValue(scalar_ty, 0),
6937 .Float => try mod.floatValue(scalar_ty, 0.0),
6970 .Add => switch (scalar_ty.zigTypeTag(zcu)) {
6971 .Int => try zcu.intValue(scalar_ty, 0),
6972 .Float => try zcu.floatValue(scalar_ty, 0.0),
69386973 else => unreachable,
69396974 },
6940 .Mul => switch (scalar_ty.zigTypeTag(mod)) {
6941 .Int => try mod.intValue(scalar_ty, 1),
6942 .Float => try mod.floatValue(scalar_ty, 1.0),
6975 .Mul => switch (scalar_ty.zigTypeTag(zcu)) {
6976 .Int => try zcu.intValue(scalar_ty, 1),
6977 .Float => try zcu.floatValue(scalar_ty, 1.0),
69436978 else => unreachable,
69446979 },
6945 .Min => switch (scalar_ty.zigTypeTag(mod)) {
6980 .Min => switch (scalar_ty.zigTypeTag(zcu)) {
69466981 .Bool => Value.true,
6947 .Int => try scalar_ty.maxIntScalar(mod, scalar_ty),
6948 .Float => try mod.floatValue(scalar_ty, std.math.nan(f128)),
6982 .Int => try scalar_ty.maxIntScalar(zcu, scalar_ty),
6983 .Float => try zcu.floatValue(scalar_ty, std.math.nan(f128)),
69496984 else => unreachable,
69506985 },
6951 .Max => switch (scalar_ty.zigTypeTag(mod)) {
6986 .Max => switch (scalar_ty.zigTypeTag(zcu)) {
69526987 .Bool => Value.false,
6953 .Int => try scalar_ty.minIntScalar(mod, scalar_ty),
6954 .Float => try mod.floatValue(scalar_ty, std.math.nan(f128)),
6988 .Int => try scalar_ty.minIntScalar(zcu, scalar_ty),
6989 .Float => try zcu.floatValue(scalar_ty, std.math.nan(f128)),
69556990 else => unreachable,
69566991 },
69576992 }, .Initializer);
......@@ -7007,11 +7042,11 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue {
70077042}
70087043
70097044fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {
7010 const mod = f.object.dg.module;
7011 const ip = &mod.intern_pool;
7045 const zcu = f.object.dg.zcu;
7046 const ip = &zcu.intern_pool;
70127047 const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
70137048 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)));
70157050 const elements = @as([]const Air.Inst.Ref, @ptrCast(f.air.extra[ty_pl.payload..][0..len]));
70167051 const gpa = f.object.dg.gpa;
70177052 const resolved_elements = try gpa.alloc(CValue, elements.len);
......@@ -7028,10 +7063,9 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {
70287063
70297064 const writer = f.object.writer();
70307065 const local = try f.allocLocal(inst, inst_ty);
7031 switch (inst_ty.zigTypeTag(mod)) {
7032 .Array, .Vector => {
7033 const elem_ty = inst_ty.childType(mod);
7034 const a = try Assignment.init(f, elem_ty);
7066 switch (ip.indexToKey(inst_ty.toIntern())) {
7067 inline .array_type, .vector_type => |info, tag| {
7068 const a = try Assignment.init(f, Type.fromInterned(info.child));
70357069 for (resolved_elements, 0..) |element, i| {
70367070 try a.restart(f, writer);
70377071 try f.writeCValue(writer, local, .Other);
......@@ -7040,94 +7074,112 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {
70407074 try f.writeCValue(writer, element, .Other);
70417075 try a.end(f, writer);
70427076 }
7043 if (inst_ty.sentinel(mod)) |sentinel| {
7077 if (tag == .array_type and info.sentinel != .none) {
70447078 try a.restart(f, writer);
70457079 try f.writeCValue(writer, local, .Other);
7046 try writer.print("[{d}]", .{resolved_elements.len});
7080 try writer.print("[{d}]", .{info.len});
70477081 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);
70497083 try a.end(f, writer);
70507084 }
70517085 },
7052 .Struct => switch (inst_ty.containerLayout(mod)) {
7053 .auto, .@"extern" => for (resolved_elements, 0..) |element, field_index| {
7054 if (inst_ty.structFieldIsComptime(field_index, mod)) continue;
7055 const field_ty = inst_ty.structFieldType(field_index, mod);
7056 if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
7057
7058 const a = try Assignment.start(f, writer, field_ty);
7059 try f.writeCValueMember(writer, local, if (inst_ty.isSimpleTuple(mod))
7060 .{ .field = field_index }
7061 else
7062 .{ .identifier = ip.stringToSlice(inst_ty.legacyStructFieldName(@intCast(field_index), mod)) });
7063 try a.assign(f, writer);
7064 try f.writeCValue(writer, element, .Other);
7065 try a.end(f, writer);
7066 },
7067 .@"packed" => {
7068 try f.writeCValue(writer, local, .Other);
7069 try writer.writeAll(" = ");
7070 const int_info = inst_ty.intInfo(mod);
7071
7072 const bit_offset_ty = try mod.intType(.unsigned, Type.smallestUnsignedBits(int_info.bits - 1));
7086 .struct_type => {
7087 const loaded_struct = ip.loadStructType(inst_ty.toIntern());
7088 switch (loaded_struct.layout) {
7089 .auto, .@"extern" => {
7090 var field_it = loaded_struct.iterateRuntimeOrder(ip);
7091 while (field_it.next()) |field_index| {
7092 const field_ty = Type.fromInterned(loaded_struct.field_types.get(ip)[field_index]);
7093 if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue;
7094
7095 const a = try Assignment.start(f, writer, field_ty);
7096 try f.writeCValueMember(writer, local, if (loaded_struct.fieldName(ip, field_index).unwrap()) |field_name|
7097 .{ .identifier = ip.stringToSlice(field_name) }
7098 else
7099 .{ .field = field_index });
7100 try a.assign(f, writer);
7101 try f.writeCValue(writer, resolved_elements[field_index], .Other);
7102 try a.end(f, writer);
7103 }
7104 },
7105 .@"packed" => {
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;
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;
7112 var bit_offset: u64 = 0;
70817113
7082 if (!empty) {
7083 try writer.writeAll("zig_or_");
7114 var empty = true;
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_");
70847136 try f.object.dg.renderTypeForBuiltinFnName(writer, inst_ty);
70857137 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))) {
7102 try f.renderIntCast(writer, inst_ty, element, .{}, field_ty, .FunctionArgument);
7103 } else {
7104 try writer.writeByte('(');
7105 try f.renderType(writer, inst_ty);
7106 try writer.writeByte(')');
7107 if (field_ty.isPtrAtRuntime(mod)) {
7139 if (inst_ty.isAbiInt(zcu) and (field_ty.isAbiInt(zcu) or field_ty.isPtrAtRuntime(zcu))) {
7140 try f.renderIntCast(writer, inst_ty, element, .{}, field_ty, .FunctionArgument);
7141 } else {
71087142 try writer.writeByte('(');
7109 try f.renderType(writer, switch (int_info.signedness) {
7110 .unsigned => Type.usize,
7111 .signed => Type.isize,
7112 });
7143 try f.renderType(writer, inst_ty);
71137144 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);
71147154 }
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);
7126 empty = false;
7127 }
7156 try writer.print(", {}", .{
7157 try f.fmtIntLiteral(try zcu.intValue(bit_offset_ty, bit_offset)),
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");
7130 },
7163 bit_offset += field_ty.bitSize(zcu);
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);
71317183 },
71327184 else => unreachable,
71337185 }
......@@ -7136,21 +7188,21 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {
71367188}
71377189
71387190fn airUnionInit(f: *Function, inst: Air.Inst.Index) !CValue {
7139 const mod = f.object.dg.module;
7140 const ip = &mod.intern_pool;
7191 const zcu = f.object.dg.zcu;
7192 const ip = &zcu.intern_pool;
71417193 const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
71427194 const extra = f.air.extraData(Air.UnionInit, ty_pl.payload).data;
71437195
71447196 const union_ty = f.typeOfIndex(inst);
7145 const union_obj = mod.typeToUnion(union_ty).?;
7146 const field_name = union_obj.loadTagType(ip).names.get(ip)[extra.field_index];
7197 const loaded_union = ip.loadUnionType(union_ty.toIntern());
7198 const field_name = loaded_union.loadTagType(ip).names.get(ip)[extra.field_index];
71477199 const payload_ty = f.typeOf(extra.init);
71487200 const payload = try f.resolveInst(extra.init);
71497201 try reap(f, inst, &.{extra.init});
71507202
71517203 const writer = f.object.writer();
71527204 const local = try f.allocLocal(inst, union_ty);
7153 if (union_obj.getLayout(ip) == .@"packed") {
7205 if (loaded_union.getLayout(ip) == .@"packed") {
71547206 try f.writeCValue(writer, local, .Other);
71557207 try writer.writeAll(" = ");
71567208 try f.writeCValue(writer, payload, .Initializer);
......@@ -7158,19 +7210,16 @@ fn airUnionInit(f: *Function, inst: Air.Inst.Index) !CValue {
71587210 return local;
71597211 }
71607212
7161 const field: CValue = if (union_ty.unionTagTypeSafety(mod)) |tag_ty| field: {
7162 const layout = union_ty.unionGetLayout(mod);
7213 const field: CValue = if (union_ty.unionTagTypeSafety(zcu)) |tag_ty| field: {
7214 const layout = union_ty.unionGetLayout(zcu);
71637215 if (layout.tag_size != 0) {
7164 const field_index = tag_ty.enumFieldIndex(field_name, mod).?;
7165
7166 const tag_val = try mod.enumValueFieldIndex(tag_ty, field_index);
7167
7168 const int_val = try tag_val.intFromEnum(tag_ty, mod);
7216 const field_index = tag_ty.enumFieldIndex(field_name, zcu).?;
7217 const tag_val = try zcu.enumValueFieldIndex(tag_ty, field_index);
71697218
71707219 const a = try Assignment.start(f, writer, tag_ty);
71717220 try f.writeCValueMember(writer, local, .{ .identifier = "tag" });
71727221 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))});
71747223 try a.end(f, writer);
71757224 }
71767225 break :field .{ .payload_identifier = ip.stringToSlice(field_name) };
......@@ -7185,7 +7234,7 @@ fn airUnionInit(f: *Function, inst: Air.Inst.Index) !CValue {
71857234}
71867235
71877236fn airPrefetch(f: *Function, inst: Air.Inst.Index) !CValue {
7188 const mod = f.object.dg.module;
7237 const zcu = f.object.dg.zcu;
71897238 const prefetch = f.air.instructions.items(.data)[@intFromEnum(inst)].prefetch;
71907239
71917240 const ptr_ty = f.typeOf(prefetch.ptr);
......@@ -7196,7 +7245,7 @@ fn airPrefetch(f: *Function, inst: Air.Inst.Index) !CValue {
71967245 switch (prefetch.cache) {
71977246 .data => {
71987247 try writer.writeAll("zig_prefetch(");
7199 if (ptr_ty.isSlice(mod))
7248 if (ptr_ty.isSlice(zcu))
72007249 try f.writeCValueMember(writer, ptr, .{ .identifier = "ptr" })
72017250 else
72027251 try f.writeCValue(writer, ptr, .FunctionArgument);
......@@ -7242,14 +7291,14 @@ fn airWasmMemoryGrow(f: *Function, inst: Air.Inst.Index) !CValue {
72427291}
72437292
72447293fn airFloatNeg(f: *Function, inst: Air.Inst.Index) !CValue {
7245 const mod = f.object.dg.module;
7294 const zcu = f.object.dg.zcu;
72467295 const un_op = f.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
72477296
72487297 const operand = try f.resolveInst(un_op);
72497298 try reap(f, inst, &.{un_op});
72507299
72517300 const operand_ty = f.typeOf(un_op);
7252 const scalar_ty = operand_ty.scalarType(mod);
7301 const scalar_ty = operand_ty.scalarType(zcu);
72537302
72547303 const writer = f.object.writer();
72557304 const local = try f.allocLocal(inst, operand_ty);
......@@ -7268,15 +7317,15 @@ fn airFloatNeg(f: *Function, inst: Air.Inst.Index) !CValue {
72687317}
72697318
72707319fn airAbs(f: *Function, inst: Air.Inst.Index) !CValue {
7271 const mod = f.object.dg.module;
7320 const zcu = f.object.dg.zcu;
72727321 const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
72737322 const operand = try f.resolveInst(ty_op.operand);
72747323 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)) {
7278 .Int => if (ty.zigTypeTag(mod) == .Vector) {
7279 return f.fail("TODO implement airAbs for '{}'", .{ty.fmt(mod)});
7326 switch (scalar_ty.zigTypeTag(zcu)) {
7327 .Int => if (ty.zigTypeTag(zcu) == .Vector) {
7328 return f.fail("TODO implement airAbs for '{}'", .{ty.fmt(zcu)});
72807329 } else {
72817330 return airUnBuiltinCall(f, inst, "abs", .none);
72827331 },
......@@ -7286,8 +7335,8 @@ fn airAbs(f: *Function, inst: Air.Inst.Index) !CValue {
72867335}
72877336
72887337fn unFloatOp(f: *Function, inst: Air.Inst.Index, operand: CValue, ty: Type, operation: []const u8) !CValue {
7289 const mod = f.object.dg.module;
7290 const scalar_ty = ty.scalarType(mod);
7338 const zcu = f.object.dg.zcu;
7339 const scalar_ty = ty.scalarType(zcu);
72917340
72927341 const writer = f.object.writer();
72937342 const local = try f.allocLocal(inst, ty);
......@@ -7316,7 +7365,7 @@ fn airUnFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CVal
73167365}
73177366
73187367fn 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;
73207369 const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
73217370
73227371 const lhs = try f.resolveInst(bin_op.lhs);
......@@ -7324,7 +7373,7 @@ fn airBinFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CVa
73247373 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
73257374
73267375 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
73297378 const writer = f.object.writer();
73307379 const local = try f.allocLocal(inst, inst_ty);
......@@ -7346,7 +7395,7 @@ fn airBinFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CVa
73467395}
73477396
73487397fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue {
7349 const mod = f.object.dg.module;
7398 const zcu = f.object.dg.zcu;
73507399 const pl_op = f.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
73517400 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 {
73567405 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs, pl_op.operand });
73577406
73587407 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
73617410 const writer = f.object.writer();
73627411 const local = try f.allocLocal(inst, inst_ty);
......@@ -7381,20 +7430,20 @@ fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue {
73817430}
73827431
73837432fn airCVaStart(f: *Function, inst: Air.Inst.Index) !CValue {
7384 const mod = f.object.dg.module;
7433 const zcu = f.object.dg.zcu;
73857434 const inst_ty = f.typeOfIndex(inst);
73867435 const decl_index = f.object.dg.pass.decl;
7387 const decl = mod.declPtr(decl_index);
7388 const fn_cty = try f.typeToCType(decl.typeOf(mod), .complete);
7389 const param_len = fn_cty.castTag(.varargs_function).?.data.param_types.len;
7436 const decl = zcu.declPtr(decl_index);
7437 const function_ctype = try f.ctypeFromType(decl.typeOf(zcu), .complete);
7438 const params_len = function_ctype.info(&f.object.dg.ctype_pool).function.param_ctypes.len;
73907439
73917440 const writer = f.object.writer();
73927441 const local = try f.allocLocal(inst, inst_ty);
73937442 try writer.writeAll("va_start(*(va_list *)&");
73947443 try f.writeCValue(writer, local, .Other);
7395 if (param_len > 0) {
7444 if (params_len > 0) {
73967445 try writer.writeAll(", ");
7397 try f.writeCValue(writer, .{ .arg = param_len - 1 }, .FunctionArgument);
7446 try f.writeCValue(writer, .{ .arg = params_len - 1 }, .FunctionArgument);
73987447 }
73997448 try writer.writeAll(");\n");
74007449 return local;
......@@ -7589,9 +7638,8 @@ fn signAbbrev(signedness: std.builtin.Signedness) u8 {
75897638 };
75907639}
75917640
7592fn compilerRtAbbrev(ty: Type, mod: *Module) []const u8 {
7593 const target = mod.getTarget();
7594 return if (ty.isInt(mod)) switch (ty.intInfo(mod).bits) {
7641fn compilerRtAbbrev(ty: Type, zcu: *Zcu, target: std.Target) []const u8 {
7642 return if (ty.isInt(zcu)) switch (ty.intInfo(zcu).bits) {
75957643 1...32 => "si",
75967644 33...64 => "di",
75977645 65...128 => "ti",
......@@ -7744,7 +7792,7 @@ const FormatIntLiteralContext = struct {
77447792 dg: *DeclGen,
77457793 int_info: InternPool.Key.IntType,
77467794 kind: CType.Kind,
7747 cty: CType,
7795 ctype: CType,
77487796 val: Value,
77497797};
77507798fn formatIntLiteral(
......@@ -7753,8 +7801,9 @@ fn formatIntLiteral(
77537801 options: std.fmt.FormatOptions,
77547802 writer: anytype,
77557803) @TypeOf(writer).Error!void {
7756 const mod = data.dg.module;
7757 const target = mod.getTarget();
7804 const zcu = data.dg.zcu;
7805 const target = &data.dg.mod.resolved_target.result;
7806 const ctype_pool = &data.dg.ctype_pool;
77587807
77597808 const ExpectedContents = struct {
77607809 const base = 10;
......@@ -7774,7 +7823,7 @@ fn formatIntLiteral(
77747823 defer allocator.free(undef_limbs);
77757824
77767825 var int_buf: Value.BigIntSpace = undefined;
7777 const int = if (data.val.isUndefDeep(mod)) blk: {
7826 const int = if (data.val.isUndefDeep(zcu)) blk: {
77787827 undef_limbs = try allocator.alloc(BigIntLimb, BigInt.calcTwosCompLimbCount(data.int_info.bits));
77797828 @memset(undef_limbs, undefPattern(BigIntLimb));
77807829
......@@ -7785,10 +7834,10 @@ fn formatIntLiteral(
77857834 };
77867835 undef_int.truncate(undef_int.toConst(), data.int_info.signedness, data.int_info.bits);
77877836 break :blk undef_int.toConst();
7788 } else data.val.toBigInt(&int_buf, mod);
7837 } else data.val.toBigInt(&int_buf, zcu);
77897838 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);
77927841 var one_limbs: [BigInt.calcLimbLen(1)]BigIntLimb = undefined;
77937842 const one = BigInt.Mutable.init(&one_limbs, 1).toConst();
77947843
......@@ -7800,45 +7849,45 @@ fn formatIntLiteral(
78007849 defer allocator.free(wrap.limbs);
78017850
78027851 const c_limb_info: struct {
7803 cty: CType,
7852 ctype: CType,
78047853 count: usize,
78057854 endian: std.builtin.Endian,
78067855 homogeneous: bool,
7807 } = switch (data.cty.tag()) {
7808 else => .{
7809 .cty = CType.initTag(.void),
7810 .count = 1,
7811 .endian = .little,
7812 .homogeneous = true,
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(),
7856 } = switch (data.ctype.info(ctype_pool)) {
7857 .basic => |basic_info| switch (basic_info) {
7858 else => .{
7859 .ctype = .{ .index = .void },
7860 .count = 1,
7861 .endian = .little,
78267862 .homogeneous = true,
7827 };
7863 },
7864 .zig_u128, .zig_i128 => .{
7865 .ctype = .{ .index = .uint64_t },
7866 .count = 2,
7867 .endian = .big,
7868 .homogeneous = false,
7869 },
78287870 },
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,
78297878 };
78307879 if (c_limb_info.count == 1) {
78317880 if (wrap.addWrap(int, one, data.int_info.signedness, c_bits) or
78327881 data.int_info.signedness == .signed and wrap.subWrap(int, one, data.int_info.signedness, c_bits))
78337882 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}", .{
78357884 if (int.positive) "max" else "min", signAbbrev(data.int_info.signedness), c_bits,
78367885 }),
78377886 if (int.positive) "MAX" else "MIN",
78387887 });
78397888
78407889 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
78437892 const style: struct { base: u8, case: std.fmt.Case = undefined } = switch (fmt.len) {
78447893 0 => .{ .base = 10 },
......@@ -7869,7 +7918,7 @@ fn formatIntLiteral(
78697918 defer allocator.free(string);
78707919 try writer.writeAll(string);
78717920 } else {
7872 try data.cty.renderLiteralPrefix(writer, data.kind);
7921 try data.ctype.renderLiteralPrefix(writer, data.kind, ctype_pool);
78737922 wrap.convertToTwosComplement(int, data.int_info.signedness, c_bits);
78747923 @memset(wrap.limbs[wrap.len..], 0);
78757924 wrap.len = wrap.limbs.len;
......@@ -7879,7 +7928,7 @@ fn formatIntLiteral(
78797928 .signedness = undefined,
78807929 .bits = @as(u16, @intCast(@divExact(c_bits, c_limb_info.count))),
78817930 };
7882 var c_limb_cty: CType = undefined;
7931 var c_limb_ctype: CType = undefined;
78837932
78847933 var limb_offset: usize = 0;
78857934 const most_significant_limb_i = wrap.len - limbs_per_c_limb;
......@@ -7900,7 +7949,7 @@ fn formatIntLiteral(
79007949 {
79017950 // most significant limb is actually signed
79027951 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
79057954 c_limb_mut.positive = wrap.positive;
79067955 c_limb_mut.truncate(
......@@ -7910,7 +7959,7 @@ fn formatIntLiteral(
79107959 );
79117960 } else {
79127961 c_limb_int_info.signedness = .unsigned;
7913 c_limb_cty = c_limb_info.cty;
7962 c_limb_ctype = c_limb_info.ctype;
79147963 }
79157964
79167965 if (limb_offset > 0) try writer.writeAll(", ");
......@@ -7918,12 +7967,12 @@ fn formatIntLiteral(
79187967 .dg = data.dg,
79197968 .int_info = c_limb_int_info,
79207969 .kind = data.kind,
7921 .cty = c_limb_cty,
7922 .val = try mod.intValue_big(Type.comptime_int, c_limb_mut.toConst()),
7970 .ctype = c_limb_ctype,
7971 .val = try zcu.intValue_big(Type.comptime_int, c_limb_mut.toConst()),
79237972 }, fmt, options, writer);
79247973 }
79257974 }
7926 try data.cty.renderLiteralSuffix(writer);
7975 try data.ctype.renderLiteralSuffix(writer, ctype_pool);
79277976}
79287977
79297978const Materialize = struct {
......@@ -7966,10 +8015,10 @@ const Materialize = struct {
79668015};
79678016
79688017const Assignment = struct {
7969 cty: CType.Index,
8018 ctype: CType,
79708019
79718020 pub fn init(f: *Function, ty: Type) !Assignment {
7972 return .{ .cty = try f.typeToIndex(ty, .complete) };
8021 return .{ .ctype = try f.ctypeFromType(ty, .complete) };
79738022 }
79748023
79758024 pub fn start(f: *Function, writer: anytype, ty: Type) !Assignment {
......@@ -7997,7 +8046,7 @@ const Assignment = struct {
79978046 .assign => {},
79988047 .memcpy => {
79998048 try writer.writeAll(", sizeof(");
8000 try f.renderCType(writer, self.cty);
8049 try f.renderCType(writer, self.ctype);
80018050 try writer.writeAll("))");
80028051 },
80038052 }
......@@ -8005,7 +8054,7 @@ const Assignment = struct {
80058054 }
80068055
80078056 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)) {
80098058 else => .assign,
80108059 .array, .vector => .memcpy,
80118060 };
......@@ -8016,21 +8065,17 @@ const Vectorize = struct {
80168065 index: CValue = .none,
80178066
80188067 pub fn start(f: *Function, inst: Air.Inst.Index, writer: anytype, ty: Type) !Vectorize {
8019 const mod = f.object.dg.module;
8020 return if (ty.zigTypeTag(mod) == .Vector) index: {
8021 const len_val = try mod.intValue(Type.usize, ty.vectorLen(mod));
8022
8068 const zcu = f.object.dg.zcu;
8069 return if (ty.zigTypeTag(zcu) == .Vector) index: {
80238070 const local = try f.allocLocal(inst, Type.usize);
80248071
80258072 try writer.writeAll("for (");
80268073 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))});
80288075 try f.writeCValue(writer, local, .Other);
8029 try writer.print(" < {d}; ", .{
8030 try f.fmtIntLiteral(Type.usize, len_val),
8031 });
8076 try writer.print(" < {d}; ", .{try f.fmtIntLiteral(try zcu.intValue(Type.usize, ty.vectorLen(zcu)))});
80328077 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))});
80348079 f.object.indent_writer.pushIndent();
80358080
80368081 break :index .{ .index = local };
......@@ -8054,32 +8099,10 @@ const Vectorize = struct {
80548099 }
80558100};
80568101
8057fn lowerFnRetTy(ret_ty: Type, mod: *Module) !Type {
8058 if (ret_ty.ip_index == .noreturn_type) return Type.noreturn;
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)) {
8102fn lowersToArray(ty: Type, zcu: *Zcu) bool {
8103 return switch (ty.zigTypeTag(zcu)) {
80818104 .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,
80838106 };
80848107}
80858108
......@@ -8098,7 +8121,7 @@ fn die(f: *Function, inst: Air.Inst.Index, ref: Air.Inst.Ref) !void {
80988121 const ref_inst = ref.toIndex() orelse return;
80998122 const c_value = (f.value_map.fetchRemove(ref) orelse return).value;
81008123 const local_index = switch (c_value) {
8101 .local, .new_local => |l| l,
8124 .new_local, .local => |l| l,
81028125 else => return,
81038126 };
81048127 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 {
20332033 owner_decl.src_node + 1, // Line
20342034 try o.lowerDebugType(int_ty),
20352035 ty.abiSize(mod) * 8,
2036 ty.abiAlignment(mod).toByteUnits(0) * 8,
2036 (ty.abiAlignment(mod).toByteUnits() orelse 0) * 8,
20372037 try o.builder.debugTuple(enumerators),
20382038 );
20392039
......@@ -2120,7 +2120,7 @@ pub const Object = struct {
21202120 0, // Line
21212121 try o.lowerDebugType(ptr_ty),
21222122 ptr_size * 8,
2123 ptr_align.toByteUnits(0) * 8,
2123 (ptr_align.toByteUnits() orelse 0) * 8,
21242124 0, // Offset
21252125 );
21262126
......@@ -2131,7 +2131,7 @@ pub const Object = struct {
21312131 0, // Line
21322132 try o.lowerDebugType(len_ty),
21332133 len_size * 8,
2134 len_align.toByteUnits(0) * 8,
2134 (len_align.toByteUnits() orelse 0) * 8,
21352135 len_offset * 8,
21362136 );
21372137
......@@ -2142,7 +2142,7 @@ pub const Object = struct {
21422142 line,
21432143 .none, // Underlying type
21442144 ty.abiSize(mod) * 8,
2145 ty.abiAlignment(mod).toByteUnits(0) * 8,
2145 (ty.abiAlignment(mod).toByteUnits() orelse 0) * 8,
21462146 try o.builder.debugTuple(&.{
21472147 debug_ptr_type,
21482148 debug_len_type,
......@@ -2170,7 +2170,7 @@ pub const Object = struct {
21702170 0, // Line
21712171 debug_elem_ty,
21722172 target.ptrBitWidth(),
2173 ty.ptrAlignment(mod).toByteUnits(0) * 8,
2173 (ty.ptrAlignment(mod).toByteUnits() orelse 0) * 8,
21742174 0, // Offset
21752175 );
21762176
......@@ -2217,7 +2217,7 @@ pub const Object = struct {
22172217 0, // Line
22182218 try o.lowerDebugType(ty.childType(mod)),
22192219 ty.abiSize(mod) * 8,
2220 ty.abiAlignment(mod).toByteUnits(0) * 8,
2220 (ty.abiAlignment(mod).toByteUnits() orelse 0) * 8,
22212221 try o.builder.debugTuple(&.{
22222222 try o.builder.debugSubrange(
22232223 try o.builder.debugConstant(try o.builder.intConst(.i64, 0)),
......@@ -2260,7 +2260,7 @@ pub const Object = struct {
22602260 0, // Line
22612261 debug_elem_type,
22622262 ty.abiSize(mod) * 8,
2263 ty.abiAlignment(mod).toByteUnits(0) * 8,
2263 (ty.abiAlignment(mod).toByteUnits() orelse 0) * 8,
22642264 try o.builder.debugTuple(&.{
22652265 try o.builder.debugSubrange(
22662266 try o.builder.debugConstant(try o.builder.intConst(.i64, 0)),
......@@ -2316,7 +2316,7 @@ pub const Object = struct {
23162316 0, // Line
23172317 try o.lowerDebugType(child_ty),
23182318 payload_size * 8,
2319 payload_align.toByteUnits(0) * 8,
2319 (payload_align.toByteUnits() orelse 0) * 8,
23202320 0, // Offset
23212321 );
23222322
......@@ -2327,7 +2327,7 @@ pub const Object = struct {
23272327 0,
23282328 try o.lowerDebugType(non_null_ty),
23292329 non_null_size * 8,
2330 non_null_align.toByteUnits(0) * 8,
2330 (non_null_align.toByteUnits() orelse 0) * 8,
23312331 non_null_offset * 8,
23322332 );
23332333
......@@ -2338,7 +2338,7 @@ pub const Object = struct {
23382338 0, // Line
23392339 .none, // Underlying type
23402340 ty.abiSize(mod) * 8,
2341 ty.abiAlignment(mod).toByteUnits(0) * 8,
2341 (ty.abiAlignment(mod).toByteUnits() orelse 0) * 8,
23422342 try o.builder.debugTuple(&.{
23432343 debug_data_type,
23442344 debug_some_type,
......@@ -2396,7 +2396,7 @@ pub const Object = struct {
23962396 0, // Line
23972397 try o.lowerDebugType(Type.anyerror),
23982398 error_size * 8,
2399 error_align.toByteUnits(0) * 8,
2399 (error_align.toByteUnits() orelse 0) * 8,
24002400 error_offset * 8,
24012401 );
24022402 fields[payload_index] = try o.builder.debugMemberType(
......@@ -2406,7 +2406,7 @@ pub const Object = struct {
24062406 0, // Line
24072407 try o.lowerDebugType(payload_ty),
24082408 payload_size * 8,
2409 payload_align.toByteUnits(0) * 8,
2409 (payload_align.toByteUnits() orelse 0) * 8,
24102410 payload_offset * 8,
24112411 );
24122412
......@@ -2417,7 +2417,7 @@ pub const Object = struct {
24172417 0, // Line
24182418 .none, // Underlying type
24192419 ty.abiSize(mod) * 8,
2420 ty.abiAlignment(mod).toByteUnits(0) * 8,
2420 (ty.abiAlignment(mod).toByteUnits() orelse 0) * 8,
24212421 try o.builder.debugTuple(&fields),
24222422 );
24232423
......@@ -2485,7 +2485,7 @@ pub const Object = struct {
24852485 0,
24862486 try o.lowerDebugType(Type.fromInterned(field_ty)),
24872487 field_size * 8,
2488 field_align.toByteUnits(0) * 8,
2488 (field_align.toByteUnits() orelse 0) * 8,
24892489 field_offset * 8,
24902490 ));
24912491 }
......@@ -2497,7 +2497,7 @@ pub const Object = struct {
24972497 0, // Line
24982498 .none, // Underlying type
24992499 ty.abiSize(mod) * 8,
2500 ty.abiAlignment(mod).toByteUnits(0) * 8,
2500 (ty.abiAlignment(mod).toByteUnits() orelse 0) * 8,
25012501 try o.builder.debugTuple(fields.items),
25022502 );
25032503
......@@ -2566,7 +2566,7 @@ pub const Object = struct {
25662566 0, // Line
25672567 try o.lowerDebugType(field_ty),
25682568 field_size * 8,
2569 field_align.toByteUnits(0) * 8,
2569 (field_align.toByteUnits() orelse 0) * 8,
25702570 field_offset * 8,
25712571 ));
25722572 }
......@@ -2578,7 +2578,7 @@ pub const Object = struct {
25782578 0, // Line
25792579 .none, // Underlying type
25802580 ty.abiSize(mod) * 8,
2581 ty.abiAlignment(mod).toByteUnits(0) * 8,
2581 (ty.abiAlignment(mod).toByteUnits() orelse 0) * 8,
25822582 try o.builder.debugTuple(fields.items),
25832583 );
25842584
......@@ -2621,7 +2621,7 @@ pub const Object = struct {
26212621 0, // Line
26222622 .none, // Underlying type
26232623 ty.abiSize(mod) * 8,
2624 ty.abiAlignment(mod).toByteUnits(0) * 8,
2624 (ty.abiAlignment(mod).toByteUnits() orelse 0) * 8,
26252625 try o.builder.debugTuple(
26262626 &.{try o.lowerDebugType(Type.fromInterned(union_type.enum_tag_ty))},
26272627 ),
......@@ -2661,7 +2661,7 @@ pub const Object = struct {
26612661 0, // Line
26622662 try o.lowerDebugType(Type.fromInterned(field_ty)),
26632663 field_size * 8,
2664 field_align.toByteUnits(0) * 8,
2664 (field_align.toByteUnits() orelse 0) * 8,
26652665 0, // Offset
26662666 ));
26672667 }
......@@ -2680,7 +2680,7 @@ pub const Object = struct {
26802680 0, // Line
26812681 .none, // Underlying type
26822682 ty.abiSize(mod) * 8,
2683 ty.abiAlignment(mod).toByteUnits(0) * 8,
2683 (ty.abiAlignment(mod).toByteUnits() orelse 0) * 8,
26842684 try o.builder.debugTuple(fields.items),
26852685 );
26862686
......@@ -2711,7 +2711,7 @@ pub const Object = struct {
27112711 0, // Line
27122712 try o.lowerDebugType(Type.fromInterned(union_type.enum_tag_ty)),
27132713 layout.tag_size * 8,
2714 layout.tag_align.toByteUnits(0) * 8,
2714 (layout.tag_align.toByteUnits() orelse 0) * 8,
27152715 tag_offset * 8,
27162716 );
27172717
......@@ -2722,7 +2722,7 @@ pub const Object = struct {
27222722 0, // Line
27232723 debug_union_type,
27242724 layout.payload_size * 8,
2725 layout.payload_align.toByteUnits(0) * 8,
2725 (layout.payload_align.toByteUnits() orelse 0) * 8,
27262726 payload_offset * 8,
27272727 );
27282728
......@@ -2739,7 +2739,7 @@ pub const Object = struct {
27392739 0, // Line
27402740 .none, // Underlying type
27412741 ty.abiSize(mod) * 8,
2742 ty.abiAlignment(mod).toByteUnits(0) * 8,
2742 (ty.abiAlignment(mod).toByteUnits() orelse 0) * 8,
27432743 try o.builder.debugTuple(&full_fields),
27442744 );
27452745
......@@ -4473,7 +4473,7 @@ pub const Object = struct {
44734473 // The value cannot be undefined, because we use the `nonnull` annotation
44744474 // for non-optional pointers. We also need to respect the alignment, even though
44754475 // the address will never be dereferenced.
4476 const int: u64 = ptr_ty.ptrInfo(mod).flags.alignment.toByteUnitsOptional() orelse
4476 const int: u64 = ptr_ty.ptrInfo(mod).flags.alignment.toByteUnits() orelse
44774477 // Note that these 0xaa values are appropriate even in release-optimized builds
44784478 // because we need a well-defined value that is not null, and LLVM does not
44794479 // 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 {
172172 };
173173}
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 {
176176 // TODO: use alarm() here to prevent infinite loops
177177 PanicSwitch.preDispatch();
178178
src/link.zig+31-64
......@@ -188,15 +188,10 @@ pub const File = struct {
188188 emit: Compilation.Emit,
189189 options: OpenOptions,
190190 ) !*File {
191 const tag = Tag.fromObjectFormat(comp.root_mod.resolved_target.result.ofmt);
192 switch (tag) {
193 .c => {
194 const ptr = try C.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);
191 switch (Tag.fromObjectFormat(comp.root_mod.resolved_target.result.ofmt)) {
192 inline else => |tag| {
193 if (tag != .c and build_options.only_c) unreachable;
194 const ptr = try tag.Type().open(arena, comp, emit, options);
200195 return &ptr.base;
201196 },
202197 }
......@@ -208,25 +203,17 @@ pub const File = struct {
208203 emit: Compilation.Emit,
209204 options: OpenOptions,
210205 ) !*File {
211 const tag = Tag.fromObjectFormat(comp.root_mod.resolved_target.result.ofmt);
212 switch (tag) {
213 .c => {
214 const ptr = try C.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);
206 switch (Tag.fromObjectFormat(comp.root_mod.resolved_target.result.ofmt)) {
207 inline else => |tag| {
208 if (tag != .c and build_options.only_c) unreachable;
209 const ptr = try tag.Type().createEmpty(arena, comp, emit, options);
220210 return &ptr.base;
221211 },
222212 }
223213 }
224214
225215 pub fn cast(base: *File, comptime T: type) ?*T {
226 if (base.tag != T.base_tag)
227 return null;
228
229 return @fieldParentPtr(T, "base", base);
216 return if (base.tag == T.base_tag) @fieldParentPtr("base", base) else null;
230217 }
231218
232219 pub fn makeWritable(base: *File) !void {
......@@ -383,7 +370,7 @@ pub const File = struct {
383370 .c => unreachable,
384371 .nvptx => unreachable,
385372 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);
387374 },
388375 }
389376 }
......@@ -402,7 +389,7 @@ pub const File = struct {
402389 .c => unreachable,
403390 .nvptx => unreachable,
404391 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);
406393 },
407394 }
408395 }
......@@ -412,12 +399,9 @@ pub const File = struct {
412399 const decl = module.declPtr(decl_index);
413400 assert(decl.has_tv);
414401 switch (base.tag) {
415 .c => {
416 return @fieldParentPtr(C, "base", base).updateDecl(module, decl_index);
417 },
418402 inline else => |tag| {
419 if (build_options.only_c) unreachable;
420 return @fieldParentPtr(tag.Type(), "base", base).updateDecl(module, decl_index);
403 if (tag != .c and build_options.only_c) unreachable;
404 return @as(*tag.Type(), @fieldParentPtr("base", base)).updateDecl(module, decl_index);
421405 },
422406 }
423407 }
......@@ -431,12 +415,9 @@ pub const File = struct {
431415 liveness: Liveness,
432416 ) UpdateDeclError!void {
433417 switch (base.tag) {
434 .c => {
435 return @fieldParentPtr(C, "base", base).updateFunc(module, func_index, air, liveness);
436 },
437418 inline else => |tag| {
438 if (build_options.only_c) unreachable;
439 return @fieldParentPtr(tag.Type(), "base", base).updateFunc(module, func_index, air, liveness);
419 if (tag != .c and build_options.only_c) unreachable;
420 return @as(*tag.Type(), @fieldParentPtr("base", base)).updateFunc(module, func_index, air, liveness);
440421 },
441422 }
442423 }
......@@ -446,12 +427,9 @@ pub const File = struct {
446427 assert(decl.has_tv);
447428 switch (base.tag) {
448429 .spirv, .nvptx => {},
449 .c => {
450 return @fieldParentPtr(C, "base", base).updateDeclLineNumber(module, decl_index);
451 },
452430 inline else => |tag| {
453 if (build_options.only_c) unreachable;
454 return @fieldParentPtr(tag.Type(), "base", base).updateDeclLineNumber(module, decl_index);
431 if (tag != .c and build_options.only_c) unreachable;
432 return @as(*tag.Type(), @fieldParentPtr("base", base)).updateDeclLineNumber(module, decl_index);
455433 },
456434 }
457435 }
......@@ -473,11 +451,9 @@ pub const File = struct {
473451 base.releaseLock();
474452 if (base.file) |f| f.close();
475453 switch (base.tag) {
476 .c => @fieldParentPtr(C, "base", base).deinit(),
477
478454 inline else => |tag| {
479 if (build_options.only_c) unreachable;
480 @fieldParentPtr(tag.Type(), "base", base).deinit();
455 if (tag != .c and build_options.only_c) unreachable;
456 @as(*tag.Type(), @fieldParentPtr("base", base)).deinit();
481457 },
482458 }
483459 }
......@@ -560,7 +536,7 @@ pub const File = struct {
560536 pub fn flush(base: *File, arena: Allocator, prog_node: *std.Progress.Node) FlushError!void {
561537 if (build_options.only_c) {
562538 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);
564540 }
565541 const comp = base.comp;
566542 if (comp.clang_preprocessor_mode == .yes or comp.clang_preprocessor_mode == .pch) {
......@@ -587,7 +563,7 @@ pub const File = struct {
587563 }
588564 switch (base.tag) {
589565 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);
591567 },
592568 }
593569 }
......@@ -596,12 +572,9 @@ pub const File = struct {
596572 /// rather than final output mode.
597573 pub fn flushModule(base: *File, arena: Allocator, prog_node: *std.Progress.Node) FlushError!void {
598574 switch (base.tag) {
599 .c => {
600 return @fieldParentPtr(C, "base", base).flushModule(arena, prog_node);
601 },
602575 inline else => |tag| {
603 if (build_options.only_c) unreachable;
604 return @fieldParentPtr(tag.Type(), "base", base).flushModule(arena, prog_node);
576 if (tag != .c and build_options.only_c) unreachable;
577 return @as(*tag.Type(), @fieldParentPtr("base", base)).flushModule(arena, prog_node);
605578 },
606579 }
607580 }
......@@ -609,12 +582,9 @@ pub const File = struct {
609582 /// Called when a Decl is deleted from the Module.
610583 pub fn freeDecl(base: *File, decl_index: InternPool.DeclIndex) void {
611584 switch (base.tag) {
612 .c => {
613 @fieldParentPtr(C, "base", base).freeDecl(decl_index);
614 },
615585 inline else => |tag| {
616 if (build_options.only_c) unreachable;
617 @fieldParentPtr(tag.Type(), "base", base).freeDecl(decl_index);
586 if (tag != .c and build_options.only_c) unreachable;
587 @as(*tag.Type(), @fieldParentPtr("base", base)).freeDecl(decl_index);
618588 },
619589 }
620590 }
......@@ -635,12 +605,9 @@ pub const File = struct {
635605 exports: []const *Module.Export,
636606 ) UpdateExportsError!void {
637607 switch (base.tag) {
638 .c => {
639 return @fieldParentPtr(C, "base", base).updateExports(module, exported, exports);
640 },
641608 inline else => |tag| {
642 if (build_options.only_c) unreachable;
643 return @fieldParentPtr(tag.Type(), "base", base).updateExports(module, exported, exports);
609 if (tag != .c and build_options.only_c) unreachable;
610 return @as(*tag.Type(), @fieldParentPtr("base", base)).updateExports(module, exported, exports);
644611 },
645612 }
646613 }
......@@ -664,7 +631,7 @@ pub const File = struct {
664631 .spirv => unreachable,
665632 .nvptx => unreachable,
666633 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);
668635 },
669636 }
670637 }
......@@ -683,7 +650,7 @@ pub const File = struct {
683650 .spirv => unreachable,
684651 .nvptx => unreachable,
685652 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);
687654 },
688655 }
689656 }
......@@ -695,7 +662,7 @@ pub const File = struct {
695662 .spirv => unreachable,
696663 .nvptx => unreachable,
697664 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);
699666 },
700667 }
701668 }
......@@ -714,7 +681,7 @@ pub const File = struct {
714681 => {},
715682
716683 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);
718685 },
719686 }
720687 }
src/link/C.zig+157-164
......@@ -6,7 +6,8 @@ const fs = std.fs;
66
77const C = @This();
88const build_options = @import("build_options");
9const Module = @import("../Module.zig");
9const Zcu = @import("../Module.zig");
10const Module = @import("../Package/Module.zig");
1011const InternPool = @import("../InternPool.zig");
1112const Alignment = InternPool.Alignment;
1213const Compilation = @import("../Compilation.zig");
......@@ -68,13 +69,13 @@ pub const DeclBlock = struct {
6869 fwd_decl: String = String.empty,
6970 /// Each `Decl` stores a set of used `CType`s. In `flush()`, we iterate
7071 /// over each `Decl` and generate the definition for each used `CType` once.
71 ctypes: codegen.CType.Store = .{},
72 /// Key and Value storage use the ctype arena.
72 ctype_pool: codegen.CType.Pool = codegen.CType.Pool.empty,
73 /// May contain string references to ctype_pool
7374 lazy_fns: codegen.LazyFnMap = .{},
7475
7576 fn deinit(db: *DeclBlock, gpa: Allocator) void {
7677 db.lazy_fns.deinit(gpa);
77 db.ctypes.deinit(gpa);
78 db.ctype_pool.deinit(gpa);
7879 db.* = undefined;
7980 }
8081};
......@@ -177,23 +178,24 @@ pub fn freeDecl(self: *C, decl_index: InternPool.DeclIndex) void {
177178
178179pub fn updateFunc(
179180 self: *C,
180 module: *Module,
181 zcu: *Zcu,
181182 func_index: InternPool.Index,
182183 air: Air,
183184 liveness: Liveness,
184185) !void {
185186 const gpa = self.base.comp.gpa;
186187
187 const func = module.funcInfo(func_index);
188 const func = zcu.funcInfo(func_index);
188189 const decl_index = func.owner_decl;
189 const decl = module.declPtr(decl_index);
190 const decl = zcu.declPtr(decl_index);
190191 const gop = try self.decl_table.getOrPut(gpa, decl_index);
191192 if (!gop.found_existing) gop.value_ptr.* = .{};
192 const ctypes = &gop.value_ptr.ctypes;
193 const ctype_pool = &gop.value_ptr.ctype_pool;
193194 const lazy_fns = &gop.value_ptr.lazy_fns;
194195 const fwd_decl = &self.fwd_decl_buf;
195196 const code = &self.code_buf;
196 ctypes.clearRetainingCapacity(gpa);
197 try ctype_pool.init(gpa);
198 ctype_pool.clearRetainingCapacity();
197199 lazy_fns.clearRetainingCapacity();
198200 fwd_decl.clearRetainingCapacity();
199201 code.clearRetainingCapacity();
......@@ -206,12 +208,14 @@ pub fn updateFunc(
206208 .object = .{
207209 .dg = .{
208210 .gpa = gpa,
209 .module = module,
211 .zcu = zcu,
212 .mod = zcu.namespacePtr(decl.src_namespace).file_scope.mod,
210213 .error_msg = null,
211214 .pass = .{ .decl = decl_index },
212 .is_naked_fn = decl.typeOf(module).fnCallingConvention(module) == .Naked,
215 .is_naked_fn = decl.typeOf(zcu).fnCallingConvention(zcu) == .Naked,
213216 .fwd_decl = fwd_decl.toManaged(gpa),
214 .ctypes = ctypes.*,
217 .ctype_pool = ctype_pool.*,
218 .scratch = .{},
215219 .anon_decl_deps = self.anon_decls,
216220 .aligned_anon_decls = self.aligned_anon_decls,
217221 },
......@@ -220,36 +224,32 @@ pub fn updateFunc(
220224 },
221225 .lazy_fns = lazy_fns.*,
222226 };
223
224227 function.object.indent_writer = .{ .underlying_writer = function.object.code.writer() };
225228 defer {
226229 self.anon_decls = function.object.dg.anon_decl_deps;
227230 self.aligned_anon_decls = function.object.dg.aligned_anon_decls;
228231 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());
229237 code.* = function.object.code.moveToUnmanaged();
230238 function.deinit();
231239 }
232240
233241 codegen.genFunc(&function) catch |err| switch (err) {
234242 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.?);
236244 return;
237245 },
238246 else => |e| return e,
239247 };
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);
249248 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);
250250}
251251
252fn updateAnonDecl(self: *C, module: *Module, i: usize) !void {
252fn updateAnonDecl(self: *C, zcu: *Zcu, i: usize) !void {
253253 const gpa = self.base.comp.gpa;
254254 const anon_decl = self.anon_decls.keys()[i];
255255
......@@ -261,12 +261,14 @@ fn updateAnonDecl(self: *C, module: *Module, i: usize) !void {
261261 var object: codegen.Object = .{
262262 .dg = .{
263263 .gpa = gpa,
264 .module = module,
264 .zcu = zcu,
265 .mod = zcu.root_mod,
265266 .error_msg = null,
266267 .pass = .{ .anon = anon_decl },
267268 .is_naked_fn = false,
268269 .fwd_decl = fwd_decl.toManaged(gpa),
269 .ctypes = .{},
270 .ctype_pool = codegen.CType.Pool.empty,
271 .scratch = .{},
270272 .anon_decl_deps = self.anon_decls,
271273 .aligned_anon_decls = self.aligned_anon_decls,
272274 },
......@@ -274,62 +276,64 @@ fn updateAnonDecl(self: *C, module: *Module, i: usize) !void {
274276 .indent_writer = undefined, // set later so we can get a pointer to object.code
275277 };
276278 object.indent_writer = .{ .underlying_writer = object.code.writer() };
277
278279 defer {
279280 self.anon_decls = object.dg.anon_decl_deps;
280281 self.aligned_anon_decls = object.dg.aligned_anon_decls;
281 object.dg.ctypes.deinit(object.dg.gpa);
282282 fwd_decl.* = object.dg.fwd_decl.moveToUnmanaged();
283 object.dg.ctype_pool.deinit(object.dg.gpa);
284 object.dg.scratch.deinit(gpa);
283285 code.* = object.code.moveToUnmanaged();
284286 }
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) };
287290 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) {
289292 error.AnalysisFail => {
290293 @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.?);
292295 //return;
293296 },
294297 else => |e| return e,
295298 };
296299
297 // Free excess allocated memory for this Decl.
298 object.dg.ctypes.shrinkAndFree(gpa, object.dg.ctypes.count());
299
300 object.dg.ctype_pool.freeUnusedCapacity(gpa);
300301 object.dg.anon_decl_deps.values()[i] = .{
301302 .code = try self.addString(object.code.items),
302303 .fwd_decl = try self.addString(object.dg.fwd_decl.items),
303 .ctypes = object.dg.ctypes.move(),
304 .ctype_pool = object.dg.ctype_pool.move(),
304305 };
305306}
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 {
308309 const tracy = trace(@src());
309310 defer tracy.end();
310311
311312 const gpa = self.base.comp.gpa;
312313
314 const decl = zcu.declPtr(decl_index);
313315 const gop = try self.decl_table.getOrPut(gpa, decl_index);
314 if (!gop.found_existing) {
315 gop.value_ptr.* = .{};
316 }
317 const ctypes = &gop.value_ptr.ctypes;
316 errdefer _ = self.decl_table.pop();
317 if (!gop.found_existing) gop.value_ptr.* = .{};
318 const ctype_pool = &gop.value_ptr.ctype_pool;
318319 const fwd_decl = &self.fwd_decl_buf;
319320 const code = &self.code_buf;
320 ctypes.clearRetainingCapacity(gpa);
321 try ctype_pool.init(gpa);
322 ctype_pool.clearRetainingCapacity();
321323 fwd_decl.clearRetainingCapacity();
322324 code.clearRetainingCapacity();
323325
324326 var object: codegen.Object = .{
325327 .dg = .{
326328 .gpa = gpa,
327 .module = module,
329 .zcu = zcu,
330 .mod = zcu.namespacePtr(decl.src_namespace).file_scope.mod,
328331 .error_msg = null,
329332 .pass = .{ .decl = decl_index },
330333 .is_naked_fn = false,
331334 .fwd_decl = fwd_decl.toManaged(gpa),
332 .ctypes = ctypes.*,
335 .ctype_pool = ctype_pool.*,
336 .scratch = .{},
333337 .anon_decl_deps = self.anon_decls,
334338 .aligned_anon_decls = self.aligned_anon_decls,
335339 },
......@@ -340,33 +344,29 @@ pub fn updateDecl(self: *C, module: *Module, decl_index: InternPool.DeclIndex) !
340344 defer {
341345 self.anon_decls = object.dg.anon_decl_deps;
342346 self.aligned_anon_decls = object.dg.aligned_anon_decls;
343 object.dg.ctypes.deinit(object.dg.gpa);
344347 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);
345351 code.* = object.code.moveToUnmanaged();
346352 }
347353
348354 codegen.genDecl(&object) catch |err| switch (err) {
349355 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.?);
351357 return;
352358 },
353359 else => |e| return e,
354360 };
355
356 ctypes.* = object.dg.ctypes.move();
357
358 // Free excess allocated memory for this Decl.
359 ctypes.shrinkAndFree(gpa, ctypes.count());
360
361361 gop.value_ptr.code = try self.addString(object.code.items);
362362 gop.value_ptr.fwd_decl = try self.addString(object.dg.fwd_decl.items);
363363}
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 {
366366 // The C backend does not have the ability to fix line numbers without re-generating
367367 // the entire Decl.
368368 _ = self;
369 _ = module;
369 _ = zcu;
370370 _ = decl_index;
371371}
372372
......@@ -399,22 +399,25 @@ pub fn flushModule(self: *C, arena: Allocator, prog_node: *std.Progress.Node) !v
399399
400400 const comp = self.base.comp;
401401 const gpa = comp.gpa;
402 const module = self.base.comp.module.?;
402 const zcu = self.base.comp.module.?;
403403
404404 {
405405 var i: usize = 0;
406406 while (i < self.anon_decls.count()) : (i += 1) {
407 try updateAnonDecl(self, module, i);
407 try updateAnonDecl(self, zcu, i);
408408 }
409409 }
410410
411411 // This code path happens exclusively with -ofmt=c. The flush logic for
412412 // 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 };
415418 defer f.deinit(gpa);
416419
417 const abi_defines = try self.abiDefines(module.getTarget());
420 const abi_defines = try self.abiDefines(zcu.getTarget());
418421 defer abi_defines.deinit();
419422
420423 // 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
429432 {
430433 var asm_buf = f.asm_buf.toManaged(gpa);
431434 defer f.asm_buf = asm_buf.moveToUnmanaged();
432 try codegen.genGlobalAsm(module, asm_buf.writer());
435 try codegen.genGlobalAsm(zcu, asm_buf.writer());
433436 f.appendBufAssumeCapacity(asm_buf.items);
434437 }
435438
......@@ -438,7 +441,8 @@ pub fn flushModule(self: *C, arena: Allocator, prog_node: *std.Progress.Node) !v
438441
439442 self.lazy_fwd_decl_buf.clearRetainingCapacity();
440443 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
443447 // Unlike other backends, the .c code we are emitting has order-dependent decls.
444448 // `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
446450 {
447451 var export_names: std.AutoHashMapUnmanaged(InternPool.NullTerminatedString, void) = .{};
448452 defer export_names.deinit(gpa);
449 try export_names.ensureTotalCapacity(gpa, @intCast(module.decl_exports.entries.len));
450 for (module.decl_exports.values()) |exports| for (exports.items) |@"export"|
453 try export_names.ensureTotalCapacity(gpa, @intCast(zcu.decl_exports.entries.len));
454 for (zcu.decl_exports.values()) |exports| for (exports.items) |@"export"|
451455 try export_names.put(gpa, @"export".opts.name, {});
452456
453457 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);
455459 }
456460
457461 for (self.decl_table.keys(), self.decl_table.values()) |decl_index, *decl_block| {
458 assert(module.declPtr(decl_index).has_tv);
459 const decl = module.declPtr(decl_index);
460 const extern_symbol_name = if (decl.isExtern(module)) decl.name.toOptional() else .none;
461 try self.flushDeclBlock(&f, decl_block, export_names, extern_symbol_name);
462 const decl = zcu.declPtr(decl_index);
463 assert(decl.has_tv);
464 const extern_symbol_name = if (decl.isExtern(zcu)) decl.name.toOptional() else .none;
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);
462467 }
463468 }
464469
465470 {
466471 // We need to flush lazy ctypes after flushing all decls but before flushing any decl ctypes.
467472 // This ensures that every lazy CType.Index exactly matches the global CType.Index.
468 assert(f.ctypes.count() == 0);
469 try self.flushCTypes(&f, .flush, f.lazy_ctypes);
473 try f.ctype_pool.init(gpa);
474 try self.flushCTypes(zcu, &f, .flush, &f.lazy_ctype_pool);
470475
471476 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);
473478 }
474479
475480 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);
477482 }
478483 }
479484
......@@ -504,11 +509,11 @@ pub fn flushModule(self: *C, arena: Allocator, prog_node: *std.Progress.Node) !v
504509}
505510
506511const Flush = struct {
507 ctypes: codegen.CType.Store = .{},
508 ctypes_map: std.ArrayListUnmanaged(codegen.CType.Index) = .{},
512 ctype_pool: codegen.CType.Pool,
513 ctype_global_from_decl_map: std.ArrayListUnmanaged(codegen.CType) = .{},
509514 ctypes_buf: std.ArrayListUnmanaged(u8) = .{},
510515
511 lazy_ctypes: codegen.CType.Store = .{},
516 lazy_ctype_pool: codegen.CType.Pool,
512517 lazy_fns: LazyFns = .{},
513518
514519 asm_buf: std.ArrayListUnmanaged(u8) = .{},
......@@ -530,10 +535,11 @@ const Flush = struct {
530535 f.all_buffers.deinit(gpa);
531536 f.asm_buf.deinit(gpa);
532537 f.lazy_fns.deinit(gpa);
533 f.lazy_ctypes.deinit(gpa);
538 f.lazy_ctype_pool.deinit(gpa);
534539 f.ctypes_buf.deinit(gpa);
535 f.ctypes_map.deinit(gpa);
536 f.ctypes.deinit(gpa);
540 assert(f.ctype_global_from_decl_map.items.len == 0);
541 f.ctype_global_from_decl_map.deinit(gpa);
542 f.ctype_pool.deinit(gpa);
537543 }
538544};
539545
......@@ -543,91 +549,62 @@ const FlushDeclError = error{
543549
544550fn flushCTypes(
545551 self: *C,
552 zcu: *Zcu,
546553 f: *Flush,
547554 pass: codegen.DeclGen.Pass,
548 decl_ctypes: codegen.CType.Store,
555 decl_ctype_pool: *const codegen.CType.Pool,
549556) FlushDeclError!void {
550557 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();
554 f.ctypes_map.clearRetainingCapacity();
555 try f.ctypes_map.ensureTotalCapacity(gpa, decl_ctypes_len);
556
557 var global_ctypes = f.ctypes.promote(gpa);
558 defer f.ctypes.demote(global_ctypes);
560 const global_from_decl_map = &f.ctype_global_from_decl_map;
561 assert(global_from_decl_map.items.len == 0);
562 try global_from_decl_map.ensureTotalCapacity(gpa, decl_ctype_pool.items.len);
563 defer global_from_decl_map.clearRetainingCapacity();
559564
560565 var ctypes_buf = f.ctypes_buf.toManaged(gpa);
561566 defer f.ctypes_buf = ctypes_buf.moveToUnmanaged();
562567 const writer = ctypes_buf.writer();
563568
564 const slice = decl_ctypes.set.map.entries.slice();
565 for (slice.items(.key), 0..) |decl_cty, decl_i| {
566 const Context = struct {
567 arena: Allocator,
568 ctypes_map: []codegen.CType.Index,
569 cached_hash: codegen.CType.Store.Set.Map.Hash,
570 idx: codegen.CType.Index,
571
572 pub fn hash(ctx: @This(), _: codegen.CType) codegen.CType.Store.Set.Map.Hash {
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;
569 for (0..decl_ctype_pool.items.len) |decl_ctype_pool_index| {
570 const PoolAdapter = struct {
571 global_from_decl_map: []const codegen.CType,
572 pub fn eql(pool_adapter: @This(), decl_ctype: codegen.CType, global_ctype: codegen.CType) bool {
573 return if (decl_ctype.toPoolIndex()) |decl_pool_index|
574 decl_pool_index < pool_adapter.global_from_decl_map.len and
575 pool_adapter.global_from_decl_map[decl_pool_index].eql(global_ctype)
576 else
577 decl_ctype.index == global_ctype.index;
588578 }
589 pub fn copyIndex(ctx: @This(), idx: codegen.CType.Index) codegen.CType.Index {
590 if (idx < codegen.CType.Tag.no_payload_count) return idx;
591 return ctx.ctypes_map[idx - codegen.CType.Tag.no_payload_count];
579 pub fn copy(pool_adapter: @This(), decl_ctype: codegen.CType) codegen.CType {
580 return if (decl_ctype.toPoolIndex()) |decl_pool_index|
581 pool_adapter.global_from_decl_map[decl_pool_index]
582 else
583 decl_ctype;
592584 }
593585 };
594 const decl_idx = @as(codegen.CType.Index, @intCast(codegen.CType.Tag.no_payload_count + decl_i));
595 const ctx = Context{
596 .arena = global_ctypes.arena.allocator(),
597 .ctypes_map = f.ctypes_map.items,
598 .cached_hash = decl_ctypes.indexToHash(decl_idx),
599 .idx = decl_idx,
600 };
601 const gop = try global_ctypes.set.map.getOrPutContextAdapted(gpa, decl_cty, ctx, .{
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 }
586 const decl_ctype = codegen.CType.fromPoolIndex(decl_ctype_pool_index);
587 const global_ctype, const found_existing = try global_ctype_pool.getOrPutAdapted(
588 gpa,
589 decl_ctype_pool,
590 decl_ctype,
591 PoolAdapter{ .global_from_decl_map = global_from_decl_map.items },
592 );
593 global_from_decl_map.appendAssumeCapacity(global_ctype);
617594 try codegen.genTypeDecl(
618 mod,
595 zcu,
619596 writer,
620 global_ctypes.set,
621 global_idx,
597 global_ctype_pool,
598 global_ctype,
622599 pass,
623 decl_ctypes.set,
624 decl_idx,
625 gop.found_existing,
600 decl_ctype_pool,
601 decl_ctype,
602 found_existing,
626603 );
627604 }
628605}
629606
630fn flushErrDecls(self: *C, ctypes: *codegen.CType.Store) FlushDeclError!void {
607fn flushErrDecls(self: *C, zcu: *Zcu, ctype_pool: *codegen.CType.Pool) FlushDeclError!void {
631608 const gpa = self.base.comp.gpa;
632609
633610 const fwd_decl = &self.lazy_fwd_decl_buf;
......@@ -636,12 +613,14 @@ fn flushErrDecls(self: *C, ctypes: *codegen.CType.Store) FlushDeclError!void {
636613 var object = codegen.Object{
637614 .dg = .{
638615 .gpa = gpa,
639 .module = self.base.comp.module.?,
616 .zcu = zcu,
617 .mod = zcu.root_mod,
640618 .error_msg = null,
641619 .pass = .flush,
642620 .is_naked_fn = false,
643621 .fwd_decl = fwd_decl.toManaged(gpa),
644 .ctypes = ctypes.*,
622 .ctype_pool = ctype_pool.*,
623 .scratch = .{},
645624 .anon_decl_deps = self.anon_decls,
646625 .aligned_anon_decls = self.aligned_anon_decls,
647626 },
......@@ -652,8 +631,10 @@ fn flushErrDecls(self: *C, ctypes: *codegen.CType.Store) FlushDeclError!void {
652631 defer {
653632 self.anon_decls = object.dg.anon_decl_deps;
654633 self.aligned_anon_decls = object.dg.aligned_anon_decls;
655 object.dg.ctypes.deinit(gpa);
656634 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);
657638 code.* = object.code.moveToUnmanaged();
658639 }
659640
......@@ -661,13 +642,14 @@ fn flushErrDecls(self: *C, ctypes: *codegen.CType.Store) FlushDeclError!void {
661642 error.AnalysisFail => unreachable,
662643 else => |e| return e,
663644 };
664
665 ctypes.* = object.dg.ctypes.move();
666645}
667646
668647fn flushLazyFn(
669648 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,
671653 lazy_fn: codegen.LazyFnMap.Entry,
672654) FlushDeclError!void {
673655 const gpa = self.base.comp.gpa;
......@@ -678,12 +660,14 @@ fn flushLazyFn(
678660 var object = codegen.Object{
679661 .dg = .{
680662 .gpa = gpa,
681 .module = self.base.comp.module.?,
663 .zcu = zcu,
664 .mod = mod,
682665 .error_msg = null,
683666 .pass = .flush,
684667 .is_naked_fn = false,
685668 .fwd_decl = fwd_decl.toManaged(gpa),
686 .ctypes = ctypes.*,
669 .ctype_pool = ctype_pool.*,
670 .scratch = .{},
687671 .anon_decl_deps = .{},
688672 .aligned_anon_decls = .{},
689673 },
......@@ -696,20 +680,27 @@ fn flushLazyFn(
696680 // `updateFunc()` does.
697681 assert(object.dg.anon_decl_deps.count() == 0);
698682 assert(object.dg.aligned_anon_decls.count() == 0);
699 object.dg.ctypes.deinit(gpa);
700683 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);
701687 code.* = object.code.moveToUnmanaged();
702688 }
703689
704 codegen.genLazyFn(&object, lazy_fn) catch |err| switch (err) {
690 codegen.genLazyFn(&object, lazy_ctype_pool, lazy_fn) catch |err| switch (err) {
705691 error.AnalysisFail => unreachable,
706692 else => |e| return e,
707693 };
708
709 ctypes.* = object.dg.ctypes.move();
710694}
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 {
713704 const gpa = self.base.comp.gpa;
714705 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
718709 const gop = f.lazy_fns.getOrPutAssumeCapacity(entry.key_ptr.*);
719710 if (gop.found_existing) continue;
720711 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);
722713 }
723714}
724715
725716fn flushDeclBlock(
726717 self: *C,
718 zcu: *Zcu,
719 mod: *Module,
727720 f: *Flush,
728721 decl_block: *DeclBlock,
729722 export_names: std.AutoHashMapUnmanaged(InternPool.NullTerminatedString, void),
730723 extern_symbol_name: InternPool.OptionalNullTerminatedString,
731724) FlushDeclError!void {
732725 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);
734727 try f.all_buffers.ensureUnusedCapacity(gpa, 1);
735728 fwd_decl: {
736729 if (extern_symbol_name.unwrap()) |name| {
......@@ -740,15 +733,15 @@ fn flushDeclBlock(
740733 }
741734}
742735
743pub fn flushEmitH(module: *Module) !void {
736pub fn flushEmitH(zcu: *Zcu) !void {
744737 const tracy = trace(@src());
745738 defer tracy.end();
746739
747 const emit_h = module.emit_h orelse return;
740 const emit_h = zcu.emit_h orelse return;
748741
749742 // We collect a list of buffers to write, and write them all at once with pwritev 😎
750743 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);
752745 defer all_buffers.deinit();
753746
754747 var file_size: u64 = zig_h.len;
......@@ -771,7 +764,7 @@ pub fn flushEmitH(module: *Module) !void {
771764 }
772765 }
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;
775768 const file = try directory.handle.createFile(emit_h.loc.basename, .{
776769 // We set the end position explicitly below; by not truncating the file, we possibly
777770 // make it easier on the file system by doing 1 reallocation instead of two.
......@@ -785,12 +778,12 @@ pub fn flushEmitH(module: *Module) !void {
785778
786779pub fn updateExports(
787780 self: *C,
788 module: *Module,
789 exported: Module.Exported,
790 exports: []const *Module.Export,
781 zcu: *Zcu,
782 exported: Zcu.Exported,
783 exports: []const *Zcu.Export,
791784) !void {
792785 _ = exports;
793786 _ = exported;
794 _ = module;
787 _ = zcu;
795788 _ = self;
796789}
src/link/Coff.zig+3-3
......@@ -1223,7 +1223,7 @@ fn lowerConst(self: *Coff, name: []const u8, val: Value, required_alignment: Int
12231223 atom.getSymbolPtr(self).value = try self.allocateAtom(
12241224 atom_index,
12251225 atom.size,
1226 @intCast(required_alignment.toByteUnitsOptional().?),
1226 @intCast(required_alignment.toByteUnits().?),
12271227 );
12281228 errdefer self.freeAtom(atom_index);
12291229
......@@ -1344,7 +1344,7 @@ fn updateLazySymbolAtom(
13441344 symbol.section_number = @as(coff.SectionNumber, @enumFromInt(section_index + 1));
13451345 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));
13481348 errdefer self.freeAtom(atom_index);
13491349
13501350 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
14281428 const decl_name = mod.intern_pool.stringToSlice(try decl.fullyQualifiedName(mod));
14291429
14301430 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
14331433 const decl_metadata = self.decls.get(decl_index).?;
14341434 const atom_index = decl_metadata.atom;
src/link/Elf.zig+1-1
......@@ -4051,7 +4051,7 @@ fn updateSectionSizes(self: *Elf) !void {
40514051 const padding = offset - shdr.sh_size;
40524052 atom_ptr.value = offset;
40534053 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);
40554055 }
40564056 }
40574057
src/link/Elf/Atom.zig+1-1
......@@ -208,7 +208,7 @@ pub fn allocate(self: *Atom, elf_file: *Elf) !void {
208208 zig_object.debug_aranges_section_dirty = true;
209209 }
210210 }
211 shdr.sh_addralign = @max(shdr.sh_addralign, self.alignment.toByteUnitsOptional().?);
211 shdr.sh_addralign = @max(shdr.sh_addralign, self.alignment.toByteUnits().?);
212212
213213 // This function can also reallocate an atom.
214214 // 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
313313 shdr.sh_addr = 0;
314314 shdr.sh_offset = 0;
315315 shdr.sh_size = atom.size;
316 shdr.sh_addralign = atom.alignment.toByteUnits(1);
316 shdr.sh_addralign = atom.alignment.toByteUnits() orelse 1;
317317 return shdr;
318318}
319319
src/link/Elf/relocatable.zig+1-1
......@@ -330,7 +330,7 @@ fn updateSectionSizes(elf_file: *Elf) !void {
330330 const padding = offset - shdr.sh_size;
331331 atom_ptr.value = offset;
332332 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);
334334 }
335335 }
336336
src/link/Elf/thunks.zig+1-1
......@@ -63,7 +63,7 @@ fn advance(shdr: *elf.Elf64_Shdr, size: u64, alignment: Atom.Alignment) !u64 {
6363 const offset = alignment.forward(shdr.sh_size);
6464 const padding = offset - shdr.sh_size;
6565 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);
6767 return offset;
6868}
6969
src/link/MachO.zig+1-1
......@@ -2060,7 +2060,7 @@ fn calcSectionSizes(self: *MachO) !void {
20602060
20612061 for (atoms.items) |atom_index| {
20622062 const atom = self.getAtom(atom_index).?;
2063 const atom_alignment = atom.alignment.toByteUnits(1);
2063 const atom_alignment = atom.alignment.toByteUnits() orelse 1;
20642064 const offset = mem.alignForward(u64, header.size, atom_alignment);
20652065 const padding = offset - header.size;
20662066 atom.value = offset;
src/link/MachO/relocatable.zig+1-1
......@@ -380,7 +380,7 @@ fn calcSectionSizes(macho_file: *MachO) !void {
380380 if (atoms.items.len == 0) continue;
381381 for (atoms.items) |atom_index| {
382382 const atom = macho_file.getAtom(atom_index).?;
383 const atom_alignment = atom.alignment.toByteUnits(1);
383 const atom_alignment = atom.alignment.toByteUnits() orelse 1;
384384 const offset = mem.alignForward(u64, header.size, atom_alignment);
385385 const padding = offset - header.size;
386386 atom.value = offset;
src/link/Wasm.zig+1-1
......@@ -2263,7 +2263,7 @@ fn setupMemory(wasm: *Wasm) !void {
22632263 }
22642264 if (wasm.findGlobalSymbol("__tls_align")) |loc| {
22652265 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().?);
22672267 }
22682268 if (wasm.findGlobalSymbol("__tls_base")) |loc| {
22692269 const sym = loc.getSymbol(wasm);
src/link/tapi/parse.zig+15-24
......@@ -29,34 +29,28 @@ pub const Node = struct {
2929 map,
3030 list,
3131 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 }
3241 };
3342
3443 pub fn cast(self: *const Node, comptime T: type) ?*const T {
3544 if (self.tag != T.base_tag) {
3645 return null;
3746 }
38 return @fieldParentPtr(T, "base", self);
47 return @fieldParentPtr("base", self);
3948 }
4049
4150 pub fn deinit(self: *Node, allocator: Allocator) void {
4251 switch (self.tag) {
43 .doc => {
44 const parent = @fieldParentPtr(Node.Doc, "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);
52 inline else => |tag| {
53 const parent: *tag.Type() = @fieldParentPtr("base", self);
6054 parent.deinit(allocator);
6155 allocator.destroy(parent);
6256 },
......@@ -69,12 +63,9 @@ pub const Node = struct {
6963 options: std.fmt.FormatOptions,
7064 writer: anytype,
7165 ) !void {
72 return switch (self.tag) {
73 .doc => @fieldParentPtr(Node.Doc, "base", self).format(fmt, options, writer),
74 .map => @fieldParentPtr(Node.Map, "base", self).format(fmt, options, writer),
75 .list => @fieldParentPtr(Node.List, "base", self).format(fmt, options, writer),
76 .value => @fieldParentPtr(Node.Value, "base", self).format(fmt, options, writer),
77 };
66 switch (self.tag) {
67 inline else => |tag| return @as(*tag.Type(), @fieldParentPtr("base", self)).format(fmt, options, writer),
68 }
7869 }
7970
8071 pub const Doc = struct {
src/main.zig+1-5
......@@ -3544,11 +3544,7 @@ fn createModule(
35443544 // If the target is not overridden, use the parent's target. Of course,
35453545 // if this is the root module then we need to proceed to resolve the
35463546 // target.
3547 if (cli_mod.target_arch_os_abi == null and
3548 cli_mod.target_mcpu == null and
3549 create_module.dynamic_linker == null and
3550 create_module.object_format == null)
3551 {
3547 if (cli_mod.target_arch_os_abi == null and cli_mod.target_mcpu == null) {
35523548 if (parent) |p| break :t p.resolved_target;
35533549 }
35543550
src/print_value.zig+1-1
......@@ -80,7 +80,7 @@ pub fn print(
8080 inline .u64, .i64, .big_int => |x| try writer.print("{}", .{x}),
8181 .lazy_align => |ty| if (opt_sema) |sema| {
8282 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});
8484 } else try writer.print("@alignOf({})", .{Type.fromInterned(ty).fmt(mod)}),
8585 .lazy_size => |ty| if (opt_sema) |sema| {
8686 const s = (try Type.fromInterned(ty).abiSizeAdvanced(mod, .{ .sema = sema })).scalar;
src/print_zir.zig+15-8
......@@ -355,7 +355,6 @@ const Writer = struct {
355355 .atomic_rmw => try self.writeAtomicRmw(stream, inst),
356356 .shuffle => try self.writeShuffle(stream, inst),
357357 .mul_add => try self.writeMulAdd(stream, inst),
358 .field_parent_ptr => try self.writeFieldParentPtr(stream, inst),
359358 .builtin_call => try self.writeBuiltinCall(stream, inst),
360359
361360 .field_type_ref => try self.writeFieldTypeRef(stream, inst),
......@@ -609,6 +608,7 @@ const Writer = struct {
609608
610609 .restore_err_ret_index => try self.writeRestoreErrRetIndex(stream, extended),
611610 .closure_get => try self.writeClosureGet(stream, extended),
611 .field_parent_ptr => try self.writeFieldParentPtr(stream, extended),
612612 }
613613 }
614614
......@@ -901,16 +901,21 @@ const Writer = struct {
901901 try self.writeSrc(stream, inst_data.src());
902902 }
903903
904 fn writeFieldParentPtr(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {
905 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
906 const extra = self.code.extraData(Zir.Inst.FieldParentPtr, inst_data.payload_index).data;
907 try self.writeInstRef(stream, extra.parent_type);
904 fn writeFieldParentPtr(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void {
905 const extra = self.code.extraData(Zir.Inst.FieldParentPtr, extended.operand).data;
906 const FlagsInt = @typeInfo(Zir.Inst.FullPtrCastFlags).Struct.backing_integer.?;
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);
908913 try stream.writeAll(", ");
909914 try self.writeInstRef(stream, extra.field_name);
910915 try stream.writeAll(", ");
911916 try self.writeInstRef(stream, extra.field_ptr);
912917 try stream.writeAll(") ");
913 try self.writeSrc(stream, inst_data.src());
918 try self.writeSrc(stream, extra.src());
914919 }
915920
916921 fn writeBuiltinAsyncCall(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void {
......@@ -1069,7 +1074,8 @@ const Writer = struct {
10691074 }
10701075
10711076 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)));
10731079 const extra = self.code.extraData(Zir.Inst.BinNode, extended.operand).data;
10741080 const src = LazySrcLoc.nodeOffset(extra.node);
10751081 if (flags.ptr_cast) try stream.writeAll("ptr_cast, ");
......@@ -1085,7 +1091,8 @@ const Writer = struct {
10851091 }
10861092
10871093 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)));
10891096 const extra = self.code.extraData(Zir.Inst.UnNode, extended.operand).data;
10901097 const src = LazySrcLoc.nodeOffset(extra.node);
10911098 if (flags.const_cast) try stream.writeAll("const_cast, ");
src/register_manager.zig+1-1
......@@ -59,7 +59,7 @@ pub fn RegisterManager(
5959 pub const RegisterBitSet = StaticBitSet(tracked_registers.len);
6060
6161 fn getFunction(self: *Self) *Function {
62 return @fieldParentPtr(Function, "register_manager", self);
62 return @alignCast(@fieldParentPtr("register_manager", self));
6363 }
6464
6565 fn excludeRegister(reg: Register, register_class: RegisterBitSet) bool {
src/target.zig+1-1
......@@ -525,7 +525,7 @@ pub fn backendSupportsFeature(
525525 .error_return_trace => use_llvm,
526526 .is_named_enum_value => use_llvm,
527527 .error_set_has_value => use_llvm or cpu_arch.isWasm(),
528 .field_reordering => use_llvm,
528 .field_reordering => ofmt == .c or use_llvm,
529529 .safety_checked_instructions => use_llvm,
530530 };
531531}
src/type.zig+25-27
......@@ -203,7 +203,7 @@ pub const Type = struct {
203203 info.flags.alignment
204204 else
205205 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
208208 if (info.packed_offset.bit_offset != 0 or info.packed_offset.host_size != 0) {
209209 try writer.print(":{d}:{d}", .{
......@@ -863,7 +863,7 @@ pub const Type = struct {
863863 pub fn lazyAbiAlignment(ty: Type, mod: *Module) !Value {
864864 switch (try ty.abiAlignmentAdvanced(mod, .lazy)) {
865865 .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),
867867 }
868868 }
869869
......@@ -905,7 +905,7 @@ pub const Type = struct {
905905 return .{ .scalar = intAbiAlignment(int_type.bits, target) };
906906 },
907907 .ptr_type, .anyframe_type => {
908 return .{ .scalar = Alignment.fromByteUnits(@divExact(target.ptrBitWidth(), 8)) };
908 return .{ .scalar = ptrAbiAlignment(target) };
909909 },
910910 .array_type => |array_type| {
911911 return Type.fromInterned(array_type.child).abiAlignmentAdvanced(mod, strat);
......@@ -920,6 +920,9 @@ pub const Type = struct {
920920 const alignment = std.math.ceilPowerOfTwoAssert(u32, bytes);
921921 return .{ .scalar = Alignment.fromByteUnits(alignment) };
922922 },
923 .stage2_c => {
924 return Type.fromInterned(vector_type.child).abiAlignmentAdvanced(mod, strat);
925 },
923926 .stage2_x86_64 => {
924927 if (vector_type.child == .bool_type) {
925928 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 {
966969
967970 .usize,
968971 .isize,
972 => return .{ .scalar = intAbiAlignment(target.ptrBitWidth(), target) },
973
969974 .export_options,
970975 .extern_options,
971976 .type_info,
972 => return .{
973 .scalar = Alignment.fromByteUnits(@divExact(target.ptrBitWidth(), 8)),
974 },
977 => return .{ .scalar = ptrAbiAlignment(target) },
975978
976979 .c_char => return .{ .scalar = cTypeAlign(target, .char) },
977980 .c_short => return .{ .scalar = cTypeAlign(target, .short) },
......@@ -1160,9 +1163,7 @@ pub const Type = struct {
11601163 const child_type = ty.optionalChild(mod);
11611164
11621165 switch (child_type.zigTypeTag(mod)) {
1163 .Pointer => return .{
1164 .scalar = Alignment.fromByteUnits(@divExact(target.ptrBitWidth(), 8)),
1165 },
1166 .Pointer => return .{ .scalar = ptrAbiAlignment(target) },
11661167 .ErrorSet => return abiAlignmentAdvanced(Type.anyerror, mod, strat),
11671168 .NoReturn => return .{ .scalar = .@"1" },
11681169 else => {},
......@@ -1274,6 +1275,10 @@ pub const Type = struct {
12741275 const total_bits = elem_bits * vector_type.len;
12751276 break :total_bytes (total_bits + 7) / 8;
12761277 },
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 },
12771282 .stage2_x86_64 => total_bytes: {
12781283 if (vector_type.child == .bool_type) break :total_bytes std.math.divCeil(u32, vector_type.len, 8) catch unreachable;
12791284 const elem_bytes: u32 = @intCast((try Type.fromInterned(vector_type.child).abiSizeAdvanced(mod, strat)).scalar);
......@@ -1527,15 +1532,19 @@ pub const Type = struct {
15271532 // guaranteed to be >= that of bool's (1 byte) the added size is exactly equal
15281533 // to the child type's ABI alignment.
15291534 return AbiSizeAdvanced{
1530 .scalar = child_ty.abiAlignment(mod).toByteUnits(0) + payload_size,
1535 .scalar = (child_ty.abiAlignment(mod).toByteUnits() orelse 0) + payload_size,
15311536 };
15321537 }
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 {
15351544 return intAbiAlignment(bits, target).forward(@as(u16, @intCast((@as(u17, bits) + 7) / 8)));
15361545 }
15371546
1538 fn intAbiAlignment(bits: u16, target: Target) Alignment {
1547 pub fn intAbiAlignment(bits: u16, target: Target) Alignment {
15391548 return Alignment.fromByteUnits(@min(
15401549 std.math.ceilPowerOfTwoPromote(u16, @as(u16, @intCast((@as(u17, bits) + 7) / 8))),
15411550 target.maxIntAlignment(),
......@@ -1572,7 +1581,7 @@ pub const Type = struct {
15721581 if (len == 0) return 0;
15731582 const elem_ty = Type.fromInterned(array_type.child);
15741583 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,
15761585 (try elem_ty.abiSizeAdvanced(mod, strat)).scalar,
15771586 );
15781587 if (elem_size == 0) return 0;
......@@ -3016,26 +3025,15 @@ pub const Type = struct {
30163025 }
30173026
30183027 /// 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 {
30203029 const ip = &mod.intern_pool;
30213030 return switch (ip.indexToKey(ty.toIntern())) {
3022 .struct_type => ip.loadStructType(ty.toIntern()).fieldName(ip, field_index),
3023 .anon_struct_type => |anon_struct| anon_struct.fieldName(ip, field_index),
3031 .struct_type => ip.loadStructType(ty.toIntern()).fieldName(ip, index),
3032 .anon_struct_type => |anon_struct| anon_struct.fieldName(ip, index),
30243033 else => unreachable,
30253034 };
30263035 }
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
30393037 pub fn structFieldCount(ty: Type, mod: *Module) u32 {
30403038 const ip = &mod.intern_pool;
30413039 return switch (ip.indexToKey(ty.toIntern())) {
stage1/zig.h+13-14
......@@ -130,22 +130,18 @@ typedef char bool;
130130#define zig_restrict
131131#endif
132132
133#if __STDC_VERSION__ >= 201112L
134#define zig_align(alignment) _Alignas(alignment)
135#elif zig_has_attribute(aligned)
136#define zig_align(alignment) __attribute__((aligned(alignment)))
133#if zig_has_attribute(aligned)
134#define zig_under_align(alignment) __attribute__((aligned(alignment)))
137135#elif _MSC_VER
138#define zig_align(alignment) __declspec(align(alignment))
136#define zig_under_align(alignment) __declspec(align(alignment))
139137#else
140#define zig_align zig_align_unavailable
138#define zig_under_align zig_align_unavailable
141139#endif
142140
143#if zig_has_attribute(aligned)
144#define zig_under_align(alignment) __attribute__((aligned(alignment)))
145#elif _MSC_VER
146#define zig_under_align(alignment) zig_align(alignment)
141#if __STDC_VERSION__ >= 201112L
142#define zig_align(alignment) _Alignas(alignment)
147143#else
148#define zig_align zig_align_unavailable
144#define zig_align(alignment) zig_under_align(alignment)
149145#endif
150146
151147#if zig_has_attribute(aligned)
......@@ -165,11 +161,14 @@ typedef char bool;
165161#endif
166162
167163#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
169166#elif _MSC_VER
170#define zig_linksection(name, def, ...) __pragma(section(name, __VA_ARGS__)) __declspec(allocate(name)) def
167#define zig_linksection(name) __pragma(section(name, read, write)) __declspec(allocate(name))
168#define zig_linksection_fn(name) __pragma(section(name, read, execute)) __declspec(code_seg(name))
171169#else
172#define zig_linksection(name, def, ...) zig_linksection_unavailable
170#define zig_linksection(name) zig_linksection_unavailable
171#define zig_linksection_fn zig_linksection
173172#endif
174173
175174#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" {
624624 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
625625 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
626626 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
627 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
628627
629628 // 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" {
694693 try expect(@intFromPtr(&s) % 2 == 0);
695694 try expect(@intFromPtr(&s.y) - @intFromPtr(&s.x) == 2);
696695 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);
698697}
test/behavior/field_parent_ptr.zig+1882-84
......@@ -1,126 +1,1924 @@
11const expect = @import("std").testing.expect;
22const builtin = @import("builtin");
33
4test "@fieldParentPtr non-first field" {
5 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
6 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
4test "@fieldParentPtr struct" {
5 const C = struct {
6 a: bool = true,
7 b: f32 = 3.14,
8 c: struct { u8 } = .{42},
9 d: i32 = 12345,
10 };
711
8 try testParentFieldPtr(&foo.c);
9 try comptime testParentFieldPtr(&foo.c);
12 {
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 }
10135}
11136
12test "@fieldParentPtr first field" {
13 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
14 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
137test "@fieldParentPtr extern struct" {
138 const C = extern struct {
139 a: bool = true,
140 b: f32 = 3.14,
141 c: extern struct { x: u8 } = .{ .x = 42 },
142 d: i32 = 12345,
143 };
144
145 {
146 const c: C = .{ .a = false };
147 const pcf = &c.a;
148 const pc: *const C = @alignCast(@fieldParentPtr("a", pcf));
149 try expect(pc == &c);
150 }
151 {
152 const c: C = .{ .a = false };
153 const pcf = &c.a;
154 var pc: *const C = undefined;
155 pc = @alignCast(@fieldParentPtr("a", pcf));
156 try expect(pc == &c);
157 }
158 {
159 const c: C = .{ .a = false };
160 var pcf: @TypeOf(&c.a) = undefined;
161 pcf = &c.a;
162 var pc: *const C = undefined;
163 pc = @alignCast(@fieldParentPtr("a", pcf));
164 try expect(pc == &c);
165 }
166 {
167 var c: C = undefined;
168 c = .{ .a = false };
169 var pcf: @TypeOf(&c.a) = undefined;
170 pcf = &c.a;
171 var pc: *C = undefined;
172 pc = @alignCast(@fieldParentPtr("a", pcf));
173 try expect(pc == &c);
174 }
175
176 {
177 const c: C = .{ .b = 666.667 };
178 const pcf = &c.b;
179 const pc: *const C = @alignCast(@fieldParentPtr("b", pcf));
180 try expect(pc == &c);
181 }
182 {
183 const c: C = .{ .b = 666.667 };
184 const pcf = &c.b;
185 var pc: *const C = undefined;
186 pc = @alignCast(@fieldParentPtr("b", pcf));
187 try expect(pc == &c);
188 }
189 {
190 const c: C = .{ .b = 666.667 };
191 var pcf: @TypeOf(&c.b) = undefined;
192 pcf = &c.b;
193 var pc: *const C = undefined;
194 pc = @alignCast(@fieldParentPtr("b", pcf));
195 try expect(pc == &c);
196 }
197 {
198 var c: C = undefined;
199 c = .{ .b = 666.667 };
200 var pcf: @TypeOf(&c.b) = undefined;
201 pcf = &c.b;
202 var pc: *C = undefined;
203 pc = @alignCast(@fieldParentPtr("b", pcf));
204 try expect(pc == &c);
205 }
15206
16 try testParentFieldPtrFirst(&foo.a);
17 try comptime testParentFieldPtrFirst(&foo.a);
207 {
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 }
18268}
19269
20const Foo = struct {
21 a: bool,
22 b: f32,
23 c: i32,
24 d: i32,
25};
270test "@fieldParentPtr extern struct first zero-bit field" {
271 const C = extern struct {
272 a: u0 = 0,
273 b: f32 = 3.14,
274 c: i32 = 12345,
275 };
26276
27const foo = Foo{
28 .a = true,
29 .b = 0.123,
30 .c = 1234,
31 .d = -10,
32};
277 {
278 const c: C = .{ .a = 0 };
279 const pcf = &c.a;
280 const pc: *const C = @alignCast(@fieldParentPtr("a", pcf));
281 try expect(pc == &c);
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 {
35 try expect(c == &foo.c);
308 {
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);
38 try expect(base == &foo);
39 try expect(&base.c == c);
339 {
340 const c: C = .{ .c = -1111111111 };
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 }
40369}
41370
42fn testParentFieldPtrFirst(a: *const bool) !void {
43 try expect(a == &foo.a);
371test "@fieldParentPtr extern struct middle zero-bit field" {
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);
46 try expect(base == &foo);
47 try expect(&base.a == a);
409 {
410 const c: C = .{ .b = 0 };
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 }
48470}
49471
50test "@fieldParentPtr untagged union" {
51 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
52 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
53 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
472test "@fieldParentPtr extern struct last zero-bit field" {
473 const C = extern struct {
474 a: f32 = 3.14,
475 b: i32 = 12345,
476 c: u0 = 0,
477 };
478
479 {
480 const c: C = .{ .a = 666.667 };
481 const pcf = &c.a;
482 const pc: *const C = @alignCast(@fieldParentPtr("a", pcf));
483 try expect(pc == &c);
484 }
485 {
486 const c: C = .{ .a = 666.667 };
487 const pcf = &c.a;
488 var pc: *const C = undefined;
489 pc = @alignCast(@fieldParentPtr("a", pcf));
490 try expect(pc == &c);
491 }
492 {
493 const c: C = .{ .a = 666.667 };
494 var pcf: @TypeOf(&c.a) = undefined;
495 pcf = &c.a;
496 var pc: *const C = undefined;
497 pc = @alignCast(@fieldParentPtr("a", pcf));
498 try expect(pc == &c);
499 }
500 {
501 var c: C = undefined;
502 c = .{ .a = 666.667 };
503 var pcf: @TypeOf(&c.a) = undefined;
504 pcf = &c.a;
505 var pc: *C = undefined;
506 pc = @alignCast(@fieldParentPtr("a", pcf));
507 try expect(pc == &c);
508 }
509
510 {
511 const c: C = .{ .b = -1111111111 };
512 const pcf = &c.b;
513 const pc: *const C = @alignCast(@fieldParentPtr("b", pcf));
514 try expect(pc == &c);
515 }
516 {
517 const c: C = .{ .b = -1111111111 };
518 const pcf = &c.b;
519 var pc: *const C = undefined;
520 pc = @alignCast(@fieldParentPtr("b", pcf));
521 try expect(pc == &c);
522 }
523 {
524 const c: C = .{ .b = -1111111111 };
525 var pcf: @TypeOf(&c.b) = undefined;
526 pcf = &c.b;
527 var pc: *const C = undefined;
528 pc = @alignCast(@fieldParentPtr("b", pcf));
529 try expect(pc == &c);
530 }
531 {
532 var c: C = undefined;
533 c = .{ .b = -1111111111 };
534 var pcf: @TypeOf(&c.b) = undefined;
535 pcf = &c.b;
536 var pc: *C = undefined;
537 pc = @alignCast(@fieldParentPtr("b", pcf));
538 try expect(pc == &c);
539 }
540
541 {
542 const c: C = .{ .c = 0 };
543 const pcf = &c.c;
544 const pc: *const C = @alignCast(@fieldParentPtr("c", pcf));
545 try expect(pc == &c);
546 }
547 {
548 const c: C = .{ .c = 0 };
549 const pcf = &c.c;
550 var pc: *const C = undefined;
551 pc = @alignCast(@fieldParentPtr("c", pcf));
552 try expect(pc == &c);
553 }
554 {
555 const c: C = .{ .c = 0 };
556 var pcf: @TypeOf(&c.c) = undefined;
557 pcf = &c.c;
558 var pc: *const C = undefined;
559 pc = @alignCast(@fieldParentPtr("c", pcf));
560 try expect(pc == &c);
561 }
562 {
563 var c: C = undefined;
564 c = .{ .c = 0 };
565 var pcf: @TypeOf(&c.c) = undefined;
566 pcf = &c.c;
567 var pc: *C = undefined;
568 pc = @alignCast(@fieldParentPtr("c", pcf));
569 try expect(pc == &c);
570 }
571}
572
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);
56 try comptime testFieldParentPtrUnion(&bar.c);
647 {
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 }
57708}
58709
59const Bar = union(enum) {
60 a: bool,
61 b: f32,
62 c: i32,
63 d: i32,
64};
710test "@fieldParentPtr aligned packed struct" {
711 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
712 if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
713 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
714
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 {
69 try expect(c == &bar.c);
979 {
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);
72 try expect(base == &bar);
73 try expect(&base.c == c);
990 {
991 var c: C = undefined;
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 }
741318}
751319
761320test "@fieldParentPtr tagged union" {
77 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
78 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
79 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1321 const C = union(enum) {
1322 a: bool,
1323 b: f32,
1324 c: struct { u8 },
1325 d: i32,
1326 };
1327
1328 {
1329 const c: C = .{ .a = false };
1330 const pcf = &c.a;
1331 const pc: *const C = @alignCast(@fieldParentPtr("a", pcf));
1332 try expect(pc == &c);
1333 }
1334 {
1335 const c: C = .{ .a = false };
1336 const pcf = &c.a;
1337 var pc: *const C = undefined;
1338 pc = @alignCast(@fieldParentPtr("a", pcf));
1339 try expect(pc == &c);
1340 }
1341 {
1342 const c: C = .{ .a = false };
1343 var pcf: @TypeOf(&c.a) = undefined;
1344 pcf = &c.a;
1345 var pc: *const C = undefined;
1346 pc = @alignCast(@fieldParentPtr("a", pcf));
1347 try expect(pc == &c);
1348 }
1349 {
1350 var c: C = undefined;
1351 c = .{ .a = false };
1352 var pcf: @TypeOf(&c.a) = undefined;
1353 pcf = &c.a;
1354 var pc: *C = undefined;
1355 pc = @alignCast(@fieldParentPtr("a", pcf));
1356 try expect(pc == &c);
1357 }
1358
1359 {
1360 const c: C = .{ .b = 0 };
1361 const pcf = &c.b;
1362 const pc: *const C = @alignCast(@fieldParentPtr("b", pcf));
1363 try expect(pc == &c);
1364 }
1365 {
1366 const c: C = .{ .b = 0 };
1367 const pcf = &c.b;
1368 var pc: *const C = undefined;
1369 pc = @alignCast(@fieldParentPtr("b", pcf));
1370 try expect(pc == &c);
1371 }
1372 {
1373 const c: C = .{ .b = 0 };
1374 var pcf: @TypeOf(&c.b) = undefined;
1375 pcf = &c.b;
1376 var pc: *const C = undefined;
1377 pc = @alignCast(@fieldParentPtr("b", pcf));
1378 try expect(pc == &c);
1379 }
1380 {
1381 var c: C = undefined;
1382 c = .{ .b = 0 };
1383 var pcf: @TypeOf(&c.b) = undefined;
1384 pcf = &c.b;
1385 var pc: *C = undefined;
1386 pc = @alignCast(@fieldParentPtr("b", pcf));
1387 try expect(pc == &c);
1388 }
1389
1390 {
1391 const c: C = .{ .c = .{255} };
1392 const pcf = &c.c;
1393 const pc: *const C = @alignCast(@fieldParentPtr("c", pcf));
1394 try expect(pc == &c);
1395 }
1396 {
1397 const c: C = .{ .c = .{255} };
1398 const pcf = &c.c;
1399 var pc: *const C = undefined;
1400 pc = @alignCast(@fieldParentPtr("c", pcf));
1401 try expect(pc == &c);
1402 }
1403 {
1404 const c: C = .{ .c = .{255} };
1405 var pcf: @TypeOf(&c.c) = undefined;
1406 pcf = &c.c;
1407 var pc: *const C = undefined;
1408 pc = @alignCast(@fieldParentPtr("c", pcf));
1409 try expect(pc == &c);
1410 }
1411 {
1412 var c: C = undefined;
1413 c = .{ .c = .{255} };
1414 var pcf: @TypeOf(&c.c) = undefined;
1415 pcf = &c.c;
1416 var pc: *C = undefined;
1417 pc = @alignCast(@fieldParentPtr("c", pcf));
1418 try expect(pc == &c);
1419 }
801420
81 try testFieldParentPtrTaggedUnion(&bar_tagged.c);
82 try comptime testFieldParentPtrTaggedUnion(&bar_tagged.c);
1421 {
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 }
831451}
841452
85const BarTagged = union(enum) {
86 a: bool,
87 b: f32,
88 c: i32,
89 d: i32,
90};
1453test "@fieldParentPtr untagged union" {
1454 const C = union {
1455 a: bool,
1456 b: f32,
1457 c: struct { u8 },
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 {
95 try expect(c == &bar_tagged.c);
1523 {
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);
98 try expect(base == &bar_tagged);
99 try expect(&base.c == c);
1554 {
1555 const c: C = .{ .d = -1111111111 };
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 }
1001584}
1011585
1021586test "@fieldParentPtr extern union" {
103 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
104 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
105 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1587 const C = extern union {
1588 a: bool,
1589 b: f32,
1590 c: extern struct { x: u8 },
1591 d: i32,
1592 };
1593
1594 {
1595 const c: C = .{ .a = false };
1596 const pcf = &c.a;
1597 const pc: *const C = @alignCast(@fieldParentPtr("a", pcf));
1598 try expect(pc == &c);
1599 }
1600 {
1601 const c: C = .{ .a = false };
1602 const pcf = &c.a;
1603 var pc: *const C = undefined;
1604 pc = @alignCast(@fieldParentPtr("a", pcf));
1605 try expect(pc == &c);
1606 }
1607 {
1608 const c: C = .{ .a = false };
1609 var pcf: @TypeOf(&c.a) = undefined;
1610 pcf = &c.a;
1611 var pc: *const C = undefined;
1612 pc = @alignCast(@fieldParentPtr("a", pcf));
1613 try expect(pc == &c);
1614 }
1615 {
1616 var c: C = undefined;
1617 c = .{ .a = false };
1618 var pcf: @TypeOf(&c.a) = undefined;
1619 pcf = &c.a;
1620 var pc: *C = undefined;
1621 pc = @alignCast(@fieldParentPtr("a", pcf));
1622 try expect(pc == &c);
1623 }
1624
1625 {
1626 const c: C = .{ .b = 0 };
1627 const pcf = &c.b;
1628 const pc: *const C = @alignCast(@fieldParentPtr("b", pcf));
1629 try expect(pc == &c);
1630 }
1631 {
1632 const c: C = .{ .b = 0 };
1633 const pcf = &c.b;
1634 var pc: *const C = undefined;
1635 pc = @alignCast(@fieldParentPtr("b", pcf));
1636 try expect(pc == &c);
1637 }
1638 {
1639 const c: C = .{ .b = 0 };
1640 var pcf: @TypeOf(&c.b) = undefined;
1641 pcf = &c.b;
1642 var pc: *const C = undefined;
1643 pc = @alignCast(@fieldParentPtr("b", pcf));
1644 try expect(pc == &c);
1645 }
1646 {
1647 var c: C = undefined;
1648 c = .{ .b = 0 };
1649 var pcf: @TypeOf(&c.b) = undefined;
1650 pcf = &c.b;
1651 var pc: *C = undefined;
1652 pc = @alignCast(@fieldParentPtr("b", pcf));
1653 try expect(pc == &c);
1654 }
1655
1656 {
1657 const c: C = .{ .c = .{ .x = 255 } };
1658 const pcf = &c.c;
1659 const pc: *const C = @alignCast(@fieldParentPtr("c", pcf));
1660 try expect(pc == &c);
1661 }
1662 {
1663 const c: C = .{ .c = .{ .x = 255 } };
1664 const pcf = &c.c;
1665 var pc: *const C = undefined;
1666 pc = @alignCast(@fieldParentPtr("c", pcf));
1667 try expect(pc == &c);
1668 }
1669 {
1670 const c: C = .{ .c = .{ .x = 255 } };
1671 var pcf: @TypeOf(&c.c) = undefined;
1672 pcf = &c.c;
1673 var pc: *const C = undefined;
1674 pc = @alignCast(@fieldParentPtr("c", pcf));
1675 try expect(pc == &c);
1676 }
1677 {
1678 var c: C = undefined;
1679 c = .{ .c = .{ .x = 255 } };
1680 var pcf: @TypeOf(&c.c) = undefined;
1681 pcf = &c.c;
1682 var pc: *C = undefined;
1683 pc = @alignCast(@fieldParentPtr("c", pcf));
1684 try expect(pc == &c);
1685 }
1686
1687 {
1688 const c: C = .{ .d = -1111111111 };
1689 const pcf = &c.d;
1690 const pc: *const C = @alignCast(@fieldParentPtr("d", pcf));
1691 try expect(pc == &c);
1692 }
1693 {
1694 const c: C = .{ .d = -1111111111 };
1695 const pcf = &c.d;
1696 var pc: *const C = undefined;
1697 pc = @alignCast(@fieldParentPtr("d", pcf));
1698 try expect(pc == &c);
1699 }
1700 {
1701 const c: C = .{ .d = -1111111111 };
1702 var pcf: @TypeOf(&c.d) = undefined;
1703 pcf = &c.d;
1704 var pc: *const C = undefined;
1705 pc = @alignCast(@fieldParentPtr("d", pcf));
1706 try expect(pc == &c);
1707 }
1708 {
1709 var c: C = undefined;
1710 c = .{ .d = -1111111111 };
1711 var pcf: @TypeOf(&c.d) = undefined;
1712 pcf = &c.d;
1713 var pc: *C = undefined;
1714 pc = @alignCast(@fieldParentPtr("d", pcf));
1715 try expect(pc == &c);
1716 }
1717}
1718
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);
108 try comptime testFieldParentPtrExternUnion(&bar_extern.c);
1822 {
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 }
1091852}
1101853
111const BarExtern = extern union {
112 a: bool,
113 b: f32,
114 c: i32,
115 d: i32,
116};
1854test "@fieldParentPtr tagged union all zero-bit fields" {
1855 if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
1856 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
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 {
121 try expect(c == &bar_extern.c);
1863 {
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);
124 try expect(base == &bar_extern);
125 try expect(&base.c == c);
1894 {
1895 const c: C = .{ .b = 0 };
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 }
1261924}
test/behavior/struct.zig+6-6
......@@ -1392,13 +1392,13 @@ test "fieldParentPtr of a zero-bit field" {
13921392 {
13931393 const a = A{ .u = 0 };
13941394 const b_ptr = &a.b;
1395 const a_ptr = @fieldParentPtr(A, "b", b_ptr);
1395 const a_ptr: *const A = @fieldParentPtr("b", b_ptr);
13961396 try std.testing.expectEqual(&a, a_ptr);
13971397 }
13981398 {
13991399 var a = A{ .u = 0 };
14001400 const b_ptr = &a.b;
1401 const a_ptr = @fieldParentPtr(A, "b", b_ptr);
1401 const a_ptr: *A = @fieldParentPtr("b", b_ptr);
14021402 try std.testing.expectEqual(&a, a_ptr);
14031403 }
14041404 }
......@@ -1406,17 +1406,17 @@ test "fieldParentPtr of a zero-bit field" {
14061406 {
14071407 const a = A{ .u = 0 };
14081408 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);
14101410 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);
14121412 try std.testing.expectEqual(&a, a_ptr);
14131413 }
14141414 {
14151415 var a = A{ .u = 0 };
14161416 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);
14181418 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);
14201420 try std.testing.expectEqual(&a, a_ptr);
14211421 }
14221422 }
test/behavior/tuple.zig+2-2
......@@ -222,7 +222,7 @@ test "fieldParentPtr of tuple" {
222222 var x: u32 = 0;
223223 _ = &x;
224224 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])));
226226}
227227
228228test "fieldParentPtr of anon struct" {
......@@ -233,7 +233,7 @@ test "fieldParentPtr of anon struct" {
233233 var x: u32 = 0;
234234 _ = &x;
235235 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)));
237237}
238238
239239test "offsetOf tuple" {
test/behavior/vector.zig+4
......@@ -1176,18 +1176,22 @@ test "@shlWithOverflow" {
11761176test "alignment of vectors" {
11771177 try expect(@alignOf(@Vector(2, u8)) == switch (builtin.zig_backend) {
11781178 else => 2,
1179 .stage2_c => @alignOf(u8),
11791180 .stage2_x86_64 => 16,
11801181 });
11811182 try expect(@alignOf(@Vector(2, u1)) == switch (builtin.zig_backend) {
11821183 else => 1,
1184 .stage2_c => @alignOf(u1),
11831185 .stage2_x86_64 => 16,
11841186 });
11851187 try expect(@alignOf(@Vector(1, u1)) == switch (builtin.zig_backend) {
11861188 else => 1,
1189 .stage2_c => @alignOf(u1),
11871190 .stage2_x86_64 => 16,
11881191 });
11891192 try expect(@alignOf(@Vector(2, u16)) == switch (builtin.zig_backend) {
11901193 else => 4,
1194 .stage2_c => @alignOf(u16),
11911195 .stage2_x86_64 => 16,
11921196 });
11931197}
test/cases/compile_errors/fieldParentPtr-bad_field_name.zig+2-2
......@@ -2,12 +2,12 @@ const Foo = extern struct {
22 derp: i32,
33};
44export fn foo(a: *i32) *Foo {
5 return @fieldParentPtr(Foo, "a", a);
5 return @fieldParentPtr("a", a);
66}
77
88// error
99// backend=stage2
1010// target=native
1111//
12// :5:33: error: no field named 'a' in struct 'tmp.Foo'
12// :5:28: error: no field named 'a' in struct 'tmp.Foo'
1313// :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{
99
1010comptime {
1111 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);
1313 _ = another_foo_ptr;
1414}
1515
......@@ -17,4 +17,4 @@ comptime {
1717// backend=stage2
1818// target=native
1919//
20// :12:55: error: pointer value not based on parent struct
20// :12:62: error: pointer value not based on parent struct
test/cases/compile_errors/fieldParentPtr-comptime_wrong_field_index.zig+2-2
......@@ -8,7 +8,7 @@ const foo = Foo{
88};
99
1010comptime {
11 const another_foo_ptr = @fieldParentPtr(Foo, "b", &foo.a);
11 const another_foo_ptr: *const Foo = @fieldParentPtr("b", &foo.a);
1212 _ = another_foo_ptr;
1313}
1414
......@@ -16,5 +16,5 @@ comptime {
1616// backend=stage2
1717// target=native
1818//
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'
2020// :1:13: note: struct declared here
test/cases/compile_errors/fieldParentPtr-field_pointer_is_not_pointer.zig+3-3
......@@ -1,12 +1,12 @@
11const Foo = extern struct {
22 a: i32,
33};
4export fn foo(a: i32) *Foo {
5 return @fieldParentPtr(Foo, "a", a);
4export fn foo(a: i32) *const Foo {
5 return @fieldParentPtr("a", a);
66}
77
88// error
99// backend=stage2
1010// target=native
1111//
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 {
55 @offsetOf(T, "a");
66}
77pub export fn entry2() void {
8 @fieldParentPtr(T, "a", undefined);
8 @as(*T, @fieldParentPtr("a", undefined));
99}
1010
1111// error
......@@ -13,4 +13,4 @@ pub export fn entry2() void {
1313// target=native
1414//
1515// :5:5: error: no offset available for comptime field
16// :8:5: error: cannot get @fieldParentPtr of a comptime field
16// :8:29: error: cannot get @fieldParentPtr of a comptime field
test/cases/compile_errors/increase_pointer_alignment_in_ptrCast.zig+1-1
......@@ -8,7 +8,7 @@ export fn entry() u32 {
88// backend=stage2
99// target=native
1010//
11// :3:23: error: cast increases pointer alignment
11// :3:23: error: @ptrCast increases pointer alignment
1212// :3:32: note: '*u8' has alignment '1'
1313// :3:23: note: '*u32' has alignment '4'
1414// :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 {
1616//
1717// :3:45: error: null pointer casted to type '*const u32'
1818// :6:34: error: expected pointer type, found 'comptime_int'
19// :9:22: error: cast increases pointer alignment
19// :9:22: error: @ptrCast increases pointer alignment
2020// :9:71: note: '?*const u8' has alignment '1'
2121// :9:22: note: '?*f32' has alignment '4'
2222// :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 {
88// backend=stage2
99// target=native
1010//
11// :3:21: error: cast discards const qualifier
11// :3:21: error: @ptrCast discards const qualifier
1212// :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 {
8686 const expected_fmt = "expected_{s}";
8787
8888 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
9191 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 {
11641164 compile_c.addCSourceFile(.{
11651165 .file = these_tests.getEmittedBin(),
11661166 .flags = &.{
1167 // TODO output -std=c89 compatible C code
1167 // Tracking issue for making the C backend generate C89 compatible code:
1168 // https://github.com/ziglang/zig/issues/19468
11681169 "-std=c99",
11691170 "-pedantic",
11701171 "-Werror",
1171 // TODO stop violating these pedantic errors. spotted everywhere
1172
1173 // Tracking issue for making the C backend generate code
1174 // that does not trigger warnings:
1175 // https://github.com/ziglang/zig/issues/19467
1176
1177 // spotted everywhere
11721178 "-Wno-builtin-requires-header",
1173 // TODO stop violating these pedantic errors. spotted on linux
1174 "-Wno-address-of-packed-member",
1179
1180 // spotted on linux
11751181 "-Wno-gnu-folding-constant",
11761182 "-Wno-incompatible-function-pointer-types",
11771183 "-Wno-incompatible-pointer-types",
11781184 "-Wno-overlength-strings",
1179 // TODO stop violating these pedantic errors. spotted on darwin
1185
1186 // spotted on darwin
11801187 "-Wno-dollar-in-identifier-extension",
11811188 "-Wno-absolute-value",
11821189 },
tools/lldb_pretty_printers.py+4-4
......@@ -354,7 +354,7 @@ def InstRef_SummaryProvider(value, _=None):
354354def InstIndex_SummaryProvider(value, _=None):
355355 return 'instructions[%d]' % value.unsigned
356356
357class Module_Decl__Module_Decl_Index_SynthProvider:
357class zig_DeclIndex_SynthProvider:
358358 def __init__(self, value, _=None): self.value = value
359359 def update(self):
360360 try:
......@@ -425,7 +425,7 @@ def InternPool_Find(thread):
425425 for frame in thread:
426426 ip = frame.FindVariable('ip') or frame.FindVariable('intern_pool')
427427 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')
429429 if mod:
430430 ip = mod.GetChildMemberWithName('intern_pool')
431431 if ip: return ip
......@@ -617,7 +617,7 @@ type_tag_handlers = {
617617
618618def value_Value_str_lit(payload):
619619 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')
621621 if mod: break
622622 else: return
623623 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):
714714 add(debugger, category='zig.stage2', type='Air.Inst::Air.Inst.Index', identifier='InstIndex', summary=True)
715715 add(debugger, category='zig.stage2', regex=True, type=MultiArrayList_Entry('Air\\.Inst'), identifier='TagAndPayload', synth=True, inline_children=True, summary=True)
716716 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)
718718 add(debugger, category='zig.stage2', type='Module.Namespace::Module.Namespace.Index', synth=True)
719719 add(debugger, category='zig.stage2', type='Module.LazySrcLoc', identifier='zig_TaggedUnion', synth=True)
720720 add(debugger, category='zig.stage2', type='InternPool.Index', synth=True)