| ... | @@ -34,6 +34,8 @@ pub const CValue = union(enum) { | ... | @@ -34,6 +34,8 @@ pub const CValue = union(enum) { |
| 34 | /// By-value | 34 | /// By-value |
| 35 | decl: *Decl, | 35 | decl: *Decl, |
| 36 | decl_ref: *Decl, | 36 | decl_ref: *Decl, |
| | 37 | /// Render the slice as an identifier (using fmtIdent) |
| | 38 | identifier: []const u8, |
| 37 | /// Render these bytes literally. | 39 | /// Render these bytes literally. |
| 38 | /// TODO make this a [*:0]const u8 to save memory | 40 | /// TODO make this a [*:0]const u8 to save memory |
| 39 | bytes: []const u8, | 41 | bytes: []const u8, |
| ... | @@ -78,6 +80,7 @@ fn formatIdent( | ... | @@ -78,6 +80,7 @@ fn formatIdent( |
| 78 | ) !void { | 80 | ) !void { |
| 79 | _ = fmt; | 81 | _ = fmt; |
| 80 | _ = options; | 82 | _ = options; |
| | 83 | try writer.writeAll("__"); // Add double underscore to avoid conflicting with C's reserved keywords |
| 81 | for (ident) |c, i| { | 84 | for (ident) |c, i| { |
| 82 | switch (c) { | 85 | switch (c) { |
| 83 | 'a'...'z', 'A'...'Z', '_' => try writer.writeByte(c), | 86 | 'a'...'z', 'A'...'Z', '_' => try writer.writeByte(c), |
| ... | @@ -408,6 +411,18 @@ pub const DeclGen = struct { | ... | @@ -408,6 +411,18 @@ pub const DeclGen = struct { |
| 408 | try dg.renderValue(writer, Type.usize, slice.len); | 411 | try dg.renderValue(writer, Type.usize, slice.len); |
| 409 | try writer.writeAll("}"); | 412 | try writer.writeAll("}"); |
| 410 | }, | 413 | }, |
| | 414 | .elem_ptr => { |
| | 415 | const elem_ptr = val.castTag(.elem_ptr).?.data; |
| | 416 | var arena = std.heap.ArenaAllocator.init(dg.module.gpa); |
| | 417 | defer arena.deinit(); |
| | 418 | const elem_ptr_ty = try ty.elemPtrType(arena.allocator()); |
| | 419 | |
| | 420 | try writer.writeAll("(&(("); |
| | 421 | try dg.renderType(writer, ty); |
| | 422 | try writer.writeByte(')'); |
| | 423 | try dg.renderValue(writer, elem_ptr_ty, elem_ptr.array_ptr); |
| | 424 | try writer.print(")[{d}])", .{elem_ptr.index}); |
| | 425 | }, |
| 411 | .function => { | 426 | .function => { |
| 412 | const func = val.castTag(.function).?.data; | 427 | const func = val.castTag(.function).?.data; |
| 413 | try dg.renderDeclName(func.owner_decl, writer); | 428 | try dg.renderDeclName(func.owner_decl, writer); |
| ... | @@ -527,6 +542,15 @@ pub const DeclGen = struct { | ... | @@ -527,6 +542,15 @@ pub const DeclGen = struct { |
| 527 | return writer.print("{d}", .{field_index}); | 542 | return writer.print("{d}", .{field_index}); |
| 528 | } | 543 | } |
| 529 | }, | 544 | }, |
| | 545 | .enum_numbered => { |
| | 546 | const enum_obj = ty.castTag(.enum_numbered).?.data; |
| | 547 | if (enum_obj.values.count() != 0) { |
| | 548 | const tag_val = enum_obj.values.keys()[field_index]; |
| | 549 | return dg.renderValue(writer, enum_obj.tag_ty, tag_val); |
| | 550 | } else { |
| | 551 | return writer.print("{d}", .{field_index}); |
| | 552 | } |
| | 553 | }, |
| 530 | else => unreachable, | 554 | else => unreachable, |
| 531 | } | 555 | } |
| 532 | }, | 556 | }, |
| ... | @@ -565,6 +589,37 @@ pub const DeclGen = struct { | ... | @@ -565,6 +589,37 @@ pub const DeclGen = struct { |
| 565 | | 589 | |
| 566 | try writer.writeAll("}"); | 590 | try writer.writeAll("}"); |
| 567 | }, | 591 | }, |
| | 592 | .Union => { |
| | 593 | const union_obj = val.castTag(.@"union").?.data; |
| | 594 | const union_ty = ty.cast(Type.Payload.Union).?.data; |
| | 595 | const target = dg.module.getTarget(); |
| | 596 | const layout = ty.unionGetLayout(target); |
| | 597 | |
| | 598 | try writer.writeAll("("); |
| | 599 | try dg.renderType(writer, ty); |
| | 600 | try writer.writeAll("){"); |
| | 601 | |
| | 602 | if (ty.unionTagType()) |tag_ty| { |
| | 603 | if (layout.tag_size != 0) { |
| | 604 | try writer.writeAll(".tag = "); |
| | 605 | try dg.renderValue(writer, tag_ty, union_obj.tag); |
| | 606 | try writer.writeAll(", "); |
| | 607 | } |
| | 608 | try writer.writeAll(".payload = {"); |
| | 609 | } |
| | 610 | |
| | 611 | const index = union_ty.tag_ty.enumTagFieldIndex(union_obj.tag).?; |
| | 612 | const field_ty = ty.unionFields().values()[index].ty; |
| | 613 | const field_name = ty.unionFields().keys()[index]; |
| | 614 | if (field_ty.hasCodeGenBits()) { |
| | 615 | try writer.print(".{} = ", .{fmtIdent(field_name)}); |
| | 616 | try dg.renderValue(writer, field_ty, union_obj.val); |
| | 617 | } |
| | 618 | if (ty.unionTagType()) |_| { |
| | 619 | try writer.writeAll("}"); |
| | 620 | } |
| | 621 | try writer.writeAll("}"); |
| | 622 | }, |
| 568 | | 623 | |
| 569 | .ComptimeInt => unreachable, | 624 | .ComptimeInt => unreachable, |
| 570 | .ComptimeFloat => unreachable, | 625 | .ComptimeFloat => unreachable, |
| ... | @@ -577,7 +632,6 @@ pub const DeclGen = struct { | ... | @@ -577,7 +632,6 @@ pub const DeclGen = struct { |
| 577 | .BoundFn => unreachable, | 632 | .BoundFn => unreachable, |
| 578 | .Opaque => unreachable, | 633 | .Opaque => unreachable, |
| 579 | | 634 | |
| 580 | .Union, | | |
| 581 | .Frame, | 635 | .Frame, |
| 582 | .AnyFrame, | 636 | .AnyFrame, |
| 583 | .Vector, | 637 | .Vector, |
| ... | @@ -609,22 +663,24 @@ pub const DeclGen = struct { | ... | @@ -609,22 +663,24 @@ pub const DeclGen = struct { |
| 609 | try dg.renderDeclName(dg.decl, w); | 663 | try dg.renderDeclName(dg.decl, w); |
| 610 | try w.writeAll("("); | 664 | try w.writeAll("("); |
| 611 | const param_len = dg.decl.ty.fnParamLen(); | 665 | const param_len = dg.decl.ty.fnParamLen(); |
| 612 | const is_var_args = dg.decl.ty.fnIsVarArgs(); | 666 | |
| 613 | if (param_len == 0 and !is_var_args) | 667 | var index: usize = 0; |
| 614 | try w.writeAll("void") | 668 | var params_written: usize = 0; |
| 615 | else { | 669 | while (index < param_len) : (index += 1) { |
| 616 | var index: usize = 0; | 670 | if (dg.decl.ty.fnParamType(index).zigTypeTag() == .Void) continue; |
| 617 | while (index < param_len) : (index += 1) { | 671 | if (params_written > 0) { |
| 618 | if (index > 0) { | 672 | try w.writeAll(", "); |
| 619 | try w.writeAll(", "); | | |
| 620 | } | | |
| 621 | try dg.renderType(w, dg.decl.ty.fnParamType(index)); | | |
| 622 | try w.print(" a{d}", .{index}); | | |
| 623 | } | 673 | } |
| | 674 | try dg.renderType(w, dg.decl.ty.fnParamType(index)); |
| | 675 | try w.print(" a{d}", .{index}); |
| | 676 | params_written += 1; |
| 624 | } | 677 | } |
| 625 | if (is_var_args) { | 678 | |
| 626 | if (param_len != 0) try w.writeAll(", "); | 679 | if (dg.decl.ty.fnIsVarArgs()) { |
| | 680 | if (params_written != 0) try w.writeAll(", "); |
| 627 | try w.writeAll("..."); | 681 | try w.writeAll("..."); |
| | 682 | } else if (params_written == 0) { |
| | 683 | try w.writeAll("void"); |
| 628 | } | 684 | } |
| 629 | try w.writeByte(')'); | 685 | try w.writeByte(')'); |
| 630 | } | 686 | } |
| ... | @@ -646,21 +702,23 @@ pub const DeclGen = struct { | ... | @@ -646,21 +702,23 @@ pub const DeclGen = struct { |
| 646 | const name_end = buffer.items.len - 2; | 702 | const name_end = buffer.items.len - 2; |
| 647 | | 703 | |
| 648 | const param_len = fn_info.param_types.len; | 704 | const param_len = fn_info.param_types.len; |
| 649 | const is_var_args = fn_info.is_var_args; | 705 | |
| 650 | if (param_len == 0 and !is_var_args) | 706 | var params_written: usize = 0; |
| 651 | try bw.writeAll("void") | 707 | var index: usize = 0; |
| 652 | else { | 708 | while (index < param_len) : (index += 1) { |
| 653 | var index: usize = 0; | 709 | if (fn_info.param_types[index].zigTypeTag() == .Void) continue; |
| 654 | while (index < param_len) : (index += 1) { | 710 | if (params_written > 0) { |
| 655 | if (index > 0) { | 711 | try bw.writeAll(", "); |
| 656 | try bw.writeAll(", "); | | |
| 657 | } | | |
| 658 | try dg.renderType(bw, fn_info.param_types[index]); | | |
| 659 | } | 712 | } |
| | 713 | try dg.renderType(bw, fn_info.param_types[index]); |
| | 714 | params_written += 1; |
| 660 | } | 715 | } |
| 661 | if (is_var_args) { | 716 | |
| 662 | if (param_len != 0) try bw.writeAll(", "); | 717 | if (fn_info.is_var_args) { |
| | 718 | if (params_written != 0) try bw.writeAll(", "); |
| 663 | try bw.writeAll("..."); | 719 | try bw.writeAll("..."); |
| | 720 | } else if (params_written == 0) { |
| | 721 | try bw.writeAll("void"); |
| 664 | } | 722 | } |
| 665 | try bw.writeAll(");\n"); | 723 | try bw.writeAll(");\n"); |
| 666 | | 724 | |
| ... | @@ -729,7 +787,7 @@ pub const DeclGen = struct { | ... | @@ -729,7 +787,7 @@ pub const DeclGen = struct { |
| 729 | if (!field_ty.hasCodeGenBits()) continue; | 787 | if (!field_ty.hasCodeGenBits()) continue; |
| 730 | | 788 | |
| 731 | const alignment = entry.value_ptr.abi_align; | 789 | const alignment = entry.value_ptr.abi_align; |
| 732 | const name: CValue = .{ .bytes = entry.key_ptr.* }; | 790 | const name: CValue = .{ .identifier = entry.key_ptr.* }; |
| 733 | try buffer.append(' '); | 791 | try buffer.append(' '); |
| 734 | try dg.renderTypeAndName(buffer.writer(), field_ty, name, .Mut, alignment); | 792 | try dg.renderTypeAndName(buffer.writer(), field_ty, name, .Mut, alignment); |
| 735 | try buffer.appendSlice(";\n"); | 793 | try buffer.appendSlice(";\n"); |
| ... | @@ -753,6 +811,62 @@ pub const DeclGen = struct { | ... | @@ -753,6 +811,62 @@ pub const DeclGen = struct { |
| 753 | return name; | 811 | return name; |
| 754 | } | 812 | } |
| 755 | | 813 | |
| | 814 | fn renderUnionTypedef(dg: *DeclGen, t: Type) error{ OutOfMemory, AnalysisFail }![]const u8 { |
| | 815 | const union_ty = t.cast(Type.Payload.Union).?.data; |
| | 816 | const fqn = try union_ty.getFullyQualifiedName(dg.typedefs.allocator); |
| | 817 | defer dg.typedefs.allocator.free(fqn); |
| | 818 | |
| | 819 | const target = dg.module.getTarget(); |
| | 820 | const layout = t.unionGetLayout(target); |
| | 821 | |
| | 822 | var buffer = std.ArrayList(u8).init(dg.typedefs.allocator); |
| | 823 | defer buffer.deinit(); |
| | 824 | |
| | 825 | try buffer.appendSlice("typedef "); |
| | 826 | if (t.unionTagType()) |tag_ty| { |
| | 827 | const name: CValue = .{ .bytes = "tag" }; |
| | 828 | try buffer.appendSlice("struct {\n "); |
| | 829 | if (layout.tag_size != 0) { |
| | 830 | try dg.renderTypeAndName(buffer.writer(), tag_ty, name, .Mut, Value.initTag(.abi_align_default)); |
| | 831 | try buffer.appendSlice(";\n"); |
| | 832 | } |
| | 833 | } |
| | 834 | |
| | 835 | try buffer.appendSlice("union {\n"); |
| | 836 | { |
| | 837 | var it = t.unionFields().iterator(); |
| | 838 | while (it.next()) |entry| { |
| | 839 | const field_ty = entry.value_ptr.ty; |
| | 840 | if (!field_ty.hasCodeGenBits()) continue; |
| | 841 | const alignment = entry.value_ptr.abi_align; |
| | 842 | const name: CValue = .{ .identifier = entry.key_ptr.* }; |
| | 843 | try buffer.append(' '); |
| | 844 | try dg.renderTypeAndName(buffer.writer(), field_ty, name, .Mut, alignment); |
| | 845 | try buffer.appendSlice(";\n"); |
| | 846 | } |
| | 847 | } |
| | 848 | try buffer.appendSlice("} "); |
| | 849 | |
| | 850 | if (t.unionTagType()) |_| { |
| | 851 | try buffer.appendSlice("payload;\n} "); |
| | 852 | } |
| | 853 | |
| | 854 | const name_start = buffer.items.len; |
| | 855 | try buffer.writer().print("zig_U_{s};\n", .{fmtIdent(fqn)}); |
| | 856 | |
| | 857 | const rendered = buffer.toOwnedSlice(); |
| | 858 | errdefer dg.typedefs.allocator.free(rendered); |
| | 859 | const name = rendered[name_start .. rendered.len - 2]; |
| | 860 | |
| | 861 | try dg.typedefs.ensureUnusedCapacity(1); |
| | 862 | dg.typedefs.putAssumeCapacityNoClobber( |
| | 863 | try t.copy(dg.typedefs_arena), |
| | 864 | .{ .name = name, .rendered = rendered }, |
| | 865 | ); |
| | 866 | |
| | 867 | return name; |
| | 868 | } |
| | 869 | |
| 756 | fn renderErrorUnionTypedef(dg: *DeclGen, t: Type) error{ OutOfMemory, AnalysisFail }![]const u8 { | 870 | fn renderErrorUnionTypedef(dg: *DeclGen, t: Type) error{ OutOfMemory, AnalysisFail }![]const u8 { |
| 757 | const child_type = t.errorUnionPayload(); | 871 | const child_type = t.errorUnionPayload(); |
| 758 | const err_set_type = t.errorUnionSet(); | 872 | const err_set_type = t.errorUnionSet(); |
| ... | @@ -931,6 +1045,12 @@ pub const DeclGen = struct { | ... | @@ -931,6 +1045,12 @@ pub const DeclGen = struct { |
| 931 | | 1045 | |
| 932 | return w.writeAll(name); | 1046 | return w.writeAll(name); |
| 933 | }, | 1047 | }, |
| | 1048 | .Union => { |
| | 1049 | const name = dg.getTypedefName(t) orelse |
| | 1050 | try dg.renderUnionTypedef(t); |
| | 1051 | |
| | 1052 | return w.writeAll(name); |
| | 1053 | }, |
| 934 | .Enum => { | 1054 | .Enum => { |
| 935 | // For enums, we simply use the integer tag type. | 1055 | // For enums, we simply use the integer tag type. |
| 936 | var int_tag_ty_buffer: Type.Payload.Bits = undefined; | 1056 | var int_tag_ty_buffer: Type.Payload.Bits = undefined; |
| ... | @@ -939,7 +1059,6 @@ pub const DeclGen = struct { | ... | @@ -939,7 +1059,6 @@ pub const DeclGen = struct { |
| 939 | try dg.renderType(w, int_tag_ty); | 1059 | try dg.renderType(w, int_tag_ty); |
| 940 | }, | 1060 | }, |
| 941 | | 1061 | |
| 942 | .Union, | | |
| 943 | .Frame, | 1062 | .Frame, |
| 944 | .AnyFrame, | 1063 | .AnyFrame, |
| 945 | .Vector, | 1064 | .Vector, |
| ... | @@ -1021,6 +1140,7 @@ pub const DeclGen = struct { | ... | @@ -1021,6 +1140,7 @@ pub const DeclGen = struct { |
| 1021 | try w.writeByte('&'); | 1140 | try w.writeByte('&'); |
| 1022 | return dg.renderDeclName(decl, w); | 1141 | return dg.renderDeclName(decl, w); |
| 1023 | }, | 1142 | }, |
| | 1143 | .identifier => |ident| return w.print("{}", .{fmtIdent(ident)}), |
| 1024 | .bytes => |bytes| return w.writeAll(bytes), | 1144 | .bytes => |bytes| return w.writeAll(bytes), |
| 1025 | } | 1145 | } |
| 1026 | } | 1146 | } |
| ... | @@ -1103,13 +1223,10 @@ pub fn genDecl(o: *Object) !void { | ... | @@ -1103,13 +1223,10 @@ pub fn genDecl(o: *Object) !void { |
| 1103 | if (variable.is_threadlocal) { | 1223 | if (variable.is_threadlocal) { |
| 1104 | try fwd_decl_writer.writeAll("zig_threadlocal "); | 1224 | try fwd_decl_writer.writeAll("zig_threadlocal "); |
| 1105 | } | 1225 | } |
| 1106 | try o.dg.renderType(fwd_decl_writer, o.dg.decl.ty); | 1226 | |
| 1107 | try fwd_decl_writer.writeAll(" "); | 1227 | const decl_c_value: CValue = if (is_global) .{ .bytes = mem.span(o.dg.decl.name) } else .{ .decl = o.dg.decl }; |
| 1108 | if (is_global) { | 1228 | |
| 1109 | try fwd_decl_writer.writeAll(mem.span(o.dg.decl.name)); | 1229 | try o.dg.renderTypeAndName(fwd_decl_writer, o.dg.decl.ty, decl_c_value, .Mut, o.dg.decl.align_val); |
| 1110 | } else { | | |
| 1111 | try o.dg.renderDeclName(o.dg.decl, fwd_decl_writer); | | |
| 1112 | } | | |
| 1113 | try fwd_decl_writer.writeAll(";\n"); | 1230 | try fwd_decl_writer.writeAll(";\n"); |
| 1114 | | 1231 | |
| 1115 | if (variable.init.isUndefDeep()) { | 1232 | if (variable.init.isUndefDeep()) { |
| ... | @@ -1118,13 +1235,7 @@ pub fn genDecl(o: *Object) !void { | ... | @@ -1118,13 +1235,7 @@ pub fn genDecl(o: *Object) !void { |
| 1118 | | 1235 | |
| 1119 | try o.indent_writer.insertNewline(); | 1236 | try o.indent_writer.insertNewline(); |
| 1120 | const w = o.writer(); | 1237 | const w = o.writer(); |
| 1121 | try o.dg.renderType(w, o.dg.decl.ty); | 1238 | try o.dg.renderTypeAndName(w, o.dg.decl.ty, decl_c_value, .Mut, o.dg.decl.align_val); |
| 1122 | try w.writeAll(" "); | | |
| 1123 | if (is_global) { | | |
| 1124 | try w.writeAll(mem.span(o.dg.decl.name)); | | |
| 1125 | } else { | | |
| 1126 | try o.dg.renderDeclName(o.dg.decl, w); | | |
| 1127 | } | | |
| 1128 | try w.writeAll(" = "); | 1239 | try w.writeAll(" = "); |
| 1129 | if (variable.init.tag() != .unreachable_value) { | 1240 | if (variable.init.tag() != .unreachable_value) { |
| 1130 | try o.dg.renderValue(w, tv.ty, variable.init); | 1241 | try o.dg.renderValue(w, tv.ty, variable.init); |
| ... | @@ -2339,9 +2450,9 @@ fn airBitcast(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -2339,9 +2450,9 @@ fn airBitcast(f: *Function, inst: Air.Inst.Index) !CValue { |
| 2339 | try f.writeCValue(writer, local); | 2450 | try f.writeCValue(writer, local); |
| 2340 | try writer.writeAll(", &"); | 2451 | try writer.writeAll(", &"); |
| 2341 | try f.writeCValue(writer, operand); | 2452 | try f.writeCValue(writer, operand); |
| 2342 | try writer.writeAll(", sizeof "); | 2453 | try writer.writeAll(", sizeof("); |
| 2343 | try f.writeCValue(writer, local); | 2454 | try f.writeCValue(writer, local); |
| 2344 | try writer.writeAll(");\n"); | 2455 | try writer.writeAll("));\n"); |
| 2345 | | 2456 | |
| 2346 | return local; | 2457 | return local; |
| 2347 | } | 2458 | } |
| ... | @@ -2650,21 +2761,36 @@ fn airStructFieldPtrIndex(f: *Function, inst: Air.Inst.Index, index: u8) !CValue | ... | @@ -2650,21 +2761,36 @@ fn airStructFieldPtrIndex(f: *Function, inst: Air.Inst.Index, index: u8) !CValue |
| 2650 | | 2761 | |
| 2651 | fn structFieldPtr(f: *Function, inst: Air.Inst.Index, struct_ptr_ty: Type, struct_ptr: CValue, index: u32) !CValue { | 2762 | fn structFieldPtr(f: *Function, inst: Air.Inst.Index, struct_ptr_ty: Type, struct_ptr: CValue, index: u32) !CValue { |
| 2652 | const writer = f.object.writer(); | 2763 | const writer = f.object.writer(); |
| 2653 | const struct_obj = struct_ptr_ty.elemType().castTag(.@"struct").?.data; | 2764 | const struct_ty = struct_ptr_ty.elemType(); |
| 2654 | const field_name = struct_obj.fields.keys()[index]; | 2765 | var field_name: []const u8 = undefined; |
| 2655 | const field_val = struct_obj.fields.values()[index]; | 2766 | var field_val_ty: Type = undefined; |
| 2656 | const addrof = if (field_val.ty.zigTypeTag() == .Array) "" else "&"; | 2767 | |
| | 2768 | switch (struct_ty.tag()) { |
| | 2769 | .@"struct" => { |
| | 2770 | const fields = struct_ty.structFields(); |
| | 2771 | field_name = fields.keys()[index]; |
| | 2772 | field_val_ty = fields.values()[index].ty; |
| | 2773 | }, |
| | 2774 | .@"union", .union_tagged => { |
| | 2775 | const fields = struct_ty.unionFields(); |
| | 2776 | field_name = fields.keys()[index]; |
| | 2777 | field_val_ty = fields.values()[index].ty; |
| | 2778 | }, |
| | 2779 | else => unreachable, |
| | 2780 | } |
| | 2781 | const addrof = if (field_val_ty.zigTypeTag() == .Array) "" else "&"; |
| | 2782 | const payload = if (struct_ty.tag() == .union_tagged) "payload." else ""; |
| 2657 | | 2783 | |
| 2658 | const inst_ty = f.air.typeOfIndex(inst); | 2784 | const inst_ty = f.air.typeOfIndex(inst); |
| 2659 | const local = try f.allocLocal(inst_ty, .Const); | 2785 | const local = try f.allocLocal(inst_ty, .Const); |
| 2660 | switch (struct_ptr) { | 2786 | switch (struct_ptr) { |
| 2661 | .local_ref => |i| { | 2787 | .local_ref => |i| { |
| 2662 | try writer.print(" = {s}t{d}.{};\n", .{ addrof, i, fmtIdent(field_name) }); | 2788 | try writer.print(" = {s}t{d}.{s}{};\n", .{ addrof, i, payload, fmtIdent(field_name) }); |
| 2663 | }, | 2789 | }, |
| 2664 | else => { | 2790 | else => { |
| 2665 | try writer.print(" = {s}", .{addrof}); | 2791 | try writer.print(" = {s}", .{addrof}); |
| 2666 | try f.writeCValue(writer, struct_ptr); | 2792 | try f.writeCValue(writer, struct_ptr); |
| 2667 | try writer.print("->{};\n", .{fmtIdent(field_name)}); | 2793 | try writer.print("->{s}{};\n", .{ payload, fmtIdent(field_name) }); |
| 2668 | }, | 2794 | }, |
| 2669 | } | 2795 | } |
| 2670 | return local; | 2796 | return local; |
| ... | @@ -2679,14 +2805,18 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -2679,14 +2805,18 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue { |
| 2679 | const writer = f.object.writer(); | 2805 | const writer = f.object.writer(); |
| 2680 | const struct_byval = try f.resolveInst(extra.struct_operand); | 2806 | const struct_byval = try f.resolveInst(extra.struct_operand); |
| 2681 | const struct_ty = f.air.typeOf(extra.struct_operand); | 2807 | const struct_ty = f.air.typeOf(extra.struct_operand); |
| 2682 | const struct_obj = struct_ty.castTag(.@"struct").?.data; | 2808 | const field_name = switch (struct_ty.tag()) { |
| 2683 | const field_name = struct_obj.fields.keys()[extra.field_index]; | 2809 | .@"struct" => struct_ty.structFields().keys()[extra.field_index], |
| | 2810 | .@"union", .union_tagged => struct_ty.unionFields().keys()[extra.field_index], |
| | 2811 | else => unreachable, |
| | 2812 | }; |
| | 2813 | const payload = if (struct_ty.tag() == .union_tagged) "payload." else ""; |
| 2684 | | 2814 | |
| 2685 | const inst_ty = f.air.typeOfIndex(inst); | 2815 | const inst_ty = f.air.typeOfIndex(inst); |
| 2686 | const local = try f.allocLocal(inst_ty, .Const); | 2816 | const local = try f.allocLocal(inst_ty, .Const); |
| 2687 | try writer.writeAll(" = "); | 2817 | try writer.writeAll(" = "); |
| 2688 | try f.writeCValue(writer, struct_byval); | 2818 | try f.writeCValue(writer, struct_byval); |
| 2689 | try writer.print(".{};\n", .{fmtIdent(field_name)}); | 2819 | try writer.print(".{s}{};\n", .{ payload, fmtIdent(field_name) }); |
| 2690 | return local; | 2820 | return local; |
| 2691 | } | 2821 | } |
| 2692 | | 2822 | |
| ... | @@ -3027,9 +3157,13 @@ fn airSetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -3027,9 +3157,13 @@ fn airSetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3027 | const new_tag = try f.resolveInst(bin_op.rhs); | 3157 | const new_tag = try f.resolveInst(bin_op.rhs); |
| 3028 | const writer = f.object.writer(); | 3158 | const writer = f.object.writer(); |
| 3029 | | 3159 | |
| 3030 | try writer.writeAll("*"); | 3160 | const union_ty = f.air.typeOf(bin_op.lhs).childType(); |
| | 3161 | const target = f.object.dg.module.getTarget(); |
| | 3162 | const layout = union_ty.unionGetLayout(target); |
| | 3163 | if (layout.tag_size == 0) return CValue.none; |
| | 3164 | |
| 3031 | try f.writeCValue(writer, union_ptr); | 3165 | try f.writeCValue(writer, union_ptr); |
| 3032 | try writer.writeAll(" = "); | 3166 | try writer.writeAll("->tag = "); |
| 3033 | try f.writeCValue(writer, new_tag); | 3167 | try f.writeCValue(writer, new_tag); |
| 3034 | try writer.writeAll(";\n"); | 3168 | try writer.writeAll(";\n"); |
| 3035 | | 3169 | |
| ... | @@ -3043,12 +3177,17 @@ fn airGetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -3043,12 +3177,17 @@ fn airGetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3043 | const inst_ty = f.air.typeOfIndex(inst); | 3177 | const inst_ty = f.air.typeOfIndex(inst); |
| 3044 | const local = try f.allocLocal(inst_ty, .Const); | 3178 | const local = try f.allocLocal(inst_ty, .Const); |
| 3045 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; | 3179 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; |
| | 3180 | const un_ty = f.air.typeOf(ty_op.operand); |
| 3046 | const writer = f.object.writer(); | 3181 | const writer = f.object.writer(); |
| 3047 | const operand = try f.resolveInst(ty_op.operand); | 3182 | const operand = try f.resolveInst(ty_op.operand); |
| 3048 | | 3183 | |
| 3049 | try writer.writeAll("get_union_tag("); | 3184 | const target = f.object.dg.module.getTarget(); |
| | 3185 | const layout = un_ty.unionGetLayout(target); |
| | 3186 | if (layout.tag_size == 0) return CValue.none; |
| | 3187 | |
| | 3188 | try writer.writeAll(" = "); |
| 3050 | try f.writeCValue(writer, operand); | 3189 | try f.writeCValue(writer, operand); |
| 3051 | try writer.writeAll(");\n"); | 3190 | try writer.writeAll(".tag;\n"); |
| 3052 | return local; | 3191 | return local; |
| 3053 | } | 3192 | } |
| 3054 | | 3193 | |