cbe: support more symbol attributes

implement codegen for:

- decl weak linkage
- decl aliases
- fn decl weak linkage

windows msvc:
- `__declspec(selectany)` is not supported for functions
- skip weak linkage for functions

closes #17050
This commit is contained in:
Michael Dusan 2023-09-24 02:57:03 -04:00 committed by Andrew Kelley
parent fb6fff2561
commit 127198e58c
2 changed files with 61 additions and 17 deletions

View File

@ -190,10 +190,13 @@ typedef char bool;
#if zig_has_attribute(weak) || defined(zig_gnuc)
#define zig_weak_linkage __attribute__((weak))
#define zig_weak_linkage_fn __attribute__((weak))
#elif _MSC_VER
#define zig_weak_linkage __declspec(selectany)
#define zig_weak_linkage_fn
#else
#define zig_weak_linkage zig_weak_linkage_unavailable
#define zig_weak_linkage_fn zig_weak_linkage_unavailable
#endif
#if zig_has_builtin(trap)

View File

@ -1840,20 +1840,24 @@ pub const DeclGen = struct {
fn renderFwdDecl(dg: *DeclGen, decl_index: Decl.Index, variable: InternPool.Key.Variable) !void {
const decl = dg.module.declPtr(decl_index);
const fwd_decl_writer = dg.fwd_decl.writer();
const fwd = dg.fwd_decl.writer();
const is_global = dg.declIsGlobal(.{ .ty = decl.ty, .val = decl.val }) or variable.is_extern;
try fwd_decl_writer.writeAll(if (is_global) "zig_extern " else "static ");
if (variable.is_threadlocal) try fwd_decl_writer.writeAll("zig_threadlocal ");
if (variable.is_weak_linkage) try fwd_decl_writer.writeAll("zig_weak_linkage ");
try fwd.writeAll(if (is_global) "zig_extern " else "static ");
const export_weak_linkage = if (dg.module.decl_exports.get(decl_index)) |exports|
exports.items[0].opts.linkage == .Weak
else
false;
if (variable.is_weak_linkage or export_weak_linkage) try fwd.writeAll("zig_weak_linkage ");
if (variable.is_threadlocal) try fwd.writeAll("zig_threadlocal ");
try dg.renderTypeAndName(
fwd_decl_writer,
fwd,
decl.ty,
.{ .decl = decl_index },
CQualifiers.init(.{ .@"const" = variable.is_const }),
decl.alignment,
.complete,
);
try fwd_decl_writer.writeAll(";\n");
try fwd.writeAll(";\n");
}
fn renderDeclName(dg: *DeclGen, writer: anytype, decl_index: Decl.Index, export_index: u32) !void {
@ -2489,16 +2493,50 @@ fn genExports(o: *Object) !void {
const mod = o.dg.module;
const ip = &mod.intern_pool;
const fwd_decl_writer = o.dg.fwd_decl.writer();
if (mod.decl_exports.get(o.dg.decl_index.unwrap().?)) |exports| {
for (exports.items[1..], 1..) |@"export", i| {
try fwd_decl_writer.writeAll("zig_export(");
try o.dg.renderFunctionSignature(fwd_decl_writer, o.dg.decl_index.unwrap().?, .forward, .{ .export_index = @as(u32, @intCast(i)) });
try fwd_decl_writer.print(", {s}, {s});\n", .{
fmtStringLiteral(ip.stringToSlice(exports.items[0].opts.name), null),
fmtStringLiteral(ip.stringToSlice(@"export".opts.name), null),
});
}
const decl = o.dg.decl.?;
const decl_index = o.dg.decl_index.unwrap().?;
const tv: TypedValue = .{ .ty = decl.ty, .val = (try decl.internValue(mod)).toValue() };
const fwd = o.dg.fwd_decl.writer();
const exports = mod.decl_exports.get(decl_index) orelse return;
if (exports.items.len < 2) return;
switch (ip.indexToKey(tv.val.toIntern())) {
.func => {
for (exports.items[1..], 1..) |@"export", i| {
try fwd.writeAll("zig_export(");
if (exports.items[i].opts.linkage == .Weak) try fwd.writeAll("zig_weak_linkage_fn ");
try o.dg.renderFunctionSignature(fwd, decl_index, .forward, .{ .export_index = @as(u32, @intCast(i)) });
try fwd.print(", {s}, {s});\n", .{
fmtStringLiteral(ip.stringToSlice(exports.items[0].opts.name), null),
fmtStringLiteral(ip.stringToSlice(@"export".opts.name), null),
});
}
},
.extern_func => {
// TODO: when sema allows re-exporting extern decls
unreachable;
},
.variable => |variable| {
for (exports.items[1..], 1..) |@"export", i| {
try fwd.writeAll("zig_export(");
if (exports.items[i].opts.linkage == .Weak) try fwd.writeAll("zig_weak_linkage ");
const alias = ip.stringToSlice(@"export".opts.name);
try o.dg.renderTypeAndName(
fwd,
decl.ty,
.{ .identifier = alias },
CQualifiers.init(.{ .@"const" = variable.is_const }),
decl.alignment,
.complete,
);
try fwd.print(", {s}, {s});\n", .{
fmtStringLiteral(ip.stringToSlice(exports.items[0].opts.name), null),
fmtStringLiteral(alias, null),
});
}
},
else => {},
}
}
@ -2593,6 +2631,7 @@ pub fn genFunc(f: *Function) !void {
defer tracy.end();
const o = &f.object;
const mod = o.dg.module;
const gpa = o.dg.gpa;
const decl_index = o.dg.decl_index.unwrap().?;
const tv: TypedValue = .{
@ -2606,6 +2645,8 @@ pub fn genFunc(f: *Function) !void {
const is_global = o.dg.declIsGlobal(tv);
const fwd_decl_writer = o.dg.fwd_decl.writer();
try fwd_decl_writer.writeAll(if (is_global) "zig_extern " else "static ");
if (mod.decl_exports.get(decl_index)) |exports|
if (exports.items[0].opts.linkage == .Weak) try fwd_decl_writer.writeAll("zig_weak_linkage_fn ");
try o.dg.renderFunctionSignature(fwd_decl_writer, decl_index, .forward, .{ .export_index = 0 });
try fwd_decl_writer.writeAll(";\n");
try genExports(o);
@ -2698,8 +2739,8 @@ pub fn genDecl(o: *Object) !void {
const is_global = o.dg.declIsGlobal(tv) or variable.is_extern;
const w = o.writer();
if (!is_global) try w.writeAll("static ");
if (variable.is_threadlocal) try w.writeAll("zig_threadlocal ");
if (variable.is_weak_linkage) try w.writeAll("zig_weak_linkage ");
if (variable.is_threadlocal) try w.writeAll("zig_threadlocal ");
if (mod.intern_pool.stringToSliceUnwrap(decl.@"linksection")) |s|
try w.print("zig_linksection(\"{s}\", ", .{s});
try o.dg.renderTypeAndName(w, tv.ty, decl_c_value, .{}, decl.alignment, .complete);