Commit 349cf54b32

riChar <wxsychi@163.com>
2022-09-04 17:44:45
llvm: fix the `type` parameter of `GlobalAlias`
Closes 12680
1 parent b7d5582
Changed files (4)
src/codegen/llvm.zig
@@ -287,6 +287,15 @@ pub fn supportsTailCall(target: std.Target) bool {
     }
 }
 
+/// TODO can this be done with simpler logic / different API binding?
+fn deleteLlvmGlobal(llvm_global: *const llvm.Value) void {
+    if (llvm_global.globalGetValueType().getTypeKind() == .Function) {
+        llvm_global.deleteFunction();
+        return;
+    }
+    return llvm_global.deleteGlobal();
+}
+
 pub const Object = struct {
     gpa: Allocator,
     module: *Module,
@@ -640,7 +649,7 @@ pub const Object = struct {
 
             const new_global_ptr = other_global.constBitCast(llvm_global.typeOf());
             llvm_global.replaceAllUsesWith(new_global_ptr);
-            object.deleteLlvmGlobal(llvm_global);
+            deleteLlvmGlobal(llvm_global);
             entry.value_ptr.* = new_global_ptr;
         }
         object.extern_collisions.clearRetainingCapacity();
@@ -666,7 +675,7 @@ pub const Object = struct {
                 const new_global_ptr = llvm_global.constBitCast(other_global.typeOf());
                 other_global.replaceAllUsesWith(new_global_ptr);
                 llvm_global.takeName(other_global);
-                other_global.deleteGlobal();
+                deleteLlvmGlobal(other_global);
                 // Problem: now we need to replace in the decl_map that
                 // the extern decl index points to this new global. However we don't
                 // know the decl index.
@@ -1184,15 +1193,6 @@ pub const Object = struct {
         return null;
     }
 
-    /// TODO can this be done with simpler logic / different API binding?
-    fn deleteLlvmGlobal(o: Object, llvm_global: *const llvm.Value) void {
-        if (o.llvm_module.getNamedFunction(llvm_global.getValueName()) != null) {
-            llvm_global.deleteFunction();
-            return;
-        }
-        return llvm_global.deleteGlobal();
-    }
-
     pub fn updateDeclExports(
         self: *Object,
         module: *Module,
@@ -1287,7 +1287,7 @@ pub const Object = struct {
                     alias.setAliasee(llvm_global);
                 } else {
                     _ = self.llvm_module.addAlias(
-                        llvm_global.typeOf(),
+                        llvm_global.globalGetValueType(),
                         0,
                         llvm_global,
                         exp_name_z,
test/behavior/bugs/12680.zig
@@ -0,0 +1,17 @@
+const std = @import("std");
+const expectEqual = std.testing.expectEqual;
+const other_file = @import("12680_other_file.zig");
+const builtin = @import("builtin");
+
+extern fn test_func() callconv(.C) usize;
+
+test "export a function twice" {
+    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
+    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
+    if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
+    if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
+    if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
+
+    // If it exports the function correctly, `test_func` and `testFunc` will points to the same address.
+    try expectEqual(test_func(), other_file.testFunc());
+}
test/behavior/bugs/12680_other_file.zig
@@ -0,0 +1,8 @@
+// export this function twice
+pub export fn testFunc() callconv(.C) usize {
+    return @ptrToInt(&testFunc);
+}
+
+comptime {
+    @export(testFunc, .{ .name = "test_func", .linkage = .Strong });
+}
test/behavior.zig
@@ -85,6 +85,7 @@ test {
     _ = @import("behavior/bugs/12033.zig");
     _ = @import("behavior/bugs/12430.zig");
     _ = @import("behavior/bugs/12486.zig");
+    _ = @import("behavior/bugs/12680.zig");
     _ = @import("behavior/byteswap.zig");
     _ = @import("behavior/byval_arg_var.zig");
     _ = @import("behavior/call.zig");