Skip to content

Commit a981c72

Browse files
authored
Merge branch 'ziglang:master' into i19875
2 parents 92d1276 + bfbf4ba commit a981c72

File tree

7 files changed

+100
-47
lines changed

7 files changed

+100
-47
lines changed

lib/compiler/aro_translate_c.zig

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1502,19 +1502,29 @@ pub fn ScopeExtra(comptime ScopeExtraContext: type, comptime ScopeExtraType: typ
15021502
return scope.base.parent.?.getAlias(name);
15031503
}
15041504

1505-
/// Finds the (potentially) mangled struct name for a locally scoped extern variable given the original declaration name.
1505+
/// Finds the (potentially) mangled struct name for a locally scoped extern variable or function given the original declaration name.
15061506
///
15071507
/// Block scoped extern declarations translate to:
15081508
/// const MangledStructName = struct {extern [qualifiers] original_extern_variable_name: [type]};
15091509
/// This finds MangledStructName given original_extern_variable_name for referencing correctly in transDeclRefExpr()
15101510
pub fn getLocalExternAlias(scope: *Block, name: []const u8) ?[]const u8 {
15111511
for (scope.statements.items) |node| {
1512-
if (node.tag() == .extern_local_var) {
1513-
const parent_node = node.castTag(.extern_local_var).?;
1514-
const init_node = parent_node.data.init.castTag(.var_decl).?;
1515-
if (std.mem.eql(u8, init_node.data.name, name)) {
1516-
return parent_node.data.name;
1517-
}
1512+
switch (node.tag()) {
1513+
.extern_local_var => {
1514+
const parent_node = node.castTag(.extern_local_var).?;
1515+
const init_node = parent_node.data.init.castTag(.var_decl).?;
1516+
if (std.mem.eql(u8, init_node.data.name, name)) {
1517+
return parent_node.data.name;
1518+
}
1519+
},
1520+
.extern_local_fn => {
1521+
const parent_node = node.castTag(.extern_local_fn).?;
1522+
const init_node = parent_node.data.init.castTag(.func).?;
1523+
if (std.mem.eql(u8, init_node.data.name.?, name)) {
1524+
return parent_node.data.name;
1525+
}
1526+
},
1527+
else => {},
15181528
}
15191529
}
15201530
return null;

lib/compiler/aro_translate_c/ast.zig

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ pub const Node = extern union {
5757
static_local_var,
5858
/// const ExternLocal_name = struct { init }
5959
extern_local_var,
60+
/// const ExternLocal_name = struct { init }
61+
extern_local_fn,
6062
/// var name = init.*
6163
mut_str,
6264
func,
@@ -367,7 +369,13 @@ pub const Node = extern union {
367369
.c_pointer, .single_pointer => Payload.Pointer,
368370
.array_type, .null_sentinel_array_type => Payload.Array,
369371
.arg_redecl, .alias, .fail_decl => Payload.ArgRedecl,
370-
.var_simple, .pub_var_simple, .static_local_var, .extern_local_var, .mut_str => Payload.SimpleVarDecl,
372+
.var_simple,
373+
.pub_var_simple,
374+
.static_local_var,
375+
.extern_local_var,
376+
.extern_local_fn,
377+
.mut_str,
378+
=> Payload.SimpleVarDecl,
371379
.enum_constant => Payload.EnumConstant,
372380
.array_filler => Payload.ArrayFiller,
373381
.pub_inline_fn => Payload.PubInlineFn,
@@ -1265,8 +1273,11 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
12651273
} },
12661274
});
12671275
},
1268-
.extern_local_var => {
1269-
const payload = node.castTag(.extern_local_var).?.data;
1276+
.extern_local_var, .extern_local_fn => {
1277+
const payload = if (node.tag() == .extern_local_var)
1278+
node.castTag(.extern_local_var).?.data
1279+
else
1280+
node.castTag(.extern_local_fn).?.data;
12701281

12711282
const const_tok = try c.addToken(.keyword_const, "const");
12721283
_ = try c.addIdentifier(payload.name);
@@ -2293,7 +2304,7 @@ fn renderNullSentinelArrayType(c: *Context, len: usize, elem_type: Node) !NodeIn
22932304
fn addSemicolonIfNeeded(c: *Context, node: Node) !void {
22942305
switch (node.tag()) {
22952306
.warning => unreachable,
2296-
.var_decl, .var_simple, .arg_redecl, .alias, .block, .empty_block, .block_single, .@"switch", .static_local_var, .extern_local_var, .mut_str => {},
2307+
.var_decl, .var_simple, .arg_redecl, .alias, .block, .empty_block, .block_single, .@"switch", .static_local_var, .extern_local_var, .extern_local_fn, .mut_str => {},
22972308
.while_true => {
22982309
const payload = node.castTag(.while_true).?.data;
22992310
return addSemicolonIfNotBlock(c, payload);
@@ -2390,6 +2401,7 @@ fn renderNodeGrouped(c: *Context, node: Node) !NodeIndex {
23902401
.builtin_extern,
23912402
.static_local_var,
23922403
.extern_local_var,
2404+
.extern_local_fn,
23932405
.mut_str,
23942406
.macro_arithmetic,
23952407
=> {

lib/std/os/linux.zig

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5151,7 +5151,6 @@ pub const NSIG = if (is_mips) 128 else 65;
51515151
pub const sigset_t = [1024 / 32]u32;
51525152

51535153
pub const all_mask: sigset_t = [_]u32{0xffffffff} ** @typeInfo(sigset_t).array.len;
5154-
pub const app_mask: sigset_t = [2]u32{ 0xfffffffc, 0x7fffffff } ++ [_]u32{0xffffffff} ** 30;
51555154

51565155
const k_sigaction_funcs = struct {
51575156
const handler = ?*align(1) const fn (i32) callconv(.c) void;

lib/std/posix.zig

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -724,9 +724,12 @@ pub fn raise(sig: u8) RaiseError!void {
724724
}
725725

726726
if (native_os == .linux) {
727+
// https://git.musl-libc.org/cgit/musl/commit/?id=0bed7e0acfd34e3fb63ca0e4d99b7592571355a9
728+
//
729+
// Unlike musl, libc-less Zig std does not have any internal signals for implementation purposes, so we
730+
// need to block all signals on the assumption that any of them could potentially fork() in a handler.
727731
var set: sigset_t = undefined;
728-
// block application signals
729-
sigprocmask(SIG.BLOCK, &linux.app_mask, &set);
732+
sigprocmask(SIG.BLOCK, &linux.all_mask, &set);
730733

731734
const tid = linux.gettid();
732735
const rc = linux.tkill(tid, sig);

lib/std/zig/system.zig

Lines changed: 17 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -125,40 +125,33 @@ pub fn getExternalExecutor(
125125
};
126126
}
127127

128+
if (options.allow_wasmtime and candidate.cpu.arch.isWasm()) {
129+
return Executor{ .wasmtime = "wasmtime" };
130+
}
131+
128132
switch (candidate.os.tag) {
129133
.windows => {
130134
if (options.allow_wine) {
131-
// x86_64 wine does not support emulating aarch64-windows and
132-
// vice versa.
133-
if (candidate.cpu.arch != builtin.cpu.arch and
134-
!(candidate.cpu.arch == .thumb and builtin.cpu.arch == .aarch64) and
135-
!(candidate.cpu.arch == .x86 and builtin.cpu.arch == .x86_64))
136-
{
137-
return bad_result;
138-
}
139-
switch (candidate.ptrBitWidth()) {
140-
32 => return Executor{ .wine = "wine" },
141-
64 => return Executor{ .wine = "wine64" },
142-
else => return bad_result,
143-
}
144-
}
145-
return bad_result;
146-
},
147-
.wasi => {
148-
if (options.allow_wasmtime) {
149-
switch (candidate.ptrBitWidth()) {
150-
32 => return Executor{ .wasmtime = "wasmtime" },
151-
else => return bad_result,
152-
}
135+
const wine_supported = switch (candidate.cpu.arch) {
136+
.thumb => switch (host.cpu.arch) {
137+
.arm, .thumb, .aarch64 => true,
138+
else => false,
139+
},
140+
.aarch64 => host.cpu.arch == .aarch64,
141+
.x86 => host.cpu.arch.isX86(),
142+
.x86_64 => host.cpu.arch == .x86_64,
143+
else => false,
144+
};
145+
return if (wine_supported) Executor{ .wine = "wine" } else bad_result;
153146
}
154147
return bad_result;
155148
},
156-
.macos => {
149+
.driverkit, .macos => {
157150
if (options.allow_darling) {
158151
// This check can be loosened once darling adds a QEMU-based emulation
159152
// layer for non-host architectures:
160153
// https://github.com/darlinghq/darling/issues/863
161-
if (candidate.cpu.arch != builtin.cpu.arch) {
154+
if (candidate.cpu.arch != host.cpu.arch) {
162155
return bad_result;
163156
}
164157
return Executor{ .darling = "darling" };

src/translate_c.zig

Lines changed: 40 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -325,7 +325,7 @@ fn declVisitorNamesOnly(c: *Context, decl: *const clang.Decl) Error!void {
325325
fn declVisitor(c: *Context, decl: *const clang.Decl) Error!void {
326326
switch (decl.getKind()) {
327327
.Function => {
328-
return visitFnDecl(c, @as(*const clang.FunctionDecl, @ptrCast(decl)));
328+
return transFnDecl(c, &c.global_scope.base, @as(*const clang.FunctionDecl, @ptrCast(decl)));
329329
},
330330
.Typedef => {
331331
try transTypeDef(c, &c.global_scope.base, @as(*const clang.TypedefNameDecl, @ptrCast(decl)));
@@ -367,15 +367,15 @@ fn transFileScopeAsm(c: *Context, scope: *Scope, file_scope_asm: *const clang.Fi
367367
try scope.appendNode(comptime_node);
368368
}
369369

370-
fn visitFnDecl(c: *Context, fn_decl: *const clang.FunctionDecl) Error!void {
370+
fn transFnDecl(c: *Context, scope: *Scope, fn_decl: *const clang.FunctionDecl) Error!void {
371371
const fn_name = try c.str(@as(*const clang.NamedDecl, @ptrCast(fn_decl)).getName_bytes_begin());
372372
if (c.global_scope.sym_table.contains(fn_name))
373373
return; // Avoid processing this decl twice
374374

375375
// Skip this declaration if a proper definition exists
376376
if (!fn_decl.isThisDeclarationADefinition()) {
377377
if (fn_decl.getDefinition()) |def|
378-
return visitFnDecl(c, def);
378+
return transFnDecl(c, scope, def);
379379
}
380380

381381
const fn_decl_loc = fn_decl.getLocation();
@@ -446,6 +446,9 @@ fn visitFnDecl(c: *Context, fn_decl: *const clang.FunctionDecl) Error!void {
446446
};
447447

448448
if (!decl_ctx.has_body) {
449+
if (scope.id != .root) {
450+
return addLocalExternFnDecl(c, scope, fn_name, Node.initPayload(&proto_node.base));
451+
}
449452
return addTopLevelDecl(c, fn_name, Node.initPayload(&proto_node.base));
450453
}
451454

@@ -455,7 +458,7 @@ fn visitFnDecl(c: *Context, fn_decl: *const clang.FunctionDecl) Error!void {
455458
block_scope.return_type = return_qt;
456459
defer block_scope.deinit();
457460

458-
const scope = &block_scope.base;
461+
const top_scope = &block_scope.base;
459462

460463
var param_id: c_uint = 0;
461464
for (proto_node.data.params) |*param| {
@@ -508,7 +511,7 @@ fn visitFnDecl(c: *Context, fn_decl: *const clang.FunctionDecl) Error!void {
508511
break :blk;
509512
}
510513

511-
const rhs = transZeroInitExpr(c, scope, fn_decl_loc, return_qt.getTypePtr()) catch |err| switch (err) {
514+
const rhs = transZeroInitExpr(c, top_scope, fn_decl_loc, return_qt.getTypePtr()) catch |err| switch (err) {
512515
error.OutOfMemory => |e| return e,
513516
error.UnsupportedTranslation,
514517
error.UnsupportedType,
@@ -1874,7 +1877,7 @@ fn transDeclStmtOne(
18741877
try transEnumDecl(c, scope, @as(*const clang.EnumDecl, @ptrCast(decl)));
18751878
},
18761879
.Function => {
1877-
try visitFnDecl(c, @as(*const clang.FunctionDecl, @ptrCast(decl)));
1880+
try transFnDecl(c, scope, @as(*const clang.FunctionDecl, @ptrCast(decl)));
18781881
},
18791882
else => {
18801883
const decl_name = try c.str(decl.getDeclKindName());
@@ -1903,11 +1906,19 @@ fn transDeclRefExpr(
19031906
const name = try c.str(@as(*const clang.NamedDecl, @ptrCast(value_decl)).getName_bytes_begin());
19041907
const mangled_name = scope.getAlias(name);
19051908
const decl_is_var = @as(*const clang.Decl, @ptrCast(value_decl)).getKind() == .Var;
1906-
const potential_local_extern = if (decl_is_var) ((@as(*const clang.VarDecl, @ptrCast(value_decl)).getStorageClass() == .Extern) and (scope.id != .root)) else false;
1909+
const storage_class = @as(*const clang.VarDecl, @ptrCast(value_decl)).getStorageClass();
1910+
const potential_local_extern = if (decl_is_var) ((storage_class == .Extern) and (scope.id != .root)) else false;
19071911

19081912
var confirmed_local_extern = false;
1913+
var confirmed_local_extern_fn = false;
19091914
var ref_expr = val: {
19101915
if (cIsFunctionDeclRef(@as(*const clang.Expr, @ptrCast(expr)))) {
1916+
if (scope.id != .root) {
1917+
if (scope.getLocalExternAlias(name)) |v| {
1918+
confirmed_local_extern_fn = true;
1919+
break :val try Tag.identifier.create(c.arena, v);
1920+
}
1921+
}
19111922
break :val try Tag.fn_identifier.create(c.arena, mangled_name);
19121923
} else if (potential_local_extern) {
19131924
if (scope.getLocalExternAlias(name)) |v| {
@@ -1934,6 +1945,11 @@ fn transDeclRefExpr(
19341945
.field_name = name, // by necessity, name will always == mangled_name
19351946
});
19361947
}
1948+
} else if (confirmed_local_extern_fn) {
1949+
ref_expr = try Tag.field_access.create(c.arena, .{
1950+
.lhs = ref_expr,
1951+
.field_name = name, // by necessity, name will always == mangled_name
1952+
});
19371953
}
19381954
scope.skipVariableDiscard(mangled_name);
19391955
return ref_expr;
@@ -4213,6 +4229,23 @@ fn addTopLevelDecl(c: *Context, name: []const u8, decl_node: Node) !void {
42134229
}
42144230
}
42154231

4232+
/// Add an "extern" function prototype declaration that's been declared within a scoped block.
4233+
/// Similar to static local variables, this will be wrapped in a struct to work with Zig's syntax requirements.
4234+
///
4235+
fn addLocalExternFnDecl(c: *Context, scope: *Scope, name: []const u8, decl_node: Node) !void {
4236+
const bs: *Scope.Block = try scope.findBlockScope(c);
4237+
4238+
// Special naming convention for local extern function wrapper struct,
4239+
// this named "ExternLocal_[name]".
4240+
const struct_name = try std.fmt.allocPrint(c.arena, "{s}_{s}", .{ Scope.Block.extern_inner_prepend, name });
4241+
4242+
// Outer Node for the wrapper struct
4243+
const node = try Tag.extern_local_fn.create(c.arena, .{ .name = struct_name, .init = decl_node });
4244+
4245+
try bs.statements.append(node);
4246+
try bs.discardVariable(c, struct_name);
4247+
}
4248+
42164249
fn transQualTypeInitializedStringLiteral(c: *Context, elem_ty: Node, string_lit: *const clang.StringLiteral) TypeError!Node {
42174250
const string_lit_size = string_lit.getLength();
42184251
const array_size = @as(usize, @intCast(string_lit_size));

test/translate_c.zig

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3537,9 +3537,12 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
35373537
\\ return bar(1, 2);
35383538
\\}
35393539
, &[_][]const u8{
3540-
\\pub extern fn bar(c_int, c_int) c_int;
35413540
\\pub export fn foo() c_int {
3542-
\\ return bar(@as(c_int, 1), @as(c_int, 2));
3541+
\\ const ExternLocal_bar = struct {
3542+
\\ pub extern fn bar(c_int, c_int) c_int;
3543+
\\ };
3544+
\\ _ = &ExternLocal_bar;
3545+
\\ return ExternLocal_bar.bar(@as(c_int, 1), @as(c_int, 2));
35433546
\\}
35443547
});
35453548

0 commit comments

Comments
 (0)