Commit 0577069af5

Veikka Tuominen <git@vexu.eu>
2022-03-21 12:25:57
stage2 llvm: fix lowerDeclRefValue for function aliases
1 parent b48d8cc
Changed files (6)
lib
src
codegen
test
lib/std/os/linux.zig
@@ -1080,13 +1080,8 @@ pub fn sigaction(sig: u6, noalias act: ?*const Sigaction, noalias oact: ?*Sigact
     const mask_size = @sizeOf(@TypeOf(ksa.mask));
 
     if (act) |new| {
-        const restore_rt_ptr = if (builtin.zig_backend == .stage1) restore_rt else &syscall_bits.restore_rt;
-        // TODO https://github.com/ziglang/zig/issues/11227
-        const restore_ptr = if (builtin.zig_backend == .stage1) restore else switch (native_arch) {
-            .arm, .thumb, .mips, .mipsel, .i386 => &syscall_bits.restore,
-            .x86_64, .aarch64, .riscv64, .sparcv9, .powerpc, .powerpc64, .powerpc64le => &syscall_bits.restore_rt,
-            else => unreachable,
-        };
+        const restore_rt_ptr = if (builtin.zig_backend == .stage1) restore_rt else &restore_rt;
+        const restore_ptr = if (builtin.zig_backend == .stage1) restore else &restore;
         const restorer_fn = if ((new.flags & SA.SIGINFO) != 0) restore_rt_ptr else restore_ptr;
         ksa = k_sigaction{
             .handler = new.handler.handler,
lib/std/fmt.zig
@@ -762,7 +762,6 @@ fn formatFloatValue(
     if (fmt.len == 0 or comptime std.mem.eql(u8, fmt, "e")) {
         formatFloatScientific(value, options, buf_stream.writer()) catch |err| switch (err) {
             error.NoSpaceLeft => unreachable,
-            else => |e| return e,
         };
     } else if (comptime std.mem.eql(u8, fmt, "d")) {
         formatFloatDecimal(value, options, buf_stream.writer()) catch |err| switch (err) {
src/codegen/llvm.zig
@@ -3073,6 +3073,17 @@ pub const DeclGen = struct {
             return self.context.constStruct(&fields, fields.len, .False);
         }
 
+        // In the case of something like:
+        // fn foo() void {}
+        // const bar = foo;
+        // ... &bar;
+        // `bar` is just an alias and we actually want to lower a reference to `foo`.
+        if (decl.val.castTag(.function)) |func| {
+            if (func.data.owner_decl != decl) {
+                return self.lowerDeclRefValue(tv, func.data.owner_decl);
+            }
+        }
+
         const is_fn_body = decl.ty.zigTypeTag() == .Fn;
         if (!is_fn_body and !decl.ty.hasRuntimeBitsIgnoreComptime()) {
             return self.lowerPtrToVoid(tv.ty);
test/behavior/bugs/11227.zig
@@ -0,0 +1,13 @@
+const std = @import("std");
+const builtin = @import("builtin");
+
+fn foo() u32 {
+    return 11227;
+}
+const bar = foo;
+test "pointer to alias behaves same as pointer to function" {
+    if (builtin.zig_backend == .stage1) return error.SkipZigTest; // stage1 has different function pointers
+
+    var a = &bar;
+    try std.testing.expect(foo() == a());
+}
test/behavior/bugs/1277.zig
@@ -2,15 +2,20 @@ const std = @import("std");
 const builtin = @import("builtin");
 
 const S = struct {
-    f: ?fn () i32,
+    f: ?*const fn () i32,
 };
 
-const s = S{ .f = f };
+const s = S{ .f = &f };
 
 fn f() i32 {
     return 1234;
 }
 
 test "don't emit an LLVM global for a const function when it's in an optional in a struct" {
+    if (builtin.zig_backend == .stage1) return error.SkipZigTest; // stage1 has different function pointers
+    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
+    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
+    if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
+
     try std.testing.expect(s.f.?() == 1234);
 }
test/behavior.zig
@@ -161,6 +161,7 @@ test {
         builtin.zig_backend != .stage2_wasm and
         builtin.zig_backend != .stage2_c)
     {
+        _ = @import("behavior/bugs/11227.zig");
         _ = @import("behavior/export.zig");
         _ = @import("behavior/export_self_referential_type_info.zig");
     }