authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2022-10-19 23:18:46-04:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2022-10-25 05:11:29-04:00
log4fdac5f1c9cad90450cbad5a8dd276a597aba870
treedf83e2a4cff08172b0f2b3872687446e012406bb
parent4765294ca4bd7dd54207892b199f3053702d9a2a

cbe: fix C syntax when rendering initializers


1 files changed, 448 insertions(+), 430 deletions(-)

src/codegen/c.zig+448-430
......@@ -63,6 +63,7 @@ const FormatTypeAsCIdentContext = struct {
6363
6464const ValueRenderLocation = enum {
6565 FunctionArgument,
66 Initializer,
6667 Other,
6768};
6869
......@@ -256,7 +257,7 @@ pub const Function = struct {
256257 0,
257258 );
258259 try writer.writeAll(" = ");
259 try f.object.dg.renderValue(writer, ty, val, .Other);
260 try f.object.dg.renderValue(writer, ty, val, .Initializer);
260261 try writer.writeAll(";\n ");
261262 return decl_c_value;
262263 },
......@@ -297,13 +298,14 @@ pub const Function = struct {
297298 return local_value;
298299 }
299300
300 fn writeCValue(f: *Function, w: anytype, c_value: CValue) !void {
301 fn writeCValue(f: *Function, w: anytype, c_value: CValue, location: ValueRenderLocation) !void {
301302 switch (c_value) {
302303 .constant => |inst| {
303304 const ty = f.air.typeOf(inst);
304305 const val = f.air.value(inst).?;
305 return f.object.dg.renderValue(w, ty, val, .Other);
306 return f.object.dg.renderValue(w, ty, val, location);
306307 },
308 .undef => |ty| return f.object.dg.renderValue(w, ty, Value.undef, location),
307309 else => return f.object.dg.writeCValue(w, c_value),
308310 }
309311 }
......@@ -425,13 +427,17 @@ pub const DeclGen = struct {
425427 if (ty.isSlice()) {
426428 try writer.writeByte('(');
427429 try dg.renderTypecast(writer, ty);
428 try writer.writeAll("){");
430 try writer.writeAll("){ .ptr = ");
431
429432 var buf: Type.SlicePtrFieldTypeBuffer = undefined;
430 try dg.renderValue(writer, ty.slicePtrFieldType(&buf), val.slicePtr(), .Other);
431 try writer.writeAll(", ");
432 try writer.print("{d}", .{val.sliceLen(dg.module)});
433 try writer.writeByte('}');
434 return;
433 try dg.renderValue(writer, ty.slicePtrFieldType(&buf), val.slicePtr(), .Initializer);
434
435 var len_pl: Value.Payload.U64 = .{
436 .base = .{ .tag = .int_u64 },
437 .data = val.sliceLen(dg.module),
438 };
439 const len_val = Value.initPayload(&len_pl.base);
440 return writer.print(", .len = {} }}", .{try dg.fmtIntLiteral(Type.usize, len_val)});
435441 }
436442
437443 // We shouldn't cast C function pointers as this is UB (when you call
......@@ -567,9 +573,13 @@ pub const DeclGen = struct {
567573 },
568574 .Pointer => switch (ty.ptrSize()) {
569575 .Slice => {
570 try writer.writeByte('(');
571 try dg.renderTypecast(writer, ty);
572 try writer.writeAll("){(");
576 if (location != .Initializer) {
577 try writer.writeByte('(');
578 try dg.renderTypecast(writer, ty);
579 try writer.writeByte(')');
580 }
581
582 try writer.writeAll("{(");
573583 var buf: Type.SlicePtrFieldTypeBuffer = undefined;
574584 const ptr_ty = ty.slicePtrFieldType(&buf);
575585 try dg.renderTypecast(writer, ptr_ty);
......@@ -593,69 +603,86 @@ pub const DeclGen = struct {
593603 return dg.renderValue(writer, payload_ty, val, location);
594604 }
595605
596 try writer.writeByte('(');
597 try dg.renderTypecast(writer, ty);
598 try writer.writeAll("){ .payload = ");
599 try dg.renderValue(writer, payload_ty, val, location);
606 if (location != .Initializer) {
607 try writer.writeByte('(');
608 try dg.renderTypecast(writer, ty);
609 try writer.writeByte(')');
610 }
611
612 try writer.writeAll("{ .payload = ");
613 try dg.renderValue(writer, payload_ty, val, .Initializer);
600614 try writer.writeAll(", .is_null = ");
601 try dg.renderValue(writer, Type.bool, val, location);
615 try dg.renderValue(writer, Type.bool, val, .Initializer);
602616 return writer.writeAll(" }");
603617 },
604618 .Struct => {
605 try writer.writeByte('(');
606 try dg.renderTypecast(writer, ty);
607 try writer.writeAll("){");
619 if (location != .Initializer) {
620 try writer.writeByte('(');
621 try dg.renderTypecast(writer, ty);
622 try writer.writeByte(')');
623 }
608624
625 try writer.writeByte('{');
609626 var empty = true;
610627 for (ty.structFields().values()) |field| {
611628 if (!field.ty.hasRuntimeBits()) continue;
612629
613630 if (!empty) try writer.writeByte(',');
614 try dg.renderValue(writer, field.ty, val, location);
631 try dg.renderValue(writer, field.ty, val, .Initializer);
615632
616633 empty = false;
617634 }
618635 if (empty) try writer.print("{x}", .{try dg.fmtIntLiteral(Type.u8, Value.undef)});
619
620636 return writer.writeByte('}');
621637 },
622638 .Union => {
623 try writer.writeByte('(');
624 try dg.renderTypecast(writer, ty);
625 try writer.writeAll("){");
639 if (location != .Initializer) {
640 try writer.writeByte('(');
641 try dg.renderTypecast(writer, ty);
642 try writer.writeByte(')');
643 }
626644
645 try writer.writeByte('{');
627646 if (ty.unionTagTypeSafety()) |tag_ty| {
628 try writer.writeAll(".tag = ");
629 try dg.renderValue(writer, tag_ty, val, location);
647 try writer.writeAll(" .tag = ");
648 try dg.renderValue(writer, tag_ty, val, .Initializer);
630649 try writer.writeAll(", .payload = {");
631650 }
632651 for (ty.unionFields().values()) |field| {
633652 if (!field.ty.hasRuntimeBits()) continue;
634 try dg.renderValue(writer, field.ty, val, location);
653 try dg.renderValue(writer, field.ty, val, .Initializer);
635654 break;
636655 } else try writer.print("{x}", .{try dg.fmtIntLiteral(Type.u8, Value.undef)});
637656 if (ty.unionTagTypeSafety()) |_| try writer.writeByte('}');
638657 return writer.writeByte('}');
639658 },
640659 .ErrorUnion => {
641 try writer.writeByte('(');
642 try dg.renderTypecast(writer, ty);
643 try writer.writeAll("){ .payload = ");
644 try dg.renderValue(writer, ty.errorUnionPayload(), val, location);
660 if (location != .Initializer) {
661 try writer.writeByte('(');
662 try dg.renderTypecast(writer, ty);
663 try writer.writeByte(')');
664 }
665
666 try writer.writeAll("{ .payload = ");
667 try dg.renderValue(writer, ty.errorUnionPayload(), val, .Initializer);
645668 return writer.print(", .error = {x} }}", .{
646669 try dg.fmtIntLiteral(ty.errorUnionSet(), val),
647670 });
648671 },
649672 .Array => {
650 try writer.writeByte('{');
673 if (location != .Initializer) {
674 try writer.writeByte('(');
675 try dg.renderTypecast(writer, ty);
676 try writer.writeByte(')');
677 }
651678
679 try writer.writeByte('{');
652680 const c_len = ty.arrayLenIncludingSentinel();
653681 var index: usize = 0;
654682 while (index < c_len) : (index += 1) {
655683 if (index > 0) try writer.writeAll(", ");
656 try dg.renderValue(writer, ty.childType(), val, location);
684 try dg.renderValue(writer, ty.childType(), val, .Initializer);
657685 }
658
659686 return writer.writeByte('}');
660687 },
661688 .ComptimeInt,
......@@ -696,21 +723,21 @@ pub const DeclGen = struct {
696723 // just generate a bit cast (exactly like we do in airBitcast)
697724 switch (ty.tag()) {
698725 .f32 => {
699 var bitcast_val_pl = Value.Payload.U64{
726 var bitcast_pl = Value.Payload.U64{
700727 .base = .{ .tag = .int_u64 },
701728 .data = @bitCast(u32, val.toFloat(f32)),
702729 };
703 const bitcast_val = Value.initPayload(&bitcast_val_pl.base);
730 const bitcast_val = Value.initPayload(&bitcast_pl.base);
704731 return writer.print("zig_bitcast_f32_u32({x})", .{
705732 try dg.fmtIntLiteral(Type.u32, bitcast_val),
706733 });
707734 },
708735 .f64 => {
709 var bitcast_val_pl = Value.Payload.U64{
736 var bitcast_pl = Value.Payload.U64{
710737 .base = .{ .tag = .int_u64 },
711738 .data = @bitCast(u64, val.toFloat(f64)),
712739 };
713 const bitcast_val = Value.initPayload(&bitcast_val_pl.base);
740 const bitcast_val = Value.initPayload(&bitcast_pl.base);
714741 return writer.print("zig_bitcast_f64_u64({x})", .{
715742 try dg.fmtIntLiteral(Type.u64, bitcast_val),
716743 });
......@@ -737,12 +764,16 @@ pub const DeclGen = struct {
737764 const slice = val.castTag(.slice).?.data;
738765 var buf: Type.SlicePtrFieldTypeBuffer = undefined;
739766
740 try writer.writeByte('(');
741 try dg.renderTypecast(writer, ty);
742 try writer.writeAll("){");
743 try dg.renderValue(writer, ty.slicePtrFieldType(&buf), slice.ptr, location);
767 if (location != .Initializer) {
768 try writer.writeByte('(');
769 try dg.renderTypecast(writer, ty);
770 try writer.writeByte(')');
771 }
772
773 try writer.writeByte('{');
774 try dg.renderValue(writer, ty.slicePtrFieldType(&buf), slice.ptr, .Initializer);
744775 try writer.writeAll(", ");
745 try dg.renderValue(writer, Type.usize, slice.len, location);
776 try dg.renderValue(writer, Type.usize, slice.len, .Initializer);
746777 try writer.writeByte('}');
747778 },
748779 .function => {
......@@ -768,13 +799,19 @@ pub const DeclGen = struct {
768799 else => unreachable,
769800 },
770801 .Array => {
802 if (location == .FunctionArgument) {
803 try writer.writeByte('(');
804 try dg.renderTypecast(writer, ty);
805 try writer.writeByte(')');
806 }
807
771808 // First try specific tag representations for more efficiency.
772809 switch (val.tag()) {
773810 .undef, .empty_struct_value, .empty_array => {
774811 try writer.writeByte('{');
775812 const ai = ty.arrayInfo();
776813 if (ai.sentinel) |s| {
777 try dg.renderValue(writer, ai.elem_type, s, location);
814 try dg.renderValue(writer, ai.elem_type, s, .Initializer);
778815 } else {
779816 try writer.writeByte('0');
780817 }
......@@ -786,23 +823,17 @@ pub const DeclGen = struct {
786823 defer arena.deinit();
787824 const arena_allocator = arena.allocator();
788825
789 if (location == .FunctionArgument) {
790 try writer.writeByte('(');
791 try dg.renderTypecast(writer, ty);
792 try writer.writeByte(')');
793 }
794
795826 try writer.writeByte('{');
796827 const ai = ty.arrayInfo();
797828 var index: usize = 0;
798829 while (index < ai.len) : (index += 1) {
799830 if (index != 0) try writer.writeByte(',');
800831 const elem_val = try val.elemValue(dg.module, arena_allocator, index);
801 try dg.renderValue(writer, ai.elem_type, elem_val, .Other);
832 try dg.renderValue(writer, ai.elem_type, elem_val, .Initializer);
802833 }
803834 if (ai.sentinel) |s| {
804835 if (index != 0) try writer.writeByte(',');
805 try dg.renderValue(writer, ai.elem_type, s, .Other);
836 try dg.renderValue(writer, ai.elem_type, s, .Initializer);
806837 }
807838 try writer.writeByte('}');
808839 },
......@@ -823,19 +854,17 @@ pub const DeclGen = struct {
823854 return dg.renderValue(writer, payload_ty, payload_val, location);
824855 }
825856
826 try writer.writeByte('(');
827 try dg.renderTypecast(writer, ty);
828 try writer.writeAll("){");
829 if (val.castTag(.opt_payload)) |pl| {
830 const payload_val = pl.data;
831 try writer.writeAll(" .payload = ");
832 try dg.renderValue(writer, payload_ty, payload_val, location);
833 try writer.writeAll(", .is_null = false }");
834 } else {
835 try writer.writeAll(" .payload = ");
836 try dg.renderValue(writer, payload_ty, Value.undef, location);
837 try writer.writeAll(", .is_null = true }");
857 if (location != .Initializer) {
858 try writer.writeByte('(');
859 try dg.renderTypecast(writer, ty);
860 try writer.writeByte(')');
838861 }
862
863 const payload_val = if (val.castTag(.opt_payload)) |pl| pl.data else Value.undef;
864
865 try writer.writeAll("{ .payload = ");
866 try dg.renderValue(writer, payload_ty, payload_val, .Initializer);
867 try writer.print(", .is_null = {} }}", .{val.tag() == .null_value});
839868 },
840869 .ErrorSet => {
841870 switch (val.tag()) {
......@@ -861,23 +890,20 @@ pub const DeclGen = struct {
861890 return dg.renderValue(writer, error_ty, err_val, location);
862891 }
863892
864 try writer.writeByte('(');
865 try dg.renderTypecast(writer, ty);
866 try writer.writeAll("){");
867 if (val.castTag(.eu_payload)) |pl| {
868 const payload_val = pl.data;
869 try writer.writeAll(" .payload = ");
870 try dg.renderValue(writer, payload_ty, payload_val, location);
871 try writer.print(", .error = {} }}", .{
872 try dg.fmtIntLiteral(error_ty, Value.zero),
873 });
874 } else {
875 try writer.writeAll(" .payload = ");
876 try dg.renderValue(writer, payload_ty, Value.undef, location);
877 try writer.writeAll(", .error = ");
878 try dg.renderValue(writer, error_ty, val, location);
879 try writer.writeAll(" }");
893 if (location != .Initializer) {
894 try writer.writeByte('(');
895 try dg.renderTypecast(writer, ty);
896 try writer.writeByte(')');
880897 }
898
899 const payload_val = if (val.castTag(.eu_payload)) |pl| pl.data else Value.undef;
900 const error_val = if (val.tag() == .eu_payload) Value.zero else val;
901
902 try writer.writeAll("{ .payload = ");
903 try dg.renderValue(writer, payload_ty, payload_val, .Initializer);
904 try writer.writeAll(", .error = ");
905 try dg.renderValue(writer, error_ty, error_val, .Initializer);
906 try writer.writeAll(" }");
881907 },
882908 .Enum => {
883909 switch (val.tag()) {
......@@ -927,36 +953,41 @@ pub const DeclGen = struct {
927953 .Struct => {
928954 const field_vals = val.castTag(.aggregate).?.data;
929955
930 try writer.writeByte('(');
931 try dg.renderTypecast(writer, ty);
932 try writer.writeAll("){");
956 if (location != .Initializer) {
957 try writer.writeByte('(');
958 try dg.renderTypecast(writer, ty);
959 try writer.writeByte(')');
960 }
933961
962 try writer.writeByte('{');
934963 var empty = true;
935964 for (field_vals) |field_val, field_index| {
936965 const field_ty = ty.structFieldType(field_index);
937966 if (!field_ty.hasRuntimeBits()) continue;
938967
939968 if (!empty) try writer.writeByte(',');
940 try dg.renderValue(writer, field_ty, field_val, location);
969 try dg.renderValue(writer, field_ty, field_val, .Initializer);
941970
942971 empty = false;
943972 }
944973 if (empty) try writer.print("{}", .{try dg.fmtIntLiteral(Type.u8, Value.zero)});
945
946974 try writer.writeByte('}');
947975 },
948976 .Union => {
949977 const union_obj = val.castTag(.@"union").?.data;
950978 const layout = ty.unionGetLayout(target);
951979
952 try writer.writeByte('(');
953 try dg.renderTypecast(writer, ty);
954 try writer.writeAll("){");
980 if (location != .Initializer) {
981 try writer.writeByte('(');
982 try dg.renderTypecast(writer, ty);
983 try writer.writeByte(')');
984 }
955985
986 try writer.writeByte('{');
956987 if (ty.unionTagTypeSafety()) |tag_ty| {
957988 if (layout.tag_size != 0) {
958989 try writer.writeAll(".tag = ");
959 try dg.renderValue(writer, tag_ty, union_obj.tag, location);
990 try dg.renderValue(writer, tag_ty, union_obj.tag, .Initializer);
960991 try writer.writeAll(", ");
961992 }
962993 try writer.writeAll(".payload = {");
......@@ -967,11 +998,9 @@ pub const DeclGen = struct {
967998 const field_name = ty.unionFields().keys()[index];
968999 if (field_ty.hasRuntimeBits()) {
9691000 try writer.print(".{ } = ", .{fmtIdent(field_name)});
970 try dg.renderValue(writer, field_ty, union_obj.val, location);
1001 try dg.renderValue(writer, field_ty, union_obj.val, .Initializer);
9711002 } else try writer.writeByte('0');
972 if (ty.unionTagTypeSafety()) |_| {
973 try writer.writeByte('}');
974 }
1003 if (ty.unionTagTypeSafety()) |_| try writer.writeByte('}');
9751004 try writer.writeByte('}');
9761005 },
9771006
......@@ -1029,7 +1058,7 @@ pub const DeclGen = struct {
10291058 try w.writeAll(", ");
10301059 }
10311060 const name = CValue{ .arg = index };
1032 try dg.renderTypeAndName(w, param_type, name, .Mut, 0);
1061 try dg.renderTypeAndName(w, param_type, name, .Const, 0);
10331062 index += 1;
10341063 }
10351064
......@@ -1737,28 +1766,28 @@ pub const DeclGen = struct {
17371766 defer dg.typedefs.allocator.free(name_z);
17381767 const name_bytes = name_z[0 .. name_z.len + 1];
17391768
1740 var tag_val_pl: Value.Payload.U32 = .{
1769 var tag_pl: Value.Payload.U32 = .{
17411770 .base = .{ .tag = .enum_field_index },
17421771 .data = @intCast(u32, index),
17431772 };
1744 const tag_val = Value.initPayload(&tag_val_pl.base);
1773 const tag_val = Value.initPayload(&tag_pl.base);
17451774
1746 var int_val_pl: Value.Payload.U64 = undefined;
1747 const int_val = tag_val.enumToInt(enum_ty, &int_val_pl);
1775 var int_pl: Value.Payload.U64 = undefined;
1776 const int_val = tag_val.enumToInt(enum_ty, &int_pl);
17481777
17491778 var name_ty_pl = Type.Payload.Len{ .base = .{ .tag = .array_u8_sentinel_0 }, .data = name.len };
17501779 const name_ty = Type.initPayload(&name_ty_pl.base);
17511780
1752 var name_val_pl = Value.Payload.Bytes{ .base = .{ .tag = .bytes }, .data = name_bytes };
1753 const name_val = Value.initPayload(&name_val_pl.base);
1781 var name_pl = Value.Payload.Bytes{ .base = .{ .tag = .bytes }, .data = name_bytes };
1782 const name_val = Value.initPayload(&name_pl.base);
17541783
1755 var len_val_pl = Value.Payload.U64{ .base = .{ .tag = .int_u64 }, .data = name.len };
1756 const len_val = Value.initPayload(&len_val_pl.base);
1784 var len_pl = Value.Payload.U64{ .base = .{ .tag = .int_u64 }, .data = name.len };
1785 const len_val = Value.initPayload(&len_pl.base);
17571786
17581787 try bw.print(" case {}: {{\n static ", .{try dg.fmtIntLiteral(enum_ty, int_val)});
17591788 try dg.renderTypeAndName(bw, name_ty, .{ .identifier = "name" }, .Const, 0);
17601789 try buffer.appendSlice(" = ");
1761 try dg.renderValue(bw, name_ty, name_val, .Other);
1790 try dg.renderValue(bw, name_ty, name_val, .Initializer);
17621791 try buffer.appendSlice(";\n return (");
17631792 try dg.renderTypecast(bw, name_slice_ty);
17641793 try bw.print("){{{}, {}}};\n", .{
......@@ -1893,8 +1922,8 @@ pub fn genErrDecls(o: *Object) !void {
18931922 var max_name_len: usize = 0;
18941923 for (o.dg.module.error_name_list.items) |name, value| {
18951924 max_name_len = std.math.max(name.len, max_name_len);
1896 var err_val_pl = Value.Payload.Error{ .data = .{ .name = name } };
1897 try o.dg.renderValue(writer, Type.anyerror, Value.initPayload(&err_val_pl.base), .Other);
1925 var err_pl = Value.Payload.Error{ .data = .{ .name = name } };
1926 try o.dg.renderValue(writer, Type.anyerror, Value.initPayload(&err_pl.base), .Other);
18981927 try writer.print(" = {d}u,\n", .{value});
18991928 }
19001929 o.indent_writer.popIndent();
......@@ -1915,13 +1944,13 @@ pub fn genErrDecls(o: *Object) !void {
19151944 var name_ty_pl = Type.Payload.Len{ .base = .{ .tag = .array_u8_sentinel_0 }, .data = name.len };
19161945 const name_ty = Type.initPayload(&name_ty_pl.base);
19171946
1918 var name_val_pl = Value.Payload.Bytes{ .base = .{ .tag = .bytes }, .data = name_z };
1919 const name_val = Value.initPayload(&name_val_pl.base);
1947 var name_pl = Value.Payload.Bytes{ .base = .{ .tag = .bytes }, .data = name_z };
1948 const name_val = Value.initPayload(&name_pl.base);
19201949
19211950 try writer.writeAll("static ");
19221951 try o.dg.renderTypeAndName(writer, name_ty, .{ .identifier = identifier }, .Const, 0);
19231952 try writer.writeAll(" = ");
1924 try o.dg.renderValue(writer, name_ty, name_val, .Other);
1953 try o.dg.renderValue(writer, name_ty, name_val, .Initializer);
19251954 try writer.writeAll(";\n");
19261955 }
19271956
......@@ -1937,8 +1966,8 @@ pub fn genErrDecls(o: *Object) !void {
19371966 for (o.dg.module.error_name_list.items) |name, value| {
19381967 if (value != 0) try writer.writeByte(',');
19391968
1940 var len_val_pl = Value.Payload.U64{ .base = .{ .tag = .int_u64 }, .data = name.len };
1941 const len_val = Value.initPayload(&len_val_pl.base);
1969 var len_pl = Value.Payload.U64{ .base = .{ .tag = .int_u64 }, .data = name.len };
1970 const len_val = Value.initPayload(&len_pl.base);
19421971
19431972 try writer.print("{{" ++ name_prefix ++ "_{}, {}}}", .{
19441973 fmtIdent(name),
......@@ -2031,7 +2060,7 @@ pub fn genDecl(o: *Object) !void {
20312060 try o.dg.renderTypeAndName(w, o.dg.decl.ty, decl_c_value, .Mut, o.dg.decl.@"align");
20322061 try w.writeAll(" = ");
20332062 if (variable.init.tag() != .unreachable_value) {
2034 try o.dg.renderValue(w, tv.ty, variable.init, .Other);
2063 try o.dg.renderValue(w, tv.ty, variable.init, .Initializer);
20352064 }
20362065 try w.writeByte(';');
20372066 try o.indent_writer.insertNewline();
......@@ -2046,7 +2075,7 @@ pub fn genDecl(o: *Object) !void {
20462075 try o.dg.renderTypeAndName(writer, tv.ty, decl_c_value, .Mut, o.dg.decl.@"align");
20472076
20482077 try writer.writeAll(" = ");
2049 try o.dg.renderValue(writer, tv.ty, tv.val, .Other);
2078 try o.dg.renderValue(writer, tv.ty, tv.val, .Initializer);
20502079 try writer.writeAll(";\n");
20512080 }
20522081}
......@@ -2099,15 +2128,15 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO
20992128 .unreach => try airUnreach(f),
21002129 .fence => try airFence(f, inst),
21012130
2102 .ptr_add => try airPtrAddSub(f, inst, " + "),
2103 .ptr_sub => try airPtrAddSub(f, inst, " - "),
2131 .ptr_add => try airPtrAddSub(f, inst, '+'),
2132 .ptr_sub => try airPtrAddSub(f, inst, '-'),
21042133
21052134 // TODO use a different strategy for add, sub, mul, div
21062135 // that communicates to the optimizer that wrapping is UB.
2107 .add => try airBinOp (f, inst, " + "),
2108 .sub => try airBinOp (f, inst, " - "),
2109 .mul => try airBinOp (f, inst, " * "),
2110 .div_float, .div_exact => try airBinOp( f, inst, " / "),
2136 .add => try airBinOp(f, inst, "+"),
2137 .sub => try airBinOp(f, inst, "-"),
2138 .mul => try airBinOp(f, inst, "*"),
2139 .div_float, .div_exact => try airBinOp(f, inst, "/"),
21112140
21122141 .rem => blk: {
21132142 const bin_op = f.air.instructions.items(.data)[inst].bin_op;
......@@ -2115,7 +2144,7 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO
21152144 // For binary operations @TypeOf(lhs)==@TypeOf(rhs),
21162145 // so we only check one.
21172146 break :blk if (lhs_ty.isInt())
2118 try airBinOp(f, inst, " % ")
2147 try airBinOp(f, inst, "%")
21192148 else
21202149 try airBinFloatOp(f, inst, "fmod"); // yes, @rem() => fmod()
21212150 },
......@@ -2125,21 +2154,21 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO
21252154 // For binary operations @TypeOf(lhs)==@TypeOf(rhs),
21262155 // so we only check one.
21272156 break :blk if (lhs_ty.isInt())
2128 try airBinOp(f, inst, " / ")
2157 try airBinOp(f, inst, "/")
21292158 else
21302159 try airBinOpBuiltinCall(f, inst, "div_trunc");
21312160 },
21322161 .div_floor => try airBinOpBuiltinCall(f, inst, "div_floor"),
21332162 .mod => try airBinOpBuiltinCall(f, inst, "mod"),
21342163
2135 .addwrap => try airWrapOp(f, inst, " + ", "addw_"),
2136 .subwrap => try airWrapOp(f, inst, " - ", "subw_"),
2137 .mulwrap => try airWrapOp(f, inst, " * ", "mulw_"),
2164 .addwrap => try airWrapOp(f, inst, "+", "add"),
2165 .subwrap => try airWrapOp(f, inst, "-", "sub"),
2166 .mulwrap => try airWrapOp(f, inst, "*", "mul"),
21382167
2139 .add_sat => try airSatOp(f, inst, "adds_"),
2140 .sub_sat => try airSatOp(f, inst, "subs_"),
2141 .mul_sat => try airSatOp(f, inst, "muls_"),
2142 .shl_sat => try airSatOp(f, inst, "shls_"),
2168 .add_sat => try airSatOp(f, inst, "add"),
2169 .sub_sat => try airSatOp(f, inst, "sub"),
2170 .mul_sat => try airSatOp(f, inst, "mul"),
2171 .shl_sat => try airSatOp(f, inst, "shl"),
21432172
21442173 .neg => try airNeg(f, inst),
21452174
......@@ -2161,20 +2190,20 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO
21612190
21622191 .mul_add => try airMulAdd(f, inst),
21632192
2164 .add_with_overflow => try airOverflow(f, inst, "addo_", .range),
2165 .sub_with_overflow => try airOverflow(f, inst, "subo_", .range),
2166 .mul_with_overflow => try airOverflow(f, inst, "mulo_", .range),
2167 .shl_with_overflow => try airOverflow(f, inst, "shlo_", .bits),
2193 .add_with_overflow => try airOverflow(f, inst, "add", .range),
2194 .sub_with_overflow => try airOverflow(f, inst, "sub", .range),
2195 .mul_with_overflow => try airOverflow(f, inst, "mul", .range),
2196 .shl_with_overflow => try airOverflow(f, inst, "shl", .bits),
21682197
2169 .min => try airMinMax(f, inst, "<"),
2170 .max => try airMinMax(f, inst, ">"),
2198 .min => try airMinMax(f, inst, '<'),
2199 .max => try airMinMax(f, inst, '>'),
21712200
21722201 .slice => try airSlice(f, inst),
21732202
2174 .cmp_gt => try airBinOp(f, inst, " > "),
2175 .cmp_gte => try airBinOp(f, inst, " >= "),
2176 .cmp_lt => try airBinOp(f, inst, " < "),
2177 .cmp_lte => try airBinOp(f, inst, " <= "),
2203 .cmp_gt => try airBinOp(f, inst, ">"),
2204 .cmp_gte => try airBinOp(f, inst, ">="),
2205 .cmp_lt => try airBinOp(f, inst, "<"),
2206 .cmp_lte => try airBinOp(f, inst, "<="),
21782207
21792208 .cmp_eq => try airEquality(f, inst, "((", "=="),
21802209 .cmp_neq => try airEquality(f, inst, "!((", "!="),
......@@ -2183,13 +2212,11 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO
21832212 .cmp_lt_errors_len => return f.fail("TODO: C backend: implement cmp_lt_errors_len", .{}),
21842213
21852214 // bool_and and bool_or are non-short-circuit operations
2186 .bool_and => try airBinOp(f, inst, " & "),
2187 .bool_or => try airBinOp(f, inst, " | "),
2188 .bit_and => try airBinOp(f, inst, " & "),
2189 .bit_or => try airBinOp(f, inst, " | "),
2190 .xor => try airBinOp(f, inst, " ^ "),
2191 .shr, .shr_exact => try airBinOp(f, inst, " >> "),
2192 .shl, .shl_exact => try airBinOp(f, inst, " << "),
2215 .bool_and, .bit_and => try airBinOp(f, inst, "&"),
2216 .bool_or, .bit_or => try airBinOp(f, inst, "|"),
2217 .xor => try airBinOp(f, inst, "^"),
2218 .shr, .shr_exact => try airBinOp(f, inst, ">>"),
2219 .shl, .shl_exact => try airBinOp(f, inst, "<<"),
21932220 .not => try airNot (f, inst),
21942221
21952222 .optional_payload => try airOptionalPayload(f, inst),
......@@ -2202,10 +2229,10 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO
22022229 .is_err_ptr => try airIsErr(f, inst, true, "!="),
22032230 .is_non_err_ptr => try airIsErr(f, inst, true, "=="),
22042231
2205 .is_null => try airIsNull(f, inst, "==", ""),
2206 .is_non_null => try airIsNull(f, inst, "!=", ""),
2207 .is_null_ptr => try airIsNull(f, inst, "==", "[0]"),
2208 .is_non_null_ptr => try airIsNull(f, inst, "!=", "[0]"),
2232 .is_null => try airIsNull(f, inst, "==", false),
2233 .is_non_null => try airIsNull(f, inst, "!=", false),
2234 .is_null_ptr => try airIsNull(f, inst, "==", true),
2235 .is_non_null_ptr => try airIsNull(f, inst, "!=", true),
22092236
22102237 .alloc => try airAlloc(f, inst),
22112238 .ret_ptr => try airRetPtr(f, inst),
......@@ -2291,11 +2318,11 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO
22912318 .field_parent_ptr => try airFieldParentPtr(f, inst),
22922319
22932320 .struct_field_val => try airStructFieldVal(f, inst),
2294 .slice_ptr => try airSliceField(f, inst, " = ", ".ptr;\n"),
2295 .slice_len => try airSliceField(f, inst, " = ", ".len;\n"),
2321 .slice_ptr => try airSliceField(f, inst, false, "ptr"),
2322 .slice_len => try airSliceField(f, inst, false, "len"),
22962323
2297 .ptr_slice_len_ptr => try airSliceField(f, inst, " = &", "->len;\n"),
2298 .ptr_slice_ptr_ptr => try airSliceField(f, inst, " = &", "->ptr;\n"),
2324 .ptr_slice_len_ptr => try airSliceField(f, inst, true, "len"),
2325 .ptr_slice_ptr_ptr => try airSliceField(f, inst, true, "ptr"),
22992326
23002327 .ptr_elem_val => try airPtrElemVal(f, inst),
23012328 .ptr_elem_ptr => try airPtrElemPtr(f, inst),
......@@ -2303,8 +2330,8 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO
23032330 .slice_elem_ptr => try airSliceElemPtr(f, inst),
23042331 .array_elem_val => try airArrayElemVal(f, inst),
23052332
2306 .unwrap_errunion_payload => try airUnwrapErrUnionPay(f, inst, ""),
2307 .unwrap_errunion_payload_ptr => try airUnwrapErrUnionPay(f, inst, "&"),
2333 .unwrap_errunion_payload => try airUnwrapErrUnionPay(f, inst, false),
2334 .unwrap_errunion_payload_ptr => try airUnwrapErrUnionPay(f, inst, true),
23082335 .unwrap_errunion_err => try airUnwrapErrUnionErr(f, inst),
23092336 .unwrap_errunion_err_ptr => try airUnwrapErrUnionErr(f, inst),
23102337 .wrap_errunion_payload => try airWrapErrUnionPay(f, inst),
......@@ -2355,7 +2382,7 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO
23552382 try writer.writeByte('}');
23562383}
23572384
2358fn airSliceField(f: *Function, inst: Air.Inst.Index, prefix: []const u8, suffix: []const u8) !CValue {
2385fn airSliceField(f: *Function, inst: Air.Inst.Index, is_ptr: bool, field_name: []const u8) !CValue {
23592386 if (f.liveness.isUnused(inst)) return CValue.none;
23602387
23612388 const inst_ty = f.air.typeOfIndex(inst);
......@@ -2363,9 +2390,12 @@ fn airSliceField(f: *Function, inst: Air.Inst.Index, prefix: []const u8, suffix:
23632390 const operand = try f.resolveInst(ty_op.operand);
23642391 const writer = f.object.writer();
23652392 const local = try f.allocLocal(inst_ty, .Const);
2366 try writer.writeAll(prefix);
2367 try f.writeCValue(writer, operand);
2368 try writer.writeAll(suffix);
2393 try writer.writeAll(" = ");
2394 if (is_ptr) try writer.writeByte('&');
2395 try f.writeCValue(writer, operand, .Other);
2396 try if (is_ptr) writer.writeAll("->") else writer.writeByte('.');
2397 try writer.writeAll(field_name);
2398 try writer.writeAll(";\n");
23692399 return local;
23702400}
23712401
......@@ -2379,9 +2409,9 @@ fn airPtrElemVal(f: *Function, inst: Air.Inst.Index) !CValue {
23792409 const writer = f.object.writer();
23802410 const local = try f.allocLocal(f.air.typeOfIndex(inst), .Const);
23812411 try writer.writeAll(" = ");
2382 try f.writeCValue(writer, ptr);
2412 try f.writeCValue(writer, ptr, .Other);
23832413 try writer.writeByte('[');
2384 try f.writeCValue(writer, index);
2414 try f.writeCValue(writer, index, .Other);
23852415 try writer.writeAll("];\n");
23862416 return local;
23872417}
......@@ -2403,10 +2433,10 @@ fn airPtrElemPtr(f: *Function, inst: Air.Inst.Index) !CValue {
24032433 // It's a pointer to an array, so we need to de-reference.
24042434 try f.writeCValueDeref(writer, ptr);
24052435 } else {
2406 try f.writeCValue(writer, ptr);
2436 try f.writeCValue(writer, ptr, .Other);
24072437 }
24082438 try writer.writeAll(")[");
2409 try f.writeCValue(writer, index);
2439 try f.writeCValue(writer, index, .Other);
24102440 try writer.writeAll("];\n");
24112441 return local;
24122442}
......@@ -2421,9 +2451,9 @@ fn airSliceElemVal(f: *Function, inst: Air.Inst.Index) !CValue {
24212451 const writer = f.object.writer();
24222452 const local = try f.allocLocal(f.air.typeOfIndex(inst), .Const);
24232453 try writer.writeAll(" = ");
2424 try f.writeCValue(writer, slice);
2454 try f.writeCValue(writer, slice, .Other);
24252455 try writer.writeAll(".ptr[");
2426 try f.writeCValue(writer, index);
2456 try f.writeCValue(writer, index, .Other);
24272457 try writer.writeAll("];\n");
24282458 return local;
24292459}
......@@ -2439,9 +2469,9 @@ fn airSliceElemPtr(f: *Function, inst: Air.Inst.Index) !CValue {
24392469 const writer = f.object.writer();
24402470 const local = try f.allocLocal(f.air.typeOfIndex(inst), .Const);
24412471 try writer.writeAll(" = &");
2442 try f.writeCValue(writer, slice);
2472 try f.writeCValue(writer, slice, .Other);
24432473 try writer.writeAll(".ptr[");
2444 try f.writeCValue(writer, index);
2474 try f.writeCValue(writer, index, .Other);
24452475 try writer.writeAll("];\n");
24462476 return local;
24472477}
......@@ -2455,9 +2485,9 @@ fn airArrayElemVal(f: *Function, inst: Air.Inst.Index) !CValue {
24552485 const writer = f.object.writer();
24562486 const local = try f.allocLocal(f.air.typeOfIndex(inst), .Const);
24572487 try writer.writeAll(" = ");
2458 try f.writeCValue(writer, array);
2488 try f.writeCValue(writer, array, .Other);
24592489 try writer.writeByte('[');
2460 try f.writeCValue(writer, index);
2490 try f.writeCValue(writer, index, .Other);
24612491 try writer.writeAll("];\n");
24622492 return local;
24632493}
......@@ -2523,11 +2553,11 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue {
25232553 // and thus we only need to know size/type information from the local type/dest.
25242554 try writer.writeAll(";\n");
25252555 try writer.writeAll("memcpy(");
2526 try f.writeCValue(writer, local);
2556 try f.writeCValue(writer, local, .FunctionArgument);
25272557 try writer.writeAll(", ");
2528 try f.writeCValue(writer, operand);
2558 try f.writeCValue(writer, operand, .FunctionArgument);
25292559 try writer.writeAll(", sizeof(");
2530 try f.writeCValue(writer, local);
2560 try f.renderTypecast(writer, inst_ty);
25312561 try writer.writeAll("));\n");
25322562 } else {
25332563 try writer.writeAll(" = ");
......@@ -2544,7 +2574,7 @@ fn airRet(f: *Function, inst: Air.Inst.Index) !CValue {
25442574 if (ret_ty.isFnOrHasRuntimeBitsIgnoreComptime()) {
25452575 const operand = try f.resolveInst(un_op);
25462576 try writer.writeAll("return ");
2547 try f.writeCValue(writer, operand);
2577 try f.writeCValue(writer, operand, .Other);
25482578 try writer.writeAll(";\n");
25492579 } else if (ret_ty.isError()) {
25502580 try writer.writeAll("return 0;");
......@@ -2563,7 +2593,7 @@ fn airRetLoad(f: *Function, inst: Air.Inst.Index) !CValue {
25632593 if (ret_ty.isFnOrHasRuntimeBitsIgnoreComptime()) {
25642594 const ptr = try f.resolveInst(un_op);
25652595 try writer.writeAll("return *");
2566 try f.writeCValue(writer, ptr);
2596 try f.writeCValue(writer, ptr, .Other);
25672597 try writer.writeAll(";\n");
25682598 } else if (ret_ty.isError()) {
25692599 try writer.writeAll("return 0;\n");
......@@ -2586,7 +2616,7 @@ fn airIntCast(f: *Function, inst: Air.Inst.Index) !CValue {
25862616 try writer.writeAll(" = (");
25872617 try f.renderTypecast(writer, inst_ty);
25882618 try writer.writeByte(')');
2589 try f.writeCValue(writer, operand);
2619 try f.writeCValue(writer, operand, .Other);
25902620 try writer.writeAll(";\n");
25912621 return local;
25922622}
......@@ -2603,32 +2633,44 @@ fn airTrunc(f: *Function, inst: Air.Inst.Index) !CValue {
26032633 const dest_int_info = inst_ty.intInfo(target);
26042634 const dest_bits = dest_int_info.bits;
26052635
2606 try writer.writeAll(" = ");
2636 try writer.writeAll(" = (");
2637 try f.renderTypecast(writer, inst_ty);
2638 try writer.writeByte(')');
26072639
26082640 if (dest_bits >= 8 and std.math.isPowerOfTwo(dest_bits)) {
2609 try f.writeCValue(writer, operand);
2641 try f.writeCValue(writer, operand, .Other);
26102642 try writer.writeAll(";\n");
2611 return local;
2612 }
2613
2614 switch (dest_int_info.signedness) {
2643 } else switch (dest_int_info.signedness) {
26152644 .unsigned => {
2616 try f.writeCValue(writer, operand);
2617 const mask = (@as(u65, 1) << @intCast(u7, dest_bits)) - 1;
2618 try writer.print(" & {d}ULL;\n", .{mask});
2619 return local;
2645 var arena = std.heap.ArenaAllocator.init(f.object.dg.module.gpa);
2646 defer arena.deinit();
2647
2648 const expected_contents = union { u: Value.Payload.U64, i: Value.Payload.I64 };
2649 var stack align(@alignOf(expected_contents)) =
2650 std.heap.stackFallback(@sizeOf(expected_contents), arena.allocator());
2651
2652 const mask_val = try inst_ty.maxInt(stack.get(), target);
2653
2654 try writer.writeByte('(');
2655 try f.writeCValue(writer, operand, .Other);
2656 try writer.print(" & {x});\n", .{try f.fmtIntLiteral(inst_ty, mask_val)});
26202657 },
26212658 .signed => {
26222659 const operand_ty = f.air.typeOf(ty_op.operand);
26232660 const c_bits = toCIntBits(operand_ty.intInfo(target).bits) orelse
26242661 return f.fail("TODO: C backend: implement integer types larger than 128 bits", .{});
2625 const shift_rhs = c_bits - dest_bits;
2626 try writer.print("(int{d}_t)((uint{d}_t)", .{ c_bits, c_bits });
2627 try f.writeCValue(writer, operand);
2628 try writer.print(" << {d}) >> {d};\n", .{ shift_rhs, shift_rhs });
2629 return local;
2662 var shift_pl = Value.Payload.U64{
2663 .base = .{ .tag = .int_u64 },
2664 .data = c_bits - dest_bits,
2665 };
2666 const shift_val = Value.initPayload(&shift_pl.base);
2667
2668 try writer.print("((int{d}_t)((uint{0d}_t)", .{c_bits});
2669 try f.writeCValue(writer, operand, .Other);
2670 try writer.print(" << {}) >> {0});\n", .{try f.fmtIntLiteral(Type.u8, shift_val)});
26302671 },
26312672 }
2673 return local;
26322674}
26332675
26342676fn airBoolToInt(f: *Function, inst: Air.Inst.Index) !CValue {
......@@ -2640,18 +2682,18 @@ fn airBoolToInt(f: *Function, inst: Air.Inst.Index) !CValue {
26402682 const operand = try f.resolveInst(un_op);
26412683 const local = try f.allocLocal(inst_ty, .Const);
26422684 try writer.writeAll(" = ");
2643 try f.writeCValue(writer, operand);
2685 try f.writeCValue(writer, operand, .Other);
26442686 try writer.writeAll(";\n");
26452687 return local;
26462688}
26472689
2648fn airStoreUndefined(f: *Function, dest_ptr: CValue) !CValue {
2690fn airStoreUndefined(f: *Function, lhs_child_ty: Type, dest_ptr: CValue) !CValue {
26492691 if (f.wantSafety()) {
26502692 const writer = f.object.writer();
26512693 try writer.writeAll("memset(");
2652 try f.writeCValue(writer, dest_ptr);
2694 try f.writeCValue(writer, dest_ptr, .FunctionArgument);
26532695 try writer.print(", {x}, sizeof(", .{try f.fmtIntLiteral(Type.u8, Value.undef)});
2654 try f.writeCValueDeref(writer, dest_ptr);
2696 try f.renderTypecast(writer, lhs_child_ty);
26552697 try writer.writeAll("));\n");
26562698 }
26572699 return CValue.none;
......@@ -2660,8 +2702,8 @@ fn airStoreUndefined(f: *Function, dest_ptr: CValue) !CValue {
26602702fn airStore(f: *Function, inst: Air.Inst.Index) !CValue {
26612703 // *a = b;
26622704 const bin_op = f.air.instructions.items(.data)[inst].bin_op;
2663 const lhs_child_type = f.air.typeOf(bin_op.lhs).childType();
2664 if (!lhs_child_type.hasRuntimeBitsIgnoreComptime()) return CValue.none;
2705 const lhs_child_ty = f.air.typeOf(bin_op.lhs).childType();
2706 if (!lhs_child_ty.hasRuntimeBitsIgnoreComptime()) return CValue.none;
26652707
26662708 const dest_ptr = try f.resolveInst(bin_op.lhs);
26672709 const src_val = try f.resolveInst(bin_op.rhs);
......@@ -2671,14 +2713,14 @@ fn airStore(f: *Function, inst: Air.Inst.Index) !CValue {
26712713 const src_val_is_undefined =
26722714 if (f.air.value(bin_op.rhs)) |v| v.isUndefDeep() else false;
26732715 if (src_val_is_undefined)
2674 return try airStoreUndefined(f, dest_ptr);
2716 return try airStoreUndefined(f, lhs_child_ty, dest_ptr);
26752717
26762718 const writer = f.object.writer();
2677 if (lhs_child_type.zigTypeTag() == .Array) {
2719 if (lhs_child_ty.zigTypeTag() == .Array) {
26782720 // For this memcpy to safely work we need the rhs to have the same
26792721 // underlying type as the lhs (i.e. they must both be arrays of the same underlying type).
26802722 const rhs_type = f.air.typeOf(bin_op.rhs);
2681 assert(rhs_type.eql(lhs_child_type, f.object.dg.module));
2723 assert(rhs_type.eql(lhs_child_ty, f.object.dg.module));
26822724
26832725 // If the source is a constant, writeCValue will emit a brace initialization
26842726 // so work around this by initializing into new local.
......@@ -2686,37 +2728,30 @@ fn airStore(f: *Function, inst: Air.Inst.Index) !CValue {
26862728 const array_src = if (src_val == .constant) blk: {
26872729 const new_local = try f.allocLocal(rhs_type, .Const);
26882730 try writer.writeAll(" = ");
2689 try f.writeCValue(writer, src_val);
2690 try writer.writeByte(';');
2691 try f.object.indent_writer.insertNewline();
2731 try f.writeCValue(writer, src_val, .Initializer);
2732 try writer.writeAll(";\n");
26922733
26932734 break :blk new_local;
26942735 } else src_val;
26952736
26962737 try writer.writeAll("memcpy(");
2697 try f.writeCValue(writer, dest_ptr);
2738 try f.writeCValue(writer, dest_ptr, .FunctionArgument);
26982739 try writer.writeAll(", ");
2699 try f.writeCValue(writer, array_src);
2740 try f.writeCValue(writer, array_src, .FunctionArgument);
27002741 try writer.writeAll(", sizeof(");
2701 try f.writeCValue(writer, array_src);
2742 try f.renderTypecast(writer, lhs_child_ty);
27022743 try writer.writeAll("));\n");
27032744 } else {
27042745 try f.writeCValueDeref(writer, dest_ptr);
27052746 try writer.writeAll(" = ");
2706 try f.writeCValue(writer, src_val);
2747 try f.writeCValue(writer, src_val, .Other);
27072748 try writer.writeAll(";\n");
27082749 }
27092750 return CValue.none;
27102751}
27112752
2712fn airWrapOp(
2713 f: *Function,
2714 inst: Air.Inst.Index,
2715 str_op: [*:0]const u8,
2716 fn_op: [*:0]const u8,
2717) !CValue {
2718 if (f.liveness.isUnused(inst))
2719 return CValue.none;
2753fn airWrapOp(f: *Function, inst: Air.Inst.Index, operator: []const u8, fn_name: []const u8) !CValue {
2754 if (f.liveness.isUnused(inst)) return CValue.none;
27202755
27212756 const bin_op = f.air.instructions.items(.data)[inst].bin_op;
27222757 const inst_ty = f.air.typeOfIndex(inst);
......@@ -2725,26 +2760,18 @@ fn airWrapOp(
27252760 const bits = int_info.bits;
27262761
27272762 // if it's an unsigned int with non-arbitrary bit size then we can just add
2728 if (int_info.signedness == .unsigned) {
2729 const ok_bits = switch (bits) {
2730 8, 16, 32, 64, 128 => true,
2731 else => false,
2732 };
2733 if (ok_bits or inst_ty.tag() != .int_unsigned) {
2734 return try airBinOp(f, inst, str_op);
2735 }
2763 if (int_info.signedness == .unsigned and bits == toCIntBits(bits)) {
2764 return try airBinOp(f, inst, operator);
27362765 }
27372766
2738 if (bits > 64) {
2739 return f.fail("TODO: C backend: airWrapOp for large integers", .{});
2740 }
2767 if (bits > 64) return f.fail("TODO: C backend: airWrapOp for large integers", .{});
27412768
27422769 const lhs = try f.resolveInst(bin_op.lhs);
27432770 const rhs = try f.resolveInst(bin_op.rhs);
27442771 const w = f.object.writer();
27452772
2746 const ret = try f.allocLocal(inst_ty, .Mut);
2747 try w.print(" = zig_{s}", .{fn_op});
2773 const local = try f.allocLocal(inst_ty, .Mut);
2774 try w.print(" = zig_{s}w_", .{fn_name});
27482775
27492776 switch (inst_ty.tag()) {
27502777 .isize => try w.writeAll("isize"),
......@@ -2766,9 +2793,9 @@ fn airWrapOp(
27662793 }
27672794
27682795 try w.writeByte('(');
2769 try f.writeCValue(w, lhs);
2796 try f.writeCValue(w, lhs, .FunctionArgument);
27702797 try w.writeAll(", ");
2771 try f.writeCValue(w, rhs);
2798 try f.writeCValue(w, rhs, .FunctionArgument);
27722799 {
27732800 var arena = std.heap.ArenaAllocator.init(f.object.dg.module.gpa);
27742801 defer arena.deinit();
......@@ -2787,12 +2814,11 @@ fn airWrapOp(
27872814 }
27882815 try f.object.indent_writer.insertNewline();
27892816
2790 return ret;
2817 return local;
27912818}
27922819
2793fn airSatOp(f: *Function, inst: Air.Inst.Index, fn_op: [*:0]const u8) !CValue {
2794 if (f.liveness.isUnused(inst))
2795 return CValue.none;
2820fn airSatOp(f: *Function, inst: Air.Inst.Index, fn_name: []const u8) !CValue {
2821 if (f.liveness.isUnused(inst)) return CValue.none;
27962822
27972823 const bin_op = f.air.instructions.items(.data)[inst].bin_op;
27982824 const inst_ty = f.air.typeOfIndex(inst);
......@@ -2800,22 +2826,14 @@ fn airSatOp(f: *Function, inst: Air.Inst.Index, fn_op: [*:0]const u8) !CValue {
28002826 const int_info = inst_ty.intInfo(target);
28012827 const bits = int_info.bits;
28022828
2803 switch (bits) {
2804 8, 16, 32, 64, 128 => {},
2805 else => return f.object.dg.fail("TODO: C backend: airSatOp for non power of 2 integers", .{}),
2806 }
2807
2808 // if it's an unsigned int with non-arbitrary bit size then we can just add
2809 if (bits > 64) {
2810 return f.object.dg.fail("TODO: C backend: airSatOp for large integers", .{});
2811 }
2829 if (bits > 64) return f.object.dg.fail("TODO: C backend: airSatOp for large integers", .{});
28122830
28132831 const lhs = try f.resolveInst(bin_op.lhs);
28142832 const rhs = try f.resolveInst(bin_op.rhs);
28152833 const w = f.object.writer();
28162834
2817 const ret = try f.allocLocal(inst_ty, .Mut);
2818 try w.print(" = zig_{s}", .{fn_op});
2835 const local = try f.allocLocal(inst_ty, .Mut);
2836 try w.print(" = zig_{s}s_", .{fn_name});
28192837
28202838 switch (inst_ty.tag()) {
28212839 .isize => try w.writeAll("isize"),
......@@ -2837,9 +2855,9 @@ fn airSatOp(f: *Function, inst: Air.Inst.Index, fn_op: [*:0]const u8) !CValue {
28372855 }
28382856
28392857 try w.writeByte('(');
2840 try f.writeCValue(w, lhs);
2858 try f.writeCValue(w, lhs, .FunctionArgument);
28412859 try w.writeAll(", ");
2842 try f.writeCValue(w, rhs);
2860 try f.writeCValue(w, rhs, .FunctionArgument);
28432861 {
28442862 var arena = std.heap.ArenaAllocator.init(f.object.dg.module.gpa);
28452863 defer arena.deinit();
......@@ -2858,10 +2876,10 @@ fn airSatOp(f: *Function, inst: Air.Inst.Index, fn_op: [*:0]const u8) !CValue {
28582876 }
28592877 try f.object.indent_writer.insertNewline();
28602878
2861 return ret;
2879 return local;
28622880}
28632881
2864fn airOverflow(f: *Function, inst: Air.Inst.Index, op_abbrev: [*:0]const u8, kind: enum { range, bits }) !CValue {
2882fn airOverflow(f: *Function, inst: Air.Inst.Index, fn_name: []const u8, kind: enum { range, bits }) !CValue {
28652883 if (f.liveness.isUnused(inst))
28662884 return CValue.none;
28672885
......@@ -2879,19 +2897,18 @@ fn airOverflow(f: *Function, inst: Air.Inst.Index, op_abbrev: [*:0]const u8, kin
28792897 const c_bits = toCIntBits(int_info.bits) orelse
28802898 return f.fail("TODO: C backend: implement integer arithmetic larger than 128 bits", .{});
28812899
2882 const ret = try f.allocLocal(inst_ty, .Mut);
2883 try w.writeByte(';');
2884 try f.object.indent_writer.insertNewline();
2885 try f.writeCValue(w, ret);
2900 const local = try f.allocLocal(inst_ty, .Mut);
2901 try w.writeAll(";\n");
28862902
2887 try w.print(".field_1 = zig_{s}{c}{d}(", .{
2888 op_abbrev, signAbbrev(int_info.signedness), c_bits,
2903 try f.writeCValue(w, local, .Other);
2904 try w.print(".field_1 = zig_{s}o_{c}{d}(", .{
2905 fn_name, signAbbrev(int_info.signedness), c_bits,
28892906 });
2890 try f.writeCValue(w, lhs);
2907 try f.writeCValue(w, lhs, .FunctionArgument);
28912908 try w.writeAll(", ");
2892 try f.writeCValue(w, rhs);
2909 try f.writeCValue(w, rhs, .FunctionArgument);
28932910 try w.writeAll(", &");
2894 try f.writeCValue(w, ret);
2911 try f.writeCValue(w, local, .Other);
28952912 try w.writeAll(".field_0, ");
28962913 switch (kind) {
28972914 .range => {
......@@ -2916,7 +2933,7 @@ fn airOverflow(f: *Function, inst: Air.Inst.Index, op_abbrev: [*:0]const u8, kin
29162933 try w.print("{x});\n", .{try f.fmtIntLiteral(Type.u8, bits_val)});
29172934 },
29182935 }
2919 return ret;
2936 return local;
29202937}
29212938
29222939fn airNot(f: *Function, inst: Air.Inst.Index) !CValue {
......@@ -2932,13 +2949,13 @@ fn airNot(f: *Function, inst: Air.Inst.Index) !CValue {
29322949
29332950 try writer.writeAll(" = ");
29342951 try writer.writeByte(if (inst_ty.tag() == .bool) '!' else '~');
2935 try f.writeCValue(writer, op);
2952 try f.writeCValue(writer, op, .Other);
29362953 try writer.writeAll(";\n");
29372954
29382955 return local;
29392956}
29402957
2941fn airBinOp(f: *Function, inst: Air.Inst.Index, operator: [*:0]const u8) !CValue {
2958fn airBinOp(f: *Function, inst: Air.Inst.Index, operator: []const u8) !CValue {
29422959 if (f.liveness.isUnused(inst))
29432960 return CValue.none;
29442961
......@@ -2951,9 +2968,11 @@ fn airBinOp(f: *Function, inst: Air.Inst.Index, operator: [*:0]const u8) !CValue
29512968 const local = try f.allocLocal(inst_ty, .Const);
29522969
29532970 try writer.writeAll(" = ");
2954 try f.writeCValue(writer, lhs);
2955 try writer.print("{s}", .{operator});
2956 try f.writeCValue(writer, rhs);
2971 try f.writeCValue(writer, lhs, .Other);
2972 try writer.writeByte(' ');
2973 try writer.writeAll(operator);
2974 try writer.writeByte(' ');
2975 try f.writeCValue(writer, rhs, .Other);
29572976 try writer.writeAll(";\n");
29582977
29592978 return local;
......@@ -2983,31 +3002,31 @@ fn airEquality(
29833002 // A = lhs.is_null ; B = rhs.is_null ; C = rhs.payload == lhs.payload
29843003
29853004 try writer.writeAll(negate_prefix);
2986 try f.writeCValue(writer, lhs);
3005 try f.writeCValue(writer, lhs, .Other);
29873006 try writer.writeAll(".is_null && ");
2988 try f.writeCValue(writer, rhs);
3007 try f.writeCValue(writer, rhs, .Other);
29893008 try writer.writeAll(".is_null) || (");
2990 try f.writeCValue(writer, lhs);
3009 try f.writeCValue(writer, lhs, .Other);
29913010 try writer.writeAll(".payload == ");
2992 try f.writeCValue(writer, rhs);
3011 try f.writeCValue(writer, rhs, .Other);
29933012 try writer.writeAll(".payload && ");
2994 try f.writeCValue(writer, lhs);
3013 try f.writeCValue(writer, lhs, .Other);
29953014 try writer.writeAll(".is_null == ");
2996 try f.writeCValue(writer, rhs);
3015 try f.writeCValue(writer, rhs, .Other);
29973016 try writer.writeAll(".is_null));\n");
29983017
29993018 return local;
30003019 }
30013020
3002 try f.writeCValue(writer, lhs);
3021 try f.writeCValue(writer, lhs, .Other);
30033022 try writer.writeAll(eq_op_str);
3004 try f.writeCValue(writer, rhs);
3023 try f.writeCValue(writer, rhs, .Other);
30053024 try writer.writeAll(";\n");
30063025
30073026 return local;
30083027}
30093028
3010fn airPtrAddSub(f: *Function, inst: Air.Inst.Index, operator: [*:0]const u8) !CValue {
3029fn airPtrAddSub(f: *Function, inst: Air.Inst.Index, operator: u8) !CValue {
30113030 if (f.liveness.isUnused(inst)) return CValue.none;
30123031
30133032 const ty_pl = f.air.instructions.items(.data)[inst].ty_pl;
......@@ -3031,17 +3050,19 @@ fn airPtrAddSub(f: *Function, inst: Air.Inst.Index, operator: [*:0]const u8) !CV
30313050 try writer.writeAll(" = (");
30323051 try f.renderTypecast(writer, inst_ty);
30333052 try writer.writeAll(")(((uintptr_t)");
3034 try f.writeCValue(writer, lhs);
3035 try writer.print("){s}(", .{operator});
3036 try f.writeCValue(writer, rhs);
3053 try f.writeCValue(writer, lhs, .Other);
3054 try writer.writeAll(") ");
3055 try writer.writeByte(operator);
3056 try writer.writeAll(" (");
3057 try f.writeCValue(writer, rhs, .Other);
30373058 try writer.writeAll("*sizeof(");
30383059 try f.renderTypecast(writer, elem_ty);
3039 try writer.print(")));\n", .{});
3060 try writer.writeAll(")));\n");
30403061
30413062 return local;
30423063}
30433064
3044fn airMinMax(f: *Function, inst: Air.Inst.Index, operator: [*:0]const u8) !CValue {
3065fn airMinMax(f: *Function, inst: Air.Inst.Index, operator: u8) !CValue {
30453066 if (f.liveness.isUnused(inst)) return CValue.none;
30463067
30473068 const bin_op = f.air.instructions.items(.data)[inst].bin_op;
......@@ -3054,13 +3075,15 @@ fn airMinMax(f: *Function, inst: Air.Inst.Index, operator: [*:0]const u8) !CValu
30543075
30553076 // (lhs <> rhs) ? lhs : rhs
30563077 try writer.writeAll(" = (");
3057 try f.writeCValue(writer, lhs);
3058 try writer.print("{s}", .{operator});
3059 try f.writeCValue(writer, rhs);
3078 try f.writeCValue(writer, lhs, .Other);
3079 try writer.writeByte(' ');
3080 try writer.writeByte(operator);
3081 try writer.writeByte(' ');
3082 try f.writeCValue(writer, rhs, .Other);
30603083 try writer.writeAll(") ? ");
3061 try f.writeCValue(writer, lhs);
3084 try f.writeCValue(writer, lhs, .Other);
30623085 try writer.writeAll(" : ");
3063 try f.writeCValue(writer, rhs);
3086 try f.writeCValue(writer, rhs, .Other);
30643087 try writer.writeAll(";\n");
30653088
30663089 return local;
......@@ -3082,9 +3105,9 @@ fn airSlice(f: *Function, inst: Air.Inst.Index) !CValue {
30823105 var buf: Type.SlicePtrFieldTypeBuffer = undefined;
30833106 try f.renderTypecast(writer, inst_ty.slicePtrFieldType(&buf));
30843107 try writer.writeByte(')');
3085 try f.writeCValue(writer, ptr);
3108 try f.writeCValue(writer, ptr, .Other);
30863109 try writer.writeAll(", ");
3087 try f.writeCValue(writer, len);
3110 try f.writeCValue(writer, len, .Initializer);
30883111 try writer.writeAll("};\n");
30893112
30903113 return local;
......@@ -3151,7 +3174,7 @@ fn airCall(
31513174 }
31523175 // Fall back to function pointer call.
31533176 const callee = try f.resolveInst(pl_op.operand);
3154 try f.writeCValue(writer, callee);
3177 try f.writeCValue(writer, callee, .Other);
31553178 }
31563179
31573180 try writer.writeByte('(');
......@@ -3171,12 +3194,7 @@ fn airCall(
31713194 if (ty.isVolatilePtr()) try writer.writeAll(" volatile");
31723195 try writer.writeAll(" *)");
31733196 }
3174 if (f.air.value(arg)) |val| {
3175 try f.object.dg.renderValue(writer, f.air.typeOf(arg), val, .FunctionArgument);
3176 } else {
3177 const val = try f.resolveInst(arg);
3178 try f.writeCValue(writer, val);
3179 }
3197 try f.writeCValue(writer, try f.resolveInst(arg), .FunctionArgument);
31803198 args_written += 1;
31813199 }
31823200 try writer.writeAll(");\n");
......@@ -3286,18 +3304,18 @@ fn lowerTry(
32863304 } else {
32873305 try writer.writeAll("if(");
32883306 }
3289 try f.writeCValue(writer, err_union);
3307 try f.writeCValue(writer, err_union, .Other);
32903308 try writer.writeByte(')');
32913309 break :err;
32923310 }
32933311 if (operand_is_ptr or isByRef(err_union_ty)) {
32943312 try writer.writeAll("if(");
3295 try f.writeCValue(writer, err_union);
3313 try f.writeCValue(writer, err_union, .Other);
32963314 try writer.writeAll("->error)");
32973315 break :err;
32983316 }
32993317 try writer.writeAll("if(");
3300 try f.writeCValue(writer, err_union);
3318 try f.writeCValue(writer, err_union, .Other);
33013319 try writer.writeAll(".error)");
33023320 }
33033321
......@@ -3318,20 +3336,20 @@ fn lowerTry(
33183336 if (is_array) {
33193337 try writer.writeAll(";\n");
33203338 try writer.writeAll("memcpy(");
3321 try f.writeCValue(writer, local);
3339 try f.writeCValue(writer, local, .FunctionArgument);
33223340 try writer.writeAll(", ");
3323 try f.writeCValue(writer, err_union);
3341 try f.writeCValue(writer, err_union, .Other);
33243342 try writer.writeAll(".payload, sizeof(");
3325 try f.writeCValue(writer, local);
3343 try f.renderTypecast(writer, payload_ty);
33263344 try writer.writeAll("));\n");
33273345 } else {
33283346 if (operand_is_ptr or isByRef(payload_ty)) {
33293347 try writer.writeAll(" = &");
3330 try f.writeCValue(writer, err_union);
3348 try f.writeCValue(writer, err_union, .Other);
33313349 try writer.writeAll("->payload;\n");
33323350 } else {
33333351 try writer.writeAll(" = ");
3334 try f.writeCValue(writer, err_union);
3352 try f.writeCValue(writer, err_union, .Other);
33353353 try writer.writeAll(".payload;\n");
33363354 }
33373355 }
......@@ -3347,9 +3365,9 @@ fn airBr(f: *Function, inst: Air.Inst.Index) !CValue {
33473365 // If result is .none then the value of the block is unused.
33483366 if (result != .none) {
33493367 const operand = try f.resolveInst(branch.operand);
3350 try f.writeCValue(writer, result);
3368 try f.writeCValue(writer, result, .Other);
33513369 try writer.writeAll(" = ");
3352 try f.writeCValue(writer, operand);
3370 try f.writeCValue(writer, operand, .Other);
33533371 try writer.writeAll(";\n");
33543372 }
33553373
......@@ -3374,7 +3392,7 @@ fn airBitcast(f: *Function, inst: Air.Inst.Index) !CValue {
33743392 try f.renderTypecast(writer, inst_ty);
33753393
33763394 try writer.writeByte(')');
3377 try f.writeCValue(writer, operand);
3395 try f.writeCValue(writer, operand, .Other);
33783396 try writer.writeAll(";\n");
33793397 return local;
33803398 }
......@@ -3383,11 +3401,11 @@ fn airBitcast(f: *Function, inst: Air.Inst.Index) !CValue {
33833401 try writer.writeAll(";\n");
33843402
33853403 try writer.writeAll("memcpy(&");
3386 try f.writeCValue(writer, local);
3404 try f.writeCValue(writer, local, .Other);
33873405 try writer.writeAll(", &");
3388 try f.writeCValue(writer, operand);
3406 try f.writeCValue(writer, operand, .Other);
33893407 try writer.writeAll(", sizeof(");
3390 try f.writeCValue(writer, local);
3408 try f.renderTypecast(writer, inst_ty);
33913409 try writer.writeAll("));\n");
33923410
33933411 return local;
......@@ -3456,7 +3474,7 @@ fn airCondBr(f: *Function, inst: Air.Inst.Index) !CValue {
34563474 const writer = f.object.writer();
34573475
34583476 try writer.writeAll("if (");
3459 try f.writeCValue(writer, cond);
3477 try f.writeCValue(writer, cond, .Other);
34603478 try writer.writeAll(") ");
34613479 try genBody(f, then_body);
34623480 try writer.writeAll(" else ");
......@@ -3475,7 +3493,7 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index) !CValue {
34753493
34763494 try writer.writeAll("switch (");
34773495 if (condition_ty.tag() == .bool) try writer.writeAll("(int)");
3478 try f.writeCValue(writer, condition);
3496 try f.writeCValue(writer, condition, .Other);
34793497 try writer.writeAll(") {");
34803498 f.object.indent_writer.pushIndent();
34813499
......@@ -3527,7 +3545,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
35273545 const local = try f.allocLocal(inst_ty, .Mut);
35283546 if (f.wantSafety()) {
35293547 try writer.writeAll(" = ");
3530 try f.writeCValue(writer, .{ .undef = inst_ty });
3548 try f.writeCValue(writer, .{ .undef = inst_ty }, .Initializer);
35313549 }
35323550 try writer.writeAll(";\n");
35333551 break :local local;
......@@ -3555,7 +3573,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
35553573 try writer.writeAll("\")");
35563574 if (f.wantSafety()) {
35573575 try writer.writeAll(" = ");
3558 try f.writeCValue(writer, .{ .undef = output_ty });
3576 try f.writeCValue(writer, .{ .undef = output_ty }, .Initializer);
35593577 }
35603578 try writer.writeAll(";\n");
35613579 } else if (constraint.len < 2 or constraint[0] != '=') {
......@@ -3581,7 +3599,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
35813599 try writer.writeAll(" __asm(\"");
35823600 try writer.writeAll(constraint["{".len .. constraint.len - "}".len]);
35833601 try writer.writeAll("\") = ");
3584 try f.writeCValue(writer, try f.resolveInst(input));
3602 try f.writeCValue(writer, try f.resolveInst(input), .Initializer);
35853603 try writer.writeAll(";\n");
35863604 } else if (constraint.len >= 1 and std.mem.indexOfScalar(u8, "=+&%", constraint[0]) == null) {
35873605 const input_val = try f.resolveInst(input);
......@@ -3590,7 +3608,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
35903608 .local = input_locals_begin + index,
35913609 }, .Const, 0);
35923610 try writer.writeAll(" = ");
3593 try f.writeCValue(writer, input_val);
3611 try f.writeCValue(writer, input_val, .Initializer);
35943612 try writer.writeAll(";\n");
35953613 }
35963614 } else {
......@@ -3626,7 +3644,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
36263644 try writer.writeByte(' ');
36273645 if (constraint[1] == '{') {
36283646 try writer.print("{s}(", .{fmtStringLiteral("=r")});
3629 try f.writeCValue(writer, .{ .local = output_locals_begin + index });
3647 try f.writeCValue(writer, .{ .local = output_locals_begin + index }, .Other);
36303648 } else {
36313649 try writer.print("{s}(", .{fmtStringLiteral(constraint)});
36323650 try f.writeCValueDeref(writer, try f.resolveInst(output));
......@@ -3646,13 +3664,14 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
36463664 try writer.writeByte(' ');
36473665 if (constraint[0] == '{') {
36483666 try writer.print("{s}(", .{fmtStringLiteral("r")});
3649 try f.writeCValue(writer, .{ .local = input_locals_begin + index });
3667 try f.writeCValue(writer, .{ .local = input_locals_begin + index }, .Other);
36503668 } else {
36513669 const input_val = try f.resolveInst(input);
36523670 try writer.print("{s}(", .{fmtStringLiteral(constraint)});
3653 try f.writeCValue(writer, if (input_val == .constant) CValue{
3654 .local = input_locals_begin + index,
3655 } else input_val);
3671 try f.writeCValue(writer, if (input_val == .constant)
3672 CValue{ .local = input_locals_begin + index }
3673 else
3674 input_val, .Other);
36563675 }
36573676 try writer.writeByte(')');
36583677 }
......@@ -3683,11 +3702,12 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
36833702 extra_i += (constraint.len + name.len + (2 + 3)) / 4;
36843703
36853704 if (constraint[1] == '{') {
3686 try f.writeCValueDeref(writer, if (output == .none) CValue{
3687 .local_ref = local.local,
3688 } else try f.resolveInst(output));
3705 try f.writeCValueDeref(writer, if (output == .none)
3706 CValue{ .local_ref = local.local }
3707 else
3708 try f.resolveInst(output));
36893709 try writer.writeAll(" = ");
3690 try f.writeCValue(writer, .{ .local = output_locals_begin + index });
3710 try f.writeCValue(writer, .{ .local = output_locals_begin + index }, .Other);
36913711 try writer.writeAll(";\n");
36923712 }
36933713 }
......@@ -3698,8 +3718,8 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
36983718fn airIsNull(
36993719 f: *Function,
37003720 inst: Air.Inst.Index,
3701 operator: [*:0]const u8,
3702 deref_suffix: [*:0]const u8,
3721 operator: []const u8,
3722 is_ptr: bool,
37033723) !CValue {
37043724 if (f.liveness.isUnused(inst))
37053725 return CValue.none;
......@@ -3709,25 +3729,23 @@ fn airIsNull(
37093729 const operand = try f.resolveInst(un_op);
37103730
37113731 const local = try f.allocLocal(Type.initTag(.bool), .Const);
3712 try writer.writeAll(" = (");
3713 try f.writeCValue(writer, operand);
3732 try writer.writeAll(" = ");
3733 try if (is_ptr) f.writeCValueDeref(writer, operand) else f.writeCValue(writer, operand, .Other);
37143734
3715 const ty = f.air.typeOf(un_op);
3716 var opt_buf: Type.Payload.ElemType = undefined;
3717 const payload_ty = if (deref_suffix[0] != 0)
3718 ty.childType().optionalChild(&opt_buf)
3719 else
3720 ty.optionalChild(&opt_buf);
3735 const operand_ty = f.air.typeOf(un_op);
3736 const optional_ty = if (is_ptr) operand_ty.childType() else operand_ty;
3737 var payload_buf: Type.Payload.ElemType = undefined;
3738 const payload_ty = optional_ty.optionalChild(&payload_buf);
37213739
37223740 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
3723 try writer.print("){s} {s} true;\n", .{ deref_suffix, operator });
3724 } else if (ty.isPtrLikeOptional()) {
3741 try writer.print(" {s} true;\n", .{operator});
3742 } else if (operand_ty.isPtrLikeOptional()) {
37253743 // operand is a regular pointer, test `operand !=/== NULL`
3726 try writer.print("){s} {s} NULL;\n", .{ deref_suffix, operator });
3744 try writer.print(" {s} NULL;\n", .{operator});
37273745 } else if (payload_ty.zigTypeTag() == .ErrorSet) {
3728 try writer.print("){s} {s} 0;\n", .{ deref_suffix, operator });
3746 try writer.print(" {s} 0;\n", .{operator});
37293747 } else {
3730 try writer.print("){s}.is_null {s} true;\n", .{ deref_suffix, operator });
3748 try writer.print(".is_null {s} true;\n", .{operator});
37313749 }
37323750 return local;
37333751}
......@@ -3754,7 +3772,7 @@ fn airOptionalPayload(f: *Function, inst: Air.Inst.Index) !CValue {
37543772 const inst_ty = f.air.typeOfIndex(inst);
37553773 const local = try f.allocLocal(inst_ty, .Const);
37563774 try writer.writeAll(" = (");
3757 try f.writeCValue(writer, operand);
3775 try f.writeCValue(writer, operand, .Other);
37583776 try writer.writeAll(").payload;\n");
37593777 return local;
37603778}
......@@ -3781,7 +3799,7 @@ fn airOptionalPayloadPtr(f: *Function, inst: Air.Inst.Index) !CValue {
37813799
37823800 const local = try f.allocLocal(inst_ty, .Const);
37833801 try writer.writeAll(" = &(");
3784 try f.writeCValue(writer, operand);
3802 try f.writeCValue(writer, operand, .Other);
37853803 try writer.writeAll(")->payload;\n");
37863804 return local;
37873805}
......@@ -3882,7 +3900,7 @@ fn structFieldPtr(f: *Function, inst: Air.Inst.Index, struct_ptr_ty: Type, struc
38823900 try writer.writeAll(" = (");
38833901 try f.renderTypecast(writer, inst_ty);
38843902 try writer.writeByte(')');
3885 try f.writeCValue(writer, struct_ptr);
3903 try f.writeCValue(writer, struct_ptr, .Other);
38863904 try writer.writeAll(";\n");
38873905 }
38883906 return local;
......@@ -3920,15 +3938,15 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {
39203938 if (is_array) {
39213939 try writer.writeAll(";\n");
39223940 try writer.writeAll("memcpy(");
3923 try f.writeCValue(writer, local);
3941 try f.writeCValue(writer, local, .FunctionArgument);
39243942 try writer.writeAll(", ");
3925 try f.writeCValue(writer, struct_byval);
3943 try f.writeCValue(writer, struct_byval, .Other);
39263944 try writer.print(".{s}{ }, sizeof(", .{ payload, fmtIdent(field_name) });
3927 try f.writeCValue(writer, local);
3945 try f.renderTypecast(writer, inst_ty);
39283946 try writer.writeAll("));\n");
39293947 } else {
39303948 try writer.writeAll(" = ");
3931 try f.writeCValue(writer, struct_byval);
3949 try f.writeCValue(writer, struct_byval, .Other);
39323950 try writer.print(".{s}{ };\n", .{ payload, fmtIdent(field_name) });
39333951 }
39343952 return local;
......@@ -3956,7 +3974,7 @@ fn airUnwrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue {
39563974 }
39573975 const local = try f.allocLocal(inst_ty, .Const);
39583976 try writer.writeAll(" = *");
3959 try f.writeCValue(writer, operand);
3977 try f.writeCValue(writer, operand, .Other);
39603978 try writer.writeAll(";\n");
39613979 return local;
39623980 }
......@@ -3972,13 +3990,13 @@ fn airUnwrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue {
39723990 if (operand_ty.zigTypeTag() == .Pointer) {
39733991 try f.writeCValueDeref(writer, operand);
39743992 } else {
3975 try f.writeCValue(writer, operand);
3993 try f.writeCValue(writer, operand, .Other);
39763994 }
39773995 try writer.writeAll(".error;\n");
39783996 return local;
39793997}
39803998
3981fn airUnwrapErrUnionPay(f: *Function, inst: Air.Inst.Index, maybe_addrof: [*:0]const u8) !CValue {
3999fn airUnwrapErrUnionPay(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValue {
39824000 if (f.liveness.isUnused(inst))
39834001 return CValue.none;
39844002
......@@ -3994,13 +4012,15 @@ fn airUnwrapErrUnionPay(f: *Function, inst: Air.Inst.Index, maybe_addrof: [*:0]c
39944012 }
39954013
39964014 const inst_ty = f.air.typeOfIndex(inst);
3997 const maybe_deref = if (operand_is_ptr) "->" else ".";
39984015
39994016 const local = try f.allocLocal(inst_ty, .Const);
4000 try writer.print(" = {s}(", .{maybe_addrof});
4001 try f.writeCValue(writer, operand);
4002
4003 try writer.print("){s}payload;\n", .{maybe_deref});
4017 try writer.writeAll(" = ");
4018 if (is_ptr) try writer.writeByte('&');
4019 try writer.writeByte('(');
4020 try f.writeCValue(writer, operand, .Other);
4021 try writer.writeByte(')');
4022 try if (operand_is_ptr) writer.writeAll("->") else writer.writeByte('.');
4023 try writer.writeAll("payload;\n");
40044024 return local;
40054025}
40064026
......@@ -4020,7 +4040,7 @@ fn airWrapOptional(f: *Function, inst: Air.Inst.Index) !CValue {
40204040 // .wrap_optional is used to convert non-optionals into optionals so it can never be null.
40214041 const local = try f.allocLocal(inst_ty, .Const);
40224042 try writer.writeAll(" = { .payload = ");
4023 try f.writeCValue(writer, operand);
4043 try f.writeCValue(writer, operand, .Initializer);
40244044 try writer.writeAll(", .is_null = false };\n");
40254045 return local;
40264046}
......@@ -4039,9 +4059,9 @@ fn airWrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue {
40394059
40404060 const local = try f.allocLocal(err_un_ty, .Const);
40414061 try writer.writeAll(" = { .payload = ");
4042 try f.writeCValue(writer, .{ .undef = payload_ty });
4062 try f.writeCValue(writer, .{ .undef = payload_ty }, .Initializer);
40434063 try writer.writeAll(", .error = ");
4044 try f.writeCValue(writer, operand);
4064 try f.writeCValue(writer, operand, .Initializer);
40454065 try writer.writeAll(" };\n");
40464066 return local;
40474067}
......@@ -4104,33 +4124,29 @@ fn airWrapErrUnionPay(f: *Function, inst: Air.Inst.Index) !CValue {
41044124
41054125 const inst_ty = f.air.typeOfIndex(inst);
41064126 const payload_ty = inst_ty.errorUnionPayload();
4127 const error_ty = inst_ty.errorUnionSet();
41074128 const is_array = payload_ty.zigTypeTag() == .Array;
41084129 const local = try f.allocLocal(inst_ty, if (is_array) .Mut else .Const);
41094130 try writer.writeAll(" = { .payload = ");
4110 try f.writeCValue(writer, if (is_array) CValue{ .undef = payload_ty } else operand);
4111 try writer.print(", .error = {} }};\n", .{
4112 try f.fmtIntLiteral(inst_ty.errorUnionSet(), Value.zero),
4113 });
4131 try f.writeCValue(writer, if (is_array) CValue{ .undef = payload_ty } else operand, .Initializer);
4132 try writer.writeAll(", .error = ");
4133 try f.object.dg.renderValue(writer, error_ty, Value.zero, .Initializer);
4134 try writer.writeAll(" };\n");
41144135
41154136 if (is_array) {
41164137 try writer.writeAll("memcpy(");
4117 try f.writeCValue(writer, local);
4138 try f.writeCValue(writer, local, .Other);
41184139 try writer.writeAll(".payload, ");
4119 try f.writeCValue(writer, operand);
4140 try f.writeCValue(writer, operand, .FunctionArgument);
41204141 try writer.writeAll(", sizeof(");
4121 try f.writeCValue(writer, local);
4122 try writer.writeAll(".payload));\n");
4142 try f.renderTypecast(writer, payload_ty);
4143 try writer.writeAll("));\n");
41234144 }
41244145
41254146 return local;
41264147}
41274148
4128fn airIsErr(
4129 f: *Function,
4130 inst: Air.Inst.Index,
4131 is_ptr: bool,
4132 op_str: [*:0]const u8,
4133) !CValue {
4149fn airIsErr(f: *Function, inst: Air.Inst.Index, is_ptr: bool, operator: []const u8) !CValue {
41344150 if (f.liveness.isUnused(inst))
41354151 return CValue.none;
41364152
......@@ -4146,18 +4162,17 @@ fn airIsErr(
41464162 try writer.writeAll(" = ");
41474163
41484164 if (error_ty.errorSetIsEmpty()) {
4149 try writer.print("0 {s} 0;\n", .{op_str});
4165 try writer.writeByte('0');
41504166 } else {
4151 if (is_ptr) {
4152 try f.writeCValueDeref(writer, operand);
4153 } else {
4154 try f.writeCValue(writer, operand);
4155 }
4167 try f.writeCValue(writer, operand, .Other);
41564168 if (payload_ty.hasRuntimeBits()) {
4157 try writer.writeAll(".error");
4169 try if (is_ptr) writer.writeAll("->") else writer.writeByte('.');
4170 try writer.writeAll("error");
41584171 }
4159 try writer.print(" {s} 0;\n", .{op_str});
41604172 }
4173 try writer.writeByte(' ');
4174 try writer.writeAll(operator);
4175 try writer.writeAll(" 0;\n");
41614176 return local;
41624177}
41634178
......@@ -4177,13 +4192,16 @@ fn airArrayToSlice(f: *Function, inst: Air.Inst.Index) !CValue {
41774192 // Unfortunately, C does not support any equivalent to
41784193 // &(*(void *)p)[0], although LLVM does via GetElementPtr
41794194 var buf: Type.SlicePtrFieldTypeBuffer = undefined;
4180 try f.writeCValue(writer, CValue{ .undef = inst_ty.slicePtrFieldType(&buf) });
4195 try f.writeCValue(writer, CValue{ .undef = inst_ty.slicePtrFieldType(&buf) }, .Initializer);
41814196 } else {
41824197 try writer.writeAll("&(");
41834198 try f.writeCValueDeref(writer, operand);
41844199 try writer.writeAll(")[0]");
41854200 }
4186 try writer.print(", .len = {d} }};\n", .{array_len});
4201
4202 var len_pl: Value.Payload.U64 = .{ .base = .{ .tag = .int_u64 }, .data = array_len };
4203 const len_val = Value.initPayload(&len_pl.base);
4204 try writer.print(", .len = {} }};\n", .{try f.fmtIntLiteral(Type.usize, len_val)});
41874205 return local;
41884206}
41894207
......@@ -4199,7 +4217,7 @@ fn airSimpleCast(f: *Function, inst: Air.Inst.Index) !CValue {
41994217 const operand = try f.resolveInst(ty_op.operand);
42004218
42014219 try writer.writeAll(" = ");
4202 try f.writeCValue(writer, operand);
4220 try f.writeCValue(writer, operand, .Other);
42034221 try writer.writeAll(";\n");
42044222 return local;
42054223}
......@@ -4216,7 +4234,7 @@ fn airPtrToInt(f: *Function, inst: Air.Inst.Index) !CValue {
42164234 try writer.writeAll(" = (");
42174235 try f.renderTypecast(writer, inst_ty);
42184236 try writer.writeByte(')');
4219 try f.writeCValue(writer, operand);
4237 try f.writeCValue(writer, operand, .Other);
42204238 try writer.writeAll(";\n");
42214239 return local;
42224240}
......@@ -4237,7 +4255,7 @@ fn airBuiltinCall(f: *Function, inst: Air.Inst.Index, fn_name: [*:0]const u8) !C
42374255
42384256 try writer.print(" = zig_{s}_", .{fn_name});
42394257 try writer.print("{c}{d}(", .{ signAbbrev(int_info.signedness), c_bits });
4240 try f.writeCValue(writer, try f.resolveInst(operand));
4258 try f.writeCValue(writer, try f.resolveInst(operand), .FunctionArgument);
42414259 try writer.print(", {d});\n", .{int_info.bits});
42424260 return local;
42434261}
......@@ -4266,9 +4284,9 @@ fn airBinOpBuiltinCall(f: *Function, inst: Air.Inst.Index, fn_name: [*:0]const u
42664284 }
42674285
42684286 try writer.writeByte('(');
4269 try f.writeCValue(writer, try f.resolveInst(bin_op.lhs));
4287 try f.writeCValue(writer, try f.resolveInst(bin_op.lhs), .FunctionArgument);
42704288 try writer.writeAll(", ");
4271 try f.writeCValue(writer, try f.resolveInst(bin_op.rhs));
4289 try f.writeCValue(writer, try f.resolveInst(bin_op.rhs), .FunctionArgument);
42724290 try writer.writeAll(");\n");
42734291 return local;
42744292}
......@@ -4287,12 +4305,12 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue
42874305 const local = try f.allocLocal(inst_ty, .Mut);
42884306 try writer.writeAll(" = ");
42894307 if (is_struct) try writer.writeAll("{ .payload = ");
4290 try f.writeCValue(writer, expected_value);
4308 try f.writeCValue(writer, expected_value, .Initializer);
42914309 if (is_struct) try writer.writeAll(", .is_null = false }");
42924310 try writer.writeAll(";\n");
42934311
42944312 if (is_struct) {
4295 try f.writeCValue(writer, local);
4313 try f.writeCValue(writer, local, .Other);
42964314 try writer.writeAll(".is_null = ");
42974315 } else {
42984316 try writer.writeAll("if (");
......@@ -4302,14 +4320,14 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue
43024320 try writer.writeByte(')');
43034321 if (ptr_ty.isVolatilePtr()) try writer.writeAll(" volatile");
43044322 try writer.writeAll(" *)");
4305 try f.writeCValue(writer, ptr);
4323 try f.writeCValue(writer, ptr, .Other);
43064324 try writer.writeAll(", ");
4307 try f.writeCValue(writer, local);
4325 try f.writeCValue(writer, local, .FunctionArgument);
43084326 if (is_struct) {
43094327 try writer.writeAll(".payload");
43104328 }
43114329 try writer.writeAll(", ");
4312 try f.writeCValue(writer, new_value);
4330 try f.writeCValue(writer, new_value, .FunctionArgument);
43134331 try writer.writeAll(", ");
43144332 try writeMemoryOrder(writer, extra.successOrder());
43154333 try writer.writeAll(", ");
......@@ -4320,7 +4338,7 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue
43204338 } else {
43214339 try writer.writeAll(") {\n");
43224340 f.object.indent_writer.pushIndent();
4323 try f.writeCValue(writer, local);
4341 try f.writeCValue(writer, local, .Other);
43244342 try writer.writeAll(" = NULL;\n");
43254343 f.object.indent_writer.popIndent();
43264344 try writer.writeAll("}\n");
......@@ -4353,9 +4371,9 @@ fn airAtomicRmw(f: *Function, inst: Air.Inst.Index) !CValue {
43534371 }
43544372 if (ptr_ty.isVolatilePtr()) try writer.writeAll(" volatile");
43554373 try writer.writeAll(" *)");
4356 try f.writeCValue(writer, ptr);
4374 try f.writeCValue(writer, ptr, .Other);
43574375 try writer.writeAll(", ");
4358 try f.writeCValue(writer, operand);
4376 try f.writeCValue(writer, operand, .FunctionArgument);
43594377 try writer.writeAll(", ");
43604378 try writeMemoryOrder(writer, extra.ordering());
43614379 try writer.writeAll(");\n");
......@@ -4379,7 +4397,7 @@ fn airAtomicLoad(f: *Function, inst: Air.Inst.Index) !CValue {
43794397 try writer.writeByte(')');
43804398 if (ptr_ty.isVolatilePtr()) try writer.writeAll(" volatile");
43814399 try writer.writeAll(" *)");
4382 try f.writeCValue(writer, ptr);
4400 try f.writeCValue(writer, ptr, .Other);
43834401 try writer.writeAll(", ");
43844402 try writeMemoryOrder(writer, atomic_load.order);
43854403 try writer.writeAll(");\n");
......@@ -4399,9 +4417,9 @@ fn airAtomicStore(f: *Function, inst: Air.Inst.Index, order: [*:0]const u8) !CVa
43994417 try writer.writeByte(')');
44004418 if (ptr_ty.isVolatilePtr()) try writer.writeAll(" volatile");
44014419 try writer.writeAll(" *)");
4402 try f.writeCValue(writer, ptr);
4420 try f.writeCValue(writer, ptr, .Other);
44034421 try writer.writeAll(", ");
4404 try f.writeCValue(writer, element);
4422 try f.writeCValue(writer, element, .FunctionArgument);
44054423 try writer.print(", {s});\n", .{order});
44064424
44074425 return CValue.none;
......@@ -4416,11 +4434,11 @@ fn airMemset(f: *Function, inst: Air.Inst.Index) !CValue {
44164434 const writer = f.object.writer();
44174435
44184436 try writer.writeAll("memset(");
4419 try f.writeCValue(writer, dest_ptr);
4437 try f.writeCValue(writer, dest_ptr, .FunctionArgument);
44204438 try writer.writeAll(", ");
4421 try f.writeCValue(writer, value);
4439 try f.writeCValue(writer, value, .FunctionArgument);
44224440 try writer.writeAll(", ");
4423 try f.writeCValue(writer, len);
4441 try f.writeCValue(writer, len, .FunctionArgument);
44244442 try writer.writeAll(");\n");
44254443
44264444 return CValue.none;
......@@ -4435,11 +4453,11 @@ fn airMemcpy(f: *Function, inst: Air.Inst.Index) !CValue {
44354453 const writer = f.object.writer();
44364454
44374455 try writer.writeAll("memcpy(");
4438 try f.writeCValue(writer, dest_ptr);
4456 try f.writeCValue(writer, dest_ptr, .FunctionArgument);
44394457 try writer.writeAll(", ");
4440 try f.writeCValue(writer, src_ptr);
4458 try f.writeCValue(writer, src_ptr, .FunctionArgument);
44414459 try writer.writeAll(", ");
4442 try f.writeCValue(writer, len);
4460 try f.writeCValue(writer, len, .FunctionArgument);
44434461 try writer.writeAll(");\n");
44444462
44454463 return CValue.none;
......@@ -4457,9 +4475,9 @@ fn airSetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue {
44574475 if (layout.tag_size == 0) return CValue.none;
44584476
44594477 try writer.writeByte('(');
4460 try f.writeCValue(writer, union_ptr);
4478 try f.writeCValue(writer, union_ptr, .Other);
44614479 try writer.writeAll(")->tag = ");
4462 try f.writeCValue(writer, new_tag);
4480 try f.writeCValue(writer, new_tag, .Other);
44634481 try writer.writeAll(";\n");
44644482
44654483 return CValue.none;
......@@ -4481,7 +4499,7 @@ fn airGetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue {
44814499 if (layout.tag_size == 0) return CValue.none;
44824500
44834501 try writer.writeAll(" = ");
4484 try f.writeCValue(writer, operand);
4502 try f.writeCValue(writer, operand, .Other);
44854503 try writer.writeAll(".tag;\n");
44864504 return local;
44874505}
......@@ -4497,7 +4515,7 @@ fn airTagName(f: *Function, inst: Air.Inst.Index) !CValue {
44974515 const writer = f.object.writer();
44984516 const local = try f.allocLocal(inst_ty, .Const);
44994517 try writer.print(" = {s}(", .{try f.object.dg.getTagNameFn(enum_ty)});
4500 try f.writeCValue(writer, operand);
4518 try f.writeCValue(writer, operand, .Other);
45014519 try writer.writeAll(");\n");
45024520
45034521 try f.object.dg.fwd_decl.writer().writeAll("// This is where the fwd decl for tagName ended up\n");
......@@ -4515,7 +4533,7 @@ fn airErrorName(f: *Function, inst: Air.Inst.Index) !CValue {
45154533 const local = try f.allocLocal(inst_ty, .Const);
45164534
45174535 try writer.writeAll(" = zig_errorName[");
4518 try f.writeCValue(writer, operand);
4536 try f.writeCValue(writer, operand, .Other);
45194537 try writer.writeAll("];\n");
45204538 return local;
45214539}
......@@ -4600,12 +4618,12 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {
46004618 var empty = true;
46014619 for (elements) |element| {
46024620 if (!empty) try writer.writeAll(", ");
4603 try f.writeCValue(writer, try f.resolveInst(element));
4621 try f.writeCValue(writer, try f.resolveInst(element), .Initializer);
46044622 empty = false;
46054623 }
46064624 if (inst_ty.sentinel()) |sentinel| {
46074625 if (!empty) try writer.writeAll(", ");
4608 try f.object.dg.renderValue(writer, elem_ty, sentinel, .Other);
4626 try f.object.dg.renderValue(writer, elem_ty, sentinel, .Initializer);
46094627 empty = false;
46104628 }
46114629 if (empty) try writer.print("{}", .{try f.fmtIntLiteral(Type.u8, Value.zero)});
......@@ -4625,7 +4643,7 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {
46254643 try f.writeCValue(writer, switch (element_ty.zigTypeTag()) {
46264644 .Array => CValue{ .undef = element_ty },
46274645 else => try f.resolveInst(element),
4628 });
4646 }, .Initializer);
46294647 empty = false;
46304648 }
46314649 if (empty) try writer.print("{}", .{try f.fmtIntLiteral(Type.u8, Value.zero)});
......@@ -4647,12 +4665,12 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {
46474665
46484666 try writer.writeAll(";\n");
46494667 try writer.writeAll("memcpy(");
4650 try f.writeCValue(writer, local);
4668 try f.writeCValue(writer, local, .Other);
46514669 try writer.print(".{ }, ", .{fmtIdent(field_name)});
4652 try f.writeCValue(writer, try f.resolveInst(element));
4670 try f.writeCValue(writer, try f.resolveInst(element), .FunctionArgument);
46534671 try writer.writeAll(", sizeof(");
4654 try f.writeCValue(writer, local);
4655 try writer.print(".{ }));\n", .{fmtIdent(field_name)});
4672 try f.renderTypecast(writer, element_ty);
4673 try writer.writeAll("));\n");
46564674 }
46574675 },
46584676 .Vector => return f.fail("TODO: C backend: implement airAggregateInit for vectors", .{}),
......@@ -4681,14 +4699,14 @@ fn airUnionInit(f: *Function, inst: Air.Inst.Index) !CValue {
46814699 if (layout.tag_size != 0) {
46824700 const field_index = tag_ty.enumFieldIndex(field_name).?;
46834701
4684 var tag_val_pl: Value.Payload.U32 = .{
4702 var tag_pl: Value.Payload.U32 = .{
46854703 .base = .{ .tag = .enum_field_index },
46864704 .data = @intCast(u32, field_index),
46874705 };
4688 const tag_val = Value.initPayload(&tag_val_pl.base);
4706 const tag_val = Value.initPayload(&tag_pl.base);
46894707
4690 var int_val_pl: Value.Payload.U64 = undefined;
4691 const int_val = tag_val.enumToInt(tag_ty, &int_val_pl);
4708 var int_pl: Value.Payload.U64 = undefined;
4709 const int_val = tag_val.enumToInt(tag_ty, &int_pl);
46924710
46934711 try writer.print(".tag = {}, ", .{try f.fmtIntLiteral(tag_ty, int_val)});
46944712 }
......@@ -4696,7 +4714,7 @@ fn airUnionInit(f: *Function, inst: Air.Inst.Index) !CValue {
46964714 }
46974715
46984716 try writer.print(".{ } = ", .{fmtIdent(field_name)});
4699 try f.writeCValue(writer, payload);
4717 try f.writeCValue(writer, payload, .Initializer);
47004718
47014719 if (union_ty.unionTagTypeSafety()) |_| try writer.writeByte('}');
47024720 try writer.writeAll("};\n");
......@@ -4716,7 +4734,7 @@ fn airPrefetch(f: *Function, inst: Air.Inst.Index) !CValue {
47164734 const ptr = try f.resolveInst(prefetch.ptr);
47174735 const writer = f.object.writer();
47184736 try writer.writeAll("zig_prefetch(");
4719 try f.writeCValue(writer, ptr);
4737 try f.writeCValue(writer, ptr, .FunctionArgument);
47204738 try writer.print(", {d}, {d});\n", .{
47214739 @enumToInt(prefetch.rw), prefetch.locality,
47224740 });
......@@ -4748,7 +4766,7 @@ fn airWasmMemoryGrow(f: *Function, inst: Air.Inst.Index) !CValue {
47484766
47494767 try writer.writeAll(" = ");
47504768 try writer.print("zig_wasm_memory_grow({d}, ", .{pl_op.payload});
4751 try f.writeCValue(writer, operand);
4769 try f.writeCValue(writer, operand, .FunctionArgument);
47524770 try writer.writeAll(");\n");
47534771 return local;
47544772}
......@@ -4762,7 +4780,7 @@ fn airNeg(f: *Function, inst: Air.Inst.Index) !CValue {
47624780 const operand = try f.resolveInst(un_op);
47634781 const local = try f.allocLocal(inst_ty, .Const);
47644782 try writer.writeAll(" = -");
4765 try f.writeCValue(writer, operand);
4783 try f.writeCValue(writer, operand, .Other);
47664784 try writer.writeAll(";\n");
47674785 return local;
47684786}
......@@ -4777,7 +4795,7 @@ fn airUnFloatOp(f: *Function, inst: Air.Inst.Index, fn_name: []const u8) !CValue
47774795 try writer.writeAll(" = ");
47784796 try f.renderFloatFnName(fn_name, inst_ty);
47794797 try writer.writeByte('(');
4780 try f.writeCValue(writer, operand);
4798 try f.writeCValue(writer, operand, .FunctionArgument);
47814799 try writer.writeAll(");\n");
47824800 return local;
47834801}
......@@ -4793,9 +4811,9 @@ fn airBinFloatOp(f: *Function, inst: Air.Inst.Index, fn_name: []const u8) !CValu
47934811 try writer.writeAll(" = ");
47944812 try f.renderFloatFnName(fn_name, inst_ty);
47954813 try writer.writeByte('(');
4796 try f.writeCValue(writer, lhs);
4814 try f.writeCValue(writer, lhs, .FunctionArgument);
47974815 try writer.writeAll(", ");
4798 try f.writeCValue(writer, rhs);
4816 try f.writeCValue(writer, rhs, .FunctionArgument);
47994817 try writer.writeAll(");\n");
48004818 return local;
48014819}
......@@ -4813,11 +4831,11 @@ fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue {
48134831 try writer.writeAll(" = ");
48144832 try f.renderFloatFnName("fma", inst_ty);
48154833 try writer.writeByte('(');
4816 try f.writeCValue(writer, mulend1);
4834 try f.writeCValue(writer, mulend1, .FunctionArgument);
48174835 try writer.writeAll(", ");
4818 try f.writeCValue(writer, mulend2);
4836 try f.writeCValue(writer, mulend2, .FunctionArgument);
48194837 try writer.writeAll(", ");
4820 try f.writeCValue(writer, addend);
4838 try f.writeCValue(writer, addend, .FunctionArgument);
48214839 try writer.writeAll(");\n");
48224840 return local;
48234841}
......@@ -5013,15 +5031,15 @@ fn formatIntLiteral(
50135031 }
50145032
50155033 const split = std.math.min(int.limbs.len, limbs_count_64);
5016 var upper_val_pl = Value.Payload.BigInt{
5034 var upper_pl = Value.Payload.BigInt{
50175035 .base = .{ .tag = .int_big_positive },
50185036 .data = int.limbs[split..],
50195037 };
5020 const have_upper = !upper_val_pl.asBigInt().eqZero();
5038 const have_upper = !upper_pl.asBigInt().eqZero();
50215039 if (have_upper) try writer.writeByte('(');
50225040 if (have_upper or !int.positive) try writer.writeAll("(uint128_t)");
50235041 if (have_upper) {
5024 const upper_val = Value.initPayload(&upper_val_pl.base);
5042 const upper_val = Value.initPayload(&upper_pl.base);
50255043 try formatIntLiteral(.{
50265044 .ty = Type.u64,
50275045 .val = upper_val,
......@@ -5030,11 +5048,11 @@ fn formatIntLiteral(
50305048 try writer.writeAll("<<64|");
50315049 }
50325050
5033 var lower_val_pl = Value.Payload.BigInt{
5051 var lower_pl = Value.Payload.BigInt{
50345052 .base = .{ .tag = .int_big_positive },
50355053 .data = int.limbs[0..split],
50365054 };
5037 const lower_val = Value.initPayload(&lower_val_pl.base);
5055 const lower_val = Value.initPayload(&lower_pl.base);
50385056 try formatIntLiteral(.{
50395057 .ty = Type.u64,
50405058 .val = lower_val,