authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-04-25 00:20:49-04:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-04-25 13:42:10-04:00
logf1782c07a9c1c66da843e6c7f345e9f004bc3b45
tree76b6b21b4f24df2981941e0e3d3f03bdebc599b2
parente485d0062130e9a76f3916ff57c6740a8e7529d3

cbe: implement @extern


2 files changed, 59 insertions(+), 38 deletions(-)

lib/zig.h+8
......@@ -188,6 +188,14 @@ typedef char bool;
188188#define zig_export(sig, symbol, name) __asm(name " = " symbol)
189189#endif
190190
191#if zig_has_attribute(weak) || defined(zig_gnuc)
192#define zig_weak_linkage __attribute__((weak))
193#elif _MSC_VER
194#define zig_weak_linkage __declspec(selectany)
195#else
196#define zig_weak_linkage zig_weak_linkage_unavailable
197#endif
198
191199#if zig_has_builtin(trap)
192200#define zig_trap() __builtin_trap()
193201#elif _MSC_VER && (_M_IX86 || _M_X64)
src/codegen/c.zig+51-38
......@@ -220,8 +220,8 @@ fn isReservedIdent(ident: []const u8) bool {
220220 'A'...'Z', '_' => return true,
221221 else => return false,
222222 }
223 } else if (std.mem.startsWith(u8, ident, "DUMMYSTRUCTNAME") or
224 std.mem.startsWith(u8, ident, "DUMMYUNIONNAME"))
223 } else if (mem.startsWith(u8, ident, "DUMMYSTRUCTNAME") or
224 mem.startsWith(u8, ident, "DUMMYUNIONNAME"))
225225 { // windows.h
226226 return true;
227227 } else return reserved_idents.has(ident);
......@@ -498,7 +498,7 @@ pub const Object = struct {
498498
499499/// This data is available both when outputting .c code and when outputting an .h file.
500500pub const DeclGen = struct {
501 gpa: std.mem.Allocator,
501 gpa: mem.Allocator,
502502 module: *Module,
503503 decl: ?*Decl,
504504 decl_index: Decl.OptionalIndex,
......@@ -536,6 +536,9 @@ pub const DeclGen = struct {
536536 if (func.data.owner_decl != decl_index)
537537 return dg.renderDeclValue(writer, ty, val, func.data.owner_decl, location);
538538
539 if (decl.val.castTag(.variable)) |var_payload|
540 try dg.renderFwdDecl(decl_index, var_payload.data);
541
539542 if (ty.isSlice()) {
540543 if (location == .StaticInitializer) {
541544 try writer.writeByte('{');
......@@ -1816,8 +1819,23 @@ pub const DeclGen = struct {
18161819 try dg.writeCValue(writer, member);
18171820 }
18181821
1819 const IdentHasher = std.crypto.auth.siphash.SipHash128(1, 3);
1820 const ident_hasher_init: IdentHasher = IdentHasher.init(&[_]u8{0} ** IdentHasher.key_length);
1822 fn renderFwdDecl(dg: *DeclGen, decl_index: Decl.Index, variable: *Module.Var) !void {
1823 const decl = dg.module.declPtr(decl_index);
1824 const fwd_decl_writer = dg.fwd_decl.writer();
1825 const is_global = dg.declIsGlobal(.{ .ty = decl.ty, .val = decl.val }) or variable.is_extern;
1826 try fwd_decl_writer.writeAll(if (is_global) "zig_extern " else "static ");
1827 if (variable.is_threadlocal) try fwd_decl_writer.writeAll("zig_threadlocal ");
1828 if (variable.is_weak_linkage) try fwd_decl_writer.writeAll("zig_weak_linkage ");
1829 try dg.renderTypeAndName(
1830 fwd_decl_writer,
1831 decl.ty,
1832 .{ .decl = decl_index },
1833 CQualifiers.init(.{ .@"const" = !variable.is_mutable }),
1834 decl.@"align",
1835 .complete,
1836 );
1837 try fwd_decl_writer.writeAll(";\n");
1838 }
18211839
18221840 fn renderDeclName(dg: *DeclGen, writer: anytype, decl_index: Decl.Index, export_index: u32) !void {
18231841 const decl = dg.module.declPtr(decl_index);
......@@ -1826,7 +1844,7 @@ pub const DeclGen = struct {
18261844 if (dg.module.decl_exports.get(decl_index)) |exports| {
18271845 try writer.writeAll(exports.items[export_index].options.name);
18281846 } else if (decl.isExtern()) {
1829 try writer.writeAll(mem.sliceTo(decl.name, 0));
1847 try writer.writeAll(mem.span(decl.name));
18301848 } else {
18311849 // MSVC has a limit of 4095 character token length limit, and fmtIdent can (worst case),
18321850 // expand to 3x the length of its input, but let's cut it off at a much shorter limit.
......@@ -2393,9 +2411,9 @@ pub fn genErrDecls(o: *Object) !void {
23932411 const name_buf = try o.dg.gpa.alloc(u8, name_prefix.len + max_name_len);
23942412 defer o.dg.gpa.free(name_buf);
23952413
2396 std.mem.copy(u8, name_buf, name_prefix);
2414 mem.copy(u8, name_buf, name_prefix);
23972415 for (o.dg.module.error_name_list.items) |name| {
2398 std.mem.copy(u8, name_buf[name_prefix.len..], name);
2416 mem.copy(u8, name_buf[name_prefix.len..], name);
23992417 const identifier = name_buf[0 .. name_prefix.len + name.len];
24002418
24012419 var name_ty_pl = Type.Payload.Len{ .base = .{ .tag = .array_u8_sentinel_0 }, .data = name.len };
......@@ -2641,21 +2659,16 @@ pub fn genDecl(o: *Object) !void {
26412659 try genExports(o);
26422660 } else if (tv.val.castTag(.variable)) |var_payload| {
26432661 const variable: *Module.Var = var_payload.data;
2644
2645 const is_global = o.dg.declIsGlobal(tv) or variable.is_extern;
2646 const fwd_decl_writer = o.dg.fwd_decl.writer();
2647
2648 try fwd_decl_writer.writeAll(if (is_global) "zig_extern " else "static ");
2649 if (variable.is_threadlocal) try fwd_decl_writer.writeAll("zig_threadlocal ");
2650 try o.dg.renderTypeAndName(fwd_decl_writer, decl.ty, decl_c_value, .{}, decl.@"align", .complete);
2651 try fwd_decl_writer.writeAll(";\n");
2662 try o.dg.renderFwdDecl(decl_c_value.decl, variable);
26522663 try genExports(o);
26532664
26542665 if (variable.is_extern) return;
26552666
2667 const is_global = o.dg.declIsGlobal(tv) or variable.is_extern;
26562668 const w = o.writer();
26572669 if (!is_global) try w.writeAll("static ");
26582670 if (variable.is_threadlocal) try w.writeAll("zig_threadlocal ");
2671 if (variable.is_weak_linkage) try w.writeAll("zig_weak_linkage ");
26592672 if (decl.@"linksection") |section| try w.print("zig_linksection(\"{s}\", ", .{section});
26602673 try o.dg.renderTypeAndName(w, tv.ty, decl_c_value, .{}, decl.@"align", .complete);
26612674 if (decl.@"linksection" != null) try w.writeAll(", read, write)");
......@@ -4729,9 +4742,9 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
47294742 const locals_begin = @intCast(LocalIndex, f.locals.items.len);
47304743 const constraints_extra_begin = extra_i;
47314744 for (outputs) |output| {
4732 const extra_bytes = std.mem.sliceAsBytes(f.air.extra[extra_i..]);
4733 const constraint = std.mem.sliceTo(extra_bytes, 0);
4734 const name = std.mem.sliceTo(extra_bytes[constraint.len + 1 ..], 0);
4745 const extra_bytes = mem.sliceAsBytes(f.air.extra[extra_i..]);
4746 const constraint = mem.sliceTo(extra_bytes, 0);
4747 const name = mem.sliceTo(extra_bytes[constraint.len + 1 ..], 0);
47354748 // This equation accounts for the fact that even if we have exactly 4 bytes
47364749 // for the string, we still use the next u32 for the null terminator.
47374750 extra_i += (constraint.len + name.len + (2 + 3)) / 4;
......@@ -4761,14 +4774,14 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
47614774 }
47624775 }
47634776 for (inputs) |input| {
4764 const extra_bytes = std.mem.sliceAsBytes(f.air.extra[extra_i..]);
4765 const constraint = std.mem.sliceTo(extra_bytes, 0);
4766 const name = std.mem.sliceTo(extra_bytes[constraint.len + 1 ..], 0);
4777 const extra_bytes = mem.sliceAsBytes(f.air.extra[extra_i..]);
4778 const constraint = mem.sliceTo(extra_bytes, 0);
4779 const name = mem.sliceTo(extra_bytes[constraint.len + 1 ..], 0);
47674780 // This equation accounts for the fact that even if we have exactly 4 bytes
47684781 // for the string, we still use the next u32 for the null terminator.
47694782 extra_i += (constraint.len + name.len + (2 + 3)) / 4;
47704783
4771 if (constraint.len < 1 or std.mem.indexOfScalar(u8, "=+&%", constraint[0]) != null or
4784 if (constraint.len < 1 or mem.indexOfScalar(u8, "=+&%", constraint[0]) != null or
47724785 (constraint[0] == '{' and constraint[constraint.len - 1] != '}'))
47734786 {
47744787 return f.fail("CBE: constraint not supported: '{s}'", .{constraint});
......@@ -4794,7 +4807,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
47944807 }
47954808 }
47964809 for (0..clobbers_len) |_| {
4797 const clobber = std.mem.sliceTo(std.mem.sliceAsBytes(f.air.extra[extra_i..]), 0);
4810 const clobber = mem.sliceTo(mem.sliceAsBytes(f.air.extra[extra_i..]), 0);
47984811 // This equation accounts for the fact that even if we have exactly 4 bytes
47994812 // for the string, we still use the next u32 for the null terminator.
48004813 extra_i += clobber.len / 4 + 1;
......@@ -4859,16 +4872,16 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
48594872 var locals_index = locals_begin;
48604873 try writer.writeByte(':');
48614874 for (outputs, 0..) |output, index| {
4862 const extra_bytes = std.mem.sliceAsBytes(f.air.extra[extra_i..]);
4863 const constraint = std.mem.sliceTo(extra_bytes, 0);
4864 const name = std.mem.sliceTo(extra_bytes[constraint.len + 1 ..], 0);
4875 const extra_bytes = mem.sliceAsBytes(f.air.extra[extra_i..]);
4876 const constraint = mem.sliceTo(extra_bytes, 0);
4877 const name = mem.sliceTo(extra_bytes[constraint.len + 1 ..], 0);
48654878 // This equation accounts for the fact that even if we have exactly 4 bytes
48664879 // for the string, we still use the next u32 for the null terminator.
48674880 extra_i += (constraint.len + name.len + (2 + 3)) / 4;
48684881
48694882 if (index > 0) try writer.writeByte(',');
48704883 try writer.writeByte(' ');
4871 if (!std.mem.eql(u8, name, "_")) try writer.print("[{s}]", .{name});
4884 if (!mem.eql(u8, name, "_")) try writer.print("[{s}]", .{name});
48724885 const is_reg = constraint[1] == '{';
48734886 try writer.print("{s}(", .{fmtStringLiteral(if (is_reg) "=r" else constraint, null)});
48744887 if (is_reg) {
......@@ -4883,16 +4896,16 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
48834896 }
48844897 try writer.writeByte(':');
48854898 for (inputs, 0..) |input, index| {
4886 const extra_bytes = std.mem.sliceAsBytes(f.air.extra[extra_i..]);
4887 const constraint = std.mem.sliceTo(extra_bytes, 0);
4888 const name = std.mem.sliceTo(extra_bytes[constraint.len + 1 ..], 0);
4899 const extra_bytes = mem.sliceAsBytes(f.air.extra[extra_i..]);
4900 const constraint = mem.sliceTo(extra_bytes, 0);
4901 const name = mem.sliceTo(extra_bytes[constraint.len + 1 ..], 0);
48894902 // This equation accounts for the fact that even if we have exactly 4 bytes
48904903 // for the string, we still use the next u32 for the null terminator.
48914904 extra_i += (constraint.len + name.len + (2 + 3)) / 4;
48924905
48934906 if (index > 0) try writer.writeByte(',');
48944907 try writer.writeByte(' ');
4895 if (!std.mem.eql(u8, name, "_")) try writer.print("[{s}]", .{name});
4908 if (!mem.eql(u8, name, "_")) try writer.print("[{s}]", .{name});
48964909
48974910 const is_reg = constraint[0] == '{';
48984911 const input_val = try f.resolveInst(input);
......@@ -4906,7 +4919,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
49064919 }
49074920 try writer.writeByte(':');
49084921 for (0..clobbers_len) |clobber_i| {
4909 const clobber = std.mem.sliceTo(std.mem.sliceAsBytes(f.air.extra[extra_i..]), 0);
4922 const clobber = mem.sliceTo(mem.sliceAsBytes(f.air.extra[extra_i..]), 0);
49104923 // This equation accounts for the fact that even if we have exactly 4 bytes
49114924 // for the string, we still use the next u32 for the null terminator.
49124925 extra_i += clobber.len / 4 + 1;
......@@ -4921,9 +4934,9 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
49214934 extra_i = constraints_extra_begin;
49224935 locals_index = locals_begin;
49234936 for (outputs) |output| {
4924 const extra_bytes = std.mem.sliceAsBytes(f.air.extra[extra_i..]);
4925 const constraint = std.mem.sliceTo(extra_bytes, 0);
4926 const name = std.mem.sliceTo(extra_bytes[constraint.len + 1 ..], 0);
4937 const extra_bytes = mem.sliceAsBytes(f.air.extra[extra_i..]);
4938 const constraint = mem.sliceTo(extra_bytes, 0);
4939 const name = mem.sliceTo(extra_bytes[constraint.len + 1 ..], 0);
49274940 // This equation accounts for the fact that even if we have exactly 4 bytes
49284941 // for the string, we still use the next u32 for the null terminator.
49294942 extra_i += (constraint.len + name.len + (2 + 3)) / 4;
......@@ -7274,7 +7287,7 @@ fn formatIntLiteral(
72747287 var int_buf: Value.BigIntSpace = undefined;
72757288 const int = if (data.val.isUndefDeep()) blk: {
72767289 undef_limbs = try allocator.alloc(BigIntLimb, BigInt.calcTwosCompLimbCount(data.int_info.bits));
7277 std.mem.set(BigIntLimb, undef_limbs, undefPattern(BigIntLimb));
7290 mem.set(BigIntLimb, undef_limbs, undefPattern(BigIntLimb));
72787291
72797292 var undef_int = BigInt.Mutable{
72807293 .limbs = undef_limbs,
......@@ -7369,7 +7382,7 @@ fn formatIntLiteral(
73697382 } else {
73707383 try data.cty.renderLiteralPrefix(writer, data.kind);
73717384 wrap.convertToTwosComplement(int, data.int_info.signedness, c_bits);
7372 std.mem.set(BigIntLimb, wrap.limbs[wrap.len..], 0);
7385 mem.set(BigIntLimb, wrap.limbs[wrap.len..], 0);
73737386 wrap.len = wrap.limbs.len;
73747387 const limbs_per_c_limb = @divExact(wrap.len, c_limb_info.count);
73757388