authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2024-04-11 23:40:15-04:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2024-04-13 01:35:20-04:00
logf1c0f42cddd344d6ac56569decb42eab2dfc07e5
treeef0f626df3ac7339da7ba6394aecbd5770474874
parent05d9755766e45e454a16440bfc9f98abef992247

cbe: fix optional codegen

Also reduce ctype pool string memory usage, remove self assignments, and enable more warnings.

17 files changed, 1118 insertions(+), 850 deletions(-)

lib/std/posix/test.zig+1-1
......@@ -839,7 +839,7 @@ test "sigaction" {
839839 const S = struct {
840840 var handler_called_count: u32 = 0;
841841
842 fn handler(sig: i32, info: *const posix.siginfo_t, ctx_ptr: ?*const anyopaque) callconv(.C) void {
842 fn handler(sig: i32, info: *const posix.siginfo_t, ctx_ptr: ?*anyopaque) callconv(.C) void {
843843 _ = ctx_ptr;
844844 // Check that we received the correct signal.
845845 switch (native_os) {
src/codegen/c.zig+831-696
......@@ -43,10 +43,12 @@ pub const CValue = union(enum) {
4343 decl_ref: InternPool.DeclIndex,
4444 /// An undefined value (cannot be dereferenced)
4545 undef: Type,
46 /// Render the slice as an identifier (using fmtIdent)
46 /// Rendered as an identifier (using fmtIdent)
4747 identifier: []const u8,
48 /// Render the slice as an payload.identifier (using fmtIdent)
48 /// Rendered as "payload." followed by as identifier (using fmtIdent)
4949 payload_identifier: []const u8,
50 /// Rendered with fmtCTypePoolString
51 ctype_pool_string: CType.Pool.String,
5052};
5153
5254const BlockData = struct {
......@@ -62,10 +64,10 @@ pub const LazyFnKey = union(enum) {
6264 never_inline: InternPool.DeclIndex,
6365};
6466pub const LazyFnValue = struct {
65 fn_name: CType.String,
67 fn_name: CType.Pool.String,
6668 data: Data,
6769
68 pub const Data = union {
70 const Data = union {
6971 tag_name: Type,
7072 never_tail: void,
7173 never_inline: void,
......@@ -80,7 +82,7 @@ const Local = struct {
8082 _: u20 = undefined,
8183 },
8284
83 pub fn getType(local: Local) LocalType {
85 fn getType(local: Local) LocalType {
8486 return .{ .ctype = local.ctype, .alignas = local.flags.alignas };
8587 }
8688};
......@@ -96,12 +98,20 @@ const ValueRenderLocation = enum {
9698 StaticInitializer,
9799 Other,
98100
99 pub fn isInitializer(self: ValueRenderLocation) bool {
100 return switch (self) {
101 fn isInitializer(loc: ValueRenderLocation) bool {
102 return switch (loc) {
101103 .Initializer, .StaticInitializer => true,
102104 else => false,
103105 };
104106 }
107
108 fn toCTypeKind(loc: ValueRenderLocation) CType.Kind {
109 return switch (loc) {
110 .FunctionArgument => .parameter,
111 .Initializer, .Other => .complete,
112 .StaticInitializer => .global,
113 };
114 }
105115};
106116
107117const BuiltinInfo = enum { none, bits };
......@@ -234,12 +244,11 @@ fn isReservedIdent(ident: []const u8) bool {
234244
235245fn formatIdent(
236246 ident: []const u8,
237 comptime fmt: []const u8,
238 options: std.fmt.FormatOptions,
247 comptime fmt_str: []const u8,
248 _: std.fmt.FormatOptions,
239249 writer: anytype,
240) !void {
241 _ = options;
242 const solo = fmt.len != 0 and fmt[0] == ' '; // space means solo; not part of a bigger ident.
250) @TypeOf(writer).Error!void {
251 const solo = fmt_str.len != 0 and fmt_str[0] == ' '; // space means solo; not part of a bigger ident.
243252 if (solo and isReservedIdent(ident)) {
244253 try writer.writeAll("zig_e_");
245254 }
......@@ -256,11 +265,32 @@ fn formatIdent(
256265 }
257266 }
258267}
259
260268pub fn fmtIdent(ident: []const u8) std.fmt.Formatter(formatIdent) {
261269 return .{ .data = ident };
262270}
263271
272const CTypePoolStringFormatData = struct {
273 ctype_pool_string: CType.Pool.String,
274 ctype_pool: *const CType.Pool,
275};
276fn formatCTypePoolString(
277 data: CTypePoolStringFormatData,
278 comptime fmt_str: []const u8,
279 fmt_opts: std.fmt.FormatOptions,
280 writer: anytype,
281) @TypeOf(writer).Error!void {
282 if (data.ctype_pool_string.toSlice(data.ctype_pool)) |slice|
283 try formatIdent(slice, fmt_str, fmt_opts, writer)
284 else
285 try writer.print("{}", .{data.ctype_pool_string.fmt(data.ctype_pool)});
286}
287pub fn fmtCTypePoolString(
288 ctype_pool_string: CType.Pool.String,
289 ctype_pool: *const CType.Pool,
290) std.fmt.Formatter(formatCTypePoolString) {
291 return .{ .data = .{ .ctype_pool_string = ctype_pool_string, .ctype_pool = ctype_pool } };
292}
293
264294// Returns true if `formatIdent` would make any edits to ident.
265295// This must be kept in sync with `formatIdent`.
266296pub fn isMangledIdent(ident: []const u8, solo: bool) bool {
......@@ -321,7 +351,7 @@ pub const Function = struct {
321351 try writer.writeAll(" = ");
322352 try f.object.dg.renderValue(writer, val, .StaticInitializer);
323353 try writer.writeAll(";\n ");
324 break :result decl_c_value;
354 break :result .{ .local = decl_c_value.new_local };
325355 } else .{ .constant = val };
326356
327357 gop.value_ptr.* = result;
......@@ -377,27 +407,7 @@ pub const Function = struct {
377407 switch (c_value) {
378408 .none => unreachable,
379409 .new_local, .local => |i| try w.print("t{d}", .{i}),
380 .local_ref => |i| {
381 const local = &f.locals.items[i];
382 if (local.flags.alignas.abiOrder().compare(.lt)) {
383 const gpa = f.object.dg.gpa;
384 const mod = f.object.dg.mod;
385 const ctype_pool = &f.object.dg.ctype_pool;
386
387 try w.writeByte('(');
388 try f.renderCType(w, try ctype_pool.getPointer(gpa, .{
389 .elem_ctype = try ctype_pool.fromIntInfo(gpa, .{
390 .signedness = .unsigned,
391 .bits = @min(
392 local.flags.alignas.toByteUnits(),
393 mod.resolved_target.result.maxIntAlignment(),
394 ) * 8,
395 }, mod, .forward),
396 }));
397 try w.writeByte(')');
398 }
399 try w.print("&t{d}", .{i});
400 },
410 .local_ref => |i| try w.print("&t{d}", .{i}),
401411 .constant => |val| try f.object.dg.renderValue(w, val, location),
402412 .arg => |i| try w.print("a{d}", .{i}),
403413 .arg_array => |i| try f.writeCValueMember(w, .{ .arg = i }, .{ .identifier = "array" }),
......@@ -516,7 +526,7 @@ pub const Function = struct {
516526 },
517527 };
518528 }
519 return gop.value_ptr.fn_name.slice(ctype_pool);
529 return gop.value_ptr.fn_name.toSlice(ctype_pool).?;
520530 }
521531
522532 pub fn deinit(f: *Function) void {
......@@ -538,6 +548,43 @@ pub const Function = struct {
538548 const zcu = f.object.dg.zcu;
539549 return f.air.typeOfIndex(inst, &zcu.intern_pool);
540550 }
551
552 fn copyCValue(f: *Function, ctype: CType, dst: CValue, src: CValue) !void {
553 switch (dst) {
554 .new_local, .local => |dst_local_index| switch (src) {
555 .new_local, .local => |src_local_index| if (dst_local_index == src_local_index) return,
556 else => {},
557 },
558 else => {},
559 }
560 const writer = f.object.writer();
561 const a = try Assignment.start(f, writer, ctype);
562 try f.writeCValue(writer, dst, .Other);
563 try a.assign(f, writer);
564 try f.writeCValue(writer, src, .Initializer);
565 try a.end(f, writer);
566 }
567
568 fn moveCValue(f: *Function, inst: Air.Inst.Index, ty: Type, src: CValue) !CValue {
569 switch (src) {
570 // Move the freshly allocated local to be owned by this instruction,
571 // by returning it here instead of freeing it.
572 .new_local => return src,
573 else => {
574 try freeCValue(f, inst, src);
575 const dst = try f.allocLocal(inst, ty);
576 try f.copyCValue(try f.ctypeFromType(ty, .complete), dst, src);
577 return dst;
578 },
579 }
580 }
581
582 fn freeCValue(f: *Function, inst: ?Air.Inst.Index, val: CValue) !void {
583 switch (val) {
584 .new_local => |local_index| try freeLocal(f, inst, local_index, null),
585 else => {},
586 }
587 }
541588};
542589
543590/// This data is available when outputting .c code for a `Zcu`.
......@@ -627,13 +674,14 @@ pub const DeclGen = struct {
627674 // them). The analysis until now should ensure that the C function
628675 // pointers are compatible. If they are not, then there is a bug
629676 // somewhere and we should let the C compiler tell us about it.
630 const elem_ctype = (try dg.ctypeFromType(ptr_ty, .complete)).info(ctype_pool).pointer.elem_ctype;
677 const ptr_ctype = try dg.ctypeFromType(ptr_ty, .complete);
678 const elem_ctype = ptr_ctype.info(ctype_pool).pointer.elem_ctype;
631679 const decl_ctype = try dg.ctypeFromType(decl_ty, .complete);
632680 const need_cast = !elem_ctype.eql(decl_ctype) and
633681 (elem_ctype.info(ctype_pool) != .function or decl_ctype.info(ctype_pool) != .function);
634682 if (need_cast) {
635683 try writer.writeAll("((");
636 try dg.renderType(writer, ptr_ty);
684 try dg.renderCType(writer, ptr_ctype);
637685 try writer.writeByte(')');
638686 }
639687 try writer.writeByte('&');
......@@ -692,13 +740,14 @@ pub const DeclGen = struct {
692740 // them). The analysis until now should ensure that the C function
693741 // pointers are compatible. If they are not, then there is a bug
694742 // somewhere and we should let the C compiler tell us about it.
695 const elem_ctype = (try dg.ctypeFromType(ty, .complete)).info(ctype_pool).pointer.elem_ctype;
743 const ctype = try dg.ctypeFromType(ty, .complete);
744 const elem_ctype = ctype.info(ctype_pool).pointer.elem_ctype;
696745 const decl_ctype = try dg.ctypeFromType(decl_ty, .complete);
697746 const need_cast = !elem_ctype.eql(decl_ctype) and
698747 (elem_ctype.info(ctype_pool) != .function or decl_ctype.info(ctype_pool) != .function);
699748 if (need_cast) {
700749 try writer.writeAll("((");
701 try dg.renderType(writer, ty);
750 try dg.renderCType(writer, ctype);
702751 try writer.writeByte(')');
703752 }
704753 try writer.writeByte('&');
......@@ -828,6 +877,12 @@ pub const DeclGen = struct {
828877 }
829878 }
830879
880 fn renderErrorName(dg: *DeclGen, writer: anytype, err_name: InternPool.NullTerminatedString) !void {
881 const zcu = dg.zcu;
882 const ip = &zcu.intern_pool;
883 try writer.print("zig_error_{}", .{fmtIdent(err_name.toSlice(ip))});
884 }
885
831886 fn renderValue(
832887 dg: *DeclGen,
833888 writer: anytype,
......@@ -837,6 +892,7 @@ pub const DeclGen = struct {
837892 const zcu = dg.zcu;
838893 const ip = &zcu.intern_pool;
839894 const target = &dg.mod.resolved_target.result;
895 const ctype_pool = &dg.ctype_pool;
840896
841897 const initializer_type: ValueRenderLocation = switch (location) {
842898 .StaticInitializer => .StaticInitializer,
......@@ -845,6 +901,7 @@ pub const DeclGen = struct {
845901
846902 const ty = val.typeOf(zcu);
847903 if (val.isUndefDeep(zcu)) return dg.renderUndefValue(writer, ty, location);
904 const ctype = try dg.ctypeFromType(ty, location.toCTypeKind());
848905 switch (ip.indexToKey(val.toIntern())) {
849906 // types, not values
850907 .int_type,
......@@ -890,76 +947,53 @@ pub const DeclGen = struct {
890947 .u64, .i64, .big_int => try writer.print("{}", .{try dg.fmtIntLiteral(val, location)}),
891948 .lazy_align, .lazy_size => {
892949 try writer.writeAll("((");
893 try dg.renderType(writer, ty);
950 try dg.renderCType(writer, ctype);
894951 try writer.print("){x})", .{try dg.fmtIntLiteral(
895952 try zcu.intValue(Type.usize, val.toUnsignedInt(zcu)),
896953 .Other,
897954 )});
898955 },
899956 },
900 .err => |err| try writer.print("zig_error_{}", .{
901 fmtIdent(err.name.toSlice(ip)),
902 }),
903 .error_union => |error_union| {
904 const payload_ty = ty.errorUnionPayload(zcu);
905 const error_ty = ty.errorUnionSet(zcu);
906 const err_int_ty = try zcu.errorIntType();
907 if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) {
908 switch (error_union.val) {
909 .err_name => |err_name| return dg.renderValue(
910 writer,
911 Value.fromInterned((try zcu.intern(.{ .err = .{
912 .ty = error_ty.toIntern(),
913 .name = err_name,
914 } }))),
915 location,
916 ),
917 .payload => return dg.renderValue(
918 writer,
919 try zcu.intValue(err_int_ty, 0),
920 location,
921 ),
957 .err => |err| try dg.renderErrorName(writer, err.name),
958 .error_union => |error_union| switch (ctype.info(ctype_pool)) {
959 .basic => switch (error_union.val) {
960 .err_name => |err_name| try dg.renderErrorName(writer, err_name),
961 .payload => try writer.writeAll("0"),
962 },
963 .pointer, .aligned, .array, .vector, .fwd_decl, .function => unreachable,
964 .aggregate => |aggregate| {
965 if (!location.isInitializer()) {
966 try writer.writeByte('(');
967 try dg.renderCType(writer, ctype);
968 try writer.writeByte(')');
922969 }
923 }
924
925 if (!location.isInitializer()) {
926 try writer.writeByte('(');
927 try dg.renderType(writer, ty);
928 try writer.writeByte(')');
929 }
930
931 try writer.writeAll("{ .payload = ");
932 try dg.renderValue(
933 writer,
934 Value.fromInterned(switch (error_union.val) {
935 .err_name => (try zcu.undefValue(payload_ty)).toIntern(),
936 .payload => |payload| payload,
937 }),
938 initializer_type,
939 );
940 try writer.writeAll(", .error = ");
941 switch (error_union.val) {
942 .err_name => |err_name| try dg.renderValue(
943 writer,
944 Value.fromInterned((try zcu.intern(.{ .err = .{
945 .ty = error_ty.toIntern(),
946 .name = err_name,
947 } }))),
948 location,
949 ),
950 .payload => try dg.renderValue(
951 writer,
952 try zcu.intValue(err_int_ty, 0),
953 location,
954 ),
955 }
956 try writer.writeAll(" }");
970 try writer.writeByte('{');
971 for (0..aggregate.fields.len) |field_index| {
972 if (field_index > 0) try writer.writeByte(',');
973 switch (aggregate.fields.at(field_index, ctype_pool).name.index) {
974 .@"error" => switch (error_union.val) {
975 .err_name => |err_name| try dg.renderErrorName(writer, err_name),
976 .payload => try writer.writeByte('0'),
977 },
978 .payload => switch (error_union.val) {
979 .err_name => try dg.renderUndefValue(
980 writer,
981 ty.errorUnionPayload(zcu),
982 initializer_type,
983 ),
984 .payload => |payload| try dg.renderValue(
985 writer,
986 Value.fromInterned(payload),
987 initializer_type,
988 ),
989 },
990 else => unreachable,
991 }
992 }
993 try writer.writeByte('}');
994 },
957995 },
958 .enum_tag => |enum_tag| try dg.renderValue(
959 writer,
960 Value.fromInterned(enum_tag.int),
961 location,
962 ),
996 .enum_tag => |enum_tag| try dg.renderValue(writer, Value.fromInterned(enum_tag.int), location),
963997 .float => {
964998 const bits = ty.floatBits(target.*);
965999 const f128_val = val.toFloat(f128, zcu);
......@@ -1050,15 +1084,23 @@ pub const DeclGen = struct {
10501084 if (!empty) try writer.writeByte(')');
10511085 },
10521086 .slice => |slice| {
1087 const aggregate = ctype.info(ctype_pool).aggregate;
10531088 if (!location.isInitializer()) {
10541089 try writer.writeByte('(');
1055 try dg.renderType(writer, ty);
1090 try dg.renderCType(writer, ctype);
10561091 try writer.writeByte(')');
10571092 }
10581093 try writer.writeByte('{');
1059 try dg.renderValue(writer, Value.fromInterned(slice.ptr), initializer_type);
1060 try writer.writeAll(", ");
1061 try dg.renderValue(writer, Value.fromInterned(slice.len), initializer_type);
1094 for (0..aggregate.fields.len) |field_index| {
1095 if (field_index > 0) try writer.writeByte(',');
1096 try dg.renderValue(writer, Value.fromInterned(
1097 switch (aggregate.fields.at(field_index, ctype_pool).name.index) {
1098 .ptr => slice.ptr,
1099 .len => slice.len,
1100 else => unreachable,
1101 },
1102 ), initializer_type);
1103 }
10621104 try writer.writeByte('}');
10631105 },
10641106 .ptr => |ptr| switch (ptr.addr) {
......@@ -1066,7 +1108,7 @@ pub const DeclGen = struct {
10661108 .anon_decl => |decl_val| try dg.renderAnonDeclValue(writer, val, decl_val, location),
10671109 .int => |int| {
10681110 try writer.writeAll("((");
1069 try dg.renderType(writer, ty);
1111 try dg.renderCType(writer, ctype);
10701112 try writer.print("){x})", .{try dg.fmtIntLiteral(Value.fromInterned(int), location)});
10711113 },
10721114 .eu_payload,
......@@ -1076,54 +1118,80 @@ pub const DeclGen = struct {
10761118 => try dg.renderParentPtr(writer, val.toIntern(), location),
10771119 .comptime_field, .comptime_alloc => unreachable,
10781120 },
1079 .opt => |opt| {
1080 const payload_ty = ty.optionalChild(zcu);
1081
1082 const is_null_val = Value.makeBool(opt.val == .none);
1083 if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu))
1084 return dg.renderValue(writer, is_null_val, location);
1085
1086 if (ty.optionalReprIsPayload(zcu)) return dg.renderValue(
1087 writer,
1121 .opt => |opt| switch (ctype.info(ctype_pool)) {
1122 .basic => if (ctype.isBool()) try writer.writeAll(switch (opt.val) {
1123 .none => "true",
1124 else => "false",
1125 }) else switch (opt.val) {
1126 .none => try writer.writeAll("0"),
1127 else => |payload| switch (ip.indexToKey(payload)) {
1128 .undef => |err_ty| try dg.renderUndefValue(
1129 writer,
1130 Type.fromInterned(err_ty),
1131 location,
1132 ),
1133 .err => |err| try dg.renderErrorName(writer, err.name),
1134 else => unreachable,
1135 },
1136 },
1137 .pointer => switch (opt.val) {
1138 .none => try writer.writeAll("NULL"),
1139 else => |payload| try dg.renderValue(writer, Value.fromInterned(payload), location),
1140 },
1141 .aligned, .array, .vector, .fwd_decl, .function => unreachable,
1142 .aggregate => |aggregate| {
10881143 switch (opt.val) {
1089 .none => switch (payload_ty.zigTypeTag(zcu)) {
1090 .ErrorSet => try zcu.intValue(try zcu.errorIntType(), 0),
1091 .Pointer => try zcu.getCoerced(val, payload_ty),
1144 .none => {},
1145 else => |payload| switch (aggregate.fields.at(0, ctype_pool).name.index) {
1146 .is_null, .payload => {},
1147 .ptr, .len => return dg.renderValue(
1148 writer,
1149 Value.fromInterned(payload),
1150 location,
1151 ),
10921152 else => unreachable,
10931153 },
1094 else => |payload| Value.fromInterned(payload),
1095 },
1096 location,
1097 );
1098
1099 if (!location.isInitializer()) {
1100 try writer.writeByte('(');
1101 try dg.renderType(writer, ty);
1102 try writer.writeByte(')');
1103 }
1104
1105 try writer.writeAll("{ .payload = ");
1106 switch (opt.val) {
1107 .none => try dg.renderUndefValue(writer, payload_ty, initializer_type),
1108 else => |payload| try dg.renderValue(
1109 writer,
1110 Value.fromInterned(payload),
1111 initializer_type,
1112 ),
1113 }
1114 try writer.writeAll(", .is_null = ");
1115 try dg.renderValue(writer, is_null_val, initializer_type);
1116 try writer.writeAll(" }");
1154 }
1155 if (!location.isInitializer()) {
1156 try writer.writeByte('(');
1157 try dg.renderCType(writer, ctype);
1158 try writer.writeByte(')');
1159 }
1160 try writer.writeByte('{');
1161 for (0..aggregate.fields.len) |field_index| {
1162 if (field_index > 0) try writer.writeByte(',');
1163 switch (aggregate.fields.at(field_index, ctype_pool).name.index) {
1164 .is_null => try writer.writeAll(switch (opt.val) {
1165 .none => "true",
1166 else => "false",
1167 }),
1168 .payload => switch (opt.val) {
1169 .none => try dg.renderUndefValue(
1170 writer,
1171 ty.optionalChild(zcu),
1172 initializer_type,
1173 ),
1174 else => |payload| try dg.renderValue(
1175 writer,
1176 Value.fromInterned(payload),
1177 initializer_type,
1178 ),
1179 },
1180 .ptr => try writer.writeAll("NULL"),
1181 .len => try dg.renderUndefValue(writer, Type.usize, initializer_type),
1182 else => unreachable,
1183 }
1184 }
1185 try writer.writeByte('}');
1186 },
11171187 },
11181188 .aggregate => switch (ip.indexToKey(ty.toIntern())) {
11191189 .array_type, .vector_type => {
11201190 if (location == .FunctionArgument) {
11211191 try writer.writeByte('(');
1122 try dg.renderType(writer, ty);
1192 try dg.renderCType(writer, ctype);
11231193 try writer.writeByte(')');
11241194 }
1125 // Fall back to generic implementation.
1126
11271195 const ai = ty.arrayInfo(zcu);
11281196 if (ai.elem_type.eql(Type.u8, zcu)) {
11291197 var literal = stringLiteral(writer, ty.arrayLenIncludingSentinel(zcu));
......@@ -1160,7 +1228,7 @@ pub const DeclGen = struct {
11601228 .anon_struct_type => |tuple| {
11611229 if (!location.isInitializer()) {
11621230 try writer.writeByte('(');
1163 try dg.renderType(writer, ty);
1231 try dg.renderCType(writer, ctype);
11641232 try writer.writeByte(')');
11651233 }
11661234
......@@ -1196,7 +1264,7 @@ pub const DeclGen = struct {
11961264 .auto, .@"extern" => {
11971265 if (!location.isInitializer()) {
11981266 try writer.writeByte('(');
1199 try dg.renderType(writer, ty);
1267 try dg.renderCType(writer, ctype);
12001268 try writer.writeByte(')');
12011269 }
12021270
......@@ -1238,7 +1306,7 @@ pub const DeclGen = struct {
12381306
12391307 if (eff_num_fields == 0) {
12401308 try writer.writeByte('(');
1241 try dg.renderUndefValue(writer, ty, initializer_type);
1309 try dg.renderUndefValue(writer, ty, location);
12421310 try writer.writeByte(')');
12431311 } else if (ty.bitSize(zcu) > 64) {
12441312 // zig_or_u128(zig_or_u128(zig_shl_u128(a, a_off), zig_shl_u128(b, b_off)), zig_shl_u128(c, c_off))
......@@ -1293,7 +1361,7 @@ pub const DeclGen = struct {
12931361
12941362 if (!empty) try writer.writeAll(" | ");
12951363 try writer.writeByte('(');
1296 try dg.renderType(writer, ty);
1364 try dg.renderCType(writer, ctype);
12971365 try writer.writeByte(')');
12981366
12991367 const field_val = switch (ip.indexToKey(val.toIntern()).aggregate.storage) {
......@@ -1334,7 +1402,7 @@ pub const DeclGen = struct {
13341402 try dg.renderType(writer, backing_ty);
13351403 try writer.writeByte(')');
13361404 }
1337 try dg.renderValue(writer, Value.fromInterned(un.val), initializer_type);
1405 try dg.renderValue(writer, Value.fromInterned(un.val), location);
13381406 },
13391407 .@"extern" => {
13401408 if (location == .StaticInitializer) {
......@@ -1347,7 +1415,7 @@ pub const DeclGen = struct {
13471415 try writer.writeAll(")(");
13481416 try dg.renderType(writer, backing_ty);
13491417 try writer.writeAll("){");
1350 try dg.renderValue(writer, Value.fromInterned(un.val), initializer_type);
1418 try dg.renderValue(writer, Value.fromInterned(un.val), location);
13511419 try writer.writeAll("})");
13521420 },
13531421 else => unreachable,
......@@ -1355,7 +1423,7 @@ pub const DeclGen = struct {
13551423 } else {
13561424 if (!location.isInitializer()) {
13571425 try writer.writeByte('(');
1358 try dg.renderType(writer, ty);
1426 try dg.renderCType(writer, ctype);
13591427 try writer.writeByte(')');
13601428 }
13611429
......@@ -1366,43 +1434,56 @@ pub const DeclGen = struct {
13661434 if (field_ty.hasRuntimeBits(zcu)) {
13671435 if (field_ty.isPtrAtRuntime(zcu)) {
13681436 try writer.writeByte('(');
1369 try dg.renderType(writer, ty);
1437 try dg.renderCType(writer, ctype);
13701438 try writer.writeByte(')');
13711439 } else if (field_ty.zigTypeTag(zcu) == .Float) {
13721440 try writer.writeByte('(');
1373 try dg.renderType(writer, ty);
1441 try dg.renderCType(writer, ctype);
13741442 try writer.writeByte(')');
13751443 }
1376 try dg.renderValue(writer, Value.fromInterned(un.val), initializer_type);
1377 } else {
1378 try writer.writeAll("0");
1379 }
1444 try dg.renderValue(writer, Value.fromInterned(un.val), location);
1445 } else try writer.writeAll("0");
13801446 return;
13811447 }
13821448
1383 try writer.writeByte('{');
1384 if (ty.unionTagTypeSafety(zcu)) |_| {
1385 const layout = zcu.getUnionLayout(loaded_union);
1386 if (layout.tag_size != 0) {
1387 try writer.writeAll(" .tag = ");
1388 try dg.renderValue(writer, Value.fromInterned(un.tag), initializer_type);
1449 const has_tag = loaded_union.hasTag(ip);
1450 if (has_tag) try writer.writeByte('{');
1451 const aggregate = ctype.info(ctype_pool).aggregate;
1452 for (0..if (has_tag) aggregate.fields.len else 1) |outer_field_index| {
1453 if (outer_field_index > 0) try writer.writeByte(',');
1454 switch (if (has_tag)
1455 aggregate.fields.at(outer_field_index, ctype_pool).name.index
1456 else
1457 .payload) {
1458 .tag => try dg.renderValue(
1459 writer,
1460 Value.fromInterned(un.tag),
1461 initializer_type,
1462 ),
1463 .payload => {
1464 try writer.writeByte('{');
1465 if (field_ty.hasRuntimeBits(zcu)) {
1466 try writer.print(" .{ } = ", .{fmtIdent(field_name.toSlice(ip))});
1467 try dg.renderValue(
1468 writer,
1469 Value.fromInterned(un.val),
1470 initializer_type,
1471 );
1472 try writer.writeByte(' ');
1473 } else for (0..loaded_union.field_types.len) |inner_field_index| {
1474 const inner_field_ty = Type.fromInterned(
1475 loaded_union.field_types.get(ip)[inner_field_index],
1476 );
1477 if (!inner_field_ty.hasRuntimeBits(zcu)) continue;
1478 try dg.renderUndefValue(writer, inner_field_ty, initializer_type);
1479 break;
1480 }
1481 try writer.writeByte('}');
1482 },
1483 else => unreachable,
13891484 }
1390 if (ty.unionHasAllZeroBitFieldTypes(zcu)) return try writer.writeByte('}');
1391 if (layout.tag_size != 0) try writer.writeByte(',');
1392 try writer.writeAll(" .payload = {");
1393 }
1394 if (field_ty.hasRuntimeBits(zcu)) {
1395 try writer.print(" .{ } = ", .{fmtIdent(field_name.toSlice(ip))});
1396 try dg.renderValue(writer, Value.fromInterned(un.val), initializer_type);
1397 try writer.writeByte(' ');
1398 } else for (0..loaded_union.field_types.len) |this_field_index| {
1399 const this_field_ty = Type.fromInterned(loaded_union.field_types.get(ip)[this_field_index]);
1400 if (!this_field_ty.hasRuntimeBits(zcu)) continue;
1401 try dg.renderUndefValue(writer, this_field_ty, initializer_type);
1402 break;
14031485 }
1404 if (ty.unionTagTypeSafety(zcu)) |_| try writer.writeByte('}');
1405 try writer.writeByte('}');
1486 if (has_tag) try writer.writeByte('}');
14061487 }
14071488 },
14081489 }
......@@ -1417,6 +1498,7 @@ pub const DeclGen = struct {
14171498 const zcu = dg.zcu;
14181499 const ip = &zcu.intern_pool;
14191500 const target = &dg.mod.resolved_target.result;
1501 const ctype_pool = &dg.ctype_pool;
14201502
14211503 const initializer_type: ValueRenderLocation = switch (location) {
14221504 .StaticInitializer => .StaticInitializer,
......@@ -1428,6 +1510,7 @@ pub const DeclGen = struct {
14281510 .ReleaseFast, .ReleaseSmall => false,
14291511 };
14301512
1513 const ctype = try dg.ctypeFromType(ty, location.toCTypeKind());
14311514 switch (ty.toIntern()) {
14321515 .c_longdouble_type,
14331516 .f16_type,
......@@ -1465,48 +1548,64 @@ pub const DeclGen = struct {
14651548 => return writer.print("{x}", .{
14661549 try dg.fmtIntLiteral(try zcu.undefValue(ty), location),
14671550 }),
1468 .ptr_type => if (ty.isSlice(zcu)) {
1469 if (!location.isInitializer()) {
1470 try writer.writeByte('(');
1471 try dg.renderType(writer, ty);
1472 try writer.writeByte(')');
1473 }
1551 .ptr_type => |ptr_type| switch (ptr_type.flags.size) {
1552 .One, .Many, .C => {
1553 try writer.writeAll("((");
1554 try dg.renderCType(writer, ctype);
1555 return writer.print("){x})", .{
1556 try dg.fmtIntLiteral(try zcu.undefValue(Type.usize), .Other),
1557 });
1558 },
1559 .Slice => {
1560 if (!location.isInitializer()) {
1561 try writer.writeByte('(');
1562 try dg.renderCType(writer, ctype);
1563 try writer.writeByte(')');
1564 }
14741565
1475 try writer.writeAll("{(");
1476 const ptr_ty = ty.slicePtrFieldType(zcu);
1477 try dg.renderType(writer, ptr_ty);
1478 return writer.print("){x}, {0x}}}", .{
1479 try dg.fmtIntLiteral(try zcu.undefValue(Type.usize), .Other),
1480 });
1481 } else {
1482 try writer.writeAll("((");
1483 try dg.renderType(writer, ty);
1484 return writer.print("){x})", .{
1485 try dg.fmtIntLiteral(try zcu.undefValue(Type.usize), .Other),
1486 });
1566 try writer.writeAll("{(");
1567 const ptr_ty = ty.slicePtrFieldType(zcu);
1568 try dg.renderType(writer, ptr_ty);
1569 return writer.print("){x}, {0x}}}", .{
1570 try dg.fmtIntLiteral(try zcu.undefValue(Type.usize), .Other),
1571 });
1572 },
14871573 },
1488 .opt_type => {
1489 const payload_ty = ty.optionalChild(zcu);
1490
1491 if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) {
1492 return dg.renderUndefValue(writer, Type.bool, location);
1493 }
1494
1495 if (ty.optionalReprIsPayload(zcu)) {
1496 return dg.renderUndefValue(writer, payload_ty, location);
1497 }
1498
1499 if (!location.isInitializer()) {
1500 try writer.writeByte('(');
1501 try dg.renderType(writer, ty);
1502 try writer.writeByte(')');
1503 }
1504
1505 try writer.writeAll("{ .payload = ");
1506 try dg.renderUndefValue(writer, payload_ty, initializer_type);
1507 try writer.writeAll(", .is_null = ");
1508 try dg.renderUndefValue(writer, Type.bool, initializer_type);
1509 return writer.writeAll(" }");
1574 .opt_type => |child_type| switch (ctype.info(ctype_pool)) {
1575 .basic, .pointer => try dg.renderUndefValue(
1576 writer,
1577 Type.fromInterned(if (ctype.isBool()) .bool_type else child_type),
1578 location,
1579 ),
1580 .aligned, .array, .vector, .fwd_decl, .function => unreachable,
1581 .aggregate => |aggregate| {
1582 switch (aggregate.fields.at(0, ctype_pool).name.index) {
1583 .is_null, .payload => {},
1584 .ptr, .len => return dg.renderUndefValue(
1585 writer,
1586 Type.fromInterned(child_type),
1587 location,
1588 ),
1589 else => unreachable,
1590 }
1591 if (!location.isInitializer()) {
1592 try writer.writeByte('(');
1593 try dg.renderCType(writer, ctype);
1594 try writer.writeByte(')');
1595 }
1596 try writer.writeByte('{');
1597 for (0..aggregate.fields.len) |field_index| {
1598 if (field_index > 0) try writer.writeByte(',');
1599 try dg.renderUndefValue(writer, Type.fromInterned(
1600 switch (aggregate.fields.at(field_index, ctype_pool).name.index) {
1601 .is_null => .bool_type,
1602 .payload => child_type,
1603 else => unreachable,
1604 },
1605 ), initializer_type);
1606 }
1607 try writer.writeByte('}');
1608 },
15101609 },
15111610 .struct_type => {
15121611 const loaded_struct = ip.loadStructType(ty.toIntern());
......@@ -1514,7 +1613,7 @@ pub const DeclGen = struct {
15141613 .auto, .@"extern" => {
15151614 if (!location.isInitializer()) {
15161615 try writer.writeByte('(');
1517 try dg.renderType(writer, ty);
1616 try dg.renderCType(writer, ctype);
15181617 try writer.writeByte(')');
15191618 }
15201619
......@@ -1539,7 +1638,7 @@ pub const DeclGen = struct {
15391638 .anon_struct_type => |anon_struct_info| {
15401639 if (!location.isInitializer()) {
15411640 try writer.writeByte('(');
1542 try dg.renderType(writer, ty);
1641 try dg.renderCType(writer, ctype);
15431642 try writer.writeByte(')');
15441643 }
15451644
......@@ -1562,54 +1661,80 @@ pub const DeclGen = struct {
15621661 .auto, .@"extern" => {
15631662 if (!location.isInitializer()) {
15641663 try writer.writeByte('(');
1565 try dg.renderType(writer, ty);
1664 try dg.renderCType(writer, ctype);
15661665 try writer.writeByte(')');
15671666 }
15681667
1569 try writer.writeByte('{');
1570 if (ty.unionTagTypeSafety(zcu)) |tag_ty| {
1571 const layout = ty.unionGetLayout(zcu);
1572 if (layout.tag_size != 0) {
1573 try writer.writeAll(" .tag = ");
1574 try dg.renderUndefValue(writer, tag_ty, initializer_type);
1668 const has_tag = loaded_union.hasTag(ip);
1669 if (has_tag) try writer.writeByte('{');
1670 const aggregate = ctype.info(ctype_pool).aggregate;
1671 for (0..if (has_tag) aggregate.fields.len else 1) |outer_field_index| {
1672 if (outer_field_index > 0) try writer.writeByte(',');
1673 switch (if (has_tag)
1674 aggregate.fields.at(outer_field_index, ctype_pool).name.index
1675 else
1676 .payload) {
1677 .tag => try dg.renderUndefValue(
1678 writer,
1679 Type.fromInterned(loaded_union.enum_tag_ty),
1680 initializer_type,
1681 ),
1682 .payload => {
1683 try writer.writeByte('{');
1684 for (0..loaded_union.field_types.len) |inner_field_index| {
1685 const inner_field_ty = Type.fromInterned(
1686 loaded_union.field_types.get(ip)[inner_field_index],
1687 );
1688 if (!inner_field_ty.hasRuntimeBits(zcu)) continue;
1689 try dg.renderUndefValue(
1690 writer,
1691 inner_field_ty,
1692 initializer_type,
1693 );
1694 break;
1695 }
1696 try writer.writeByte('}');
1697 },
1698 else => unreachable,
15751699 }
1576 if (ty.unionHasAllZeroBitFieldTypes(zcu)) return try writer.writeByte('}');
1577 if (layout.tag_size != 0) try writer.writeByte(',');
1578 try writer.writeAll(" .payload = {");
1579 }
1580 for (0..loaded_union.field_types.len) |field_index| {
1581 const field_ty = Type.fromInterned(loaded_union.field_types.get(ip)[field_index]);
1582 if (!field_ty.hasRuntimeBits(zcu)) continue;
1583 try dg.renderUndefValue(writer, field_ty, initializer_type);
1584 break;
15851700 }
1586 if (ty.unionTagTypeSafety(zcu)) |_| try writer.writeByte('}');
1587 return writer.writeByte('}');
1701 if (has_tag) try writer.writeByte('}');
15881702 },
15891703 .@"packed" => return writer.print("{x}", .{
15901704 try dg.fmtIntLiteral(try zcu.undefValue(ty), .Other),
15911705 }),
15921706 }
15931707 },
1594 .error_union_type => {
1595 const payload_ty = ty.errorUnionPayload(zcu);
1596 const error_ty = ty.errorUnionSet(zcu);
1597
1598 if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) {
1599 return dg.renderUndefValue(writer, error_ty, location);
1600 }
1601
1602 if (!location.isInitializer()) {
1603 try writer.writeByte('(');
1604 try dg.renderType(writer, ty);
1605 try writer.writeByte(')');
1606 }
1607
1608 try writer.writeAll("{ .payload = ");
1609 try dg.renderUndefValue(writer, payload_ty, initializer_type);
1610 try writer.writeAll(", .error = ");
1611 try dg.renderUndefValue(writer, error_ty, initializer_type);
1612 return writer.writeAll(" }");
1708 .error_union_type => |error_union_type| switch (ctype.info(ctype_pool)) {
1709 .basic => try dg.renderUndefValue(
1710 writer,
1711 Type.fromInterned(error_union_type.error_set_type),
1712 location,
1713 ),
1714 .pointer, .aligned, .array, .vector, .fwd_decl, .function => unreachable,
1715 .aggregate => |aggregate| {
1716 if (!location.isInitializer()) {
1717 try writer.writeByte('(');
1718 try dg.renderCType(writer, ctype);
1719 try writer.writeByte(')');
1720 }
1721 try writer.writeByte('{');
1722 for (0..aggregate.fields.len) |field_index| {
1723 if (field_index > 0) try writer.writeByte(',');
1724 try dg.renderUndefValue(
1725 writer,
1726 Type.fromInterned(
1727 switch (aggregate.fields.at(field_index, ctype_pool).name.index) {
1728 .@"error" => error_union_type.error_set_type,
1729 .payload => error_union_type.payload_type,
1730 else => unreachable,
1731 },
1732 ),
1733 initializer_type,
1734 );
1735 }
1736 try writer.writeByte('}');
1737 },
16131738 },
16141739 .array_type, .vector_type => {
16151740 const ai = ty.arrayInfo(zcu);
......@@ -1624,7 +1749,7 @@ pub const DeclGen = struct {
16241749 } else {
16251750 if (!location.isInitializer()) {
16261751 try writer.writeByte('(');
1627 try dg.renderType(writer, ty);
1752 try dg.renderCType(writer, ctype);
16281753 try writer.writeByte(')');
16291754 }
16301755
......@@ -1674,6 +1799,7 @@ pub const DeclGen = struct {
16741799 name: union(enum) {
16751800 export_index: u32,
16761801 ident: []const u8,
1802 fmt_ctype_pool_string: std.fmt.Formatter(formatCTypePoolString),
16771803 },
16781804 ) !void {
16791805 const zcu = dg.zcu;
......@@ -1717,6 +1843,7 @@ pub const DeclGen = struct {
17171843 try dg.renderDeclName(w, fn_decl_index, export_index);
17181844 },
17191845 .ident => |ident| try w.print("{}{ }", .{ trailing, fmtIdent(ident) }),
1846 .fmt_ctype_pool_string => |fmt| try w.print("{}{ }", .{ trailing, fmt }),
17201847 }
17211848
17221849 try renderTypeSuffix(
......@@ -1772,7 +1899,7 @@ pub const DeclGen = struct {
17721899 });
17731900 }
17741901 },
1775 .ident => {},
1902 .ident, .fmt_ctype_pool_string => {},
17761903 }
17771904 },
17781905 .complete => {},
......@@ -1800,11 +1927,11 @@ pub const DeclGen = struct {
18001927 /// | `renderTypeAndName` | "uint8_t *name" | "uint8_t *name[10]" |
18011928 /// | `renderType` | "uint8_t *" | "uint8_t *[10]" |
18021929 ///
1803 fn renderType(dg: *DeclGen, w: anytype, t: Type) error{ OutOfMemory, AnalysisFail }!void {
1930 fn renderType(dg: *DeclGen, w: anytype, t: Type) error{OutOfMemory}!void {
18041931 try dg.renderCType(w, try dg.ctypeFromType(t, .complete));
18051932 }
18061933
1807 fn renderCType(dg: *DeclGen, w: anytype, ctype: CType) error{ OutOfMemory, AnalysisFail }!void {
1934 fn renderCType(dg: *DeclGen, w: anytype, ctype: CType) error{OutOfMemory}!void {
18081935 _ = try renderTypePrefix(dg.pass, &dg.ctype_pool, dg.zcu, w, ctype, .suffix, .{});
18091936 try renderTypeSuffix(dg.pass, &dg.ctype_pool, dg.zcu, w, ctype, .suffix, .{});
18101937 }
......@@ -1829,7 +1956,26 @@ pub const DeclGen = struct {
18291956 }
18301957 }
18311958 };
1959 fn intCastIsNoop(dg: *DeclGen, dest_ty: Type, src_ty: Type) bool {
1960 const zcu = dg.zcu;
1961 const dest_bits = dest_ty.bitSize(zcu);
1962 const dest_int_info = dest_ty.intInfo(zcu);
1963
1964 const src_is_ptr = src_ty.isPtrAtRuntime(zcu);
1965 const src_eff_ty: Type = if (src_is_ptr) switch (dest_int_info.signedness) {
1966 .unsigned => Type.usize,
1967 .signed => Type.isize,
1968 } else src_ty;
18321969
1970 const src_bits = src_eff_ty.bitSize(zcu);
1971 const src_int_info = if (src_eff_ty.isAbiInt(zcu)) src_eff_ty.intInfo(zcu) else null;
1972 if (dest_bits <= 64 and src_bits <= 64) {
1973 const needs_cast = src_int_info == null or
1974 (toCIntBits(dest_int_info.bits) != toCIntBits(src_int_info.?.bits) or
1975 dest_int_info.signedness != src_int_info.?.signedness);
1976 return !needs_cast and !src_is_ptr;
1977 } else return false;
1978 }
18331979 /// Renders a cast to an int type, from either an int or a pointer.
18341980 ///
18351981 /// Some platforms don't have 128 bit integers, so we need to use
......@@ -1843,7 +1989,14 @@ pub const DeclGen = struct {
18431989 /// | > 64 bit integer | pointer | zig_make_<dest_ty>(0, (zig_<u|i>size)src)
18441990 /// | > 64 bit integer | < 64 bit integer | zig_make_<dest_ty>(0, src)
18451991 /// | > 64 bit integer | > 64 bit integer | zig_make_<dest_ty>(zig_hi_<src_ty>(src), zig_lo_<src_ty>(src))
1846 fn renderIntCast(dg: *DeclGen, w: anytype, dest_ty: Type, context: IntCastContext, src_ty: Type, location: ValueRenderLocation) !void {
1992 fn renderIntCast(
1993 dg: *DeclGen,
1994 w: anytype,
1995 dest_ty: Type,
1996 context: IntCastContext,
1997 src_ty: Type,
1998 location: ValueRenderLocation,
1999 ) !void {
18472000 const zcu = dg.zcu;
18482001 const dest_bits = dest_ty.bitSize(zcu);
18492002 const dest_int_info = dest_ty.intInfo(zcu);
......@@ -1998,12 +2151,23 @@ pub const DeclGen = struct {
19982151 fmtIdent("payload"),
19992152 fmtIdent(ident),
20002153 }),
2154 .ctype_pool_string => |string| try w.print("{ }", .{
2155 fmtCTypePoolString(string, &dg.ctype_pool),
2156 }),
20012157 }
20022158 }
20032159
20042160 fn writeCValueDeref(dg: *DeclGen, w: anytype, c_value: CValue) !void {
20052161 switch (c_value) {
2006 .none, .new_local, .local, .local_ref, .constant, .arg, .arg_array => unreachable,
2162 .none,
2163 .new_local,
2164 .local,
2165 .local_ref,
2166 .constant,
2167 .arg,
2168 .arg_array,
2169 .ctype_pool_string,
2170 => unreachable,
20072171 .field => |i| try w.print("f{d}", .{i}),
20082172 .decl => |decl| {
20092173 try w.writeAll("(*");
......@@ -2033,7 +2197,17 @@ pub const DeclGen = struct {
20332197
20342198 fn writeCValueDerefMember(dg: *DeclGen, writer: anytype, c_value: CValue, member: CValue) !void {
20352199 switch (c_value) {
2036 .none, .new_local, .local, .local_ref, .constant, .field, .undef, .arg, .arg_array => unreachable,
2200 .none,
2201 .new_local,
2202 .local,
2203 .local_ref,
2204 .constant,
2205 .field,
2206 .undef,
2207 .arg,
2208 .arg_array,
2209 .ctype_pool_string,
2210 => unreachable,
20372211 .decl, .identifier, .payload_identifier => {
20382212 try dg.writeCValue(writer, c_value);
20392213 try writer.writeAll("->");
......@@ -2172,11 +2346,7 @@ pub const DeclGen = struct {
21722346 loc: ValueRenderLocation,
21732347 ) !std.fmt.Formatter(formatIntLiteral) {
21742348 const zcu = dg.zcu;
2175 const kind: CType.Kind = switch (loc) {
2176 .FunctionArgument => .parameter,
2177 .Initializer, .Other => .complete,
2178 .StaticInitializer => .global,
2179 };
2349 const kind = loc.toCTypeKind();
21802350 const ty = val.typeOf(zcu);
21812351 return std.fmt.Formatter(formatIntLiteral){ .data = .{
21822352 .dg = dg,
......@@ -2439,7 +2609,7 @@ fn renderFields(
24392609 .suffix,
24402610 .{},
24412611 );
2442 try writer.print("{}{ }", .{ trailing, fmtIdent(field_info.name.slice(ctype_pool)) });
2612 try writer.print("{}{ }", .{ trailing, fmtCTypePoolString(field_info.name, ctype_pool) });
24432613 try renderTypeSuffix(.flush, ctype_pool, zcu, writer, field_info.ctype, .suffix, .{});
24442614 try writer.writeAll(";\n");
24452615 }
......@@ -2698,9 +2868,7 @@ pub fn genLazyFn(o: *Object, lazy_ctype_pool: *const CType.Pool, lazy_fn: LazyFn
26982868
26992869 try w.writeAll("static ");
27002870 try o.dg.renderType(w, name_slice_ty);
2701 try w.writeByte(' ');
2702 try w.writeAll(val.fn_name.slice(lazy_ctype_pool));
2703 try w.writeByte('(');
2871 try w.print(" {}(", .{val.fn_name.fmt(lazy_ctype_pool)});
27042872 try o.dg.renderTypeAndName(w, enum_ty, .{ .identifier = "tag" }, Const, .none, .complete);
27052873 try w.writeAll(") {\n switch (tag) {\n");
27062874 const tag_names = enum_ty.enumFields(zcu);
......@@ -2744,21 +2912,18 @@ pub fn genLazyFn(o: *Object, lazy_ctype_pool: *const CType.Pool, lazy_fn: LazyFn
27442912 const fn_decl = zcu.declPtr(fn_decl_index);
27452913 const fn_ctype = try o.dg.ctypeFromType(fn_decl.typeOf(zcu), .complete);
27462914 const fn_info = fn_ctype.info(ctype_pool).function;
2747 const fn_name = val.fn_name.slice(lazy_ctype_pool);
2915 const fn_name = fmtCTypePoolString(val.fn_name, lazy_ctype_pool);
27482916
27492917 const fwd_decl_writer = o.dg.fwdDeclWriter();
27502918 try fwd_decl_writer.print("static zig_{s} ", .{@tagName(key)});
2751 try o.dg.renderFunctionSignature(
2752 fwd_decl_writer,
2753 fn_decl_index,
2754 .forward,
2755 .{ .ident = fn_name },
2756 );
2919 try o.dg.renderFunctionSignature(fwd_decl_writer, fn_decl_index, .forward, .{
2920 .fmt_ctype_pool_string = fn_name,
2921 });
27572922 try fwd_decl_writer.writeAll(";\n");
27582923
27592924 try w.print("static zig_{s} ", .{@tagName(key)});
27602925 try o.dg.renderFunctionSignature(w, fn_decl_index, .complete, .{
2761 .ident = fn_name,
2926 .fmt_ctype_pool_string = fn_name,
27622927 });
27632928 try w.writeAll(" {\n return ");
27642929 try o.dg.renderDeclName(w, fn_decl_index, 0);
......@@ -3143,8 +3308,8 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail,
31433308 .shl_exact => try airBinOp(f, inst, "<<", "shl", .none),
31443309 .not => try airNot (f, inst),
31453310
3146 .optional_payload => try airOptionalPayload(f, inst),
3147 .optional_payload_ptr => try airOptionalPayloadPtr(f, inst),
3311 .optional_payload => try airOptionalPayload(f, inst, false),
3312 .optional_payload_ptr => try airOptionalPayload(f, inst, true),
31483313 .optional_payload_ptr_set => try airOptionalPayloadPtrSet(f, inst),
31493314 .wrap_optional => try airWrapOptional(f, inst),
31503315
......@@ -3153,10 +3318,10 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail,
31533318 .is_err_ptr => try airIsErr(f, inst, true, "!="),
31543319 .is_non_err_ptr => try airIsErr(f, inst, true, "=="),
31553320
3156 .is_null => try airIsNull(f, inst, "==", false),
3157 .is_non_null => try airIsNull(f, inst, "!=", false),
3158 .is_null_ptr => try airIsNull(f, inst, "==", true),
3159 .is_non_null_ptr => try airIsNull(f, inst, "!=", true),
3321 .is_null => try airIsNull(f, inst, .eq, false),
3322 .is_non_null => try airIsNull(f, inst, .neq, false),
3323 .is_null_ptr => try airIsNull(f, inst, .eq, true),
3324 .is_non_null_ptr => try airIsNull(f, inst, .neq, true),
31603325
31613326 .alloc => try airAlloc(f, inst),
31623327 .ret_ptr => try airRetPtr(f, inst),
......@@ -3239,8 +3404,8 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail,
32393404 .slice_ptr => try airSliceField(f, inst, false, "ptr"),
32403405 .slice_len => try airSliceField(f, inst, false, "len"),
32413406
3242 .ptr_slice_len_ptr => try airSliceField(f, inst, true, "len"),
32433407 .ptr_slice_ptr_ptr => try airSliceField(f, inst, true, "ptr"),
3408 .ptr_slice_len_ptr => try airSliceField(f, inst, true, "len"),
32443409
32453410 .ptr_elem_val => try airPtrElemVal(f, inst),
32463411 .ptr_elem_ptr => try airPtrElemPtr(f, inst),
......@@ -3308,7 +3473,7 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail,
33083473 }
33093474 try f.value_map.putNoClobber(inst.toRef(), switch (result_value) {
33103475 .none => continue,
3311 .new_local => |i| .{ .local = i },
3476 .new_local => |local_index| .{ .local = local_index },
33123477 else => result_value,
33133478 });
33143479 }
......@@ -3323,7 +3488,7 @@ fn airSliceField(f: *Function, inst: Air.Inst.Index, is_ptr: bool, field_name: [
33233488
33243489 const writer = f.object.writer();
33253490 const local = try f.allocLocal(inst, inst_ty);
3326 const a = try Assignment.start(f, writer, inst_ty);
3491 const a = try Assignment.start(f, writer, try f.ctypeFromType(inst_ty, .complete));
33273492 try f.writeCValue(writer, local, .Other);
33283493 try a.assign(f, writer);
33293494 if (is_ptr) {
......@@ -3349,7 +3514,7 @@ fn airPtrElemVal(f: *Function, inst: Air.Inst.Index) !CValue {
33493514
33503515 const writer = f.object.writer();
33513516 const local = try f.allocLocal(inst, inst_ty);
3352 const a = try Assignment.start(f, writer, inst_ty);
3517 const a = try Assignment.start(f, writer, try f.ctypeFromType(inst_ty, .complete));
33533518 try f.writeCValue(writer, local, .Other);
33543519 try a.assign(f, writer);
33553520 try f.writeCValue(writer, ptr, .Other);
......@@ -3375,7 +3540,7 @@ fn airPtrElemPtr(f: *Function, inst: Air.Inst.Index) !CValue {
33753540
33763541 const writer = f.object.writer();
33773542 const local = try f.allocLocal(inst, inst_ty);
3378 const a = try Assignment.start(f, writer, inst_ty);
3543 const a = try Assignment.start(f, writer, try f.ctypeFromType(inst_ty, .complete));
33793544 try f.writeCValue(writer, local, .Other);
33803545 try a.assign(f, writer);
33813546 try writer.writeByte('(');
......@@ -3410,7 +3575,7 @@ fn airSliceElemVal(f: *Function, inst: Air.Inst.Index) !CValue {
34103575
34113576 const writer = f.object.writer();
34123577 const local = try f.allocLocal(inst, inst_ty);
3413 const a = try Assignment.start(f, writer, inst_ty);
3578 const a = try Assignment.start(f, writer, try f.ctypeFromType(inst_ty, .complete));
34143579 try f.writeCValue(writer, local, .Other);
34153580 try a.assign(f, writer);
34163581 try f.writeCValueMember(writer, slice, .{ .identifier = "ptr" });
......@@ -3437,7 +3602,7 @@ fn airSliceElemPtr(f: *Function, inst: Air.Inst.Index) !CValue {
34373602
34383603 const writer = f.object.writer();
34393604 const local = try f.allocLocal(inst, inst_ty);
3440 const a = try Assignment.start(f, writer, inst_ty);
3605 const a = try Assignment.start(f, writer, try f.ctypeFromType(inst_ty, .complete));
34413606 try f.writeCValue(writer, local, .Other);
34423607 try a.assign(f, writer);
34433608 if (elem_has_bits) try writer.writeByte('&');
......@@ -3466,7 +3631,7 @@ fn airArrayElemVal(f: *Function, inst: Air.Inst.Index) !CValue {
34663631
34673632 const writer = f.object.writer();
34683633 const local = try f.allocLocal(inst, inst_ty);
3469 const a = try Assignment.start(f, writer, inst_ty);
3634 const a = try Assignment.start(f, writer, try f.ctypeFromType(inst_ty, .complete));
34703635 try f.writeCValue(writer, local, .Other);
34713636 try a.assign(f, writer);
34723637 try f.writeCValue(writer, array, .Other);
......@@ -3691,17 +3856,18 @@ fn airIntCast(f: *Function, inst: Air.Inst.Index) !CValue {
36913856 const operand_ty = f.typeOf(ty_op.operand);
36923857 const scalar_ty = operand_ty.scalarType(zcu);
36933858
3859 if (f.object.dg.intCastIsNoop(inst_scalar_ty, scalar_ty)) return f.moveCValue(inst, inst_ty, operand);
3860
36943861 const writer = f.object.writer();
36953862 const local = try f.allocLocal(inst, inst_ty);
36963863 const v = try Vectorize.start(f, inst, writer, operand_ty);
3697 const a = try Assignment.start(f, writer, scalar_ty);
3864 const a = try Assignment.start(f, writer, try f.ctypeFromType(scalar_ty, .complete));
36983865 try f.writeCValue(writer, local, .Other);
36993866 try v.elem(f, writer);
37003867 try a.assign(f, writer);
37013868 try f.renderIntCast(writer, inst_scalar_ty, operand, v, scalar_ty, .Other);
37023869 try a.end(f, writer);
37033870 try v.end(f, inst, writer);
3704
37053871 return local;
37063872}
37073873
......@@ -3711,38 +3877,40 @@ fn airTrunc(f: *Function, inst: Air.Inst.Index) !CValue {
37113877
37123878 const operand = try f.resolveInst(ty_op.operand);
37133879 try reap(f, inst, &.{ty_op.operand});
3880
37143881 const inst_ty = f.typeOfIndex(inst);
37153882 const inst_scalar_ty = inst_ty.scalarType(zcu);
37163883 const dest_int_info = inst_scalar_ty.intInfo(zcu);
37173884 const dest_bits = dest_int_info.bits;
3718 const dest_c_bits = toCIntBits(dest_int_info.bits) orelse
3885 const dest_c_bits = toCIntBits(dest_bits) orelse
37193886 return f.fail("TODO: C backend: implement integer types larger than 128 bits", .{});
37203887 const operand_ty = f.typeOf(ty_op.operand);
37213888 const scalar_ty = operand_ty.scalarType(zcu);
37223889 const scalar_int_info = scalar_ty.intInfo(zcu);
37233890
3891 const need_cast = dest_c_bits < 64;
3892 const need_lo = scalar_int_info.bits > 64 and dest_bits <= 64;
3893 const need_mask = dest_bits < 8 or !std.math.isPowerOfTwo(dest_bits);
3894 if (!need_cast and !need_lo and !need_mask) return f.moveCValue(inst, inst_ty, operand);
3895
37243896 const writer = f.object.writer();
37253897 const local = try f.allocLocal(inst, inst_ty);
37263898 const v = try Vectorize.start(f, inst, writer, operand_ty);
3727
3899 const a = try Assignment.start(f, writer, try f.ctypeFromType(inst_scalar_ty, .complete));
37283900 try f.writeCValue(writer, local, .Other);
37293901 try v.elem(f, writer);
3730 try writer.writeAll(" = ");
3731
3732 if (dest_c_bits < 64) {
3902 try a.assign(f, writer);
3903 if (need_cast) {
37333904 try writer.writeByte('(');
37343905 try f.renderType(writer, inst_scalar_ty);
37353906 try writer.writeByte(')');
37363907 }
3737
3738 const needs_lo = scalar_int_info.bits > 64 and dest_bits <= 64;
3739 if (needs_lo) {
3908 if (need_lo) {
37403909 try writer.writeAll("zig_lo_");
37413910 try f.object.dg.renderTypeForBuiltinFnName(writer, scalar_ty);
37423911 try writer.writeByte('(');
37433912 }
3744
3745 if (dest_bits >= 8 and std.math.isPowerOfTwo(dest_bits)) {
3913 if (!need_mask) {
37463914 try f.writeCValue(writer, operand, .Other);
37473915 try v.elem(f, writer);
37483916 } else switch (dest_int_info.signedness) {
......@@ -3782,11 +3950,9 @@ fn airTrunc(f: *Function, inst: Air.Inst.Index) !CValue {
37823950 try writer.print(", {})", .{try f.fmtIntLiteral(shift_val)});
37833951 },
37843952 }
3785
3786 if (needs_lo) try writer.writeByte(')');
3787 try writer.writeAll(";\n");
3953 if (need_lo) try writer.writeByte(')');
3954 try a.end(f, writer);
37883955 try v.end(f, inst, writer);
3789
37903956 return local;
37913957}
37923958
......@@ -3797,7 +3963,7 @@ fn airIntFromBool(f: *Function, inst: Air.Inst.Index) !CValue {
37973963 const writer = f.object.writer();
37983964 const inst_ty = f.typeOfIndex(inst);
37993965 const local = try f.allocLocal(inst, inst_ty);
3800 const a = try Assignment.start(f, writer, inst_ty);
3966 const a = try Assignment.start(f, writer, try f.ctypeFromType(inst_ty, .complete));
38013967 try f.writeCValue(writer, local, .Other);
38023968 try a.assign(f, writer);
38033969 try f.writeCValue(writer, operand, .Other);
......@@ -3842,9 +4008,8 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
38424008 const src_val = try f.resolveInst(bin_op.rhs);
38434009 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
38444010
4011 const src_scalar_ctype = try f.ctypeFromType(src_ty.scalarType(zcu), .complete);
38454012 const writer = f.object.writer();
3846 const v = try Vectorize.start(f, inst, writer, ptr_ty);
3847
38484013 if (need_memcpy) {
38494014 // For this memcpy to safely work we need the rhs to have the same
38504015 // underlying type as the lhs (i.e. they must both be arrays of the same underlying type).
......@@ -3863,6 +4028,7 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
38634028 break :blk new_local;
38644029 } else src_val;
38654030
4031 const v = try Vectorize.start(f, inst, writer, ptr_ty);
38664032 try writer.writeAll("memcpy((char *)");
38674033 try f.writeCValue(writer, ptr_val, .FunctionArgument);
38684034 try v.elem(f, writer);
......@@ -3873,9 +4039,9 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
38734039 try writer.writeAll(", sizeof(");
38744040 try f.renderType(writer, src_ty);
38754041 try writer.writeAll("))");
3876 if (src_val == .constant) {
3877 try freeLocal(f, inst, array_src.new_local, null);
3878 }
4042 try f.freeCValue(inst, array_src);
4043 try writer.writeAll(";\n");
4044 try v.end(f, inst, writer);
38794045 } else if (ptr_info.packed_offset.host_size > 0 and ptr_info.flags.vector_index == .none) {
38804046 const host_bits = ptr_info.packed_offset.host_size * 8;
38814047 const host_ty = try zcu.intType(.unsigned, host_bits);
......@@ -3898,9 +4064,12 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
38984064
38994065 const mask_val = try zcu.intValue_big(host_ty, mask.toConst());
39004066
4067 const v = try Vectorize.start(f, inst, writer, ptr_ty);
4068 const a = try Assignment.start(f, writer, src_scalar_ctype);
39014069 try f.writeCValueDeref(writer, ptr_val);
39024070 try v.elem(f, writer);
3903 try writer.writeAll(" = zig_or_");
4071 try a.assign(f, writer);
4072 try writer.writeAll("zig_or_");
39044073 try f.object.dg.renderTypeForBuiltinFnName(writer, host_ty);
39054074 try writer.writeAll("(zig_and_");
39064075 try f.object.dg.renderTypeForBuiltinFnName(writer, host_ty);
......@@ -3931,16 +4100,27 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
39314100 try v.elem(f, writer);
39324101 if (cant_cast) try writer.writeByte(')');
39334102 try writer.print(", {}))", .{try f.fmtIntLiteral(bit_offset_val)});
4103 try a.end(f, writer);
4104 try v.end(f, inst, writer);
39344105 } else {
4106 switch (ptr_val) {
4107 .local_ref => |ptr_local_index| switch (src_val) {
4108 .new_local, .local => |src_local_index| if (ptr_local_index == src_local_index)
4109 return .none,
4110 else => {},
4111 },
4112 else => {},
4113 }
4114 const v = try Vectorize.start(f, inst, writer, ptr_ty);
4115 const a = try Assignment.start(f, writer, src_scalar_ctype);
39354116 try f.writeCValueDeref(writer, ptr_val);
39364117 try v.elem(f, writer);
3937 try writer.writeAll(" = ");
4118 try a.assign(f, writer);
39384119 try f.writeCValue(writer, src_val, .Other);
39394120 try v.elem(f, writer);
4121 try a.end(f, writer);
4122 try v.end(f, inst, writer);
39404123 }
3941 try writer.writeAll(";\n");
3942 try v.end(f, inst, writer);
3943
39444124 return .none;
39454125}
39464126
......@@ -4103,6 +4283,7 @@ fn airEquality(
41034283 operator: std.math.CompareOperator,
41044284) !CValue {
41054285 const zcu = f.object.dg.zcu;
4286 const ctype_pool = &f.object.dg.ctype_pool;
41064287 const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
41074288
41084289 const operand_ty = f.typeOf(bin_op.lhs);
......@@ -4124,28 +4305,47 @@ fn airEquality(
41244305 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
41254306
41264307 const writer = f.object.writer();
4127 const inst_ty = f.typeOfIndex(inst);
4128 const local = try f.allocLocal(inst, inst_ty);
4129 const a = try Assignment.start(f, writer, inst_ty);
4308 const local = try f.allocLocal(inst, Type.bool);
4309 const a = try Assignment.start(f, writer, CType.bool);
41304310 try f.writeCValue(writer, local, .Other);
41314311 try a.assign(f, writer);
41324312
4133 if (operand_ty.zigTypeTag(zcu) == .Optional and !operand_ty.optionalReprIsPayload(zcu)) {
4134 try f.writeCValueMember(writer, lhs, .{ .identifier = "is_null" });
4135 try writer.writeAll(" || ");
4136 try f.writeCValueMember(writer, rhs, .{ .identifier = "is_null" });
4137 try writer.writeAll(" ? ");
4138 try f.writeCValueMember(writer, lhs, .{ .identifier = "is_null" });
4139 try writer.writeAll(compareOperatorC(operator));
4140 try f.writeCValueMember(writer, rhs, .{ .identifier = "is_null" });
4141 try writer.writeAll(" : ");
4142 try f.writeCValueMember(writer, lhs, .{ .identifier = "payload" });
4143 try writer.writeAll(compareOperatorC(operator));
4144 try f.writeCValueMember(writer, rhs, .{ .identifier = "payload" });
4145 } else {
4146 try f.writeCValue(writer, lhs, .Other);
4147 try writer.writeAll(compareOperatorC(operator));
4148 try f.writeCValue(writer, rhs, .Other);
4313 const operand_ctype = try f.ctypeFromType(operand_ty, .complete);
4314 switch (operand_ctype.info(ctype_pool)) {
4315 .basic, .pointer => {
4316 try f.writeCValue(writer, lhs, .Other);
4317 try writer.writeAll(compareOperatorC(operator));
4318 try f.writeCValue(writer, rhs, .Other);
4319 },
4320 .aligned, .array, .vector, .fwd_decl, .function => unreachable,
4321 .aggregate => |aggregate| if (aggregate.fields.len == 2 and
4322 (aggregate.fields.at(0, ctype_pool).name.index == .is_null or
4323 aggregate.fields.at(1, ctype_pool).name.index == .is_null))
4324 {
4325 try f.writeCValueMember(writer, lhs, .{ .identifier = "is_null" });
4326 try writer.writeAll(" || ");
4327 try f.writeCValueMember(writer, rhs, .{ .identifier = "is_null" });
4328 try writer.writeAll(" ? ");
4329 try f.writeCValueMember(writer, lhs, .{ .identifier = "is_null" });
4330 try writer.writeAll(compareOperatorC(operator));
4331 try f.writeCValueMember(writer, rhs, .{ .identifier = "is_null" });
4332 try writer.writeAll(" : ");
4333 try f.writeCValueMember(writer, lhs, .{ .identifier = "payload" });
4334 try writer.writeAll(compareOperatorC(operator));
4335 try f.writeCValueMember(writer, rhs, .{ .identifier = "payload" });
4336 } else for (0..aggregate.fields.len) |field_index| {
4337 if (field_index > 0) try writer.writeAll(switch (operator) {
4338 .lt, .lte, .gte, .gt => unreachable,
4339 .eq => " && ",
4340 .neq => " || ",
4341 });
4342 const field_name: CValue = .{
4343 .ctype_pool_string = aggregate.fields.at(field_index, ctype_pool).name,
4344 };
4345 try f.writeCValueMember(writer, lhs, field_name);
4346 try writer.writeAll(compareOperatorC(operator));
4347 try f.writeCValueMember(writer, rhs, field_name);
4348 },
41494349 }
41504350 try a.end(f, writer);
41514351
......@@ -4155,12 +4355,11 @@ fn airEquality(
41554355fn airCmpLtErrorsLen(f: *Function, inst: Air.Inst.Index) !CValue {
41564356 const un_op = f.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
41574357
4158 const inst_ty = f.typeOfIndex(inst);
41594358 const operand = try f.resolveInst(un_op);
41604359 try reap(f, inst, &.{un_op});
41614360
41624361 const writer = f.object.writer();
4163 const local = try f.allocLocal(inst, inst_ty);
4362 const local = try f.allocLocal(inst, Type.bool);
41644363 try f.writeCValue(writer, local, .Other);
41654364 try writer.writeAll(" = ");
41664365 try f.writeCValue(writer, operand, .Other);
......@@ -4180,39 +4379,34 @@ fn airPtrAddSub(f: *Function, inst: Air.Inst.Index, operator: u8) !CValue {
41804379 const inst_ty = f.typeOfIndex(inst);
41814380 const inst_scalar_ty = inst_ty.scalarType(zcu);
41824381 const elem_ty = inst_scalar_ty.elemType2(zcu);
4382 if (!elem_ty.hasRuntimeBitsIgnoreComptime(zcu)) return f.moveCValue(inst, inst_ty, lhs);
4383 const inst_scalar_ctype = try f.ctypeFromType(inst_scalar_ty, .complete);
41834384
41844385 const local = try f.allocLocal(inst, inst_ty);
41854386 const writer = f.object.writer();
41864387 const v = try Vectorize.start(f, inst, writer, inst_ty);
4388 const a = try Assignment.start(f, writer, inst_scalar_ctype);
41874389 try f.writeCValue(writer, local, .Other);
41884390 try v.elem(f, writer);
4189 try writer.writeAll(" = ");
4190
4191 if (elem_ty.hasRuntimeBitsIgnoreComptime(zcu)) {
4192 // We must convert to and from integer types to prevent UB if the operation
4193 // results in a NULL pointer, or if LHS is NULL. The operation is only UB
4194 // if the result is NULL and then dereferenced.
4195 try writer.writeByte('(');
4196 try f.renderType(writer, inst_scalar_ty);
4197 try writer.writeAll(")(((uintptr_t)");
4198 try f.writeCValue(writer, lhs, .Other);
4199 try v.elem(f, writer);
4200 try writer.writeAll(") ");
4201 try writer.writeByte(operator);
4202 try writer.writeAll(" (");
4203 try f.writeCValue(writer, rhs, .Other);
4204 try v.elem(f, writer);
4205 try writer.writeAll("*sizeof(");
4206 try f.renderType(writer, elem_ty);
4207 try writer.writeAll(")))");
4208 } else {
4209 try f.writeCValue(writer, lhs, .Other);
4210 try v.elem(f, writer);
4211 }
4212
4213 try writer.writeAll(";\n");
4391 try a.assign(f, writer);
4392 // We must convert to and from integer types to prevent UB if the operation
4393 // results in a NULL pointer, or if LHS is NULL. The operation is only UB
4394 // if the result is NULL and then dereferenced.
4395 try writer.writeByte('(');
4396 try f.renderCType(writer, inst_scalar_ctype);
4397 try writer.writeAll(")(((uintptr_t)");
4398 try f.writeCValue(writer, lhs, .Other);
4399 try v.elem(f, writer);
4400 try writer.writeAll(") ");
4401 try writer.writeByte(operator);
4402 try writer.writeAll(" (");
4403 try f.writeCValue(writer, rhs, .Other);
4404 try v.elem(f, writer);
4405 try writer.writeAll("*sizeof(");
4406 try f.renderType(writer, elem_ty);
4407 try writer.writeAll(")))");
4408 try a.end(f, writer);
42144409 try v.end(f, inst, writer);
4215
42164410 return local;
42174411}
42184412
......@@ -4273,14 +4467,14 @@ fn airSlice(f: *Function, inst: Air.Inst.Index) !CValue {
42734467 const writer = f.object.writer();
42744468 const local = try f.allocLocal(inst, inst_ty);
42754469 {
4276 const a = try Assignment.start(f, writer, ptr_ty);
4470 const a = try Assignment.start(f, writer, try f.ctypeFromType(ptr_ty, .complete));
42774471 try f.writeCValueMember(writer, local, .{ .identifier = "ptr" });
42784472 try a.assign(f, writer);
42794473 try f.writeCValue(writer, ptr, .Other);
42804474 try a.end(f, writer);
42814475 }
42824476 {
4283 const a = try Assignment.start(f, writer, Type.usize);
4477 const a = try Assignment.start(f, writer, CType.usize);
42844478 try f.writeCValueMember(writer, local, .{ .identifier = "len" });
42854479 try a.assign(f, writer);
42864480 try f.writeCValue(writer, len, .Initializer);
......@@ -4347,7 +4541,7 @@ fn airCall(
43474541 }).?;
43484542 const ret_ty = Type.fromInterned(fn_info.return_type);
43494543 const ret_ctype: CType = if (ret_ty.isNoReturn(zcu))
4350 .{ .index = .void }
4544 CType.void
43514545 else
43524546 try f.ctypeFromType(ret_ty, .parameter);
43534547
......@@ -4359,7 +4553,7 @@ fn airCall(
43594553 break :result .none;
43604554 } else if (f.liveness.isUnused(inst)) {
43614555 try writer.writeByte('(');
4362 try f.renderCType(writer, .{ .index = .void });
4556 try f.renderCType(writer, CType.void);
43634557 try writer.writeByte(')');
43644558 break :result .none;
43654559 } else {
......@@ -4414,10 +4608,7 @@ fn airCall(
44144608 if (need_comma) try writer.writeAll(", ");
44154609 need_comma = true;
44164610 try f.writeCValue(writer, resolved_arg, .FunctionArgument);
4417 switch (resolved_arg) {
4418 .new_local => |local| try freeLocal(f, inst, local, null),
4419 else => {},
4420 }
4611 try f.freeCValue(inst, resolved_arg);
44214612 }
44224613 try writer.writeAll(");\n");
44234614
......@@ -4601,7 +4792,7 @@ fn lowerTry(
46014792 }
46024793
46034794 const local = try f.allocLocal(inst, inst_ty);
4604 const a = try Assignment.start(f, writer, inst_ty);
4795 const a = try Assignment.start(f, writer, try f.ctypeFromType(inst_ty, .complete));
46054796 try f.writeCValue(writer, local, .Other);
46064797 try a.assign(f, writer);
46074798 if (is_ptr) {
......@@ -4624,7 +4815,7 @@ fn airBr(f: *Function, inst: Air.Inst.Index) !CValue {
46244815 const operand = try f.resolveInst(branch.operand);
46254816 try reap(f, inst, &.{branch.operand});
46264817
4627 const a = try Assignment.start(f, writer, operand_ty);
4818 const a = try Assignment.start(f, writer, try f.ctypeFromType(operand_ty, .complete));
46284819 try f.writeCValue(writer, result, .Other);
46294820 try a.assign(f, writer);
46304821 try f.writeCValue(writer, operand, .Other);
......@@ -4637,53 +4828,17 @@ fn airBr(f: *Function, inst: Air.Inst.Index) !CValue {
46374828
46384829fn airBitcast(f: *Function, inst: Air.Inst.Index) !CValue {
46394830 const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
4640 const dest_ty = f.typeOfIndex(inst);
4831 const inst_ty = f.typeOfIndex(inst);
46414832
46424833 const operand = try f.resolveInst(ty_op.operand);
46434834 const operand_ty = f.typeOf(ty_op.operand);
46444835
4645 const bitcasted = try bitcast(f, dest_ty, operand, operand_ty);
4836 const bitcasted = try bitcast(f, inst_ty, operand, operand_ty);
46464837 try reap(f, inst, &.{ty_op.operand});
4647 return bitcasted.move(f, inst, dest_ty);
4838 return f.moveCValue(inst, inst_ty, bitcasted);
46484839}
46494840
4650const LocalResult = struct {
4651 c_value: CValue,
4652 need_free: bool,
4653
4654 fn move(lr: LocalResult, f: *Function, inst: Air.Inst.Index, dest_ty: Type) !CValue {
4655 const zcu = f.object.dg.zcu;
4656
4657 if (lr.need_free) {
4658 // Move the freshly allocated local to be owned by this instruction,
4659 // by returning it here instead of freeing it.
4660 return lr.c_value;
4661 }
4662
4663 const local = try f.allocLocal(inst, dest_ty);
4664 try lr.free(f);
4665 const writer = f.object.writer();
4666 try f.writeCValue(writer, local, .Other);
4667 if (dest_ty.isAbiInt(zcu)) {
4668 try writer.writeAll(" = ");
4669 } else {
4670 try writer.writeAll(" = (");
4671 try f.renderType(writer, dest_ty);
4672 try writer.writeByte(')');
4673 }
4674 try f.writeCValue(writer, lr.c_value, .Initializer);
4675 try writer.writeAll(";\n");
4676 return local;
4677 }
4678
4679 fn free(lr: LocalResult, f: *Function) !void {
4680 if (lr.need_free) {
4681 try freeLocal(f, null, lr.c_value.new_local, null);
4682 }
4683 }
4684};
4685
4686fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !LocalResult {
4841fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !CValue {
46874842 const zcu = f.object.dg.zcu;
46884843 const target = &f.object.dg.mod.resolved_target.result;
46894844 const ctype_pool = &f.object.dg.ctype_pool;
......@@ -4693,13 +4848,7 @@ fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !Loca
46934848 const src_info = dest_ty.intInfo(zcu);
46944849 const dest_info = operand_ty.intInfo(zcu);
46954850 if (src_info.signedness == dest_info.signedness and
4696 src_info.bits == dest_info.bits)
4697 {
4698 return .{
4699 .c_value = operand,
4700 .need_free = false,
4701 };
4702 }
4851 src_info.bits == dest_info.bits) return operand;
47034852 }
47044853
47054854 if (dest_ty.isPtrAtRuntime(zcu) and operand_ty.isPtrAtRuntime(zcu)) {
......@@ -4710,10 +4859,7 @@ fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !Loca
47104859 try writer.writeByte(')');
47114860 try f.writeCValue(writer, operand, .Other);
47124861 try writer.writeAll(";\n");
4713 return .{
4714 .c_value = local,
4715 .need_free = true,
4716 };
4862 return local;
47174863 }
47184864
47194865 const operand_lval = if (operand == .constant) blk: {
......@@ -4800,14 +4946,8 @@ fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !Loca
48004946 try writer.writeAll(");\n");
48014947 }
48024948
4803 if (operand == .constant) {
4804 try freeLocal(f, null, operand_lval.new_local, null);
4805 }
4806
4807 return .{
4808 .c_value = local,
4809 .need_free = true,
4810 };
4949 try f.freeCValue(null, operand_lval);
4950 return local;
48114951}
48124952
48134953fn airTrap(f: *Function, writer: anytype) !CValue {
......@@ -4918,13 +5058,16 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index) !CValue {
49185058 const writer = f.object.writer();
49195059
49205060 try writer.writeAll("switch (");
4921 if (condition_ty.zigTypeTag(zcu) == .Bool) {
4922 try writer.writeByte('(');
4923 try f.renderType(writer, Type.u1);
4924 try writer.writeByte(')');
4925 } else if (condition_ty.isPtrAtRuntime(zcu)) {
5061
5062 const lowered_condition_ty = if (condition_ty.toIntern() == .bool_type)
5063 Type.u1
5064 else if (condition_ty.isPtrAtRuntime(zcu))
5065 Type.usize
5066 else
5067 condition_ty;
5068 if (condition_ty.toIntern() != lowered_condition_ty.toIntern()) {
49265069 try writer.writeByte('(');
4927 try f.renderType(writer, Type.usize);
5070 try f.renderType(writer, lowered_condition_ty);
49285071 try writer.writeByte(')');
49295072 }
49305073 try f.writeCValue(writer, condition, .Other);
......@@ -4943,18 +5086,24 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index) !CValue {
49435086 for (0..switch_br.data.cases_len) |case_i| {
49445087 const case = f.air.extraData(Air.SwitchBr.Case, extra_index);
49455088 const items = @as([]const Air.Inst.Ref, @ptrCast(f.air.extra[case.end..][0..case.data.items_len]));
4946 const case_body: []const Air.Inst.Index = @ptrCast(f.air.extra[case.end + items.len ..][0..case.data.body_len]);
5089 const case_body: []const Air.Inst.Index =
5090 @ptrCast(f.air.extra[case.end + items.len ..][0..case.data.body_len]);
49475091 extra_index = case.end + case.data.items_len + case_body.len;
49485092
49495093 for (items) |item| {
49505094 try f.object.indent_writer.insertNewline();
49515095 try writer.writeAll("case ");
4952 if (condition_ty.isPtrAtRuntime(zcu)) {
4953 try writer.writeByte('(');
4954 try f.renderType(writer, Type.usize);
4955 try writer.writeByte(')');
5096 const item_value = try f.air.value(item, zcu);
5097 if (item_value.?.getUnsignedInt(zcu)) |item_int| try writer.print("{}\n", .{
5098 try f.fmtIntLiteral(try zcu.intValue(lowered_condition_ty, item_int)),
5099 }) else {
5100 if (condition_ty.isPtrAtRuntime(zcu)) {
5101 try writer.writeByte('(');
5102 try f.renderType(writer, Type.usize);
5103 try writer.writeByte(')');
5104 }
5105 try f.object.dg.renderValue(writer, (try f.air.value(item, zcu)).?, .Other);
49565106 }
4957 try f.object.dg.renderValue(writer, (try f.air.value(item, zcu)).?, .Other);
49585107 try writer.writeByte(':');
49595108 }
49605109 try writer.writeByte(' ');
......@@ -5276,10 +5425,11 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
52765425fn airIsNull(
52775426 f: *Function,
52785427 inst: Air.Inst.Index,
5279 operator: []const u8,
5428 operator: std.math.CompareOperator,
52805429 is_ptr: bool,
52815430) !CValue {
52825431 const zcu = f.object.dg.zcu;
5432 const ctype_pool = &f.object.dg.ctype_pool;
52835433 const un_op = f.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
52845434
52855435 const writer = f.object.writer();
......@@ -5287,106 +5437,84 @@ fn airIsNull(
52875437 try reap(f, inst, &.{un_op});
52885438
52895439 const local = try f.allocLocal(inst, Type.bool);
5440 const a = try Assignment.start(f, writer, CType.bool);
52905441 try f.writeCValue(writer, local, .Other);
5291 try writer.writeAll(" = ");
5292 if (is_ptr) {
5293 try f.writeCValueDeref(writer, operand);
5294 } else {
5295 try f.writeCValue(writer, operand, .Other);
5296 }
5442 try a.assign(f, writer);
52975443
52985444 const operand_ty = f.typeOf(un_op);
52995445 const optional_ty = if (is_ptr) operand_ty.childType(zcu) else operand_ty;
5300 const payload_ty = optional_ty.optionalChild(zcu);
5301 const err_int_ty = try zcu.errorIntType();
5302
5303 const rhs = if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu))
5304 Value.true
5305 else if (optional_ty.isPtrLikeOptional(zcu))
5306 // operand is a regular pointer, test `operand !=/== NULL`
5307 try zcu.getCoerced(Value.null, optional_ty)
5308 else if (payload_ty.zigTypeTag(zcu) == .ErrorSet)
5309 try zcu.intValue(err_int_ty, 0)
5310 else if (payload_ty.isSlice(zcu) and optional_ty.optionalReprIsPayload(zcu)) rhs: {
5311 try writer.writeAll(".ptr");
5312 const slice_ptr_ty = payload_ty.slicePtrFieldType(zcu);
5313 const opt_slice_ptr_ty = try zcu.optionalType(slice_ptr_ty.toIntern());
5314 break :rhs try zcu.nullValue(opt_slice_ptr_ty);
5315 } else rhs: {
5316 try writer.writeAll(".is_null");
5317 break :rhs Value.true;
5446 const opt_ctype = try f.ctypeFromType(optional_ty, .complete);
5447 const rhs = switch (opt_ctype.info(ctype_pool)) {
5448 .basic, .pointer => rhs: {
5449 if (is_ptr)
5450 try f.writeCValueDeref(writer, operand)
5451 else
5452 try f.writeCValue(writer, operand, .Other);
5453 break :rhs if (opt_ctype.isBool())
5454 "true"
5455 else if (opt_ctype.isInteger())
5456 "0"
5457 else
5458 "NULL";
5459 },
5460 .aligned, .array, .vector, .fwd_decl, .function => unreachable,
5461 .aggregate => |aggregate| switch (aggregate.fields.at(0, ctype_pool).name.index) {
5462 .is_null, .payload => rhs: {
5463 if (is_ptr)
5464 try f.writeCValueDerefMember(writer, operand, .{ .identifier = "is_null" })
5465 else
5466 try f.writeCValueMember(writer, operand, .{ .identifier = "is_null" });
5467 break :rhs "true";
5468 },
5469 .ptr, .len => rhs: {
5470 if (is_ptr)
5471 try f.writeCValueDerefMember(writer, operand, .{ .identifier = "ptr" })
5472 else
5473 try f.writeCValueMember(writer, operand, .{ .identifier = "ptr" });
5474 break :rhs "NULL";
5475 },
5476 else => unreachable,
5477 },
53185478 };
5319 try writer.writeByte(' ');
5320 try writer.writeAll(operator);
5321 try writer.writeByte(' ');
5322 try f.object.dg.renderValue(writer, rhs, .Other);
5323 try writer.writeAll(";\n");
5324 return local;
5325}
5326
5327fn airOptionalPayload(f: *Function, inst: Air.Inst.Index) !CValue {
5328 const zcu = f.object.dg.zcu;
5329 const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
5330
5331 const operand = try f.resolveInst(ty_op.operand);
5332 try reap(f, inst, &.{ty_op.operand});
5333 const opt_ty = f.typeOf(ty_op.operand);
5334
5335 const payload_ty = opt_ty.optionalChild(zcu);
5336
5337 if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) {
5338 return .none;
5339 }
5340
5341 const inst_ty = f.typeOfIndex(inst);
5342 const writer = f.object.writer();
5343 const local = try f.allocLocal(inst, inst_ty);
5344
5345 if (opt_ty.optionalReprIsPayload(zcu)) {
5346 try f.writeCValue(writer, local, .Other);
5347 try writer.writeAll(" = ");
5348 try f.writeCValue(writer, operand, .Other);
5349 try writer.writeAll(";\n");
5350 return local;
5351 }
5352
5353 const a = try Assignment.start(f, writer, inst_ty);
5354 try f.writeCValue(writer, local, .Other);
5355 try a.assign(f, writer);
5356 try f.writeCValueMember(writer, operand, .{ .identifier = "payload" });
5479 try writer.writeAll(compareOperatorC(operator));
5480 try writer.writeAll(rhs);
53575481 try a.end(f, writer);
53585482 return local;
53595483}
53605484
5361fn airOptionalPayloadPtr(f: *Function, inst: Air.Inst.Index) !CValue {
5485fn airOptionalPayload(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValue {
53625486 const zcu = f.object.dg.zcu;
5487 const ctype_pool = &f.object.dg.ctype_pool;
53635488 const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
53645489
5365 const writer = f.object.writer();
5366 const operand = try f.resolveInst(ty_op.operand);
5367 try reap(f, inst, &.{ty_op.operand});
5368 const ptr_ty = f.typeOf(ty_op.operand);
5369 const opt_ty = ptr_ty.childType(zcu);
53705490 const inst_ty = f.typeOfIndex(inst);
5491 const operand_ty = f.typeOf(ty_op.operand);
5492 const opt_ty = if (is_ptr) operand_ty.childType(zcu) else operand_ty;
5493 const opt_ctype = try f.ctypeFromType(opt_ty, .complete);
5494 if (opt_ctype.isBool()) return if (is_ptr) .{ .undef = inst_ty } else .none;
53715495
5372 if (!inst_ty.childType(zcu).hasRuntimeBitsIgnoreComptime(zcu)) {
5373 return .{ .undef = inst_ty };
5374 }
5375
5376 const local = try f.allocLocal(inst, inst_ty);
5377 try f.writeCValue(writer, local, .Other);
5378
5379 if (opt_ty.optionalReprIsPayload(zcu)) {
5380 // the operand is just a regular pointer, no need to do anything special.
5381 // *?*T -> **T and ?*T -> *T are **T -> **T and *T -> *T in C
5382 try writer.writeAll(" = ");
5383 try f.writeCValue(writer, operand, .Other);
5384 } else {
5385 try writer.writeAll(" = &");
5386 try f.writeCValueDerefMember(writer, operand, .{ .identifier = "payload" });
5496 const operand = try f.resolveInst(ty_op.operand);
5497 switch (opt_ctype.info(ctype_pool)) {
5498 .basic, .pointer => return f.moveCValue(inst, inst_ty, operand),
5499 .aligned, .array, .vector, .fwd_decl, .function => unreachable,
5500 .aggregate => |aggregate| switch (aggregate.fields.at(0, ctype_pool).name.index) {
5501 .is_null, .payload => {
5502 const writer = f.object.writer();
5503 const local = try f.allocLocal(inst, inst_ty);
5504 const a = try Assignment.start(f, writer, try f.ctypeFromType(inst_ty, .complete));
5505 try f.writeCValue(writer, local, .Other);
5506 try a.assign(f, writer);
5507 if (is_ptr) {
5508 try writer.writeByte('&');
5509 try f.writeCValueDerefMember(writer, operand, .{ .identifier = "payload" });
5510 } else try f.writeCValueMember(writer, operand, .{ .identifier = "payload" });
5511 try a.end(f, writer);
5512 return local;
5513 },
5514 .ptr, .len => return f.moveCValue(inst, inst_ty, operand),
5515 else => unreachable,
5516 },
53875517 }
5388 try writer.writeAll(";\n");
5389 return local;
53905518}
53915519
53925520fn airOptionalPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue {
......@@ -5397,38 +5525,46 @@ fn airOptionalPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue {
53975525 try reap(f, inst, &.{ty_op.operand});
53985526 const operand_ty = f.typeOf(ty_op.operand);
53995527
5400 const opt_ty = operand_ty.childType(zcu);
5401
54025528 const inst_ty = f.typeOfIndex(inst);
5403
5404 if (opt_ty.optionalReprIsPayload(zcu)) {
5405 if (f.liveness.isUnused(inst)) {
5406 return .none;
5407 }
5408 const local = try f.allocLocal(inst, inst_ty);
5409 // The payload and the optional are the same value.
5410 // Setting to non-null will be done when the payload is set.
5411 try f.writeCValue(writer, local, .Other);
5412 try writer.writeAll(" = ");
5413 try f.writeCValue(writer, operand, .Other);
5414 try writer.writeAll(";\n");
5415 return local;
5416 } else {
5417 try f.writeCValueDeref(writer, operand);
5418 try writer.writeAll(".is_null = ");
5419 try f.object.dg.renderValue(writer, Value.false, .Initializer);
5420 try writer.writeAll(";\n");
5421
5422 if (f.liveness.isUnused(inst)) {
5529 const opt_ctype = try f.ctypeFromType(operand_ty.childType(zcu), .complete);
5530 switch (opt_ctype.info(&f.object.dg.ctype_pool)) {
5531 .basic => {
5532 const a = try Assignment.start(f, writer, opt_ctype);
5533 try f.writeCValueDeref(writer, operand);
5534 try a.assign(f, writer);
5535 try f.object.dg.renderValue(writer, Value.false, .Initializer);
5536 try a.end(f, writer);
54235537 return .none;
5424 }
5425
5426 const local = try f.allocLocal(inst, inst_ty);
5427 try f.writeCValue(writer, local, .Other);
5428 try writer.writeAll(" = &");
5429 try f.writeCValueDeref(writer, operand);
5430 try writer.writeAll(".payload;\n");
5431 return local;
5538 },
5539 .pointer => {
5540 if (f.liveness.isUnused(inst)) return .none;
5541 const local = try f.allocLocal(inst, inst_ty);
5542 const a = try Assignment.start(f, writer, opt_ctype);
5543 try f.writeCValue(writer, local, .Other);
5544 try a.assign(f, writer);
5545 try f.writeCValue(writer, operand, .Other);
5546 try a.end(f, writer);
5547 return local;
5548 },
5549 .aligned, .array, .vector, .fwd_decl, .function => unreachable,
5550 .aggregate => {
5551 {
5552 const a = try Assignment.start(f, writer, opt_ctype);
5553 try f.writeCValueDerefMember(writer, operand, .{ .identifier = "is_null" });
5554 try a.assign(f, writer);
5555 try f.object.dg.renderValue(writer, Value.false, .Initializer);
5556 try a.end(f, writer);
5557 }
5558 if (f.liveness.isUnused(inst)) return .none;
5559 const local = try f.allocLocal(inst, inst_ty);
5560 const a = try Assignment.start(f, writer, opt_ctype);
5561 try f.writeCValue(writer, local, .Other);
5562 try a.assign(f, writer);
5563 try writer.writeByte('&');
5564 try f.writeCValueDerefMember(writer, operand, .{ .identifier = "payload" });
5565 try a.end(f, writer);
5566 return local;
5567 },
54325568 }
54335569}
54345570
......@@ -5688,13 +5824,15 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {
56885824 if (inst_ty.eql(field_int_ty, f.object.dg.zcu)) return temp_local;
56895825
56905826 const local = try f.allocLocal(inst, inst_ty);
5691 try writer.writeAll("memcpy(");
5692 try f.writeCValue(writer, .{ .local_ref = local.new_local }, .FunctionArgument);
5693 try writer.writeAll(", ");
5694 try f.writeCValue(writer, .{ .local_ref = temp_local.new_local }, .FunctionArgument);
5695 try writer.writeAll(", sizeof(");
5696 try f.renderType(writer, inst_ty);
5697 try writer.writeAll("));\n");
5827 if (local.new_local != temp_local.new_local) {
5828 try writer.writeAll("memcpy(");
5829 try f.writeCValue(writer, .{ .local_ref = local.new_local }, .FunctionArgument);
5830 try writer.writeAll(", ");
5831 try f.writeCValue(writer, .{ .local_ref = temp_local.new_local }, .FunctionArgument);
5832 try writer.writeAll(", sizeof(");
5833 try f.renderType(writer, inst_ty);
5834 try writer.writeAll("));\n");
5835 }
56985836 try freeLocal(f, inst, temp_local.new_local, null);
56995837 return local;
57005838 },
......@@ -5723,20 +5861,23 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {
57235861 try writer.writeAll(";\n");
57245862 break :blk operand_local;
57255863 } else struct_byval;
5726
57275864 const local = try f.allocLocal(inst, inst_ty);
5728 try writer.writeAll("memcpy(&");
5729 try f.writeCValue(writer, local, .Other);
5730 try writer.writeAll(", &");
5731 try f.writeCValue(writer, operand_lval, .Other);
5732 try writer.writeAll(", sizeof(");
5733 try f.renderType(writer, inst_ty);
5734 try writer.writeAll("));\n");
5735
5736 if (struct_byval == .constant) {
5737 try freeLocal(f, inst, operand_lval.new_local, null);
5865 if (switch (local) {
5866 .new_local, .local => |local_index| switch (operand_lval) {
5867 .new_local, .local => |operand_local_index| local_index != operand_local_index,
5868 else => true,
5869 },
5870 else => true,
5871 }) {
5872 try writer.writeAll("memcpy(&");
5873 try f.writeCValue(writer, local, .Other);
5874 try writer.writeAll(", &");
5875 try f.writeCValue(writer, operand_lval, .Other);
5876 try writer.writeAll(", sizeof(");
5877 try f.renderType(writer, inst_ty);
5878 try writer.writeAll("));\n");
57385879 }
5739
5880 try f.freeCValue(inst, operand_lval);
57405881 return local;
57415882 },
57425883 }
......@@ -5745,7 +5886,7 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {
57455886 };
57465887
57475888 const local = try f.allocLocal(inst, inst_ty);
5748 const a = try Assignment.start(f, writer, inst_ty);
5889 const a = try Assignment.start(f, writer, try f.ctypeFromType(inst_ty, .complete));
57495890 try f.writeCValue(writer, local, .Other);
57505891 try a.assign(f, writer);
57515892 try f.writeCValueMember(writer, struct_byval, field_name);
......@@ -5818,7 +5959,7 @@ fn airUnwrapErrUnionPay(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValu
58185959 }
58195960
58205961 const local = try f.allocLocal(inst, inst_ty);
5821 const a = try Assignment.start(f, writer, inst_ty);
5962 const a = try Assignment.start(f, writer, try f.ctypeFromType(inst_ty, .complete));
58225963 try f.writeCValue(writer, local, .Other);
58235964 try a.assign(f, writer);
58245965 if (is_ptr) {
......@@ -5830,35 +5971,42 @@ fn airUnwrapErrUnionPay(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValu
58305971}
58315972
58325973fn airWrapOptional(f: *Function, inst: Air.Inst.Index) !CValue {
5833 const zcu = f.object.dg.zcu;
5974 const ctype_pool = &f.object.dg.ctype_pool;
58345975 const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
58355976
58365977 const inst_ty = f.typeOfIndex(inst);
5837 const repr_is_payload = inst_ty.optionalReprIsPayload(zcu);
5838 const payload_ty = f.typeOf(ty_op.operand);
5839 const payload = try f.resolveInst(ty_op.operand);
5840 try reap(f, inst, &.{ty_op.operand});
5978 const inst_ctype = try f.ctypeFromType(inst_ty, .complete);
5979 if (inst_ctype.isBool()) return .{ .constant = Value.true };
58415980
5842 const writer = f.object.writer();
5843 const local = try f.allocLocal(inst, inst_ty);
5844 {
5845 const a = try Assignment.start(f, writer, payload_ty);
5846 if (repr_is_payload)
5847 try f.writeCValue(writer, local, .Other)
5848 else
5849 try f.writeCValueMember(writer, local, .{ .identifier = "payload" });
5850 try a.assign(f, writer);
5851 try f.writeCValue(writer, payload, .Other);
5852 try a.end(f, writer);
5853 }
5854 if (!repr_is_payload) {
5855 const a = try Assignment.start(f, writer, Type.bool);
5856 try f.writeCValueMember(writer, local, .{ .identifier = "is_null" });
5857 try a.assign(f, writer);
5858 try f.object.dg.renderValue(writer, Value.false, .Other);
5859 try a.end(f, writer);
5981 const operand = try f.resolveInst(ty_op.operand);
5982 switch (inst_ctype.info(ctype_pool)) {
5983 .basic, .pointer => return f.moveCValue(inst, inst_ty, operand),
5984 .aligned, .array, .vector, .fwd_decl, .function => unreachable,
5985 .aggregate => |aggregate| switch (aggregate.fields.at(0, ctype_pool).name.index) {
5986 .is_null, .payload => {
5987 const operand_ctype = try f.ctypeFromType(f.typeOf(ty_op.operand), .complete);
5988 const writer = f.object.writer();
5989 const local = try f.allocLocal(inst, inst_ty);
5990 {
5991 const a = try Assignment.start(f, writer, CType.bool);
5992 try f.writeCValueMember(writer, local, .{ .identifier = "is_null" });
5993 try a.assign(f, writer);
5994 try writer.writeAll("false");
5995 try a.end(f, writer);
5996 }
5997 {
5998 const a = try Assignment.start(f, writer, operand_ctype);
5999 try f.writeCValueMember(writer, local, .{ .identifier = "payload" });
6000 try a.assign(f, writer);
6001 try f.writeCValue(writer, operand, .Initializer);
6002 try a.end(f, writer);
6003 }
6004 return local;
6005 },
6006 .ptr, .len => return f.moveCValue(inst, inst_ty, operand),
6007 else => unreachable,
6008 },
58606009 }
5861 return local;
58626010}
58636011
58646012fn airWrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue {
......@@ -5881,14 +6029,14 @@ fn airWrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue {
58816029 }
58826030
58836031 if (!repr_is_err) {
5884 const a = try Assignment.start(f, writer, payload_ty);
6032 const a = try Assignment.start(f, writer, try f.ctypeFromType(payload_ty, .complete));
58856033 try f.writeCValueMember(writer, local, .{ .identifier = "payload" });
58866034 try a.assign(f, writer);
58876035 try f.object.dg.renderUndefValue(writer, payload_ty, .Other);
58886036 try a.end(f, writer);
58896037 }
58906038 {
5891 const a = try Assignment.start(f, writer, err_ty);
6039 const a = try Assignment.start(f, writer, try f.ctypeFromType(err_ty, .complete));
58926040 if (repr_is_err)
58936041 try f.writeCValue(writer, local, .Other)
58946042 else
......@@ -5904,31 +6052,43 @@ fn airErrUnionPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue {
59046052 const zcu = f.object.dg.zcu;
59056053 const writer = f.object.writer();
59066054 const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
6055 const inst_ty = f.typeOfIndex(inst);
59076056 const operand = try f.resolveInst(ty_op.operand);
5908 const error_union_ty = f.typeOf(ty_op.operand).childType(zcu);
6057 const operand_ty = f.typeOf(ty_op.operand);
6058 const error_union_ty = operand_ty.childType(zcu);
59096059
59106060 const payload_ty = error_union_ty.errorUnionPayload(zcu);
59116061 const err_int_ty = try zcu.errorIntType();
59126062 const no_err = try zcu.intValue(err_int_ty, 0);
6063 try reap(f, inst, &.{ty_op.operand});
59136064
59146065 // First, set the non-error value.
59156066 if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) {
6067 const a = try Assignment.start(f, writer, try f.ctypeFromType(operand_ty, .complete));
59166068 try f.writeCValueDeref(writer, operand);
5917 try writer.print(" = {};\n", .{try f.fmtIntLiteral(no_err)});
5918 return operand;
6069 try a.assign(f, writer);
6070 try writer.print("{}", .{try f.fmtIntLiteral(no_err)});
6071 try a.end(f, writer);
6072 return .none;
6073 }
6074 {
6075 const a = try Assignment.start(f, writer, try f.ctypeFromType(err_int_ty, .complete));
6076 try f.writeCValueDerefMember(writer, operand, .{ .identifier = "error" });
6077 try a.assign(f, writer);
6078 try writer.print("{}", .{try f.fmtIntLiteral(no_err)});
6079 try a.end(f, writer);
59196080 }
5920 try reap(f, inst, &.{ty_op.operand});
5921 try f.writeCValueDeref(writer, operand);
5922 try writer.print(".error = {};\n", .{try f.fmtIntLiteral(no_err)});
59236081
59246082 // Then return the payload pointer (only if it is used)
59256083 if (f.liveness.isUnused(inst)) return .none;
59266084
5927 const local = try f.allocLocal(inst, f.typeOfIndex(inst));
6085 const local = try f.allocLocal(inst, inst_ty);
6086 const a = try Assignment.start(f, writer, try f.ctypeFromType(inst_ty, .complete));
59286087 try f.writeCValue(writer, local, .Other);
5929 try writer.writeAll(" = &(");
5930 try f.writeCValueDeref(writer, operand);
5931 try writer.writeAll(").payload;\n");
6088 try a.assign(f, writer);
6089 try writer.writeByte('&');
6090 try f.writeCValueDerefMember(writer, operand, .{ .identifier = "payload" });
6091 try a.end(f, writer);
59326092 return local;
59336093}
59346094
......@@ -5961,14 +6121,14 @@ fn airWrapErrUnionPay(f: *Function, inst: Air.Inst.Index) !CValue {
59616121 const writer = f.object.writer();
59626122 const local = try f.allocLocal(inst, inst_ty);
59636123 if (!repr_is_err) {
5964 const a = try Assignment.start(f, writer, payload_ty);
6124 const a = try Assignment.start(f, writer, try f.ctypeFromType(payload_ty, .complete));
59656125 try f.writeCValueMember(writer, local, .{ .identifier = "payload" });
59666126 try a.assign(f, writer);
59676127 try f.writeCValue(writer, payload, .Other);
59686128 try a.end(f, writer);
59696129 }
59706130 {
5971 const a = try Assignment.start(f, writer, err_ty);
6131 const a = try Assignment.start(f, writer, try f.ctypeFromType(err_ty, .complete));
59726132 if (repr_is_err)
59736133 try f.writeCValue(writer, local, .Other)
59746134 else
......@@ -5993,7 +6153,7 @@ fn airIsErr(f: *Function, inst: Air.Inst.Index, is_ptr: bool, operator: []const
59936153 const payload_ty = err_union_ty.errorUnionPayload(zcu);
59946154 const error_ty = err_union_ty.errorUnionSet(zcu);
59956155
5996 const a = try Assignment.start(f, writer, Type.bool);
6156 const a = try Assignment.start(f, writer, CType.bool);
59976157 try f.writeCValue(writer, local, .Other);
59986158 try a.assign(f, writer);
59996159 const err_int_ty = try zcu.errorIntType();
......@@ -6030,7 +6190,7 @@ fn airArrayToSlice(f: *Function, inst: Air.Inst.Index) !CValue {
60306190 const array_ty = operand_ty.childType(zcu);
60316191
60326192 {
6033 const a = try Assignment.start(f, writer, ptr_ty);
6193 const a = try Assignment.start(f, writer, try f.ctypeFromType(ptr_ty, .complete));
60346194 try f.writeCValueMember(writer, local, .{ .identifier = "ptr" });
60356195 try a.assign(f, writer);
60366196 if (operand == .undef) {
......@@ -6056,7 +6216,7 @@ fn airArrayToSlice(f: *Function, inst: Air.Inst.Index) !CValue {
60566216 try a.end(f, writer);
60576217 }
60586218 {
6059 const a = try Assignment.start(f, writer, Type.usize);
6219 const a = try Assignment.start(f, writer, CType.usize);
60606220 try f.writeCValueMember(writer, local, .{ .identifier = "len" });
60616221 try a.assign(f, writer);
60626222 try writer.print("{}", .{
......@@ -6091,7 +6251,7 @@ fn airFloatCast(f: *Function, inst: Air.Inst.Index) !CValue {
60916251 const writer = f.object.writer();
60926252 const local = try f.allocLocal(inst, inst_ty);
60936253 const v = try Vectorize.start(f, inst, writer, operand_ty);
6094 const a = try Assignment.start(f, writer, scalar_ty);
6254 const a = try Assignment.start(f, writer, try f.ctypeFromType(scalar_ty, .complete));
60956255 try f.writeCValue(writer, local, .Other);
60966256 try v.elem(f, writer);
60976257 try a.assign(f, writer);
......@@ -6133,11 +6293,10 @@ fn airIntFromPtr(f: *Function, inst: Air.Inst.Index) !CValue {
61336293 try writer.writeAll(" = (");
61346294 try f.renderType(writer, inst_ty);
61356295 try writer.writeByte(')');
6136 if (operand_ty.isSlice(zcu)) {
6137 try f.writeCValueMember(writer, operand, .{ .identifier = "ptr" });
6138 } else {
6296 if (operand_ty.isSlice(zcu))
6297 try f.writeCValueMember(writer, operand, .{ .identifier = "ptr" })
6298 else
61396299 try f.writeCValue(writer, operand, .Other);
6140 }
61416300 try writer.writeAll(";\n");
61426301 return local;
61436302}
......@@ -6306,9 +6465,10 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue
63066465 const new_value = try f.resolveInst(extra.new_value);
63076466 const ptr_ty = f.typeOf(extra.ptr);
63086467 const ty = ptr_ty.childType(zcu);
6468 const ctype = try f.ctypeFromType(ty, .complete);
63096469
63106470 const writer = f.object.writer();
6311 const new_value_mat = try Materialize.start(f, inst, writer, ty, new_value);
6471 const new_value_mat = try Materialize.start(f, inst, ty, new_value);
63126472 try reap(f, inst, &.{ extra.ptr, extra.expected_value, extra.new_value });
63136473
63146474 const repr_ty = if (ty.isRuntimeFloat())
......@@ -6319,7 +6479,7 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue
63196479 const local = try f.allocLocal(inst, inst_ty);
63206480 if (inst_ty.isPtrLikeOptional(zcu)) {
63216481 {
6322 const a = try Assignment.start(f, writer, ty);
6482 const a = try Assignment.start(f, writer, ctype);
63236483 try f.writeCValue(writer, local, .Other);
63246484 try a.assign(f, writer);
63256485 try f.writeCValue(writer, expected_value, .Other);
......@@ -6349,7 +6509,7 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue
63496509 try writer.writeAll(") {\n");
63506510 f.object.indent_writer.pushIndent();
63516511 {
6352 const a = try Assignment.start(f, writer, ty);
6512 const a = try Assignment.start(f, writer, ctype);
63536513 try f.writeCValue(writer, local, .Other);
63546514 try a.assign(f, writer);
63556515 try writer.writeAll("NULL");
......@@ -6359,14 +6519,14 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue
63596519 try writer.writeAll("}\n");
63606520 } else {
63616521 {
6362 const a = try Assignment.start(f, writer, ty);
6522 const a = try Assignment.start(f, writer, ctype);
63636523 try f.writeCValueMember(writer, local, .{ .identifier = "payload" });
63646524 try a.assign(f, writer);
63656525 try f.writeCValue(writer, expected_value, .Other);
63666526 try a.end(f, writer);
63676527 }
63686528 {
6369 const a = try Assignment.start(f, writer, Type.bool);
6529 const a = try Assignment.start(f, writer, CType.bool);
63706530 try f.writeCValueMember(writer, local, .{ .identifier = "is_null" });
63716531 try a.assign(f, writer);
63726532 try writer.print("zig_cmpxchg_{s}((zig_atomic(", .{flavor});
......@@ -6412,7 +6572,7 @@ fn airAtomicRmw(f: *Function, inst: Air.Inst.Index) !CValue {
64126572 const operand = try f.resolveInst(extra.operand);
64136573
64146574 const writer = f.object.writer();
6415 const operand_mat = try Materialize.start(f, inst, writer, ty, operand);
6575 const operand_mat = try Materialize.start(f, inst, ty, operand);
64166576 try reap(f, inst, &.{ pl_op.operand, extra.operand });
64176577
64186578 const repr_bits = @as(u16, @intCast(ty.abiSize(zcu) * 8));
......@@ -6501,7 +6661,7 @@ fn airAtomicStore(f: *Function, inst: Air.Inst.Index, order: [*:0]const u8) !CVa
65016661 const element = try f.resolveInst(bin_op.rhs);
65026662
65036663 const writer = f.object.writer();
6504 const element_mat = try Materialize.start(f, inst, writer, ty, element);
6664 const element_mat = try Materialize.start(f, inst, ty, element);
65056665 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
65066666
65076667 const repr_ty = if (ty.isRuntimeFloat())
......@@ -6612,7 +6772,7 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
66126772 try f.writeCValue(writer, index, .Other);
66136773 try writer.writeAll(") ");
66146774
6615 const a = try Assignment.start(f, writer, elem_ty);
6775 const a = try Assignment.start(f, writer, try f.ctypeFromType(elem_ty, .complete));
66166776 try writer.writeAll("((");
66176777 try f.renderType(writer, elem_ptr_ty);
66186778 try writer.writeByte(')');
......@@ -6637,7 +6797,7 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
66376797 .Slice => {
66386798 try f.writeCValueMember(writer, dest_slice, .{ .identifier = "ptr" });
66396799 try writer.writeAll(", ");
6640 try f.writeCValue(writer, bitcasted.c_value, .FunctionArgument);
6800 try f.writeCValue(writer, bitcasted, .FunctionArgument);
66416801 try writer.writeAll(", ");
66426802 try f.writeCValueMember(writer, dest_slice, .{ .identifier = "len" });
66436803 try writer.writeAll(");\n");
......@@ -6648,12 +6808,12 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
66486808
66496809 try f.writeCValue(writer, dest_slice, .FunctionArgument);
66506810 try writer.writeAll(", ");
6651 try f.writeCValue(writer, bitcasted.c_value, .FunctionArgument);
6811 try f.writeCValue(writer, bitcasted, .FunctionArgument);
66526812 try writer.print(", {d});\n", .{len});
66536813 },
66546814 .Many, .C => unreachable,
66556815 }
6656 try bitcasted.free(f);
6816 try f.freeCValue(inst, bitcasted);
66576817 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
66586818 return .none;
66596819}
......@@ -6700,7 +6860,7 @@ fn airSetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue {
67006860 const tag_ty = union_ty.unionTagTypeSafety(zcu).?;
67016861
67026862 const writer = f.object.writer();
6703 const a = try Assignment.start(f, writer, tag_ty);
6863 const a = try Assignment.start(f, writer, try f.ctypeFromType(tag_ty, .complete));
67046864 try f.writeCValueDerefMember(writer, union_ptr, .{ .identifier = "tag" });
67056865 try a.assign(f, writer);
67066866 try f.writeCValue(writer, new_tag, .Other);
......@@ -6722,7 +6882,7 @@ fn airGetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue {
67226882 const inst_ty = f.typeOfIndex(inst);
67236883 const writer = f.object.writer();
67246884 const local = try f.allocLocal(inst, inst_ty);
6725 const a = try Assignment.start(f, writer, inst_ty);
6885 const a = try Assignment.start(f, writer, try f.ctypeFromType(inst_ty, .complete));
67266886 try f.writeCValue(writer, local, .Other);
67276887 try a.assign(f, writer);
67286888 try f.writeCValueMember(writer, operand, .{ .identifier = "tag" });
......@@ -6780,7 +6940,7 @@ fn airSplat(f: *Function, inst: Air.Inst.Index) !CValue {
67806940 const writer = f.object.writer();
67816941 const local = try f.allocLocal(inst, inst_ty);
67826942 const v = try Vectorize.start(f, inst, writer, inst_ty);
6783 const a = try Assignment.init(f, inst_scalar_ty);
6943 const a = try Assignment.start(f, writer, try f.ctypeFromType(inst_scalar_ty, .complete));
67846944 try f.writeCValue(writer, local, .Other);
67856945 try v.elem(f, writer);
67866946 try a.assign(f, writer);
......@@ -7033,7 +7193,9 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {
70337193 const local = try f.allocLocal(inst, inst_ty);
70347194 switch (ip.indexToKey(inst_ty.toIntern())) {
70357195 inline .array_type, .vector_type => |info, tag| {
7036 const a = try Assignment.init(f, Type.fromInterned(info.child));
7196 const a: Assignment = .{
7197 .ctype = try f.ctypeFromType(Type.fromInterned(info.child), .complete),
7198 };
70377199 for (resolved_elements, 0..) |element, i| {
70387200 try a.restart(f, writer);
70397201 try f.writeCValue(writer, local, .Other);
......@@ -7060,7 +7222,7 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {
70607222 const field_ty = Type.fromInterned(loaded_struct.field_types.get(ip)[field_index]);
70617223 if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue;
70627224
7063 const a = try Assignment.start(f, writer, field_ty);
7225 const a = try Assignment.start(f, writer, try f.ctypeFromType(field_ty, .complete));
70647226 try f.writeCValueMember(writer, local, if (loaded_struct.fieldName(ip, field_index).unwrap()) |field_name|
70657227 .{ .identifier = field_name.toSlice(ip) }
70667228 else
......@@ -7140,7 +7302,7 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {
71407302 const field_ty = Type.fromInterned(anon_struct_info.types.get(ip)[field_index]);
71417303 if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue;
71427304
7143 const a = try Assignment.start(f, writer, field_ty);
7305 const a = try Assignment.start(f, writer, try f.ctypeFromType(field_ty, .complete));
71447306 try f.writeCValueMember(writer, local, if (anon_struct_info.fieldName(ip, field_index).unwrap()) |field_name|
71457307 .{ .identifier = field_name.toSlice(ip) }
71467308 else
......@@ -7170,13 +7332,7 @@ fn airUnionInit(f: *Function, inst: Air.Inst.Index) !CValue {
71707332
71717333 const writer = f.object.writer();
71727334 const local = try f.allocLocal(inst, union_ty);
7173 if (loaded_union.getLayout(ip) == .@"packed") {
7174 try f.writeCValue(writer, local, .Other);
7175 try writer.writeAll(" = ");
7176 try f.writeCValue(writer, payload, .Initializer);
7177 try writer.writeAll(";\n");
7178 return local;
7179 }
7335 if (loaded_union.getLayout(ip) == .@"packed") return f.moveCValue(inst, union_ty, payload);
71807336
71817337 const field: CValue = if (union_ty.unionTagTypeSafety(zcu)) |tag_ty| field: {
71827338 const layout = union_ty.unionGetLayout(zcu);
......@@ -7184,7 +7340,7 @@ fn airUnionInit(f: *Function, inst: Air.Inst.Index) !CValue {
71847340 const field_index = tag_ty.enumFieldIndex(field_name, zcu).?;
71857341 const tag_val = try zcu.enumValueFieldIndex(tag_ty, field_index);
71867342
7187 const a = try Assignment.start(f, writer, tag_ty);
7343 const a = try Assignment.start(f, writer, try f.ctypeFromType(tag_ty, .complete));
71887344 try f.writeCValueMember(writer, local, .{ .identifier = "tag" });
71897345 try a.assign(f, writer);
71907346 try writer.print("{}", .{try f.fmtIntLiteral(try tag_val.intFromEnum(tag_ty, zcu))});
......@@ -7193,7 +7349,7 @@ fn airUnionInit(f: *Function, inst: Air.Inst.Index) !CValue {
71937349 break :field .{ .payload_identifier = field_name.toSlice(ip) };
71947350 } else .{ .identifier = field_name.toSlice(ip) };
71957351
7196 const a = try Assignment.start(f, writer, payload_ty);
7352 const a = try Assignment.start(f, writer, try f.ctypeFromType(payload_ty, .complete));
71977353 try f.writeCValueMember(writer, local, field);
71987354 try a.assign(f, writer);
71997355 try f.writeCValue(writer, payload, .Other);
......@@ -7648,11 +7804,13 @@ fn StringLiteral(comptime WriterType: type) type {
76487804 // MSVC throws C2078 if an array of size 65536 or greater is initialized with a string literal,
76497805 // regardless of the length of the string literal initializing it. Array initializer syntax is
76507806 // used instead.
7651 const max_string_initializer_len = 65535;
7807 // C99 only requires 4095.
7808 const max_string_initializer_len = @min(65535, 4095);
76527809
76537810 // MSVC has a length limit of 16380 per string literal (before concatenation)
7811 // C99 only requires 4095.
76547812 const max_char_len = 4;
7655 const max_literal_len = 16380 - max_char_len;
7813 const max_literal_len = @min(16380 - max_char_len, 4095);
76567814
76577815 return struct {
76587816 len: u64,
......@@ -7824,13 +7982,13 @@ fn formatIntLiteral(
78247982 } = switch (data.ctype.info(ctype_pool)) {
78257983 .basic => |basic_info| switch (basic_info) {
78267984 else => .{
7827 .ctype = .{ .index = .void },
7985 .ctype = CType.void,
78287986 .count = 1,
78297987 .endian = .little,
78307988 .homogeneous = true,
78317989 },
78327990 .zig_u128, .zig_i128 => .{
7833 .ctype = .{ .index = .uint64_t },
7991 .ctype = CType.u64,
78347992 .count = 2,
78357993 .endian = .big,
78367994 .homogeneous = false,
......@@ -7946,28 +8104,12 @@ fn formatIntLiteral(
79468104const Materialize = struct {
79478105 local: CValue,
79488106
7949 pub fn start(
7950 f: *Function,
7951 inst: Air.Inst.Index,
7952 writer: anytype,
7953 ty: Type,
7954 value: CValue,
7955 ) !Materialize {
7956 switch (value) {
7957 .local_ref, .constant, .decl_ref, .undef => {
7958 const local = try f.allocLocal(inst, ty);
7959
7960 const a = try Assignment.start(f, writer, ty);
7961 try f.writeCValue(writer, local, .Other);
7962 try a.assign(f, writer);
7963 try f.writeCValue(writer, value, .Other);
7964 try a.end(f, writer);
7965
7966 return .{ .local = local };
7967 },
7968 .new_local => |local| return .{ .local = .{ .local = local } },
7969 else => return .{ .local = value },
7970 }
8107 pub fn start(f: *Function, inst: Air.Inst.Index, ty: Type, value: CValue) !Materialize {
8108 return .{ .local = switch (value) {
8109 .local_ref, .constant, .decl_ref, .undef => try f.moveCValue(inst, ty, value),
8110 .new_local => |local| .{ .local = local },
8111 else => value,
8112 } };
79718113 }
79728114
79738115 pub fn mat(self: Materialize, f: *Function, writer: anytype) !void {
......@@ -7975,22 +8117,15 @@ const Materialize = struct {
79758117 }
79768118
79778119 pub fn end(self: Materialize, f: *Function, inst: Air.Inst.Index) !void {
7978 switch (self.local) {
7979 .new_local => |local| try freeLocal(f, inst, local, null),
7980 else => {},
7981 }
8120 try f.freeCValue(inst, self.local);
79828121 }
79838122};
79848123
79858124const Assignment = struct {
79868125 ctype: CType,
79878126
7988 pub fn init(f: *Function, ty: Type) !Assignment {
7989 return .{ .ctype = try f.ctypeFromType(ty, .complete) };
7990 }
7991
7992 pub fn start(f: *Function, writer: anytype, ty: Type) !Assignment {
7993 const self = try init(f, ty);
8127 pub fn start(f: *Function, writer: anytype, ctype: CType) !Assignment {
8128 const self: Assignment = .{ .ctype = ctype };
79948129 try self.restart(f, writer);
79958130 return self;
79968131 }
src/codegen/c/Type.zig+213-115
......@@ -1,13 +1,33 @@
11index: CType.Index,
22
3pub const @"void": CType = .{ .index = .void };
4pub const @"bool": CType = .{ .index = .bool };
5pub const @"i8": CType = .{ .index = .int8_t };
6pub const @"u8": CType = .{ .index = .uint8_t };
7pub const @"i16": CType = .{ .index = .int16_t };
8pub const @"u16": CType = .{ .index = .uint16_t };
9pub const @"i32": CType = .{ .index = .int32_t };
10pub const @"u32": CType = .{ .index = .uint32_t };
11pub const @"i64": CType = .{ .index = .int64_t };
12pub const @"u64": CType = .{ .index = .uint64_t };
13pub const @"i128": CType = .{ .index = .zig_i128 };
14pub const @"u128": CType = .{ .index = .zig_u128 };
15pub const @"isize": CType = .{ .index = .intptr_t };
16pub const @"usize": CType = .{ .index = .uintptr_t };
17pub const @"f16": CType = .{ .index = .zig_f16 };
18pub const @"f32": CType = .{ .index = .zig_f32 };
19pub const @"f64": CType = .{ .index = .zig_f64 };
20pub const @"f80": CType = .{ .index = .zig_f80 };
21pub const @"f128": CType = .{ .index = .zig_f128 };
22
323pub fn fromPoolIndex(pool_index: usize) CType {
424 return .{ .index = @enumFromInt(CType.Index.first_pool_index + pool_index) };
525}
626
727pub fn toPoolIndex(ctype: CType) ?u32 {
8 const pool_index, const is_basic =
28 const pool_index, const is_null =
929 @subWithOverflow(@intFromEnum(ctype.index), CType.Index.first_pool_index);
10 return switch (is_basic) {
30 return switch (is_null) {
1131 0 => pool_index,
1232 1 => null,
1333 };
......@@ -710,20 +730,6 @@ pub const Kind = enum {
710730 }
711731};
712732
713pub const String = struct {
714 index: String.Index,
715
716 const Index = enum(u32) {
717 _,
718 };
719
720 pub fn slice(string: String, pool: *const Pool) []const u8 {
721 const start = pool.string_indices.items[@intFromEnum(string.index)];
722 const end = pool.string_indices.items[@intFromEnum(string.index) + 1];
723 return pool.string_bytes.items[start..end];
724 }
725};
726
727733pub const Info = union(enum) {
728734 basic: CType.Index,
729735 pointer: Pointer,
......@@ -766,7 +772,7 @@ pub const Info = union(enum) {
766772 pub const AggregateTag = enum { @"enum", @"struct", @"union" };
767773
768774 pub const Field = struct {
769 name: String,
775 name: Pool.String,
770776 ctype: CType,
771777 alignas: AlignAs,
772778
......@@ -812,12 +818,15 @@ pub const Info = union(enum) {
812818 rhs_pool: *const Pool,
813819 pool_adapter: anytype,
814820 ) bool {
815 return std.meta.eql(lhs_field.alignas, rhs_field.alignas) and
816 pool_adapter.eql(lhs_field.ctype, rhs_field.ctype) and std.mem.eql(
817 u8,
818 lhs_field.name.slice(lhs_pool),
819 rhs_field.name.slice(rhs_pool),
820 );
821 if (!std.meta.eql(lhs_field.alignas, rhs_field.alignas)) return false;
822 if (!pool_adapter.eql(lhs_field.ctype, rhs_field.ctype)) return false;
823 return if (lhs_field.name.toPoolSlice(lhs_pool)) |lhs_name|
824 if (rhs_field.name.toPoolSlice(rhs_pool)) |rhs_name|
825 std.mem.eql(u8, lhs_name, rhs_name)
826 else
827 false
828 else
829 lhs_field.name.index == rhs_field.name.index;
821830 }
822831 };
823832
......@@ -918,6 +927,86 @@ pub const Pool = struct {
918927
919928 const Map = std.AutoArrayHashMapUnmanaged(void, void);
920929
930 pub const String = struct {
931 index: String.Index,
932
933 const FormatData = struct { string: String, pool: *const Pool };
934 fn format(
935 data: FormatData,
936 comptime fmt_str: []const u8,
937 _: std.fmt.FormatOptions,
938 writer: anytype,
939 ) @TypeOf(writer).Error!void {
940 if (fmt_str.len > 0) @compileError("invalid format string '" ++ fmt_str ++ "'");
941 if (data.string.toSlice(data.pool)) |slice|
942 try writer.writeAll(slice)
943 else
944 try writer.print("f{d}", .{@intFromEnum(data.string.index)});
945 }
946 pub fn fmt(str: String, pool: *const Pool) std.fmt.Formatter(format) {
947 return .{ .data = .{ .string = str, .pool = pool } };
948 }
949
950 fn fromUnnamed(index: u31) String {
951 return .{ .index = @enumFromInt(index) };
952 }
953
954 fn isNamed(str: String) bool {
955 return @intFromEnum(str.index) >= String.Index.first_named_index;
956 }
957
958 pub fn toSlice(str: String, pool: *const Pool) ?[]const u8 {
959 return str.toPoolSlice(pool) orelse if (str.isNamed()) @tagName(str.index) else null;
960 }
961
962 fn toPoolSlice(str: String, pool: *const Pool) ?[]const u8 {
963 if (str.toPoolIndex()) |pool_index| {
964 const start = pool.string_indices.items[pool_index + 0];
965 const end = pool.string_indices.items[pool_index + 1];
966 return pool.string_bytes.items[start..end];
967 } else return null;
968 }
969
970 fn fromPoolIndex(pool_index: usize) String {
971 return .{ .index = @enumFromInt(String.Index.first_pool_index + pool_index) };
972 }
973
974 fn toPoolIndex(str: String) ?u32 {
975 const pool_index, const is_null =
976 @subWithOverflow(@intFromEnum(str.index), String.Index.first_pool_index);
977 return switch (is_null) {
978 0 => pool_index,
979 1 => null,
980 };
981 }
982
983 const Index = enum(u32) {
984 array = first_named_index,
985 @"error",
986 is_null,
987 len,
988 payload,
989 ptr,
990 tag,
991 _,
992
993 const first_named_index: u32 = 1 << 31;
994 const first_pool_index: u32 = first_named_index + @typeInfo(String.Index).Enum.fields.len;
995 };
996
997 const Adapter = struct {
998 pool: *const Pool,
999 pub fn hash(_: @This(), slice: []const u8) Map.Hash {
1000 return @truncate(Hasher.Impl.hash(1, slice));
1001 }
1002 pub fn eql(string_adapter: @This(), lhs_slice: []const u8, _: void, rhs_index: usize) bool {
1003 const rhs_string = String.fromPoolIndex(rhs_index);
1004 const rhs_slice = rhs_string.toPoolSlice(string_adapter.pool).?;
1005 return std.mem.eql(u8, lhs_slice, rhs_slice);
1006 }
1007 };
1008 };
1009
9211010 pub const empty: Pool = .{
9221011 .map = .{},
9231012 .items = .{},
......@@ -1200,26 +1289,26 @@ pub const Pool = struct {
12001289 kind: Kind,
12011290 ) !CType {
12021291 switch (int_info.bits) {
1203 0 => return .{ .index = .void },
1292 0 => return CType.void,
12041293 1...8 => switch (int_info.signedness) {
1205 .unsigned => return .{ .index = .uint8_t },
1206 .signed => return .{ .index = .int8_t },
1294 .signed => return CType.i8,
1295 .unsigned => return CType.u8,
12071296 },
12081297 9...16 => switch (int_info.signedness) {
1209 .unsigned => return .{ .index = .uint16_t },
1210 .signed => return .{ .index = .int16_t },
1298 .signed => return CType.i16,
1299 .unsigned => return CType.u16,
12111300 },
12121301 17...32 => switch (int_info.signedness) {
1213 .unsigned => return .{ .index = .uint32_t },
1214 .signed => return .{ .index = .int32_t },
1302 .signed => return CType.i32,
1303 .unsigned => return CType.u32,
12151304 },
12161305 33...64 => switch (int_info.signedness) {
1217 .unsigned => return .{ .index = .uint64_t },
1218 .signed => return .{ .index = .int64_t },
1306 .signed => return CType.i64,
1307 .unsigned => return CType.u64,
12191308 },
12201309 65...128 => switch (int_info.signedness) {
1221 .unsigned => return .{ .index = .zig_u128 },
1222 .signed => return .{ .index = .zig_i128 },
1310 .signed => return CType.i128,
1311 .unsigned => return CType.u128,
12231312 },
12241313 else => {
12251314 const target = &mod.resolved_target.result;
......@@ -1235,7 +1324,7 @@ pub const Pool = struct {
12351324 if (!kind.isParameter()) return array_ctype;
12361325 var fields = [_]Info.Field{
12371326 .{
1238 .name = try pool.string(allocator, "array"),
1327 .name = .{ .index = .array },
12391328 .ctype = array_ctype,
12401329 .alignas = AlignAs.fromAbiAlignment(abi_align),
12411330 },
......@@ -1267,19 +1356,19 @@ pub const Pool = struct {
12671356 .null_type,
12681357 .undefined_type,
12691358 .enum_literal_type,
1270 => return .{ .index = .void },
1271 .u1_type, .u8_type => return .{ .index = .uint8_t },
1272 .i8_type => return .{ .index = .int8_t },
1273 .u16_type => return .{ .index = .uint16_t },
1274 .i16_type => return .{ .index = .int16_t },
1275 .u29_type, .u32_type => return .{ .index = .uint32_t },
1276 .i32_type => return .{ .index = .int32_t },
1277 .u64_type => return .{ .index = .uint64_t },
1278 .i64_type => return .{ .index = .int64_t },
1279 .u80_type, .u128_type => return .{ .index = .zig_u128 },
1280 .i128_type => return .{ .index = .zig_i128 },
1281 .usize_type => return .{ .index = .uintptr_t },
1282 .isize_type => return .{ .index = .intptr_t },
1359 => return CType.void,
1360 .u1_type, .u8_type => return CType.u8,
1361 .i8_type => return CType.i8,
1362 .u16_type => return CType.u16,
1363 .i16_type => return CType.i16,
1364 .u29_type, .u32_type => return CType.u32,
1365 .i32_type => return CType.i32,
1366 .u64_type => return CType.u64,
1367 .i64_type => return CType.i64,
1368 .u80_type, .u128_type => return CType.u128,
1369 .i128_type => return CType.i128,
1370 .usize_type => return CType.usize,
1371 .isize_type => return CType.isize,
12831372 .c_char_type => return .{ .index = .char },
12841373 .c_short_type => return .{ .index = .short },
12851374 .c_ushort_type => return .{ .index = .@"unsigned short" },
......@@ -1290,12 +1379,12 @@ pub const Pool = struct {
12901379 .c_longlong_type => return .{ .index = .@"long long" },
12911380 .c_ulonglong_type => return .{ .index = .@"unsigned long long" },
12921381 .c_longdouble_type => return .{ .index = .@"long double" },
1293 .f16_type => return .{ .index = .zig_f16 },
1294 .f32_type => return .{ .index = .zig_f32 },
1295 .f64_type => return .{ .index = .zig_f64 },
1296 .f80_type => return .{ .index = .zig_f80 },
1297 .f128_type => return .{ .index = .zig_f128 },
1298 .bool_type, .optional_noreturn_type => return .{ .index = .bool },
1382 .f16_type => return CType.f16,
1383 .f32_type => return CType.f32,
1384 .f64_type => return CType.f64,
1385 .f80_type => return CType.f80,
1386 .f128_type => return CType.f128,
1387 .bool_type, .optional_noreturn_type => return CType.bool,
12991388 .noreturn_type,
13001389 .anyframe_type,
13011390 .generic_poison_type,
......@@ -1324,17 +1413,17 @@ pub const Pool = struct {
13241413 }, mod, kind),
13251414 .manyptr_u8_type,
13261415 => return pool.getPointer(allocator, .{
1327 .elem_ctype = .{ .index = .uint8_t },
1416 .elem_ctype = CType.u8,
13281417 }),
13291418 .manyptr_const_u8_type,
13301419 .manyptr_const_u8_sentinel_0_type,
13311420 => return pool.getPointer(allocator, .{
1332 .elem_ctype = .{ .index = .uint8_t },
1421 .elem_ctype = CType.u8,
13331422 .@"const" = true,
13341423 }),
13351424 .single_const_pointer_to_comptime_int_type,
13361425 => return pool.getPointer(allocator, .{
1337 .elem_ctype = .{ .index = .void },
1426 .elem_ctype = CType.void,
13381427 .@"const" = true,
13391428 }),
13401429 .slice_const_u8_type,
......@@ -1343,16 +1432,16 @@ pub const Pool = struct {
13431432 const target = &mod.resolved_target.result;
13441433 var fields = [_]Info.Field{
13451434 .{
1346 .name = try pool.string(allocator, "ptr"),
1435 .name = .{ .index = .ptr },
13471436 .ctype = try pool.getPointer(allocator, .{
1348 .elem_ctype = .{ .index = .uint8_t },
1437 .elem_ctype = CType.u8,
13491438 .@"const" = true,
13501439 }),
13511440 .alignas = AlignAs.fromAbiAlignment(Type.ptrAbiAlignment(target.*)),
13521441 },
13531442 .{
1354 .name = try pool.string(allocator, "len"),
1355 .ctype = .{ .index = .uintptr_t },
1443 .name = .{ .index = .len },
1444 .ctype = CType.usize,
13561445 .alignas = AlignAs.fromAbiAlignment(
13571446 Type.intAbiAlignment(target.ptrBitWidth(), target.*),
13581447 ),
......@@ -1442,7 +1531,7 @@ pub const Pool = struct {
14421531 const target = &mod.resolved_target.result;
14431532 var fields = [_]Info.Field{
14441533 .{
1445 .name = try pool.string(allocator, "ptr"),
1534 .name = .{ .index = .ptr },
14461535 .ctype = try pool.fromType(
14471536 allocator,
14481537 scratch,
......@@ -1454,8 +1543,8 @@ pub const Pool = struct {
14541543 .alignas = AlignAs.fromAbiAlignment(Type.ptrAbiAlignment(target.*)),
14551544 },
14561545 .{
1457 .name = try pool.string(allocator, "len"),
1458 .ctype = .{ .index = .uintptr_t },
1546 .name = .{ .index = .len },
1547 .ctype = CType.usize,
14591548 .alignas = AlignAs.fromAbiAlignment(
14601549 Type.intAbiAlignment(target.ptrBitWidth(), target.*),
14611550 ),
......@@ -1466,7 +1555,7 @@ pub const Pool = struct {
14661555 },
14671556 .array_type => |array_info| {
14681557 const len = array_info.lenIncludingSentinel();
1469 if (len == 0) return .{ .index = .void };
1558 if (len == 0) return CType.void;
14701559 const elem_type = Type.fromInterned(array_info.child);
14711560 const elem_ctype = try pool.fromType(
14721561 allocator,
......@@ -1476,7 +1565,7 @@ pub const Pool = struct {
14761565 mod,
14771566 kind.noParameter(),
14781567 );
1479 if (elem_ctype.index == .void) return .{ .index = .void };
1568 if (elem_ctype.index == .void) return CType.void;
14801569 const array_ctype = try pool.getArray(allocator, .{
14811570 .elem_ctype = elem_ctype,
14821571 .len = len,
......@@ -1484,7 +1573,7 @@ pub const Pool = struct {
14841573 if (!kind.isParameter()) return array_ctype;
14851574 var fields = [_]Info.Field{
14861575 .{
1487 .name = try pool.string(allocator, "array"),
1576 .name = .{ .index = .array },
14881577 .ctype = array_ctype,
14891578 .alignas = AlignAs.fromAbiAlignment(elem_type.abiAlignment(zcu)),
14901579 },
......@@ -1492,7 +1581,7 @@ pub const Pool = struct {
14921581 return pool.fromFields(allocator, .@"struct", &fields, kind);
14931582 },
14941583 .vector_type => |vector_info| {
1495 if (vector_info.len == 0) return .{ .index = .void };
1584 if (vector_info.len == 0) return CType.void;
14961585 const elem_type = Type.fromInterned(vector_info.child);
14971586 const elem_ctype = try pool.fromType(
14981587 allocator,
......@@ -1502,7 +1591,7 @@ pub const Pool = struct {
15021591 mod,
15031592 kind.noParameter(),
15041593 );
1505 if (elem_ctype.index == .void) return .{ .index = .void };
1594 if (elem_ctype.index == .void) return CType.void;
15061595 const vector_ctype = try pool.getVector(allocator, .{
15071596 .elem_ctype = elem_ctype,
15081597 .len = vector_info.len,
......@@ -1510,7 +1599,7 @@ pub const Pool = struct {
15101599 if (!kind.isParameter()) return vector_ctype;
15111600 var fields = [_]Info.Field{
15121601 .{
1513 .name = try pool.string(allocator, "array"),
1602 .name = .{ .index = .array },
15141603 .ctype = vector_ctype,
15151604 .alignas = AlignAs.fromAbiAlignment(elem_type.abiAlignment(zcu)),
15161605 },
......@@ -1518,7 +1607,7 @@ pub const Pool = struct {
15181607 return pool.fromFields(allocator, .@"struct", &fields, kind);
15191608 },
15201609 .opt_type => |payload_type| {
1521 if (ip.isNoReturn(payload_type)) return .{ .index = .void };
1610 if (ip.isNoReturn(payload_type)) return CType.void;
15221611 const payload_ctype = try pool.fromType(
15231612 allocator,
15241613 scratch,
......@@ -1527,7 +1616,7 @@ pub const Pool = struct {
15271616 mod,
15281617 kind.noParameter(),
15291618 );
1530 if (payload_ctype.index == .void) return .{ .index = .bool };
1619 if (payload_ctype.index == .void) return CType.bool;
15311620 switch (payload_type) {
15321621 .anyerror_type => return payload_ctype,
15331622 else => switch (ip.indexToKey(payload_type)) {
......@@ -1539,12 +1628,12 @@ pub const Pool = struct {
15391628 }
15401629 var fields = [_]Info.Field{
15411630 .{
1542 .name = try pool.string(allocator, "is_null"),
1543 .ctype = .{ .index = .bool },
1631 .name = .{ .index = .is_null },
1632 .ctype = CType.bool,
15441633 .alignas = AlignAs.fromAbiAlignment(.@"1"),
15451634 },
15461635 .{
1547 .name = try pool.string(allocator, "payload"),
1636 .name = .{ .index = .payload },
15481637 .ctype = payload_ctype,
15491638 .alignas = AlignAs.fromAbiAlignment(
15501639 Type.fromInterned(payload_type).abiAlignment(zcu),
......@@ -1574,14 +1663,14 @@ pub const Pool = struct {
15741663 const target = &mod.resolved_target.result;
15751664 var fields = [_]Info.Field{
15761665 .{
1577 .name = try pool.string(allocator, "error"),
1666 .name = .{ .index = .@"error" },
15781667 .ctype = error_set_ctype,
15791668 .alignas = AlignAs.fromAbiAlignment(
15801669 Type.intAbiAlignment(error_set_bits, target.*),
15811670 ),
15821671 },
15831672 .{
1584 .name = try pool.string(allocator, "payload"),
1673 .name = .{ .index = .payload },
15851674 .ctype = payload_ctype,
15861675 .alignas = AlignAs.fromAbiAlignment(payload_type.abiAlignment(zcu)),
15871676 },
......@@ -1600,7 +1689,7 @@ pub const Pool = struct {
16001689 if (kind.isForward()) return if (ty.hasRuntimeBitsIgnoreComptime(zcu))
16011690 fwd_decl
16021691 else
1603 .{ .index = .void };
1692 CType.void;
16041693 const scratch_top = scratch.items.len;
16051694 defer scratch.shrinkRetainingCapacity(scratch_top);
16061695 try scratch.ensureUnusedCapacity(
......@@ -1627,7 +1716,7 @@ pub const Pool = struct {
16271716 .unwrap()) |field_name|
16281717 try pool.string(allocator, field_name.toSlice(ip))
16291718 else
1630 try pool.fmt(allocator, "f{d}", .{field_index});
1719 String.fromUnnamed(@intCast(field_index));
16311720 const field_alignas = AlignAs.fromAlignment(.{
16321721 .@"align" = loaded_struct.fieldAlign(ip, field_index),
16331722 .abi = field_type.abiAlignment(zcu),
......@@ -1644,7 +1733,7 @@ pub const Pool = struct {
16441733 scratch.items.len - scratch_top,
16451734 @typeInfo(Field).Struct.fields.len,
16461735 ));
1647 if (fields_len == 0) return .{ .index = .void };
1736 if (fields_len == 0) return CType.void;
16481737 try pool.ensureUnusedCapacity(allocator, 1);
16491738 const extra_index = try pool.addHashedExtra(allocator, &hasher, Aggregate, .{
16501739 .fwd_decl = fwd_decl.index,
......@@ -1700,7 +1789,7 @@ pub const Pool = struct {
17001789 scratch.items.len - scratch_top,
17011790 @typeInfo(Field).Struct.fields.len,
17021791 ));
1703 if (fields_len == 0) return .{ .index = .void };
1792 if (fields_len == 0) return CType.void;
17041793 if (kind.isForward()) {
17051794 try pool.ensureUnusedCapacity(allocator, 1);
17061795 const extra_index = try pool.addHashedExtra(
......@@ -1739,7 +1828,7 @@ pub const Pool = struct {
17391828 if (kind.isForward()) return if (ty.hasRuntimeBitsIgnoreComptime(zcu))
17401829 fwd_decl
17411830 else
1742 .{ .index = .void };
1831 CType.void;
17431832 const loaded_tag = loaded_union.loadTagType(ip);
17441833 const scratch_top = scratch.items.len;
17451834 defer scratch.shrinkRetainingCapacity(scratch_top);
......@@ -1786,7 +1875,7 @@ pub const Pool = struct {
17861875 @typeInfo(Field).Struct.fields.len,
17871876 ));
17881877 if (!has_tag) {
1789 if (fields_len == 0) return .{ .index = .void };
1878 if (fields_len == 0) return CType.void;
17901879 try pool.ensureUnusedCapacity(allocator, 1);
17911880 const extra_index = try pool.addHashedExtra(
17921881 allocator,
......@@ -1813,7 +1902,7 @@ pub const Pool = struct {
18131902 );
18141903 if (tag_ctype.index != .void) {
18151904 struct_fields[struct_fields_len] = .{
1816 .name = try pool.string(allocator, "tag"),
1905 .name = .{ .index = .tag },
18171906 .ctype = tag_ctype,
18181907 .alignas = AlignAs.fromAbiAlignment(tag_type.abiAlignment(zcu)),
18191908 };
......@@ -1846,14 +1935,14 @@ pub const Pool = struct {
18461935 };
18471936 if (payload_ctype.index != .void) {
18481937 struct_fields[struct_fields_len] = .{
1849 .name = try pool.string(allocator, "payload"),
1938 .name = .{ .index = .payload },
18501939 .ctype = payload_ctype,
18511940 .alignas = AlignAs.fromAbiAlignment(payload_align),
18521941 };
18531942 struct_fields_len += 1;
18541943 }
18551944 }
1856 if (struct_fields_len == 0) return .{ .index = .void };
1945 if (struct_fields_len == 0) return CType.void;
18571946 sortFields(struct_fields[0..struct_fields_len]);
18581947 return pool.getAggregate(allocator, .{
18591948 .tag = .@"struct",
......@@ -1867,7 +1956,7 @@ pub const Pool = struct {
18671956 }, mod, kind),
18681957 }
18691958 },
1870 .opaque_type => return .{ .index = .void },
1959 .opaque_type => return CType.void,
18711960 .enum_type => return pool.fromType(
18721961 allocator,
18731962 scratch,
......@@ -1876,7 +1965,7 @@ pub const Pool = struct {
18761965 mod,
18771966 kind,
18781967 ),
1879 .func_type => |func_info| if (func_info.is_generic) return .{ .index = .void } else {
1968 .func_type => |func_info| if (func_info.is_generic) return CType.void else {
18801969 const scratch_top = scratch.items.len;
18811970 defer scratch.shrinkRetainingCapacity(scratch_top);
18821971 try scratch.ensureUnusedCapacity(allocator, func_info.param_types.len);
......@@ -1890,7 +1979,7 @@ pub const Pool = struct {
18901979 zcu,
18911980 mod,
18921981 kind.asParameter(),
1893 ) else .{ .index = .void };
1982 ) else CType.void;
18941983 for (0..func_info.param_types.len) |param_index| {
18951984 const param_type = Type.fromInterned(
18961985 func_info.param_types.get(ip)[param_index],
......@@ -2024,7 +2113,10 @@ pub const Pool = struct {
20242113 });
20252114 for (0..fields.len) |field_index| {
20262115 const field = fields.at(field_index, source_pool);
2027 const field_name = try pool.string(allocator, field.name.slice(source_pool));
2116 const field_name = if (field.name.toPoolSlice(source_pool)) |slice|
2117 try pool.string(allocator, slice)
2118 else
2119 field.name;
20282120 pool.addExtraAssumeCapacity(Field, .{
20292121 .name = field_name.index,
20302122 .ctype = pool_adapter.copy(field.ctype).index,
......@@ -2054,7 +2146,10 @@ pub const Pool = struct {
20542146 });
20552147 for (0..aggregate_info.fields.len) |field_index| {
20562148 const field = aggregate_info.fields.at(field_index, source_pool);
2057 const field_name = try pool.string(allocator, field.name.slice(source_pool));
2149 const field_name = if (field.name.toPoolSlice(source_pool)) |slice|
2150 try pool.string(allocator, slice)
2151 else
2152 field.name;
20582153 pool.addExtraAssumeCapacity(Field, .{
20592154 .name = field_name.index,
20602155 .ctype = pool_adapter.copy(field.ctype).index,
......@@ -2082,8 +2177,8 @@ pub const Pool = struct {
20822177 return .{ ctype, gop.found_existing };
20832178 }
20842179
2085 pub fn string(pool: *Pool, allocator: std.mem.Allocator, str: []const u8) !String {
2086 try pool.string_bytes.appendSlice(allocator, str);
2180 pub fn string(pool: *Pool, allocator: std.mem.Allocator, slice: []const u8) !String {
2181 try pool.string_bytes.appendSlice(allocator, slice);
20872182 return pool.trailingString(allocator);
20882183 }
20892184
......@@ -2111,12 +2206,15 @@ pub const Pool = struct {
21112206 fn updateExtra(hasher: *Hasher, comptime Extra: type, extra: Extra, pool: *const Pool) void {
21122207 inline for (@typeInfo(Extra).Struct.fields) |field| {
21132208 const value = @field(extra, field.name);
2114 hasher.update(switch (field.type) {
2209 switch (field.type) {
21152210 Pool.Tag, String, CType => unreachable,
2116 CType.Index => (CType{ .index = value }).hash(pool),
2117 String.Index => (String{ .index = value }).slice(pool),
2118 else => value,
2119 });
2211 CType.Index => hasher.update((CType{ .index = value }).hash(pool)),
2212 String.Index => if ((String{ .index = value }).toPoolSlice(pool)) |slice|
2213 hasher.update(slice)
2214 else
2215 hasher.update(@intFromEnum(value)),
2216 else => hasher.update(value),
2217 }
21202218 }
21212219 }
21222220 fn update(hasher: *Hasher, data: anytype) void {
......@@ -2231,30 +2329,30 @@ pub const Pool = struct {
22312329 }
22322330
22332331 fn trailingString(pool: *Pool, allocator: std.mem.Allocator) !String {
2234 const StringAdapter = struct {
2235 pool: *const Pool,
2236 pub fn hash(_: @This(), slice: []const u8) Map.Hash {
2237 return @truncate(Hasher.Impl.hash(1, slice));
2238 }
2239 pub fn eql(string_adapter: @This(), lhs_slice: []const u8, _: void, rhs_index: usize) bool {
2240 const rhs_string: String = .{ .index = @enumFromInt(rhs_index) };
2241 const rhs_slice = rhs_string.slice(string_adapter.pool);
2242 return std.mem.eql(u8, lhs_slice, rhs_slice);
2243 }
2244 };
2332 const start = pool.string_indices.getLast();
2333 const slice: []const u8 = pool.string_bytes.items[start..];
2334 if (slice.len >= 2 and slice[0] == 'f' and switch (slice[1]) {
2335 '0' => slice.len == 2,
2336 '1'...'9' => true,
2337 else => false,
2338 }) if (std.fmt.parseInt(u31, slice[1..], 10)) |unnamed| {
2339 pool.string_bytes.shrinkRetainingCapacity(start);
2340 return String.fromUnnamed(unnamed);
2341 } else |_| {};
2342 if (std.meta.stringToEnum(String.Index, slice)) |index| {
2343 pool.string_bytes.shrinkRetainingCapacity(start);
2344 return .{ .index = index };
2345 }
2346
22452347 try pool.string_map.ensureUnusedCapacity(allocator, 1);
22462348 try pool.string_indices.ensureUnusedCapacity(allocator, 1);
22472349
2248 const start = pool.string_indices.getLast();
2249 const gop = pool.string_map.getOrPutAssumeCapacityAdapted(
2250 @as([]const u8, pool.string_bytes.items[start..]),
2251 StringAdapter{ .pool = pool },
2252 );
2350 const gop = pool.string_map.getOrPutAssumeCapacityAdapted(slice, String.Adapter{ .pool = pool });
22532351 if (gop.found_existing)
22542352 pool.string_bytes.shrinkRetainingCapacity(start)
22552353 else
22562354 pool.string_indices.appendAssumeCapacity(@intCast(pool.string_bytes.items.len));
2257 return .{ .index = @enumFromInt(gop.index) };
2355 return String.fromPoolIndex(gop.index);
22582356 }
22592357
22602358 const Item = struct {
test/behavior/abs.zig-2
......@@ -214,7 +214,6 @@ fn testAbsIntVectors(comptime len: comptime_int) !void {
214214}
215215
216216test "@abs unsigned int vectors" {
217 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
218217 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
219218 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
220219 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
......@@ -274,7 +273,6 @@ fn testAbsUnsignedIntVectors(comptime len: comptime_int) !void {
274273}
275274
276275test "@abs float vectors" {
277 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
278276 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
279277 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
280278 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
test/behavior/call.zig+4-4
......@@ -267,7 +267,6 @@ test "arguments to comptime parameters generated in comptime blocks" {
267267test "forced tail call" {
268268 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
269269 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
270 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
271270 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
272271 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
273272 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
......@@ -280,6 +279,8 @@ test "forced tail call" {
280279 }
281280 }
282281
282 if (builtin.zig_backend == .stage2_c and builtin.os.tag == .windows) return error.SkipZigTest; // MSVC doesn't support always tail calls
283
283284 const S = struct {
284285 fn fibonacciTailInternal(n: u16, a: u16, b: u16) u16 {
285286 if (n == 0) return a;
......@@ -301,7 +302,6 @@ test "forced tail call" {
301302test "inline call preserves tail call" {
302303 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
303304 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
304 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
305305 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
306306 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
307307 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
......@@ -314,6 +314,8 @@ test "inline call preserves tail call" {
314314 }
315315 }
316316
317 if (builtin.zig_backend == .stage2_c and builtin.os.tag == .windows) return error.SkipZigTest; // MSVC doesn't support always tail calls
318
317319 const max = std.math.maxInt(u16);
318320 const S = struct {
319321 var a: u16 = 0;
......@@ -432,7 +434,6 @@ test "method call as parameter type" {
432434
433435test "non-anytype generic parameters provide result type" {
434436 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
435 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
436437 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
437438 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
438439 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
......@@ -463,7 +464,6 @@ test "non-anytype generic parameters provide result type" {
463464
464465test "argument to generic function has correct result type" {
465466 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
466 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
467467 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
468468 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
469469 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
test/behavior/call_tail.zig+2-1
......@@ -45,9 +45,10 @@ test "arguments pointed to on stack into tailcall" {
4545 else => {},
4646 }
4747 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
48 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
4948 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
5049
50 if (builtin.zig_backend == .stage2_c and builtin.os.tag == .windows) return error.SkipZigTest; // MSVC doesn't support always tail calls
51
5152 var data = [_]u64{ 1, 6, 2, 7, 1, 9, 3 };
5253 base = @intFromPtr(&data);
5354 insertionSort(data[0..]);
test/behavior/cast.zig+1-2
......@@ -1119,7 +1119,6 @@ fn foobar(func: PFN_void) !void {
11191119}
11201120
11211121test "cast function with an opaque parameter" {
1122 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
11231122 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
11241123
11251124 if (builtin.zig_backend == .stage2_c) {
......@@ -1461,6 +1460,7 @@ test "pointer to empty struct literal to mutable slice" {
14611460test "coerce between pointers of compatible differently-named floats" {
14621461 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
14631462 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1463 if (builtin.zig_backend == .stage2_c and builtin.os.tag == .windows and !builtin.link_libc) return error.SkipZigTest;
14641464 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
14651465 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
14661466 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;
......@@ -2558,7 +2558,6 @@ test "@intCast vector of signed integer" {
25582558 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
25592559 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
25602560 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
2561 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
25622561 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
25632562
25642563 var x: @Vector(4, i32) = .{ 1, 2, 3, 4 };
test/behavior/export_builtin.zig-3
......@@ -5,7 +5,6 @@ const expect = std.testing.expect;
55test "exporting enum type and value" {
66 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
77 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
8 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
98
109 const S = struct {
1110 const E = enum(c_int) { one, two };
......@@ -20,7 +19,6 @@ test "exporting enum type and value" {
2019test "exporting with internal linkage" {
2120 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
2221 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
23 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
2422
2523 const S = struct {
2624 fn foo() callconv(.C) void {}
......@@ -34,7 +32,6 @@ test "exporting with internal linkage" {
3432test "exporting using field access" {
3533 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
3634 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
37 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
3835
3936 const S = struct {
4037 const Inner = struct {
test/behavior/extern.zig-2
......@@ -16,7 +16,6 @@ test "anyopaque extern symbol" {
1616export var a_mystery_symbol: i32 = 1234;
1717
1818test "function extern symbol" {
19 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
2019 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
2120 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;
2221 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
......@@ -30,7 +29,6 @@ export fn a_mystery_function() i32 {
3029}
3130
3231test "function extern symbol matches extern decl" {
33 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
3432 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
3533 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;
3634 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
test/behavior/fn.zig-1
......@@ -582,7 +582,6 @@ test "pass and return comptime-only types" {
582582test "pointer to alias behaves same as pointer to function" {
583583 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
584584 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
585 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
586585 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
587586
588587 const S = struct {
test/behavior/globals.zig-3
......@@ -7,7 +7,6 @@ test "store to global array" {
77 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
88 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
99 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
10 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
1110
1211 try expect(pos[1] == 0.0);
1312 pos = [2]f32{ 0.0, 1.0 };
......@@ -19,7 +18,6 @@ test "store to global vector" {
1918 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
2019 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
2120 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
22 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
2321
2422 try expect(vpos[1] == 0.0);
2523 vpos = @Vector(2, f32){ 0.0, 1.0 };
......@@ -49,7 +47,6 @@ test "global loads can affect liveness" {
4947 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
5048 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
5149 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
52 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
5350
5451 const S = struct {
5552 const ByRef = struct {
test/behavior/optional.zig+49-9
......@@ -55,17 +55,57 @@ fn testNullPtrsEql() !void {
5555 try expect(&number == x);
5656}
5757
58test "optional with void type" {
59 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
60 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
61 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
58test "optional with zero-bit type" {
59 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
60 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
6261
63 const Foo = struct {
64 x: ?void,
62 const S = struct {
63 fn doTheTest(comptime ZeroBit: type, comptime zero_bit: ZeroBit) !void {
64 const WithRuntime = struct {
65 zero_bit: ZeroBit,
66 runtime: u1,
67 };
68 var with_runtime: WithRuntime = undefined;
69 with_runtime = .{ .zero_bit = zero_bit, .runtime = 0 };
70
71 const Opt = struct { opt: ?ZeroBit };
72 var opt: Opt = .{ .opt = null };
73 try expect(opt.opt == null);
74 try expect(opt.opt != zero_bit);
75 try expect(opt.opt != with_runtime.zero_bit);
76 opt.opt = zero_bit;
77 try expect(opt.opt != null);
78 try expect(opt.opt == zero_bit);
79 try expect(opt.opt == with_runtime.zero_bit);
80 opt = .{ .opt = zero_bit };
81 try expect(opt.opt != null);
82 try expect(opt.opt == zero_bit);
83 try expect(opt.opt == with_runtime.zero_bit);
84 opt.opt = with_runtime.zero_bit;
85 try expect(opt.opt != null);
86 try expect(opt.opt == zero_bit);
87 try expect(opt.opt == with_runtime.zero_bit);
88 opt = .{ .opt = with_runtime.zero_bit };
89 try expect(opt.opt != null);
90 try expect(opt.opt == zero_bit);
91 try expect(opt.opt == with_runtime.zero_bit);
92
93 var two: ?struct { ZeroBit, ZeroBit } = undefined;
94 two = .{ with_runtime.zero_bit, with_runtime.zero_bit };
95 if (!@inComptime()) {
96 try expect(two != null);
97 try expect(two.?[0] == zero_bit);
98 try expect(two.?[0] == with_runtime.zero_bit);
99 try expect(two.?[1] == zero_bit);
100 try expect(two.?[1] == with_runtime.zero_bit);
101 }
102 }
65103 };
66 var x = Foo{ .x = null };
67 _ = &x;
68 try expect(x.x == null);
104
105 try S.doTheTest(void, {});
106 try comptime S.doTheTest(void, {});
107 try S.doTheTest(enum { only }, .only);
108 try comptime S.doTheTest(enum { only }, .only);
69109}
70110
71111test "address of unwrap optional" {
test/behavior/packed-struct.zig+2-1
......@@ -1125,12 +1125,13 @@ test "pointer loaded correctly from packed struct" {
11251125 }
11261126 }
11271127 };
1128 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
11291128 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
11301129 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
11311130 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
11321131 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
11331132
1133 if (builtin.zig_backend == .stage2_c and builtin.os.tag == .windows) return error.SkipZigTest; // crashes MSVC
1134
11341135 var ram = try RAM.new();
11351136 var cpu = try CPU.new(&ram);
11361137 try cpu.tick();
test/behavior/undefined.zig-1
......@@ -101,7 +101,6 @@ test "reslice of undefined global var slice" {
101101test "returned undef is 0xaa bytes when runtime safety is enabled" {
102102 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
103103 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
104 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
105104 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
106105 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
107106
test/behavior/union.zig-1
......@@ -1644,7 +1644,6 @@ test "undefined-layout union field pointer has correct alignment" {
16441644}
16451645
16461646test "packed union field pointer has correct alignment" {
1647 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
16481647 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
16491648 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
16501649 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
test/behavior/vector.zig-1
......@@ -1392,7 +1392,6 @@ test "store vector with memset" {
13921392 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
13931393 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
13941394 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO
1395 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
13961395
13971396 if (builtin.zig_backend == .stage2_llvm) {
13981397 switch (builtin.target.cpu.arch) {
test/tests.zig+15-7
......@@ -1092,9 +1092,17 @@ pub fn addModuleTests(b: *std.Build, options: ModuleTestOptions) *Step {
10921092 // Tracking issue for making the C backend generate C89 compatible code:
10931093 // https://github.com/ziglang/zig/issues/19468
10941094 "-std=c99",
1095 "-pedantic",
10961095 "-Werror",
10971096
1097 "-Wall",
1098 "-Wembedded-directive",
1099 "-Wempty-translation-unit",
1100 "-Wextra",
1101 "-Wgnu",
1102 "-Winvalid-utf8",
1103 "-Wkeyword-macro",
1104 "-Woverlength-strings",
1105
10981106 // Tracking issue for making the C backend generate code
10991107 // that does not trigger warnings:
11001108 // https://github.com/ziglang/zig/issues/19467
......@@ -1103,14 +1111,14 @@ pub fn addModuleTests(b: *std.Build, options: ModuleTestOptions) *Step {
11031111 "-Wno-builtin-requires-header",
11041112
11051113 // spotted on linux
1106 "-Wno-gnu-folding-constant",
1107 "-Wno-incompatible-function-pointer-types",
1108 "-Wno-incompatible-pointer-types",
1109 "-Wno-overlength-strings",
1114 "-Wno-braced-scalar-init",
1115 "-Wno-excess-initializers",
1116 "-Wno-incompatible-pointer-types-discards-qualifiers",
1117 "-Wno-unused",
1118 "-Wno-unused-parameter",
11101119
11111120 // spotted on darwin
1112 "-Wno-dollar-in-identifier-extension",
1113 "-Wno-absolute-value",
1121 "-Wno-incompatible-pointer-types",
11141122 },
11151123 });
11161124 compile_c.addIncludePath(b.path("lib")); // for zig.h