authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-12-04 01:52:04-05:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-12-04 01:52:04-05:00
log19dd6de180275cc3f79a514b5cbc05eb9cbadb75
tree31b74583e93ce827d36b0149e20e1c1331c1ec71
parentf68bfe2eb70065b76e187c85a203493be5b4959e
parente3b8658e657118054fd57aa18aff281747f63ee8
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #13756 from jacobly0/cbe-behavior

cbe: pass more behavior tests

10 files changed, 259 insertions(+), 132 deletions(-)

lib/zig.h+16-1
......@@ -65,8 +65,17 @@ typedef char bool;
6565#elif zig_has_attribute(aligned)
6666#define zig_align(alignment) __attribute__((aligned(alignment)))
6767#elif _MSC_VER
68#define zig_align zig_align_unavailable
6869#else
69#error the C compiler being used does not support aligning variables
70#define zig_align zig_align_unavailable
71#endif
72
73#if zig_has_attribute(aligned)
74#define zig_align_fn(alignment) __attribute__((aligned(alignment)))
75#elif _MSC_VER
76#define zig_align_fn zig_align_fn_unavailable
77#else
78#define zig_align_fn zig_align_fn_unavailable
7079#endif
7180
7281#if zig_has_builtin(unreachable)
......@@ -81,6 +90,12 @@ typedef char bool;
8190#define zig_extern extern
8291#endif
8392
93#if zig_has_attribute(alias)
94#define zig_export(sig, symbol, name) zig_extern sig __attribute__((alias(symbol)))
95#else
96#define zig_export(sig, symbol, name) __asm(name " = " symbol)
97#endif
98
8499#if zig_has_builtin(debugtrap)
85100#define zig_breakpoint() __builtin_debugtrap()
86101#elif zig_has_builtin(trap)
src/codegen/c.zig+223-118
......@@ -569,7 +569,7 @@ pub const DeclGen = struct {
569569 try writer.writeByte(')');
570570 }
571571 try writer.writeByte('&');
572 try dg.renderDeclName(writer, decl_index);
572 try dg.renderDeclName(writer, decl_index, 0);
573573 if (need_typecast) try writer.writeByte(')');
574574 }
575575
......@@ -1026,11 +1026,11 @@ pub const DeclGen = struct {
10261026 },
10271027 .function => {
10281028 const func = val.castTag(.function).?.data;
1029 try dg.renderDeclName(writer, func.owner_decl);
1029 try dg.renderDeclName(writer, func.owner_decl, 0);
10301030 },
10311031 .extern_fn => {
10321032 const extern_fn = val.castTag(.extern_fn).?.data;
1033 try dg.renderDeclName(writer, extern_fn.owner_decl);
1033 try dg.renderDeclName(writer, extern_fn.owner_decl, 0);
10341034 },
10351035 .int_u64, .one => {
10361036 try writer.writeAll("((");
......@@ -1356,7 +1356,7 @@ pub const DeclGen = struct {
13561356 }
13571357 }
13581358
1359 fn renderFunctionSignature(dg: *DeclGen, w: anytype, kind: TypedefKind) !void {
1359 fn renderFunctionSignature(dg: *DeclGen, w: anytype, kind: TypedefKind, export_index: u32) !void {
13601360 const fn_info = dg.decl.ty.fnInfo();
13611361 if (fn_info.cc == .Naked) try w.writeAll("zig_naked ");
13621362 if (dg.decl.val.castTag(.function)) |func_payload|
......@@ -1368,7 +1368,7 @@ pub const DeclGen = struct {
13681368
13691369 try dg.renderType(w, ret_ty, kind);
13701370 try w.writeByte(' ');
1371 try dg.renderDeclName(w, dg.decl_index);
1371 try dg.renderDeclName(w, dg.decl_index, export_index);
13721372 try w.writeByte('(');
13731373
13741374 var index: usize = 0;
......@@ -1387,6 +1387,7 @@ pub const DeclGen = struct {
13871387 try dg.renderType(w, Type.void, kind);
13881388 }
13891389 try w.writeByte(')');
1390 if (fn_info.alignment > 0) try w.print(" zig_align_fn({})", .{fn_info.alignment});
13901391 }
13911392
13921393 fn renderPtrToFnTypedef(dg: *DeclGen, t: Type) error{ OutOfMemory, AnalysisFail }![]const u8 {
......@@ -1487,29 +1488,42 @@ pub const DeclGen = struct {
14871488 // The forward declaration for T is stored with a key of *const T.
14881489 const child_ty = t.childType();
14891490
1490 var fqn_buf = std.ArrayList(u8).init(dg.typedefs.allocator);
1491 defer fqn_buf.deinit();
1492
1493 const owner_decl_index = child_ty.getOwnerDecl();
1494 const owner_decl = dg.module.declPtr(owner_decl_index);
1495 try owner_decl.renderFullyQualifiedName(dg.module, fqn_buf.writer());
1496
14971491 var buffer = std.ArrayList(u8).init(dg.typedefs.allocator);
14981492 defer buffer.deinit();
1493 const bw = buffer.writer();
14991494
15001495 const tag = switch (child_ty.zigTypeTag()) {
1501 .Struct => "struct ",
1502 .Union => if (child_ty.unionTagTypeSafety()) |_| "struct " else "union ",
1496 .Struct, .ErrorUnion, .Optional => "struct",
1497 .Union => if (child_ty.unionTagTypeSafety()) |_| "struct" else "union",
15031498 else => unreachable,
15041499 };
1505 const name_begin = buffer.items.len + "typedef ".len + tag.len;
1506 try buffer.writer().print("typedef {s}zig_S_{}__{d} ", .{
1507 tag,
1508 fmtIdent(fqn_buf.items),
1509 @enumToInt(owner_decl_index),
1510 });
1511 const name_end = buffer.items.len - " ".len;
1512 try buffer.ensureUnusedCapacity((name_end - name_begin) + ";\n".len);
1500 try bw.writeAll("typedef ");
1501 try bw.writeAll(tag);
1502 const name_begin = buffer.items.len + " ".len;
1503 try bw.writeAll(" zig_");
1504 switch (child_ty.zigTypeTag()) {
1505 .Struct, .Union => {
1506 var fqn_buf = std.ArrayList(u8).init(dg.typedefs.allocator);
1507 defer fqn_buf.deinit();
1508
1509 const owner_decl_index = child_ty.getOwnerDecl();
1510 const owner_decl = dg.module.declPtr(owner_decl_index);
1511 try owner_decl.renderFullyQualifiedName(dg.module, fqn_buf.writer());
1512
1513 try bw.print("S_{}__{d}", .{ fmtIdent(fqn_buf.items), @enumToInt(owner_decl_index) });
1514 },
1515 .ErrorUnion => {
1516 try bw.print("E_{}", .{typeToCIdentifier(child_ty.errorUnionPayload(), dg.module)});
1517 },
1518 .Optional => {
1519 var opt_buf: Type.Payload.ElemType = undefined;
1520 try bw.print("Q_{}", .{typeToCIdentifier(child_ty.optionalChild(&opt_buf), dg.module)});
1521 },
1522 else => unreachable,
1523 }
1524 const name_end = buffer.items.len;
1525 try buffer.ensureUnusedCapacity(" ".len + (name_end - name_begin) + ";\n".len);
1526 buffer.appendAssumeCapacity(' ');
15131527 buffer.appendSliceAssumeCapacity(buffer.items[name_begin..name_end]);
15141528 buffer.appendSliceAssumeCapacity(";\n");
15151529
......@@ -1569,7 +1583,11 @@ pub const DeclGen = struct {
15691583 return name;
15701584 }
15711585
1572 fn renderTupleTypedef(dg: *DeclGen, t: Type) error{ OutOfMemory, AnalysisFail }![]const u8 {
1586 fn renderTupleTypedef(
1587 dg: *DeclGen,
1588 t: Type,
1589 kind: TypedefKind,
1590 ) error{ OutOfMemory, AnalysisFail }![]const u8 {
15731591 var buffer = std.ArrayList(u8).init(dg.typedefs.allocator);
15741592 defer buffer.deinit();
15751593
......@@ -1581,7 +1599,7 @@ pub const DeclGen = struct {
15811599 if (!field_ty.hasRuntimeBits() or fields.values[i].tag() != .unreachable_value) continue;
15821600
15831601 try buffer.append(' ');
1584 try dg.renderTypeAndName(buffer.writer(), field_ty, .{ .field = field_id }, .Mut, 0, .Complete);
1602 try dg.renderTypeAndName(buffer.writer(), field_ty, .{ .field = field_id }, .Mut, 0, kind);
15851603 try buffer.appendSlice(";\n");
15861604
15871605 field_id += 1;
......@@ -1669,6 +1687,11 @@ pub const DeclGen = struct {
16691687 fn renderErrorUnionTypedef(dg: *DeclGen, t: Type) error{ OutOfMemory, AnalysisFail }![]const u8 {
16701688 assert(t.errorUnionSet().tag() == .anyerror);
16711689
1690 var ptr_pl = Type.Payload.ElemType{ .base = .{ .tag = .single_const_pointer }, .data = t };
1691 const ptr_ty = Type.initPayload(&ptr_pl.base);
1692 const name = dg.getTypedefName(ptr_ty) orelse
1693 try dg.renderFwdTypedef(ptr_ty);
1694
16721695 var buffer = std.ArrayList(u8).init(dg.typedefs.allocator);
16731696 defer buffer.deinit();
16741697 const bw = buffer.writer();
......@@ -1681,7 +1704,9 @@ pub const DeclGen = struct {
16811704 const target = dg.module.getTarget();
16821705 const payload_align = payload_ty.abiAlignment(target);
16831706 const error_align = error_ty.abiAlignment(target);
1684 try bw.writeAll("typedef struct {\n ");
1707 try bw.writeAll("struct ");
1708 try bw.writeAll(name);
1709 try bw.writeAll(" {\n ");
16851710 if (error_align > payload_align) {
16861711 try dg.renderTypeAndName(bw, payload_ty, payload_name, .Mut, 0, .Complete);
16871712 try bw.writeAll(";\n ");
......@@ -1691,15 +1716,10 @@ pub const DeclGen = struct {
16911716 try bw.writeAll(";\n ");
16921717 try dg.renderTypeAndName(bw, payload_ty, payload_name, .Mut, 0, .Complete);
16931718 }
1694 try bw.writeAll(";\n} ");
1695 const name_begin = buffer.items.len;
1696 try bw.print("zig_E_{}", .{typeToCIdentifier(payload_ty, dg.module)});
1697 const name_end = buffer.items.len;
1698 try bw.writeAll(";\n");
1719 try bw.writeAll(";\n};\n");
16991720
17001721 const rendered = try buffer.toOwnedSlice();
17011722 errdefer dg.typedefs.allocator.free(rendered);
1702 const name = rendered[name_begin..name_end];
17031723
17041724 try dg.typedefs.ensureUnusedCapacity(1);
17051725 dg.typedefs.putAssumeCapacityNoClobber(
......@@ -1743,24 +1763,29 @@ pub const DeclGen = struct {
17431763 return name;
17441764 }
17451765
1746 fn renderOptionalTypedef(dg: *DeclGen, t: Type, child_type: Type) error{ OutOfMemory, AnalysisFail }![]const u8 {
1766 fn renderOptionalTypedef(dg: *DeclGen, t: Type) error{ OutOfMemory, AnalysisFail }![]const u8 {
1767 var ptr_pl = Type.Payload.ElemType{ .base = .{ .tag = .single_const_pointer }, .data = t };
1768 const ptr_ty = Type.initPayload(&ptr_pl.base);
1769 const name = dg.getTypedefName(ptr_ty) orelse
1770 try dg.renderFwdTypedef(ptr_ty);
1771
17471772 var buffer = std.ArrayList(u8).init(dg.typedefs.allocator);
17481773 defer buffer.deinit();
17491774 const bw = buffer.writer();
17501775
1751 try bw.writeAll("typedef struct {\n ");
1752 try dg.renderTypeAndName(bw, child_type, .{ .identifier = "payload" }, .Mut, 0, .Complete);
1776 var opt_buf: Type.Payload.ElemType = undefined;
1777 const child_ty = t.optionalChild(&opt_buf);
1778
1779 try bw.writeAll("struct ");
1780 try bw.writeAll(name);
1781 try bw.writeAll(" {\n");
1782 try dg.renderTypeAndName(bw, child_ty, .{ .identifier = "payload" }, .Mut, 0, .Complete);
17531783 try bw.writeAll(";\n ");
17541784 try dg.renderTypeAndName(bw, Type.bool, .{ .identifier = "is_null" }, .Mut, 0, .Complete);
1755 try bw.writeAll(";\n} ");
1756 const name_begin = buffer.items.len;
1757 try bw.print("zig_Q_{}", .{typeToCIdentifier(child_type, dg.module)});
1758 const name_end = buffer.items.len;
1759 try bw.writeAll(";\n");
1785 try bw.writeAll(";\n};\n");
17601786
17611787 const rendered = try buffer.toOwnedSlice();
17621788 errdefer dg.typedefs.allocator.free(rendered);
1763 const name = rendered[name_begin..name_end];
17641789
17651790 try dg.typedefs.ensureUnusedCapacity(1);
17661791 dg.typedefs.putAssumeCapacityNoClobber(
......@@ -1899,18 +1924,34 @@ pub const DeclGen = struct {
18991924 },
19001925 .Optional => {
19011926 var opt_buf: Type.Payload.ElemType = undefined;
1902 const child_type = t.optionalChild(&opt_buf);
1927 const child_ty = t.optionalChild(&opt_buf);
19031928
1904 if (!child_type.hasRuntimeBitsIgnoreComptime())
1929 if (!child_ty.hasRuntimeBitsIgnoreComptime())
19051930 return dg.renderType(w, Type.bool, kind);
19061931
19071932 if (t.optionalReprIsPayload())
1908 return dg.renderType(w, child_type, kind);
1933 return dg.renderType(w, child_ty, kind);
19091934
1910 const name = dg.getTypedefName(t) orelse
1911 try dg.renderOptionalTypedef(t, child_type);
1935 switch (kind) {
1936 .Complete => {
1937 const name = dg.getTypedefName(t) orelse
1938 try dg.renderOptionalTypedef(t);
19121939
1913 return w.writeAll(name);
1940 try w.writeAll(name);
1941 },
1942 .Forward => {
1943 var ptr_pl = Type.Payload.ElemType{
1944 .base = .{ .tag = .single_const_pointer },
1945 .data = t,
1946 };
1947 const ptr_ty = Type.initPayload(&ptr_pl.base);
1948
1949 const name = dg.getTypedefName(ptr_ty) orelse
1950 try dg.renderFwdTypedef(ptr_ty);
1951
1952 try w.writeAll(name);
1953 },
1954 }
19141955 },
19151956 .ErrorUnion => {
19161957 const payload_ty = t.errorUnionPayload();
......@@ -1923,10 +1964,26 @@ pub const DeclGen = struct {
19231964 };
19241965 const error_union_ty = Type.initPayload(&error_union_pl.base);
19251966
1926 const name = dg.getTypedefName(error_union_ty) orelse
1927 try dg.renderErrorUnionTypedef(error_union_ty);
1967 switch (kind) {
1968 .Complete => {
1969 const name = dg.getTypedefName(error_union_ty) orelse
1970 try dg.renderErrorUnionTypedef(error_union_ty);
19281971
1929 return w.writeAll(name);
1972 try w.writeAll(name);
1973 },
1974 .Forward => {
1975 var ptr_pl = Type.Payload.ElemType{
1976 .base = .{ .tag = .single_const_pointer },
1977 .data = error_union_ty,
1978 };
1979 const ptr_ty = Type.initPayload(&ptr_pl.base);
1980
1981 const name = dg.getTypedefName(ptr_ty) orelse
1982 try dg.renderFwdTypedef(ptr_ty);
1983
1984 try w.writeAll(name);
1985 },
1986 }
19301987 },
19311988 .Struct, .Union => |tag| if (t.containerLayout() == .Packed) {
19321989 if (t.castTag(.@"struct")) |struct_obj| {
......@@ -1964,28 +2021,31 @@ pub const DeclGen = struct {
19642021 const tuple_ty = Type.initPayload(&tuple_pl.base);
19652022
19662023 const name = dg.getTypedefName(tuple_ty) orelse
1967 try dg.renderTupleTypedef(tuple_ty);
2024 try dg.renderTupleTypedef(tuple_ty, kind);
19682025
19692026 try w.writeAll(name);
1970 } else if (kind == .Complete) {
1971 const name = dg.getTypedefName(t) orelse switch (tag) {
1972 .Struct => try dg.renderStructTypedef(t),
1973 .Union => try dg.renderUnionTypedef(t),
1974 else => unreachable,
1975 };
2027 } else switch (kind) {
2028 .Complete => {
2029 const name = dg.getTypedefName(t) orelse switch (tag) {
2030 .Struct => try dg.renderStructTypedef(t),
2031 .Union => try dg.renderUnionTypedef(t),
2032 else => unreachable,
2033 };
19762034
1977 try w.writeAll(name);
1978 } else {
1979 var ptr_pl = Type.Payload.ElemType{
1980 .base = .{ .tag = .single_const_pointer },
1981 .data = t,
1982 };
1983 const ptr_ty = Type.initPayload(&ptr_pl.base);
2035 try w.writeAll(name);
2036 },
2037 .Forward => {
2038 var ptr_pl = Type.Payload.ElemType{
2039 .base = .{ .tag = .single_const_pointer },
2040 .data = t,
2041 };
2042 const ptr_ty = Type.initPayload(&ptr_pl.base);
19842043
1985 const name = dg.getTypedefName(ptr_ty) orelse
1986 try dg.renderFwdTypedef(ptr_ty);
2044 const name = dg.getTypedefName(ptr_ty) orelse
2045 try dg.renderFwdTypedef(ptr_ty);
19872046
1988 try w.writeAll(name);
2047 try w.writeAll(name);
2048 },
19892049 },
19902050 .Enum => {
19912051 // For enums, we simply use the integer tag type.
......@@ -2213,10 +2273,10 @@ pub const DeclGen = struct {
22132273 .constant => unreachable,
22142274 .arg => |i| return w.print("a{d}", .{i}),
22152275 .field => |i| return w.print("f{d}", .{i}),
2216 .decl => |decl| return dg.renderDeclName(w, decl),
2276 .decl => |decl| return dg.renderDeclName(w, decl, 0),
22172277 .decl_ref => |decl| {
22182278 try w.writeByte('&');
2219 return dg.renderDeclName(w, decl);
2279 return dg.renderDeclName(w, decl, 0);
22202280 },
22212281 .undef => |ty| return dg.renderValue(w, ty, Value.undef, .Other),
22222282 .identifier => |ident| return w.print("{ }", .{fmtIdent(ident)}),
......@@ -2234,10 +2294,10 @@ pub const DeclGen = struct {
22342294 .field => |i| return w.print("f{d}", .{i}),
22352295 .decl => |decl| {
22362296 try w.writeAll("(*");
2237 try dg.renderDeclName(w, decl);
2297 try dg.renderDeclName(w, decl, 0);
22382298 return w.writeByte(')');
22392299 },
2240 .decl_ref => |decl| return dg.renderDeclName(w, decl),
2300 .decl_ref => |decl| return dg.renderDeclName(w, decl, 0),
22412301 .undef => unreachable,
22422302 .identifier => |ident| return w.print("(*{ })", .{fmtIdent(ident)}),
22432303 .bytes => |bytes| {
......@@ -2269,12 +2329,12 @@ pub const DeclGen = struct {
22692329 try dg.writeCValue(writer, member);
22702330 }
22712331
2272 fn renderDeclName(dg: *DeclGen, writer: anytype, decl_index: Decl.Index) !void {
2332 fn renderDeclName(dg: *DeclGen, writer: anytype, decl_index: Decl.Index, export_index: u32) !void {
22732333 const decl = dg.module.declPtr(decl_index);
22742334 dg.module.markDeclAlive(decl);
22752335
22762336 if (dg.module.decl_exports.get(decl_index)) |exports| {
2277 return writer.writeAll(exports.items[0].options.name);
2337 return writer.writeAll(exports.items[export_index].options.name);
22782338 } else if (decl.isExtern()) {
22792339 return writer.writeAll(mem.sliceTo(decl.name, 0));
22802340 } else if (dg.module.test_functions.get(decl_index)) |_| {
......@@ -2422,24 +2482,44 @@ pub fn genErrDecls(o: *Object) !void {
24222482 try writer.writeAll("};\n");
24232483}
24242484
2485fn genExports(o: *Object) !void {
2486 const tracy = trace(@src());
2487 defer tracy.end();
2488
2489 const fwd_decl_writer = o.dg.fwd_decl.writer();
2490 if (o.dg.module.decl_exports.get(o.dg.decl_index)) |exports| for (exports.items[1..]) |@"export", i| {
2491 try fwd_decl_writer.writeAll("zig_export(");
2492 try o.dg.renderFunctionSignature(fwd_decl_writer, .Forward, @intCast(u32, 1 + i));
2493 try fwd_decl_writer.print(", {s}, {s});\n", .{
2494 fmtStringLiteral(exports.items[0].options.name),
2495 fmtStringLiteral(@"export".options.name),
2496 });
2497 };
2498}
2499
24252500pub fn genFunc(f: *Function) !void {
24262501 const tracy = trace(@src());
24272502 defer tracy.end();
24282503
24292504 const o = &f.object;
2505 const tv: TypedValue = .{
2506 .ty = o.dg.decl.ty,
2507 .val = o.dg.decl.val,
2508 };
24302509
24312510 o.code_header = std.ArrayList(u8).init(f.object.dg.gpa);
24322511 defer o.code_header.deinit();
24332512
2434 const is_global = o.dg.module.decl_exports.contains(f.func.owner_decl);
2513 const is_global = o.dg.declIsGlobal(tv);
24352514 const fwd_decl_writer = o.dg.fwd_decl.writer();
24362515 try fwd_decl_writer.writeAll(if (is_global) "zig_extern " else "static ");
2437 try o.dg.renderFunctionSignature(fwd_decl_writer, .Forward);
2516 try o.dg.renderFunctionSignature(fwd_decl_writer, .Forward, 0);
24382517 try fwd_decl_writer.writeAll(";\n");
2518 try genExports(o);
24392519
24402520 try o.indent_writer.insertNewline();
24412521 if (!is_global) try o.writer().writeAll("static ");
2442 try o.dg.renderFunctionSignature(o.writer(), .Complete);
2522 try o.dg.renderFunctionSignature(o.writer(), .Complete, 0);
24432523 try o.writer().writeByte(' ');
24442524
24452525 // In case we need to use the header, populate it with a copy of the function
......@@ -2474,23 +2554,22 @@ pub fn genDecl(o: *Object) !void {
24742554 if (tv.val.tag() == .extern_fn) {
24752555 const fwd_decl_writer = o.dg.fwd_decl.writer();
24762556 try fwd_decl_writer.writeAll("zig_extern ");
2477 try o.dg.renderFunctionSignature(fwd_decl_writer, .Forward);
2557 try o.dg.renderFunctionSignature(fwd_decl_writer, .Forward, 0);
24782558 try fwd_decl_writer.writeAll(";\n");
2559 try genExports(o);
24792560 } else if (tv.val.castTag(.variable)) |var_payload| {
24802561 const variable: *Module.Var = var_payload.data;
2562
24812563 const is_global = o.dg.declIsGlobal(tv) or variable.is_extern;
24822564 const fwd_decl_writer = o.dg.fwd_decl.writer();
24832565
2484 const decl_c_value: CValue = if (is_global) .{
2485 .bytes = mem.span(o.dg.decl.name),
2486 } else .{
2487 .decl = o.dg.decl_index,
2488 };
2566 const decl_c_value = CValue{ .decl = o.dg.decl_index };
24892567
24902568 try fwd_decl_writer.writeAll(if (is_global) "zig_extern " else "static ");
24912569 if (variable.is_threadlocal) try fwd_decl_writer.writeAll("zig_threadlocal ");
24922570 try o.dg.renderTypeAndName(fwd_decl_writer, o.dg.decl.ty, decl_c_value, .Mut, o.dg.decl.@"align", .Complete);
24932571 try fwd_decl_writer.writeAll(";\n");
2572 try genExports(o);
24942573
24952574 if (variable.is_extern) return;
24962575
......@@ -2536,7 +2615,7 @@ pub fn genHeader(dg: *DeclGen) error{ AnalysisFail, OutOfMemory }!void {
25362615 const is_global = dg.declIsGlobal(tv);
25372616 if (is_global) {
25382617 try writer.writeAll("zig_extern ");
2539 try dg.renderFunctionSignature(writer, .Complete);
2618 try dg.renderFunctionSignature(writer, .Complete, 0);
25402619 try dg.fwd_decl.appendSlice(";\n");
25412620 }
25422621 },
......@@ -3676,7 +3755,7 @@ fn airCall(
36763755 };
36773756 };
36783757 name = f.object.dg.module.declPtr(fn_decl).name;
3679 try f.object.dg.renderDeclName(writer, fn_decl);
3758 try f.object.dg.renderDeclName(writer, fn_decl, 0);
36803759 break :callee;
36813760 }
36823761 // Fall back to function pointer call.
......@@ -4195,7 +4274,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
41954274 }
41964275 }
41974276 {
4198 const asm_source = std.mem.sliceAsBytes(f.air.extra[extra_i..])[0..extra.data.source_len];
4277 const asm_source = mem.sliceAsBytes(f.air.extra[extra_i..])[0..extra.data.source_len];
41994278
42004279 var stack = std.heap.stackFallback(256, f.object.dg.gpa);
42014280 const allocator = stack.get();
......@@ -4204,29 +4283,43 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
42044283
42054284 var src_i: usize = 0;
42064285 var dst_i: usize = 0;
4207 while (src_i < asm_source.len) : (src_i += 1) {
4208 fixed_asm_source[dst_i] = asm_source[src_i];
4209 dst_i += 1;
4210 if (asm_source[src_i] != '%' or src_i + 1 >= asm_source.len) continue;
4286 while (true) {
4287 const literal = mem.sliceTo(asm_source[src_i..], '%');
4288 src_i += literal.len;
4289
4290 mem.copy(u8, fixed_asm_source[dst_i..], literal);
4291 dst_i += literal.len;
4292
4293 if (src_i >= asm_source.len) break;
4294
42114295 src_i += 1;
4296 if (src_i >= asm_source.len)
4297 return f.fail("CBE: invalid inline asm string '{s}'", .{asm_source});
4298
4299 fixed_asm_source[dst_i] = '%';
4300 dst_i += 1;
4301
42124302 if (asm_source[src_i] != '[') {
4213 // This handles %%
4303 // This also handles %%
42144304 fixed_asm_source[dst_i] = asm_source[src_i];
4305 src_i += 1;
42154306 dst_i += 1;
42164307 continue;
42174308 }
4218 const len = std.mem.indexOfScalar(u8, asm_source[src_i + 1 ..], ']') orelse
4219 return f.fail("CBE: invalid inline asm string '{s}'", .{asm_source});
4220 if (std.mem.indexOfScalar(u8, asm_source[src_i + 1 ..][0..len], ':')) |colon| {
4221 const modifier = asm_source[src_i + 1 + colon + 1 .. src_i + 1 + len];
4222 std.mem.copy(u8, fixed_asm_source[dst_i..], modifier);
4223 dst_i += modifier.len;
42244309
4225 const name = asm_source[src_i .. src_i + 1 + colon];
4226 std.mem.copy(u8, fixed_asm_source[dst_i..], name);
4310 const desc = mem.sliceTo(asm_source[src_i..], ']');
4311 if (mem.indexOfScalar(u8, desc, ':')) |colon| {
4312 const name = desc[0..colon];
4313 const modifier = desc[colon + 1 ..];
4314
4315 mem.copy(u8, fixed_asm_source[dst_i..], modifier);
4316 dst_i += modifier.len;
4317 mem.copy(u8, fixed_asm_source[dst_i..], name);
42274318 dst_i += name.len;
42284319
4229 src_i += len;
4320 src_i += desc.len;
4321 if (src_i >= asm_source.len)
4322 return f.fail("CBE: invalid inline asm string '{s}'", .{asm_source});
42304323 }
42314324 }
42324325
......@@ -4535,9 +4628,18 @@ fn structFieldPtr(f: *Function, inst: Air.Inst.Index, struct_ptr_ty: Type, struc
45354628 else => .none,
45364629 };
45374630
4538 const field_name: CValue = switch (struct_ty.tag()) {
4631 const FieldLoc = union(enum) {
4632 begin: void,
4633 field: CValue,
4634 end: void,
4635 };
4636 const field_loc = switch (struct_ty.tag()) {
45394637 .@"struct" => switch (struct_ty.containerLayout()) {
4540 .Auto, .Extern => CValue{ .identifier = struct_ty.structFieldName(index) },
4638 .Auto, .Extern => for (struct_ty.structFields().values()[index..]) |field, offset| {
4639 if (field.ty.hasRuntimeBitsIgnoreComptime()) break FieldLoc{ .field = .{
4640 .identifier = struct_ty.structFieldName(index + offset),
4641 } };
4642 } else @as(FieldLoc, .end),
45414643 .Packed => if (field_ptr_info.data.host_size == 0) {
45424644 const target = f.object.dg.module.getTarget();
45434645
......@@ -4562,40 +4664,43 @@ fn structFieldPtr(f: *Function, inst: Air.Inst.Index, struct_ptr_ty: Type, struc
45624664 try f.writeCValue(writer, struct_ptr, .Other);
45634665 try writer.print(")[{}];\n", .{try f.fmtIntLiteral(Type.usize, byte_offset_val)});
45644666 return local;
4565 } else @as(CValue, CValue.none), // this @as is needed because of a stage1 bug
4667 } else @as(FieldLoc, .begin),
45664668 },
45674669 .@"union", .union_safety_tagged, .union_tagged => if (struct_ty.containerLayout() == .Packed) {
45684670 try f.writeCValue(writer, struct_ptr, .Other);
45694671 try writer.writeAll(";\n");
45704672 return local;
4571 } else .{
4673 } else if (field_ty.hasRuntimeBitsIgnoreComptime()) FieldLoc{ .field = .{
45724674 .identifier = struct_ty.unionFields().keys()[index],
4573 },
4675 } } else @as(FieldLoc, .end),
45744676 .tuple, .anon_struct => field_name: {
45754677 const tuple = struct_ty.tupleFields();
45764678 if (tuple.values[index].tag() != .unreachable_value) return CValue.none;
45774679
45784680 var id: usize = 0;
4579 for (tuple.values[0..index]) |value|
4580 id += @boolToInt(value.tag() == .unreachable_value);
4581 break :field_name .{ .field = id };
4681 break :field_name for (tuple.values) |value, i| {
4682 if (value.tag() != .unreachable_value) continue;
4683 if (!tuple.types[i].hasRuntimeBitsIgnoreComptime()) continue;
4684 if (i >= index) break FieldLoc{ .field = .{ .field = id } };
4685 id += 1;
4686 } else @as(FieldLoc, .end);
45824687 },
45834688 else => unreachable,
45844689 };
45854690
4586 if (field_ty.hasRuntimeBitsIgnoreComptime()) {
4587 try writer.writeByte('&');
4588 if (extra_name != .none) {
4691 try writer.writeByte('&');
4692 switch (field_loc) {
4693 .begin, .end => {
4694 try writer.writeByte('(');
4695 try f.writeCValue(writer, struct_ptr, .Other);
4696 try writer.print(")[{}]", .{@boolToInt(field_loc == .end)});
4697 },
4698 .field => |field| if (extra_name != .none) {
45894699 try f.writeCValueDerefMember(writer, struct_ptr, extra_name);
4590 if (field_name != .none) {
4591 try writer.writeByte('.');
4592 try f.writeCValue(writer, field_name, .Other);
4593 }
4594 } else if (field_name != .none)
4595 try f.writeCValueDerefMember(writer, struct_ptr, field_name)
4596 else
4597 try f.writeCValueDeref(writer, struct_ptr);
4598 } else try f.writeCValue(writer, struct_ptr, .Other);
4700 try writer.writeByte('.');
4701 try f.writeCValue(writer, field, .Other);
4702 } else try f.writeCValueDerefMember(writer, struct_ptr, field),
4703 }
45994704 try writer.writeAll(";\n");
46004705 return local;
46014706}
src/link/C.zig+20-6
......@@ -290,9 +290,17 @@ pub fn flushModule(self: *C, comp: *Compilation, prog_node: *std.Progress.Node)
290290 f.remaining_decls.putAssumeCapacityNoClobber(decl_index, {});
291291 }
292292
293 while (f.remaining_decls.popOrNull()) |kv| {
294 const decl_index = kv.key;
295 try self.flushDecl(&f, decl_index);
293 {
294 var export_names = std.StringHashMapUnmanaged(void){};
295 defer export_names.deinit(gpa);
296 try export_names.ensureTotalCapacity(gpa, @intCast(u32, module.decl_exports.entries.len));
297 for (module.decl_exports.values()) |exports| for (exports.items) |@"export"|
298 try export_names.put(gpa, @"export".options.name, {});
299
300 while (f.remaining_decls.popOrNull()) |kv| {
301 const decl_index = kv.key;
302 try self.flushDecl(&f, decl_index, export_names);
303 }
296304 }
297305
298306 f.all_buffers.items[typedef_index] = .{
......@@ -415,7 +423,12 @@ fn flushErrDecls(self: *C, f: *Flush) FlushDeclError!void {
415423}
416424
417425/// Assumes `decl` was in the `remaining_decls` set, and has already been removed.
418fn flushDecl(self: *C, f: *Flush, decl_index: Module.Decl.Index) FlushDeclError!void {
426fn flushDecl(
427 self: *C,
428 f: *Flush,
429 decl_index: Module.Decl.Index,
430 export_names: std.StringHashMapUnmanaged(void),
431) FlushDeclError!void {
419432 const module = self.base.options.module.?;
420433 const decl = module.declPtr(decl_index);
421434 // Before flushing any particular Decl we must ensure its
......@@ -423,7 +436,7 @@ fn flushDecl(self: *C, f: *Flush, decl_index: Module.Decl.Index) FlushDeclError!
423436 // file comes out correctly.
424437 for (decl.dependencies.keys()) |dep| {
425438 if (f.remaining_decls.swapRemove(dep)) {
426 try flushDecl(self, f, dep);
439 try flushDecl(self, f, dep, export_names);
427440 }
428441 }
429442
......@@ -432,7 +445,8 @@ fn flushDecl(self: *C, f: *Flush, decl_index: Module.Decl.Index) FlushDeclError!
432445
433446 try self.flushTypedefs(f, decl_block.typedefs);
434447 try f.all_buffers.ensureUnusedCapacity(gpa, 2);
435 f.appendBufAssumeCapacity(decl_block.fwd_decl.items);
448 if (!(decl.isExtern() and export_names.contains(mem.span(decl.name))))
449 f.appendBufAssumeCapacity(decl_block.fwd_decl.items);
436450}
437451
438452pub fn flushEmitH(module: *Module) !void {
test/behavior/align.zig-1
......@@ -520,7 +520,6 @@ test "align(@alignOf(T)) T does not force resolution of T" {
520520
521521test "align(N) on functions" {
522522 if (builtin.zig_backend == .stage1) return error.SkipZigTest;
523 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
524523 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
525524 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
526525 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
test/behavior/basic.zig-1
......@@ -788,7 +788,6 @@ test "extern variable with non-pointer opaque type" {
788788 return error.SkipZigTest;
789789 }
790790 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
791 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
792791 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
793792 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
794793 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
test/behavior/bugs/12680.zig-1
......@@ -8,7 +8,6 @@ extern fn test_func() callconv(.C) usize;
88test "export a function twice" {
99 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1010 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
11 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
1211 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
1312 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
1413
test/behavior/bugs/3112.zig-1
......@@ -14,7 +14,6 @@ fn prev(p: ?State) void {
1414test "zig test crash" {
1515 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1616 if (builtin.zig_backend == .stage1) return error.SkipZigTest;
17 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
1817 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
1918 var global: State = undefined;
2019 global.enter = prev;
test/behavior/bugs/529.zig-1
......@@ -11,7 +11,6 @@ comptime {
1111const builtin = @import("builtin");
1212
1313test "issue 529 fixed" {
14 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
1514 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1615 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1716 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
test/behavior/optional.zig-1
......@@ -184,7 +184,6 @@ test "nested orelse" {
184184}
185185
186186test "self-referential struct through a slice of optional" {
187 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
188187 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
189188
190189 const S = struct {
test/behavior/struct.zig-1
......@@ -1390,7 +1390,6 @@ test "address of zero-bit field is equal to address of only field" {
13901390 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
13911391 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
13921392 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1393 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
13941393
13951394 {
13961395 const A = struct { b: void = {}, u: u8 };