authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-11-02 15:53:59-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-11-02 14:11:31-07:00
loga0ac10d90310ae8c6f4400b522f4a5264e028ea5
treead87a4cc5b06a1759e77f8a027f519fc72b4ca21
parent5f11e341d8fee91acdb153c6e29ee8f484130f2d

Merge pull request #13389 from jacobly0/fix-only-c

cbe: enough fixes for `-Donly-c` to be able to produce an executable

18 files changed, 332 insertions(+), 184 deletions(-)

build.zig+5-5
...@@ -17,7 +17,7 @@ pub fn build(b: *Builder) !void {...@@ -17,7 +17,7 @@ pub fn build(b: *Builder) !void {
17 b.setPreferredReleaseMode(.ReleaseFast);17 b.setPreferredReleaseMode(.ReleaseFast);
18 const test_step = b.step("test", "Run all the tests");18 const test_step = b.step("test", "Run all the tests");
19 const mode = b.standardReleaseOptions();19 const mode = b.standardReleaseOptions();
20 const target = b.standardTargetOptions(.{});20 var target = b.standardTargetOptions(.{});
21 const single_threaded = b.option(bool, "single-threaded", "Build artifacts that run in single threaded mode");21 const single_threaded = b.option(bool, "single-threaded", "Build artifacts that run in single threaded mode");
22 const use_zig_libcxx = b.option(bool, "use-zig-libcxx", "If libc++ is needed, use zig's bundled version, don't try to integrate with the system") orelse false;22 const use_zig_libcxx = b.option(bool, "use-zig-libcxx", "If libc++ is needed, use zig's bundled version, don't try to integrate with the system") orelse false;
2323
...@@ -141,6 +141,10 @@ pub fn build(b: *Builder) !void {...@@ -141,6 +141,10 @@ pub fn build(b: *Builder) !void {
141 break :blk 4;141 break :blk 4;
142 };142 };
143143
144 if (only_c) {
145 target.ofmt = .c;
146 }
147
144 const main_file: ?[]const u8 = mf: {148 const main_file: ?[]const u8 = mf: {
145 if (!have_stage1) break :mf "src/main.zig";149 if (!have_stage1) break :mf "src/main.zig";
146 if (use_zig0) break :mf null;150 if (use_zig0) break :mf null;
...@@ -172,10 +176,6 @@ pub fn build(b: *Builder) !void {...@@ -172,10 +176,6 @@ pub fn build(b: *Builder) !void {
172 test_cases.want_lto = false;176 test_cases.want_lto = false;
173 }177 }
174178
175 if (only_c) {
176 exe.ofmt = .c;
177 }
178
179 const exe_options = b.addOptions();179 const exe_options = b.addOptions();
180 exe.addOptions("build_options", exe_options);180 exe.addOptions("build_options", exe_options);
181181
lib/include/zig.h+1-1
...@@ -19,7 +19,7 @@...@@ -19,7 +19,7 @@
19#endif19#endif
2020
21#if __STDC_VERSION__ >= 201112L21#if __STDC_VERSION__ >= 201112L
22#define zig_threadlocal thread_local22#define zig_threadlocal _Thread_local
23#elif defined(__GNUC__)23#elif defined(__GNUC__)
24#define zig_threadlocal __thread24#define zig_threadlocal __thread
25#elif _MSC_VER25#elif _MSC_VER
lib/std/build.zig+1-2
...@@ -1622,7 +1622,6 @@ pub const LibExeObjStep = struct {...@@ -1622,7 +1622,6 @@ pub const LibExeObjStep = struct {
1622 use_stage1: ?bool = null,1622 use_stage1: ?bool = null,
1623 use_llvm: ?bool = null,1623 use_llvm: ?bool = null,
1624 use_lld: ?bool = null,1624 use_lld: ?bool = null,
1625 ofmt: ?std.Target.ObjectFormat = null,
16261625
1627 output_path_source: GeneratedFile,1626 output_path_source: GeneratedFile,
1628 output_lib_path_source: GeneratedFile,1627 output_lib_path_source: GeneratedFile,
...@@ -2490,7 +2489,7 @@ pub const LibExeObjStep = struct {...@@ -2490,7 +2489,7 @@ pub const LibExeObjStep = struct {
2490 }2489 }
2491 }2490 }
24922491
2493 if (self.ofmt) |ofmt| {2492 if (self.target.ofmt) |ofmt| {
2494 try zig_args.append(try std.fmt.allocPrint(builder.allocator, "-ofmt={s}", .{@tagName(ofmt)}));2493 try zig_args.append(try std.fmt.allocPrint(builder.allocator, "-ofmt={s}", .{@tagName(ofmt)}));
2495 }2494 }
24962495
lib/std/crypto/blake3.zig+4-1
...@@ -200,7 +200,10 @@ const CompressGeneric = struct {...@@ -200,7 +200,10 @@ const CompressGeneric = struct {
200 }200 }
201};201};
202202
203const compress = if (builtin.cpu.arch == .x86_64) CompressVectorized.compress else CompressGeneric.compress;203const compress = if (builtin.cpu.arch == .x86_64 and builtin.zig_backend != .stage2_c)
204 CompressVectorized.compress
205else
206 CompressGeneric.compress;
204207
205fn first8Words(words: [16]u32) [8]u32 {208fn first8Words(words: [16]u32) [8]u32 {
206 return @ptrCast(*const [8]u32, &words).*;209 return @ptrCast(*const [8]u32, &words).*;
lib/std/crypto/gimli.zig+1-1
...@@ -152,7 +152,7 @@ pub const State = struct {...@@ -152,7 +152,7 @@ pub const State = struct {
152 self.endianSwap();152 self.endianSwap();
153 }153 }
154154
155 pub const permute = if (builtin.cpu.arch == .x86_64) impl: {155 pub const permute = if (builtin.cpu.arch == .x86_64 and builtin.zig_backend != .stage2_c) impl: {
156 break :impl permute_vectorized;156 break :impl permute_vectorized;
157 } else if (builtin.mode == .ReleaseSmall) impl: {157 } else if (builtin.mode == .ReleaseSmall) impl: {
158 break :impl permute_small;158 break :impl permute_small;
lib/std/multi_array_list.zig+9-3
...@@ -436,9 +436,15 @@ pub fn MultiArrayList(comptime S: type) type {...@@ -436,9 +436,15 @@ pub fn MultiArrayList(comptime S: type) type {
436 }436 }
437437
438 fn capacityInBytes(capacity: usize) usize {438 fn capacityInBytes(capacity: usize) usize {
439 const sizes_vector: @Vector(sizes.bytes.len, usize) = sizes.bytes;439 if (builtin.zig_backend == .stage2_c) {
440 const capacity_vector = @splat(sizes.bytes.len, capacity);440 var bytes: usize = 0;
441 return @reduce(.Add, capacity_vector * sizes_vector);441 for (sizes.bytes) |size| bytes += size * capacity;
442 return bytes;
443 } else {
444 const sizes_vector: @Vector(sizes.bytes.len, usize) = sizes.bytes;
445 const capacity_vector = @splat(sizes.bytes.len, capacity);
446 return @reduce(.Add, capacity_vector * sizes_vector);
447 }
442 }448 }
443449
444 fn allocatedBytes(self: Self) []align(@alignOf(S)) u8 {450 fn allocatedBytes(self: Self) []align(@alignOf(S)) u8 {
lib/std/target.zig+11-2
...@@ -1,4 +1,5 @@...@@ -1,4 +1,5 @@
1const std = @import("std.zig");1const std = @import("std.zig");
2const builtin = @import("builtin");
2const mem = std.mem;3const mem = std.mem;
3const Version = std.builtin.Version;4const Version = std.builtin.Version;
45
...@@ -719,7 +720,11 @@ pub const Target = struct {...@@ -719,7 +720,11 @@ pub const Target = struct {
719720
720 /// Adds the specified feature set but not its dependencies.721 /// Adds the specified feature set but not its dependencies.
721 pub fn addFeatureSet(set: *Set, other_set: Set) void {722 pub fn addFeatureSet(set: *Set, other_set: Set) void {
722 set.ints = @as(@Vector(usize_count, usize), set.ints) | @as(@Vector(usize_count, usize), other_set.ints);723 if (builtin.zig_backend == .stage2_c) {
724 for (set.ints) |*int, i| int.* |= other_set.ints[i];
725 } else {
726 set.ints = @as(@Vector(usize_count, usize), set.ints) | @as(@Vector(usize_count, usize), other_set.ints);
727 }
723 }728 }
724729
725 /// Removes the specified feature but not its dependents.730 /// Removes the specified feature but not its dependents.
...@@ -731,7 +736,11 @@ pub const Target = struct {...@@ -731,7 +736,11 @@ pub const Target = struct {
731736
732 /// Removes the specified feature but not its dependents.737 /// Removes the specified feature but not its dependents.
733 pub fn removeFeatureSet(set: *Set, other_set: Set) void {738 pub fn removeFeatureSet(set: *Set, other_set: Set) void {
734 set.ints = @as(@Vector(usize_count, usize), set.ints) & ~@as(@Vector(usize_count, usize), other_set.ints);739 if (builtin.zig_backend == .stage2_c) {
740 for (set.ints) |*int, i| int.* &= ~other_set.ints[i];
741 } else {
742 set.ints = @as(@Vector(usize_count, usize), set.ints) & ~@as(@Vector(usize_count, usize), other_set.ints);
743 }
735 }744 }
736745
737 pub fn populateDependencies(set: *Set, all_features_list: []const Cpu.Feature) void {746 pub fn populateDependencies(set: *Set, all_features_list: []const Cpu.Feature) void {
lib/std/zig/system/x86.zig+14-20
...@@ -528,26 +528,20 @@ const CpuidLeaf = packed struct {...@@ -528,26 +528,20 @@ const CpuidLeaf = packed struct {
528};528};
529529
530fn cpuid(leaf_id: u32, subid: u32) CpuidLeaf {530fn cpuid(leaf_id: u32, subid: u32) CpuidLeaf {
531 // Workaround for https://github.com/ziglang/zig/issues/215
532 // Inline assembly in zig only supports one output,
533 // so we pass a pointer to the struct.
534 var cpuid_leaf: CpuidLeaf = undefined;
535
536 // valid for both x86 and x86_64531 // valid for both x86 and x86_64
537 asm volatile (532 var eax: u32 = undefined;
538 \\ cpuid533 var ebx: u32 = undefined;
539 \\ movl %%eax, 0(%[leaf_ptr])534 var ecx: u32 = undefined;
540 \\ movl %%ebx, 4(%[leaf_ptr])535 var edx: u32 = undefined;
541 \\ movl %%ecx, 8(%[leaf_ptr])536 asm volatile ("cpuid"
542 \\ movl %%edx, 12(%[leaf_ptr])537 : [_] "={eax}" (eax),
543 :538 [_] "={ebx}" (ebx),
544 : [leaf_id] "{eax}" (leaf_id),539 [_] "={ecx}" (ecx),
545 [subid] "{ecx}" (subid),540 [_] "={edx}" (edx),
546 [leaf_ptr] "r" (&cpuid_leaf),541 : [_] "{eax}" (leaf_id),
547 : "eax", "ebx", "ecx", "edx"542 [_] "{ecx}" (subid),
548 );543 );
549544 return .{ .eax = eax, .ebx = ebx, .ecx = ecx, .edx = edx };
550 return cpuid_leaf;
551}545}
552546
553// Read control register 0 (XCR0). Used to detect features such as AVX.547// Read control register 0 (XCR0). Used to detect features such as AVX.
...@@ -555,8 +549,8 @@ fn getXCR0() u32 {...@@ -555,8 +549,8 @@ fn getXCR0() u32 {
555 return asm volatile (549 return asm volatile (
556 \\ xor %%ecx, %%ecx550 \\ xor %%ecx, %%ecx
557 \\ xgetbv551 \\ xgetbv
558 : [ret] "={eax}" (-> u32),552 : [_] "={eax}" (-> u32),
559 :553 :
560 : "eax", "edx", "ecx"554 : "edx", "ecx"
561 );555 );
562}556}
src/codegen/c.zig+283-140
...@@ -32,6 +32,8 @@ pub const CValue = union(enum) {...@@ -32,6 +32,8 @@ pub const CValue = union(enum) {
32 constant: Air.Inst.Ref,32 constant: Air.Inst.Ref,
33 /// Index into the parameters33 /// Index into the parameters
34 arg: usize,34 arg: usize,
35 /// Index into a tuple's fields
36 field: usize,
35 /// By-value37 /// By-value
36 decl: Decl.Index,38 decl: Decl.Index,
37 decl_ref: Decl.Index,39 decl_ref: Decl.Index,
...@@ -79,7 +81,6 @@ const BuiltinInfo = enum {...@@ -79,7 +81,6 @@ const BuiltinInfo = enum {
79 Bits,81 Bits,
80};82};
8183
82/// TODO make this not cut off at 128 bytes
83fn formatTypeAsCIdentifier(84fn formatTypeAsCIdentifier(
84 data: FormatTypeAsCIdentContext,85 data: FormatTypeAsCIdentContext,
85 comptime fmt: []const u8,86 comptime fmt: []const u8,
...@@ -1297,7 +1298,8 @@ pub const DeclGen = struct {...@@ -1297,7 +1298,8 @@ pub const DeclGen = struct {
1297 var fqn_buf = std.ArrayList(u8).init(dg.typedefs.allocator);1298 var fqn_buf = std.ArrayList(u8).init(dg.typedefs.allocator);
1298 defer fqn_buf.deinit();1299 defer fqn_buf.deinit();
12991300
1300 const owner_decl = dg.module.declPtr(child_ty.getOwnerDecl());1301 const owner_decl_index = child_ty.getOwnerDecl();
1302 const owner_decl = dg.module.declPtr(owner_decl_index);
1301 try owner_decl.renderFullyQualifiedName(dg.module, fqn_buf.writer());1303 try owner_decl.renderFullyQualifiedName(dg.module, fqn_buf.writer());
13021304
1303 var buffer = std.ArrayList(u8).init(dg.typedefs.allocator);1305 var buffer = std.ArrayList(u8).init(dg.typedefs.allocator);
...@@ -1309,7 +1311,11 @@ pub const DeclGen = struct {...@@ -1309,7 +1311,11 @@ pub const DeclGen = struct {
1309 else => unreachable,1311 else => unreachable,
1310 };1312 };
1311 const name_begin = buffer.items.len + "typedef ".len + tag.len;1313 const name_begin = buffer.items.len + "typedef ".len + tag.len;
1312 try buffer.writer().print("typedef {s}zig_S_{} ", .{ tag, fmtIdent(fqn_buf.items) });1314 try buffer.writer().print("typedef {s}zig_S_{}__{d} ", .{
1315 tag,
1316 fmtIdent(fqn_buf.items),
1317 @enumToInt(owner_decl_index),
1318 });
1313 const name_end = buffer.items.len - " ".len;1319 const name_end = buffer.items.len - " ".len;
1314 try buffer.ensureUnusedCapacity((name_end - name_begin) + ";\n".len);1320 try buffer.ensureUnusedCapacity((name_end - name_begin) + ";\n".len);
1315 buffer.appendSliceAssumeCapacity(buffer.items[name_begin..name_end]);1321 buffer.appendSliceAssumeCapacity(buffer.items[name_begin..name_end]);
...@@ -1378,26 +1384,17 @@ pub const DeclGen = struct {...@@ -1378,26 +1384,17 @@ pub const DeclGen = struct {
1378 try buffer.appendSlice("typedef struct {\n");1384 try buffer.appendSlice("typedef struct {\n");
1379 {1385 {
1380 const fields = t.tupleFields();1386 const fields = t.tupleFields();
1381 var empty = true;1387 var field_id: usize = 0;
1382 for (fields.types) |field_ty, i| {1388 for (fields.types) |field_ty, i| {
1383 if (!field_ty.hasRuntimeBits()) continue;1389 if (!field_ty.hasRuntimeBits() or fields.values[i].tag() != .unreachable_value) continue;
1384 const val = fields.values[i];
1385 if (val.tag() != .unreachable_value) continue;
1386
1387 var field_name_buf: []const u8 = &.{};
1388 defer dg.typedefs.allocator.free(field_name_buf);
1389 const field_name = if (t.isTuple()) field_name: {
1390 field_name_buf = try std.fmt.allocPrint(dg.typedefs.allocator, "field_{d}", .{i});
1391 break :field_name field_name_buf;
1392 } else t.structFieldName(i);
13931390
1394 try buffer.append(' ');1391 try buffer.append(' ');
1395 try dg.renderTypeAndName(buffer.writer(), field_ty, .{ .identifier = field_name }, .Mut, 0, .Complete);1392 try dg.renderTypeAndName(buffer.writer(), field_ty, .{ .field = field_id }, .Mut, 0, .Complete);
1396 try buffer.appendSlice(";\n");1393 try buffer.appendSlice(";\n");
13971394
1398 empty = false;1395 field_id += 1;
1399 }1396 }
1400 if (empty) try buffer.appendSlice(" char empty_tuple;\n");1397 if (field_id == 0) try buffer.appendSlice(" char empty_tuple;\n");
1401 }1398 }
1402 const name_begin = buffer.items.len + "} ".len;1399 const name_begin = buffer.items.len + "} ".len;
1403 try buffer.writer().print("}} zig_T_{};\n", .{typeToCIdentifier(t, dg.module)});1400 try buffer.writer().print("}} zig_T_{};\n", .{typeToCIdentifier(t, dg.module)});
...@@ -1751,12 +1748,38 @@ pub const DeclGen = struct {...@@ -1751,12 +1748,38 @@ pub const DeclGen = struct {
1751 },1748 },
1752 .Struct, .Union => |tag| if (tag == .Struct and t.containerLayout() == .Packed)1749 .Struct, .Union => |tag| if (tag == .Struct and t.containerLayout() == .Packed)
1753 try dg.renderType(w, t.castTag(.@"struct").?.data.backing_int_ty, kind)1750 try dg.renderType(w, t.castTag(.@"struct").?.data.backing_int_ty, kind)
1754 else if (kind == .Complete or t.isTupleOrAnonStruct()) {1751 else if (t.isTupleOrAnonStruct()) {
1752 const ExpectedContents = struct { types: [8]Type, values: [8]Value };
1753 var stack align(@alignOf(ExpectedContents)) =
1754 std.heap.stackFallback(@sizeOf(ExpectedContents), dg.gpa);
1755 const allocator = stack.get();
1756
1757 var tuple_storage = std.MultiArrayList(struct { type: Type, value: Value }){};
1758 defer tuple_storage.deinit(allocator);
1759 try tuple_storage.ensureTotalCapacity(allocator, t.structFieldCount());
1760
1761 const fields = t.tupleFields();
1762 for (fields.values) |value, index|
1763 if (value.tag() == .unreachable_value)
1764 tuple_storage.appendAssumeCapacity(.{
1765 .type = fields.types[index],
1766 .value = value,
1767 });
1768
1769 const tuple_slice = tuple_storage.slice();
1770 var tuple_pl = Type.Payload.Tuple{ .data = .{
1771 .types = tuple_slice.items(.type),
1772 .values = tuple_slice.items(.value),
1773 } };
1774 const tuple_ty = Type.initPayload(&tuple_pl.base);
1775
1776 const name = dg.getTypedefName(tuple_ty) orelse
1777 try dg.renderTupleTypedef(tuple_ty);
1778
1779 try w.writeAll(name);
1780 } else if (kind == .Complete) {
1755 const name = dg.getTypedefName(t) orelse switch (tag) {1781 const name = dg.getTypedefName(t) orelse switch (tag) {
1756 .Struct => if (t.isTupleOrAnonStruct())1782 .Struct => try dg.renderStructTypedef(t),
1757 try dg.renderTupleTypedef(t)
1758 else
1759 try dg.renderStructTypedef(t),
1760 .Union => try dg.renderUnionTypedef(t),1783 .Union => try dg.renderUnionTypedef(t),
1761 else => unreachable,1784 else => unreachable,
1762 };1785 };
...@@ -1976,6 +1999,7 @@ pub const DeclGen = struct {...@@ -1976,6 +1999,7 @@ pub const DeclGen = struct {
1976 .local_ref => |i| return w.print("&t{d}", .{i}),1999 .local_ref => |i| return w.print("&t{d}", .{i}),
1977 .constant => unreachable,2000 .constant => unreachable,
1978 .arg => |i| return w.print("a{d}", .{i}),2001 .arg => |i| return w.print("a{d}", .{i}),
2002 .field => |i| return w.print("f{d}", .{i}),
1979 .decl => |decl| return dg.renderDeclName(w, decl),2003 .decl => |decl| return dg.renderDeclName(w, decl),
1980 .decl_ref => |decl| {2004 .decl_ref => |decl| {
1981 try w.writeByte('&');2005 try w.writeByte('&');
...@@ -1994,6 +2018,7 @@ pub const DeclGen = struct {...@@ -1994,6 +2018,7 @@ pub const DeclGen = struct {
1994 .local_ref => |i| return w.print("t{d}", .{i}),2018 .local_ref => |i| return w.print("t{d}", .{i}),
1995 .constant => unreachable,2019 .constant => unreachable,
1996 .arg => |i| return w.print("(*a{d})", .{i}),2020 .arg => |i| return w.print("(*a{d})", .{i}),
2021 .field => |i| return w.print("f{d}", .{i}),
1997 .decl => |decl| {2022 .decl => |decl| {
1998 try w.writeAll("(*");2023 try w.writeAll("(*");
1999 try dg.renderDeclName(w, decl);2024 try dg.renderDeclName(w, decl);
...@@ -2018,7 +2043,7 @@ pub const DeclGen = struct {...@@ -2018,7 +2043,7 @@ pub const DeclGen = struct {
20182043
2019 fn writeCValueDerefMember(dg: *DeclGen, writer: anytype, c_value: CValue, member: CValue) !void {2044 fn writeCValueDerefMember(dg: *DeclGen, writer: anytype, c_value: CValue, member: CValue) !void {
2020 switch (c_value) {2045 switch (c_value) {
2021 .none, .constant, .undef => unreachable,2046 .none, .constant, .field, .undef => unreachable,
2022 .local, .arg, .decl, .identifier, .bytes => {2047 .local, .arg, .decl, .identifier, .bytes => {
2023 try dg.writeCValue(writer, c_value);2048 try dg.writeCValue(writer, c_value);
2024 try writer.writeAll("->");2049 try writer.writeAll("->");
...@@ -2236,12 +2261,6 @@ pub fn genDecl(o: *Object) !void {...@@ -2236,12 +2261,6 @@ pub fn genDecl(o: *Object) !void {
2236 const variable: *Module.Var = var_payload.data;2261 const variable: *Module.Var = var_payload.data;
2237 const is_global = o.dg.declIsGlobal(tv) or variable.is_extern;2262 const is_global = o.dg.declIsGlobal(tv) or variable.is_extern;
2238 const fwd_decl_writer = o.dg.fwd_decl.writer();2263 const fwd_decl_writer = o.dg.fwd_decl.writer();
2239 if (is_global) {
2240 try fwd_decl_writer.writeAll("zig_extern_c ");
2241 }
2242 if (variable.is_threadlocal) {
2243 try fwd_decl_writer.writeAll("zig_threadlocal ");
2244 }
22452264
2246 const decl_c_value: CValue = if (is_global) .{2265 const decl_c_value: CValue = if (is_global) .{
2247 .bytes = mem.span(o.dg.decl.name),2266 .bytes = mem.span(o.dg.decl.name),
...@@ -2249,6 +2268,8 @@ pub fn genDecl(o: *Object) !void {...@@ -2249,6 +2268,8 @@ pub fn genDecl(o: *Object) !void {
2249 .decl = o.dg.decl_index,2268 .decl = o.dg.decl_index,
2250 };2269 };
22512270
2271 if (is_global) try fwd_decl_writer.writeAll("zig_extern_c ");
2272 if (variable.is_threadlocal) try fwd_decl_writer.writeAll("zig_threadlocal ");
2252 try o.dg.renderTypeAndName(fwd_decl_writer, o.dg.decl.ty, decl_c_value, .Mut, o.dg.decl.@"align", .Complete);2273 try o.dg.renderTypeAndName(fwd_decl_writer, o.dg.decl.ty, decl_c_value, .Mut, o.dg.decl.@"align", .Complete);
2253 try fwd_decl_writer.writeAll(";\n");2274 try fwd_decl_writer.writeAll(";\n");
22542275
...@@ -2257,6 +2278,7 @@ pub fn genDecl(o: *Object) !void {...@@ -2257,6 +2278,7 @@ pub fn genDecl(o: *Object) !void {
2257 }2278 }
22582279
2259 const w = o.writer();2280 const w = o.writer();
2281 if (variable.is_threadlocal) try w.writeAll("zig_threadlocal ");
2260 try o.dg.renderTypeAndName(w, o.dg.decl.ty, decl_c_value, .Mut, o.dg.decl.@"align", .Complete);2282 try o.dg.renderTypeAndName(w, o.dg.decl.ty, decl_c_value, .Mut, o.dg.decl.@"align", .Complete);
2261 try w.writeAll(" = ");2283 try w.writeAll(" = ");
2262 if (variable.init.tag() != .unreachable_value) {2284 if (variable.init.tag() != .unreachable_value) {
...@@ -2595,19 +2617,36 @@ fn airSliceField(f: *Function, inst: Air.Inst.Index, is_ptr: bool, field_name: [...@@ -2595,19 +2617,36 @@ fn airSliceField(f: *Function, inst: Air.Inst.Index, is_ptr: bool, field_name: [
2595}2617}
25962618
2597fn airPtrElemVal(f: *Function, inst: Air.Inst.Index) !CValue {2619fn airPtrElemVal(f: *Function, inst: Air.Inst.Index) !CValue {
2620 const inst_ty = f.air.typeOfIndex(inst);
2598 const bin_op = f.air.instructions.items(.data)[inst].bin_op;2621 const bin_op = f.air.instructions.items(.data)[inst].bin_op;
2599 const ptr_ty = f.air.typeOf(bin_op.lhs);2622 const ptr_ty = f.air.typeOf(bin_op.lhs);
2600 if (!ptr_ty.isVolatilePtr() and f.liveness.isUnused(inst)) return CValue.none;2623 if ((!ptr_ty.isVolatilePtr() and f.liveness.isUnused(inst)) or
2624 !inst_ty.hasRuntimeBitsIgnoreComptime()) return CValue.none;
26012625
2602 const ptr = try f.resolveInst(bin_op.lhs);2626 const ptr = try f.resolveInst(bin_op.lhs);
2603 const index = try f.resolveInst(bin_op.rhs);2627 const index = try f.resolveInst(bin_op.rhs);
2628
2629 const target = f.object.dg.module.getTarget();
2630 const is_array = lowersToArray(inst_ty, target);
2631
2632 const local = try f.allocLocal(inst_ty, if (is_array) .Mut else .Const);
2604 const writer = f.object.writer();2633 const writer = f.object.writer();
2605 const local = try f.allocLocal(f.air.typeOfIndex(inst), .Const);2634 if (is_array) {
2606 try writer.writeAll(" = ");2635 try writer.writeAll(";\n");
2636 try writer.writeAll("memcpy(");
2637 try f.writeCValue(writer, local, .FunctionArgument);
2638 try writer.writeAll(", ");
2639 } else try writer.writeAll(" = ");
2607 try f.writeCValue(writer, ptr, .Other);2640 try f.writeCValue(writer, ptr, .Other);
2608 try writer.writeByte('[');2641 try writer.writeByte('[');
2609 try f.writeCValue(writer, index, .Other);2642 try f.writeCValue(writer, index, .Other);
2610 try writer.writeAll("];\n");2643 try writer.writeByte(']');
2644 if (is_array) {
2645 try writer.writeAll(", sizeof(");
2646 try f.renderTypecast(writer, inst_ty);
2647 try writer.writeAll("))");
2648 }
2649 try writer.writeAll(";\n");
2611 return local;2650 return local;
2612}2651}
26132652
...@@ -2637,19 +2676,36 @@ fn airPtrElemPtr(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -2637,19 +2676,36 @@ fn airPtrElemPtr(f: *Function, inst: Air.Inst.Index) !CValue {
2637}2676}
26382677
2639fn airSliceElemVal(f: *Function, inst: Air.Inst.Index) !CValue {2678fn airSliceElemVal(f: *Function, inst: Air.Inst.Index) !CValue {
2679 const inst_ty = f.air.typeOfIndex(inst);
2640 const bin_op = f.air.instructions.items(.data)[inst].bin_op;2680 const bin_op = f.air.instructions.items(.data)[inst].bin_op;
2641 const slice_ty = f.air.typeOf(bin_op.lhs);2681 const slice_ty = f.air.typeOf(bin_op.lhs);
2642 if (!slice_ty.isVolatilePtr() and f.liveness.isUnused(inst)) return CValue.none;2682 if ((!slice_ty.isVolatilePtr() and f.liveness.isUnused(inst)) or
2683 !inst_ty.hasRuntimeBitsIgnoreComptime()) return CValue.none;
26432684
2644 const slice = try f.resolveInst(bin_op.lhs);2685 const slice = try f.resolveInst(bin_op.lhs);
2645 const index = try f.resolveInst(bin_op.rhs);2686 const index = try f.resolveInst(bin_op.rhs);
2687
2688 const target = f.object.dg.module.getTarget();
2689 const is_array = lowersToArray(inst_ty, target);
2690
2691 const local = try f.allocLocal(inst_ty, if (is_array) .Mut else .Const);
2646 const writer = f.object.writer();2692 const writer = f.object.writer();
2647 const local = try f.allocLocal(f.air.typeOfIndex(inst), .Const);2693 if (is_array) {
2648 try writer.writeAll(" = ");2694 try writer.writeAll(";\n");
2695 try writer.writeAll("memcpy(");
2696 try f.writeCValue(writer, local, .FunctionArgument);
2697 try writer.writeAll(", ");
2698 } else try writer.writeAll(" = ");
2649 try f.writeCValue(writer, slice, .Other);2699 try f.writeCValue(writer, slice, .Other);
2650 try writer.writeAll(".ptr[");2700 try writer.writeAll(".ptr[");
2651 try f.writeCValue(writer, index, .Other);2701 try f.writeCValue(writer, index, .Other);
2652 try writer.writeAll("];\n");2702 try writer.writeByte(']');
2703 if (is_array) {
2704 try writer.writeAll(", sizeof(");
2705 try f.renderTypecast(writer, inst_ty);
2706 try writer.writeAll("))");
2707 }
2708 try writer.writeAll(";\n");
2653 return local;2709 return local;
2654}2710}
26552711
...@@ -2672,18 +2728,34 @@ fn airSliceElemPtr(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -2672,18 +2728,34 @@ fn airSliceElemPtr(f: *Function, inst: Air.Inst.Index) !CValue {
2672}2728}
26732729
2674fn airArrayElemVal(f: *Function, inst: Air.Inst.Index) !CValue {2730fn airArrayElemVal(f: *Function, inst: Air.Inst.Index) !CValue {
2675 if (f.liveness.isUnused(inst)) return CValue.none;2731 const inst_ty = f.air.typeOfIndex(inst);
2732 if (f.liveness.isUnused(inst) or !inst_ty.hasRuntimeBitsIgnoreComptime()) return CValue.none;
26762733
2677 const bin_op = f.air.instructions.items(.data)[inst].bin_op;2734 const bin_op = f.air.instructions.items(.data)[inst].bin_op;
2678 const array = try f.resolveInst(bin_op.lhs);2735 const array = try f.resolveInst(bin_op.lhs);
2679 const index = try f.resolveInst(bin_op.rhs);2736 const index = try f.resolveInst(bin_op.rhs);
2737
2738 const target = f.object.dg.module.getTarget();
2739 const is_array = lowersToArray(inst_ty, target);
2740
2741 const local = try f.allocLocal(inst_ty, if (is_array) .Mut else .Const);
2680 const writer = f.object.writer();2742 const writer = f.object.writer();
2681 const local = try f.allocLocal(f.air.typeOfIndex(inst), .Const);2743 if (is_array) {
2682 try writer.writeAll(" = ");2744 try writer.writeAll(";\n");
2745 try writer.writeAll("memcpy(");
2746 try f.writeCValue(writer, local, .FunctionArgument);
2747 try writer.writeAll(", ");
2748 } else try writer.writeAll(" = ");
2683 try f.writeCValue(writer, array, .Other);2749 try f.writeCValue(writer, array, .Other);
2684 try writer.writeByte('[');2750 try writer.writeByte('[');
2685 try f.writeCValue(writer, index, .Other);2751 try f.writeCValue(writer, index, .Other);
2686 try writer.writeAll("];\n");2752 try writer.writeByte(']');
2753 if (is_array) {
2754 try writer.writeAll(", sizeof(");
2755 try f.renderTypecast(writer, inst_ty);
2756 try writer.writeAll("))");
2757 }
2758 try writer.writeAll(";\n");
2687 return local;2759 return local;
2688}2760}
26892761
...@@ -2817,7 +2889,7 @@ fn airRet(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValue {...@@ -2817,7 +2889,7 @@ fn airRet(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValue {
2817 const array_local = try f.allocLocal(lowered_ret_ty, .Mut);2889 const array_local = try f.allocLocal(lowered_ret_ty, .Mut);
2818 try writer.writeAll(";\n");2890 try writer.writeAll(";\n");
2819 try writer.writeAll("memcpy(");2891 try writer.writeAll("memcpy(");
2820 try f.writeCValueMember(writer, array_local, .{ .identifier = "array" });2892 try f.writeCValueMember(writer, array_local, .{ .field = 0 });
2821 try writer.writeAll(", ");2893 try writer.writeAll(", ");
2822 if (deref)2894 if (deref)
2823 try f.writeCValueDeref(writer, operand)2895 try f.writeCValueDeref(writer, operand)
...@@ -3063,13 +3135,13 @@ fn airOverflow(f: *Function, inst: Air.Inst.Index, operation: []const u8, info:...@@ -3063,13 +3135,13 @@ fn airOverflow(f: *Function, inst: Air.Inst.Index, operation: []const u8, info:
3063 const local = try f.allocLocal(inst_ty, .Mut);3135 const local = try f.allocLocal(inst_ty, .Mut);
3064 try w.writeAll(";\n");3136 try w.writeAll(";\n");
30653137
3066 try f.writeCValue(w, local, .Other);3138 try f.writeCValueMember(w, local, .{ .field = 1 });
3067 try w.writeAll(".field_1 = zig_");3139 try w.writeAll(" = zig_");
3068 try w.writeAll(operation);3140 try w.writeAll(operation);
3069 try w.writeAll("o_");3141 try w.writeAll("o_");
3070 try f.object.dg.renderTypeForBuiltinFnName(w, scalar_ty);3142 try f.object.dg.renderTypeForBuiltinFnName(w, scalar_ty);
3071 try w.writeAll("(&");3143 try w.writeAll("(&");
3072 try f.writeCValueMember(w, local, .{ .identifier = "field_0" });3144 try f.writeCValueMember(w, local, .{ .field = 0 });
3073 try w.writeAll(", ");3145 try w.writeAll(", ");
3074 try f.writeCValue(w, lhs, .FunctionArgument);3146 try f.writeCValue(w, lhs, .FunctionArgument);
3075 try w.writeAll(", ");3147 try w.writeAll(", ");
...@@ -3191,7 +3263,7 @@ fn airEquality(...@@ -3191,7 +3263,7 @@ fn airEquality(
31913263
3192 try writer.writeAll(" = ");3264 try writer.writeAll(" = ");
31933265
3194 if (operand_ty.tag() == .optional) {3266 if (operand_ty.zigTypeTag() == .Optional and !operand_ty.isPtrLikeOptional()) {
3195 // (A && B) || (C && (A == B))3267 // (A && B) || (C && (A == B))
3196 // A = lhs.is_null ; B = rhs.is_null ; C = rhs.payload == lhs.payload3268 // A = lhs.is_null ; B = rhs.is_null ; C = rhs.payload == lhs.payload
31973269
...@@ -3429,7 +3501,7 @@ fn airCall(...@@ -3429,7 +3501,7 @@ fn airCall(
3429 try writer.writeAll("memcpy(");3501 try writer.writeAll("memcpy(");
3430 try f.writeCValue(writer, array_local, .FunctionArgument);3502 try f.writeCValue(writer, array_local, .FunctionArgument);
3431 try writer.writeAll(", ");3503 try writer.writeAll(", ");
3432 try f.writeCValueMember(writer, result_local, .{ .identifier = "array" });3504 try f.writeCValueMember(writer, result_local, .{ .field = 0 });
3433 try writer.writeAll(", sizeof(");3505 try writer.writeAll(", sizeof(");
3434 try f.renderTypecast(writer, ret_ty);3506 try f.renderTypecast(writer, ret_ty);
3435 try writer.writeAll("));\n");3507 try writer.writeAll("));\n");
...@@ -3590,25 +3662,39 @@ fn airBr(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -3590,25 +3662,39 @@ fn airBr(f: *Function, inst: Air.Inst.Index) !CValue {
3590 // If result is .none then the value of the block is unused.3662 // If result is .none then the value of the block is unused.
3591 if (result != .none) {3663 if (result != .none) {
3592 const operand = try f.resolveInst(branch.operand);3664 const operand = try f.resolveInst(branch.operand);
3593 try f.writeCValue(writer, result, .Other);3665
3594 try writer.writeAll(" = ");3666 const operand_ty = f.air.typeOf(branch.operand);
3595 try f.writeCValue(writer, operand, .Other);3667 const target = f.object.dg.module.getTarget();
3668 if (lowersToArray(operand_ty, target)) {
3669 try writer.writeAll("memcpy(");
3670 try f.writeCValue(writer, result, .FunctionArgument);
3671 try writer.writeAll(", ");
3672 try f.writeCValue(writer, operand, .FunctionArgument);
3673 try writer.writeAll(", sizeof(");
3674 try f.renderTypecast(writer, operand_ty);
3675 try writer.writeAll("))");
3676 } else {
3677 try f.writeCValue(writer, result, .Other);
3678 try writer.writeAll(" = ");
3679 try f.writeCValue(writer, operand, .Other);
3680 }
3596 try writer.writeAll(";\n");3681 try writer.writeAll(";\n");
3597 }3682 }
35983683
3599 try f.object.writer().print("goto zig_block_{d};\n", .{block.block_id});3684 try writer.print("goto zig_block_{d};\n", .{block.block_id});
3600 return CValue.none;3685 return CValue.none;
3601}3686}
36023687
3603fn airBitcast(f: *Function, inst: Air.Inst.Index) !CValue {3688fn airBitcast(f: *Function, inst: Air.Inst.Index) !CValue {
3604 if (f.liveness.isUnused(inst))3689 const inst_ty = f.air.typeOfIndex(inst);
3605 return CValue.none;3690 // No IgnoreComptime until Sema stops giving us garbage Air.
3691 // https://github.com/ziglang/zig/issues/13410
3692 if (f.liveness.isUnused(inst) or !inst_ty.hasRuntimeBits()) return CValue.none;
36063693
3607 const ty_op = f.air.instructions.items(.data)[inst].ty_op;3694 const ty_op = f.air.instructions.items(.data)[inst].ty_op;
3608 const operand = try f.resolveInst(ty_op.operand);3695 const operand = try f.resolveInst(ty_op.operand);
36093696
3610 const writer = f.object.writer();3697 const writer = f.object.writer();
3611 const inst_ty = f.air.typeOfIndex(inst);
3612 if (inst_ty.isPtrAtRuntime() and3698 if (inst_ty.isPtrAtRuntime() and
3613 f.air.typeOf(ty_op.operand).isPtrAtRuntime())3699 f.air.typeOf(ty_op.operand).isPtrAtRuntime())
3614 {3700 {
...@@ -3982,9 +4068,9 @@ fn airIsNull(...@@ -3982,9 +4068,9 @@ fn airIsNull(
39824068
3983 const rhs = if (!payload_ty.hasRuntimeBitsIgnoreComptime())4069 const rhs = if (!payload_ty.hasRuntimeBitsIgnoreComptime())
3984 TypedValue{ .ty = Type.bool, .val = Value.@"true" }4070 TypedValue{ .ty = Type.bool, .val = Value.@"true" }
3985 else if (operand_ty.isPtrLikeOptional())4071 else if (optional_ty.isPtrLikeOptional())
3986 // operand is a regular pointer, test `operand !=/== NULL`4072 // operand is a regular pointer, test `operand !=/== NULL`
3987 TypedValue{ .ty = operand_ty, .val = Value.@"null" }4073 TypedValue{ .ty = optional_ty, .val = Value.@"null" }
3988 else if (payload_ty.zigTypeTag() == .ErrorSet)4074 else if (payload_ty.zigTypeTag() == .ErrorSet)
3989 TypedValue{ .ty = payload_ty, .val = Value.zero }4075 TypedValue{ .ty = payload_ty, .val = Value.zero }
3990 else if (payload_ty.isSlice() and optional_ty.optionalReprIsPayload()) rhs: {4076 else if (payload_ty.isSlice() and optional_ty.optionalReprIsPayload()) rhs: {
...@@ -4007,26 +4093,34 @@ fn airOptionalPayload(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -4007,26 +4093,34 @@ fn airOptionalPayload(f: *Function, inst: Air.Inst.Index) !CValue {
4007 if (f.liveness.isUnused(inst)) return CValue.none;4093 if (f.liveness.isUnused(inst)) return CValue.none;
40084094
4009 const ty_op = f.air.instructions.items(.data)[inst].ty_op;4095 const ty_op = f.air.instructions.items(.data)[inst].ty_op;
4010 const writer = f.object.writer();
4011 const operand = try f.resolveInst(ty_op.operand);4096 const operand = try f.resolveInst(ty_op.operand);
4012 const opt_ty = f.air.typeOf(ty_op.operand);4097 const opt_ty = f.air.typeOf(ty_op.operand);
40134098
4014 var buf: Type.Payload.ElemType = undefined;4099 var buf: Type.Payload.ElemType = undefined;
4015 const payload_ty = opt_ty.optionalChild(&buf);4100 const payload_ty = opt_ty.optionalChild(&buf);
40164101
4017 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {4102 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) return CValue.none;
4018 return CValue.none;4103 if (opt_ty.optionalReprIsPayload()) return operand;
4019 }
4020
4021 if (opt_ty.optionalReprIsPayload()) {
4022 return operand;
4023 }
40244104
4025 const inst_ty = f.air.typeOfIndex(inst);4105 const inst_ty = f.air.typeOfIndex(inst);
4026 const local = try f.allocLocal(inst_ty, .Const);4106 const target = f.object.dg.module.getTarget();
4027 try writer.writeAll(" = (");4107 const is_array = lowersToArray(inst_ty, target);
4028 try f.writeCValue(writer, operand, .Other);4108
4029 try writer.writeAll(").payload;\n");4109 const local = try f.allocLocal(inst_ty, if (is_array) .Mut else .Const);
4110 const writer = f.object.writer();
4111 if (is_array) {
4112 try writer.writeAll(";\n");
4113 try writer.writeAll("memcpy(");
4114 try f.writeCValue(writer, local, .FunctionArgument);
4115 try writer.writeAll(", ");
4116 } else try writer.writeAll(" = ");
4117 try f.writeCValueMember(writer, operand, .{ .identifier = "payload" });
4118 if (is_array) {
4119 try writer.writeAll(", sizeof(");
4120 try f.renderTypecast(writer, inst_ty);
4121 try writer.writeAll("))");
4122 }
4123 try writer.writeAll(";\n");
4030 return local;4124 return local;
4031}4125}
40324126
...@@ -4159,16 +4253,14 @@ fn structFieldPtr(f: *Function, inst: Air.Inst.Index, struct_ptr_ty: Type, struc...@@ -4159,16 +4253,14 @@ fn structFieldPtr(f: *Function, inst: Air.Inst.Index, struct_ptr_ty: Type, struc
4159 try f.renderTypecast(writer, field_ptr_ty);4253 try f.renderTypecast(writer, field_ptr_ty);
4160 try writer.writeByte(')');4254 try writer.writeByte(')');
41614255
4162 const extra_name: ?[]const u8 = switch (struct_ty.tag()) {4256 const extra_name: CValue = switch (struct_ty.tag()) {
4163 .union_tagged, .union_safety_tagged => "payload",4257 .union_tagged, .union_safety_tagged => .{ .identifier = "payload" },
4164 else => null,4258 else => .none,
4165 };4259 };
41664260
4167 var field_name_buf: []const u8 = &.{};4261 const field_name: CValue = switch (struct_ty.tag()) {
4168 defer f.object.dg.gpa.free(field_name_buf);
4169 const field_name: ?[]const u8 = switch (struct_ty.tag()) {
4170 .@"struct" => switch (struct_ty.containerLayout()) {4262 .@"struct" => switch (struct_ty.containerLayout()) {
4171 .Auto, .Extern => struct_ty.structFieldName(index),4263 .Auto, .Extern => CValue{ .identifier = struct_ty.structFieldName(index) },
4172 .Packed => if (field_ptr_info.data.host_size == 0) {4264 .Packed => if (field_ptr_info.data.host_size == 0) {
4173 const target = f.object.dg.module.getTarget();4265 const target = f.object.dg.module.getTarget();
41744266
...@@ -4189,29 +4281,35 @@ fn structFieldPtr(f: *Function, inst: Air.Inst.Index, struct_ptr_ty: Type, struc...@@ -4189,29 +4281,35 @@ fn structFieldPtr(f: *Function, inst: Air.Inst.Index, struct_ptr_ty: Type, struc
4189 try f.writeCValue(writer, struct_ptr, .Other);4281 try f.writeCValue(writer, struct_ptr, .Other);
4190 try writer.print(")[{}];\n", .{try f.fmtIntLiteral(Type.usize, byte_offset_val)});4282 try writer.print(")[{}];\n", .{try f.fmtIntLiteral(Type.usize, byte_offset_val)});
4191 return local;4283 return local;
4192 } else null,4284 } else @as(CValue, CValue.none), // this @as is needed because of a stage1 bug
4285 },
4286 .@"union", .union_safety_tagged, .union_tagged => .{
4287 .identifier = struct_ty.unionFields().keys()[index],
4193 },4288 },
4194 .@"union", .union_safety_tagged, .union_tagged => struct_ty.unionFields().keys()[index],4289 .tuple, .anon_struct => field_name: {
4195 .tuple, .anon_struct => |tag| field_name: {
4196 const tuple = struct_ty.tupleFields();4290 const tuple = struct_ty.tupleFields();
4197 if (tuple.values[index].tag() != .unreachable_value) return CValue.none;4291 if (tuple.values[index].tag() != .unreachable_value) return CValue.none;
41984292
4199 if (tag == .anon_struct) break :field_name struct_ty.structFieldName(index);4293 var id: usize = 0;
42004294 for (tuple.values[0..index]) |value|
4201 field_name_buf = try std.fmt.allocPrint(f.object.dg.gpa, "field_{d}", .{index});4295 id += @boolToInt(value.tag() == .unreachable_value);
4202 break :field_name field_name_buf;4296 break :field_name .{ .field = id };
4203 },4297 },
4204 else => unreachable,4298 else => unreachable,
4205 };4299 };
42064300
4207 if (field_ty.hasRuntimeBitsIgnoreComptime()) {4301 if (field_ty.hasRuntimeBitsIgnoreComptime()) {
4208 try writer.writeByte('&');4302 try writer.writeByte('&');
4209 if (extra_name orelse field_name) |name|4303 if (extra_name != .none) {
4210 try f.writeCValueDerefMember(writer, struct_ptr, .{ .identifier = name })4304 try f.writeCValueDerefMember(writer, struct_ptr, extra_name);
4305 if (field_name != .none) {
4306 try writer.writeByte('.');
4307 try f.writeCValue(writer, field_name, .Other);
4308 }
4309 } else if (field_name != .none)
4310 try f.writeCValueDerefMember(writer, struct_ptr, field_name)
4211 else4311 else
4212 try f.writeCValueDeref(writer, struct_ptr);4312 try f.writeCValueDeref(writer, struct_ptr);
4213 if (extra_name) |_| if (field_name) |name|
4214 try writer.print(".{ }", .{fmtIdent(name)});
4215 } else try f.writeCValue(writer, struct_ptr, .Other);4313 } else try f.writeCValue(writer, struct_ptr, .Other);
4216 try writer.writeAll(";\n");4314 try writer.writeAll(";\n");
4217 return local;4315 return local;
...@@ -4221,9 +4319,11 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -4221,9 +4319,11 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {
4221 if (f.liveness.isUnused(inst))4319 if (f.liveness.isUnused(inst))
4222 return CValue.none;4320 return CValue.none;
42234321
4322 const inst_ty = f.air.typeOfIndex(inst);
4323 if (!inst_ty.hasRuntimeBitsIgnoreComptime()) return CValue.none;
4324
4224 const ty_pl = f.air.instructions.items(.data)[inst].ty_pl;4325 const ty_pl = f.air.instructions.items(.data)[inst].ty_pl;
4225 const extra = f.air.extraData(Air.StructField, ty_pl.payload).data;4326 const extra = f.air.extraData(Air.StructField, ty_pl.payload).data;
4226 const inst_ty = f.air.typeOfIndex(inst);
4227 const target = f.object.dg.module.getTarget();4327 const target = f.object.dg.module.getTarget();
4228 const struct_byval = try f.resolveInst(extra.struct_operand);4328 const struct_byval = try f.resolveInst(extra.struct_operand);
4229 const struct_ty = f.air.typeOf(extra.struct_operand);4329 const struct_ty = f.air.typeOf(extra.struct_operand);
...@@ -4232,11 +4332,14 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -4232,11 +4332,14 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {
4232 // Ensure complete type definition is visible before accessing fields.4332 // Ensure complete type definition is visible before accessing fields.
4233 try f.renderType(std.io.null_writer, struct_ty);4333 try f.renderType(std.io.null_writer, struct_ty);
42344334
4235 var field_name_buf: []const u8 = "";4335 const extra_name: CValue = switch (struct_ty.tag()) {
4236 defer f.object.dg.gpa.free(field_name_buf);4336 .union_tagged, .union_safety_tagged => .{ .identifier = "payload" },
4237 const field_name = switch (struct_ty.tag()) {4337 else => .none,
4338 };
4339
4340 const field_name: CValue = switch (struct_ty.tag()) {
4238 .@"struct" => switch (struct_ty.containerLayout()) {4341 .@"struct" => switch (struct_ty.containerLayout()) {
4239 .Auto, .Extern => struct_ty.structFieldName(extra.field_index),4342 .Auto, .Extern => .{ .identifier = struct_ty.structFieldName(extra.field_index) },
4240 .Packed => {4343 .Packed => {
4241 const struct_obj = struct_ty.castTag(.@"struct").?.data;4344 const struct_obj = struct_ty.castTag(.@"struct").?.data;
4242 const int_info = struct_ty.intInfo(target);4345 const int_info = struct_ty.intInfo(target);
...@@ -4294,19 +4397,20 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -4294,19 +4397,20 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {
4294 return local;4397 return local;
4295 },4398 },
4296 },4399 },
4297 .@"union", .union_safety_tagged, .union_tagged => struct_ty.unionFields().keys()[extra.field_index],4400 .@"union", .union_safety_tagged, .union_tagged => .{
4298 .tuple, .anon_struct => |tag| blk: {4401 .identifier = struct_ty.unionFields().keys()[extra.field_index],
4402 },
4403 .tuple, .anon_struct => blk: {
4299 const tuple = struct_ty.tupleFields();4404 const tuple = struct_ty.tupleFields();
4300 if (tuple.values[extra.field_index].tag() != .unreachable_value) return CValue.none;4405 if (tuple.values[extra.field_index].tag() != .unreachable_value) return CValue.none;
43014406
4302 if (tag == .anon_struct) break :blk struct_ty.structFieldName(extra.field_index);4407 var id: usize = 0;
43034408 for (tuple.values[0..extra.field_index]) |value|
4304 field_name_buf = try std.fmt.allocPrint(f.object.dg.gpa, "field_{d}", .{extra.field_index});4409 id += @boolToInt(value.tag() == .unreachable_value);
4305 break :blk field_name_buf;4410 break :blk .{ .field = id };
4306 },4411 },
4307 else => unreachable,4412 else => unreachable,
4308 };4413 };
4309 const payload = if (struct_ty.tag() == .union_tagged or struct_ty.tag() == .union_safety_tagged) "payload." else "";
43104414
4311 const is_array = lowersToArray(inst_ty, target);4415 const is_array = lowersToArray(inst_ty, target);
4312 const local = try f.allocLocal(inst_ty, if (is_array) .Mut else .Const);4416 const local = try f.allocLocal(inst_ty, if (is_array) .Mut else .Const);
...@@ -4315,15 +4419,18 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -4315,15 +4419,18 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {
4315 try writer.writeAll("memcpy(");4419 try writer.writeAll("memcpy(");
4316 try f.writeCValue(writer, local, .FunctionArgument);4420 try f.writeCValue(writer, local, .FunctionArgument);
4317 try writer.writeAll(", ");4421 try writer.writeAll(", ");
4318 try f.writeCValue(writer, struct_byval, .Other);4422 } else try writer.writeAll(" = ");
4319 try writer.print(".{s}{ }, sizeof(", .{ payload, fmtIdent(field_name) });4423 if (extra_name != .none) {
4424 try f.writeCValueMember(writer, struct_byval, extra_name);
4425 try writer.writeByte('.');
4426 try f.writeCValue(writer, field_name, .Other);
4427 } else try f.writeCValueMember(writer, struct_byval, field_name);
4428 if (is_array) {
4429 try writer.writeAll(", sizeof(");
4320 try f.renderTypecast(writer, inst_ty);4430 try f.renderTypecast(writer, inst_ty);
4321 try writer.writeAll("));\n");4431 try writer.writeAll("))");
4322 } else {
4323 try writer.writeAll(" = ");
4324 try f.writeCValue(writer, struct_byval, .Other);
4325 try writer.print(".{s}{ };\n", .{ payload, fmtIdent(field_name) });
4326 }4432 }
4433 try writer.writeAll(";\n");
4327 return local;4434 return local;
4328}4435}
43294436
...@@ -4383,25 +4490,33 @@ fn airUnwrapErrUnionPay(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValu...@@ -4383,25 +4490,33 @@ fn airUnwrapErrUnionPay(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValu
4383}4490}
43844491
4385fn airWrapOptional(f: *Function, inst: Air.Inst.Index) !CValue {4492fn airWrapOptional(f: *Function, inst: Air.Inst.Index) !CValue {
4386 if (f.liveness.isUnused(inst))4493 if (f.liveness.isUnused(inst)) return CValue.none;
4387 return CValue.none;
43884494
4495 const inst_ty = f.air.typeOfIndex(inst);
4389 const ty_op = f.air.instructions.items(.data)[inst].ty_op;4496 const ty_op = f.air.instructions.items(.data)[inst].ty_op;
4390 const writer = f.object.writer();4497 const payload = try f.resolveInst(ty_op.operand);
4391 const operand = try f.resolveInst(ty_op.operand);4498 if (inst_ty.optionalReprIsPayload()) return payload;
43924499
4393 const inst_ty = f.air.typeOfIndex(inst);4500 const payload_ty = f.air.typeOf(ty_op.operand);
4394 if (inst_ty.optionalReprIsPayload()) {4501 const target = f.object.dg.module.getTarget();
4395 return operand;4502 const is_array = lowersToArray(payload_ty, target);
4396 }
43974503
4398 // .wrap_optional is used to convert non-optionals into optionals so it can never be null.4504 const local = try f.allocLocal(inst_ty, if (is_array) .Mut else .Const);
4399 const local = try f.allocLocal(inst_ty, .Const);4505 const writer = f.object.writer();
4400 try writer.writeAll(" = { .payload = ");4506 try writer.writeAll(" = { .payload = ");
4401 try f.writeCValue(writer, operand, .Initializer);4507 try f.writeCValue(writer, if (is_array) CValue{ .undef = payload_ty } else payload, .Initializer);
4402 try writer.writeAll(", .is_null = ");4508 try writer.writeAll(", .is_null = ");
4403 try f.object.dg.renderValue(writer, Type.bool, Value.@"false", .Initializer);4509 try f.object.dg.renderValue(writer, Type.bool, Value.@"false", .Initializer);
4404 try writer.writeAll(" };\n");4510 try writer.writeAll(" };\n");
4511 if (is_array) {
4512 try writer.writeAll("memcpy(");
4513 try f.writeCValueMember(writer, local, .{ .identifier = "payload" });
4514 try writer.writeAll(", ");
4515 try f.writeCValue(writer, payload, .FunctionArgument);
4516 try writer.writeAll(", sizeof(");
4517 try f.renderTypecast(writer, payload_ty);
4518 try writer.writeAll("));\n");
4519 }
4405 return local;4520 return local;
4406}4521}
44074522
...@@ -4473,35 +4588,33 @@ fn airSaveErrReturnTraceIndex(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -4473,35 +4588,33 @@ fn airSaveErrReturnTraceIndex(f: *Function, inst: Air.Inst.Index) !CValue {
4473}4588}
44744589
4475fn airWrapErrUnionPay(f: *Function, inst: Air.Inst.Index) !CValue {4590fn airWrapErrUnionPay(f: *Function, inst: Air.Inst.Index) !CValue {
4476 if (f.liveness.isUnused(inst))4591 if (f.liveness.isUnused(inst)) return CValue.none;
4477 return CValue.none;
4478
4479 const ty_op = f.air.instructions.items(.data)[inst].ty_op;
4480 const writer = f.object.writer();
4481 const operand = try f.resolveInst(ty_op.operand);
44824592
4483 const inst_ty = f.air.typeOfIndex(inst);4593 const inst_ty = f.air.typeOfIndex(inst);
4484 const payload_ty = inst_ty.errorUnionPayload();
4485 const error_ty = inst_ty.errorUnionSet();4594 const error_ty = inst_ty.errorUnionSet();
4595 const ty_op = f.air.instructions.items(.data)[inst].ty_op;
4596 const payload_ty = inst_ty.errorUnionPayload();
4597 const payload = try f.resolveInst(ty_op.operand);
4598
4486 const target = f.object.dg.module.getTarget();4599 const target = f.object.dg.module.getTarget();
4487 const is_array = lowersToArray(payload_ty, target);4600 const is_array = lowersToArray(payload_ty, target);
4601
4488 const local = try f.allocLocal(inst_ty, if (is_array) .Mut else .Const);4602 const local = try f.allocLocal(inst_ty, if (is_array) .Mut else .Const);
4603 const writer = f.object.writer();
4489 try writer.writeAll(" = { .payload = ");4604 try writer.writeAll(" = { .payload = ");
4490 try f.writeCValue(writer, if (is_array) CValue{ .undef = payload_ty } else operand, .Initializer);4605 try f.writeCValue(writer, if (is_array) CValue{ .undef = payload_ty } else payload, .Initializer);
4491 try writer.writeAll(", .error = ");4606 try writer.writeAll(", .error = ");
4492 try f.object.dg.renderValue(writer, error_ty, Value.zero, .Initializer);4607 try f.object.dg.renderValue(writer, error_ty, Value.zero, .Initializer);
4493 try writer.writeAll(" };\n");4608 try writer.writeAll(" };\n");
4494
4495 if (is_array) {4609 if (is_array) {
4496 try writer.writeAll("memcpy(");4610 try writer.writeAll("memcpy(");
4497 try f.writeCValue(writer, local, .Other);4611 try f.writeCValueMember(writer, local, .{ .identifier = "payload" });
4498 try writer.writeAll(".payload, ");4612 try writer.writeAll(", ");
4499 try f.writeCValue(writer, operand, .FunctionArgument);4613 try f.writeCValue(writer, payload, .FunctionArgument);
4500 try writer.writeAll(", sizeof(");4614 try writer.writeAll(", sizeof(");
4501 try f.renderTypecast(writer, payload_ty);4615 try f.renderTypecast(writer, payload_ty);
4502 try writer.writeAll("));\n");4616 try writer.writeAll("));\n");
4503 }4617 }
4504
4505 return local;4618 return local;
4506}4619}
45074620
...@@ -4845,10 +4958,41 @@ fn airAtomicStore(f: *Function, inst: Air.Inst.Index, order: [*:0]const u8) !CVa...@@ -4845,10 +4958,41 @@ fn airAtomicStore(f: *Function, inst: Air.Inst.Index, order: [*:0]const u8) !CVa
4845fn airMemset(f: *Function, inst: Air.Inst.Index) !CValue {4958fn airMemset(f: *Function, inst: Air.Inst.Index) !CValue {
4846 const pl_op = f.air.instructions.items(.data)[inst].pl_op;4959 const pl_op = f.air.instructions.items(.data)[inst].pl_op;
4847 const extra = f.air.extraData(Air.Bin, pl_op.payload).data;4960 const extra = f.air.extraData(Air.Bin, pl_op.payload).data;
4961 const dest_ty = f.air.typeOf(pl_op.operand);
4848 const dest_ptr = try f.resolveInst(pl_op.operand);4962 const dest_ptr = try f.resolveInst(pl_op.operand);
4849 const value = try f.resolveInst(extra.lhs);4963 const value = try f.resolveInst(extra.lhs);
4850 const len = try f.resolveInst(extra.rhs);4964 const len = try f.resolveInst(extra.rhs);
4965
4851 const writer = f.object.writer();4966 const writer = f.object.writer();
4967 if (dest_ty.isVolatilePtr()) {
4968 var u8_ptr_pl = dest_ty.ptrInfo();
4969 u8_ptr_pl.data.pointee_type = Type.u8;
4970 const u8_ptr_ty = Type.initPayload(&u8_ptr_pl.base);
4971
4972 try writer.writeAll("for (");
4973 const index = try f.allocLocal(Type.usize, .Mut);
4974 try writer.writeAll(" = ");
4975 try f.object.dg.renderValue(writer, Type.usize, Value.zero, .Initializer);
4976 try writer.writeAll("; ");
4977 try f.writeCValue(writer, index, .Other);
4978 try writer.writeAll(" != ");
4979 try f.writeCValue(writer, len, .Other);
4980 try writer.writeAll("; ");
4981 try f.writeCValue(writer, index, .Other);
4982 try writer.writeAll(" += ");
4983 try f.object.dg.renderValue(writer, Type.usize, Value.one, .Other);
4984 try writer.writeAll(") ((");
4985 try f.renderTypecast(writer, u8_ptr_ty);
4986 try writer.writeByte(')');
4987 try f.writeCValue(writer, dest_ptr, .FunctionArgument);
4988 try writer.writeAll(")[");
4989 try f.writeCValue(writer, index, .Other);
4990 try writer.writeAll("] = ");
4991 try f.writeCValue(writer, value, .FunctionArgument);
4992 try writer.writeAll(";\n");
4993
4994 return CValue.none;
4995 }
48524996
4853 try writer.writeAll("memset(");4997 try writer.writeAll("memset(");
4854 try f.writeCValue(writer, dest_ptr, .FunctionArgument);4998 try f.writeCValue(writer, dest_ptr, .FunctionArgument);
...@@ -5068,27 +5212,28 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -5068,27 +5212,28 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {
5068 if (empty) try writer.print("{}", .{try f.fmtIntLiteral(Type.u8, Value.zero)});5212 if (empty) try writer.print("{}", .{try f.fmtIntLiteral(Type.u8, Value.zero)});
5069 try writer.writeAll("};\n");5213 try writer.writeAll("};\n");
50705214
5215 var field_id: usize = 0;
5071 for (elements) |element, index| {5216 for (elements) |element, index| {
5072 if (inst_ty.structFieldValueComptime(index)) |_| continue;5217 if (inst_ty.structFieldValueComptime(index)) |_| continue;
50735218
5074 const element_ty = f.air.typeOf(element);5219 const element_ty = f.air.typeOf(element);
5075 if (element_ty.zigTypeTag() != .Array) continue;5220 if (element_ty.zigTypeTag() != .Array) continue;
50765221
5077 var field_name_buf: []u8 = &.{};5222 const field_name = if (inst_ty.isTupleOrAnonStruct())
5078 defer f.object.dg.gpa.free(field_name_buf);5223 CValue{ .field = field_id }
5079 const field_name = if (inst_ty.isTuple()) field_name: {5224 else
5080 field_name_buf = try std.fmt.allocPrint(f.object.dg.gpa, "field_{d}", .{index});5225 CValue{ .identifier = inst_ty.structFieldName(index) };
5081 break :field_name field_name_buf;
5082 } else inst_ty.structFieldName(index);
50835226
5084 try writer.writeAll(";\n");5227 try writer.writeAll(";\n");
5085 try writer.writeAll("memcpy(");5228 try writer.writeAll("memcpy(");
5086 try f.writeCValue(writer, local, .Other);5229 try f.writeCValueMember(writer, local, field_name);
5087 try writer.print(".{ }, ", .{fmtIdent(field_name)});5230 try writer.writeAll(", ");
5088 try f.writeCValue(writer, try f.resolveInst(element), .FunctionArgument);5231 try f.writeCValue(writer, try f.resolveInst(element), .FunctionArgument);
5089 try writer.writeAll(", sizeof(");5232 try writer.writeAll(", sizeof(");
5090 try f.renderTypecast(writer, element_ty);5233 try f.renderTypecast(writer, element_ty);
5091 try writer.writeAll("));\n");5234 try writer.writeAll("));\n");
5235
5236 field_id += 1;
5092 }5237 }
5093 },5238 },
5094 .Packed => {5239 .Packed => {
...@@ -5634,10 +5779,9 @@ fn isByRef(ty: Type) bool {...@@ -5634,10 +5779,9 @@ fn isByRef(ty: Type) bool {
5634}5779}
56355780
5636const LowerFnRetTyBuffer = struct {5781const LowerFnRetTyBuffer = struct {
5637 const names = [1][]const u8{"array"};
5638 types: [1]Type,5782 types: [1]Type,
5639 values: [1]Value,5783 values: [1]Value,
5640 payload: Type.Payload.AnonStruct,5784 payload: Type.Payload.Tuple,
5641};5785};
5642fn lowerFnRetTy(ret_ty: Type, buffer: *LowerFnRetTyBuffer, target: std.Target) Type {5786fn lowerFnRetTy(ret_ty: Type, buffer: *LowerFnRetTyBuffer, target: std.Target) Type {
5643 if (ret_ty.zigTypeTag() == .NoReturn) return Type.initTag(.noreturn);5787 if (ret_ty.zigTypeTag() == .NoReturn) return Type.initTag(.noreturn);
...@@ -5646,7 +5790,6 @@ fn lowerFnRetTy(ret_ty: Type, buffer: *LowerFnRetTyBuffer, target: std.Target) T...@@ -5646,7 +5790,6 @@ fn lowerFnRetTy(ret_ty: Type, buffer: *LowerFnRetTyBuffer, target: std.Target) T
5646 buffer.types = [1]Type{ret_ty};5790 buffer.types = [1]Type{ret_ty};
5647 buffer.values = [1]Value{Value.initTag(.unreachable_value)};5791 buffer.values = [1]Value{Value.initTag(.unreachable_value)};
5648 buffer.payload = .{ .data = .{5792 buffer.payload = .{ .data = .{
5649 .names = &LowerFnRetTyBuffer.names,
5650 .types = &buffer.types,5793 .types = &buffer.types,
5651 .values = &buffer.values,5794 .values = &buffer.values,
5652 } };5795 } };
test/behavior/basic.zig-1
...@@ -725,7 +725,6 @@ test "comptime manyptr concatenation" {...@@ -725,7 +725,6 @@ test "comptime manyptr concatenation" {
725}725}
726726
727test "thread local variable" {727test "thread local variable" {
728 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
729 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO728 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
730 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO729 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
731 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO730 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
test/behavior/bugs/11139.zig-1
...@@ -3,7 +3,6 @@ const builtin = @import("builtin");...@@ -3,7 +3,6 @@ const builtin = @import("builtin");
3const expect = std.testing.expect;3const expect = std.testing.expect;
44
5test "store array of array of structs at comptime" {5test "store array of array of structs at comptime" {
6 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
7 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO6 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
8 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO7 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
98
test/behavior/bugs/1851.zig-1
...@@ -5,7 +5,6 @@ const expect = std.testing.expect;...@@ -5,7 +5,6 @@ const expect = std.testing.expect;
5test "allocation and looping over 3-byte integer" {5test "allocation and looping over 3-byte integer" {
6 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO6 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
7 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO7 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
8 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
9 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO8 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
10 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO9 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1110
test/behavior/bugs/7250.zig-1
...@@ -14,7 +14,6 @@ threadlocal var g_uart0 = nrfx_uart_t{...@@ -14,7 +14,6 @@ threadlocal var g_uart0 = nrfx_uart_t{
14};14};
1515
16test "reference a global threadlocal variable" {16test "reference a global threadlocal variable" {
17 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
18 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO17 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
19 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO18 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
20 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO19 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
test/behavior/cast.zig-1
...@@ -1178,7 +1178,6 @@ fn cast128Float(x: u128) f128 {...@@ -1178,7 +1178,6 @@ fn cast128Float(x: u128) f128 {
11781178
1179test "implicit cast from *[N]T to ?[*]T" {1179test "implicit cast from *[N]T to ?[*]T" {
1180 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;1180 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1181 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
1182 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1181 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1183 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO1182 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
11841183
test/behavior/fn.zig-1
...@@ -355,7 +355,6 @@ test "function call with anon list literal" {...@@ -355,7 +355,6 @@ test "function call with anon list literal" {
355}355}
356356
357test "function call with anon list literal - 2D" {357test "function call with anon list literal - 2D" {
358 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
359 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO358 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
360 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO359 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
361 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO360 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
test/behavior/if.zig-1
...@@ -146,7 +146,6 @@ test "result location with inferred type ends up being pointer to comptime_int"...@@ -146,7 +146,6 @@ test "result location with inferred type ends up being pointer to comptime_int"
146 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;146 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
147 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;147 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
148 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;148 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
149 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
150149
151 var a: ?u32 = 1234;150 var a: ?u32 = 1234;
152 var b: u32 = 2000;151 var b: u32 = 2000;
test/behavior/type.zig-1
...@@ -260,7 +260,6 @@ test "Type.ErrorSet" {...@@ -260,7 +260,6 @@ test "Type.ErrorSet" {
260260
261test "Type.Struct" {261test "Type.Struct" {
262 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO262 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
263 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
264 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO263 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
265 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO264 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
266 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO265 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
test/tests.zig+3-1
...@@ -52,6 +52,9 @@ const test_targets = blk: {...@@ -52,6 +52,9 @@ const test_targets = blk: {
52 },52 },
5353
54 .{54 .{
55 .target = .{
56 .ofmt = .c,
57 },
55 .link_libc = true,58 .link_libc = true,
56 .backend = .stage2_c,59 .backend = .stage2_c,
57 },60 },
...@@ -720,7 +723,6 @@ pub fn addPkgTests(...@@ -720,7 +723,6 @@ pub fn addPkgTests(
720 .stage2_c => {723 .stage2_c => {
721 these_tests.use_stage1 = false;724 these_tests.use_stage1 = false;
722 these_tests.use_llvm = false;725 these_tests.use_llvm = false;
723 these_tests.ofmt = .c;
724 },726 },
725 else => {727 else => {
726 these_tests.use_stage1 = false;728 these_tests.use_stage1 = false;