From 4474958d3a97dede2caa0920f7c4a4dc7aac57d3 Mon Sep 17 00:00:00 2001
From: Sami Tolvanen <samitolvanen@google.com>
Date: Tue, 22 Jun 2021 09:28:31 -0700
Subject: [PATCH] ThinLTO: Fix inline assembly references to static functions
 with CFI

Create an internal alias with the original name for static functions
that are renamed in promoteInternals to avoid breaking inline
assembly references to them.

Link: https://github.com/ClangBuiltLinux/linux/issues/1354

Reviewed By: pcc

Differential Revision: https://reviews.llvm.org/D104058
---
 .../Transforms/IPO/ThinLTOBitcodeWriter.cpp   |  9 +++++++++
 .../cfi-icall-static-inline-asm.ll            | 19 +++++++++++++++++++
 2 files changed, 28 insertions(+)
 create mode 100644 llvm/test/Transforms/ThinLTOBitcodeWriter/cfi-icall-static-inline-asm.ll

diff --git a/llvm/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp b/llvm/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp
index 37329b489555..255b1f7f4357 100644
--- a/llvm/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp
+++ b/llvm/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp
@@ -69,6 +69,15 @@ void promoteInternals(Module &ExportM, Module &ImportM, StringRef ModuleId,
       ImportGV->setName(NewName);
       ImportGV->setVisibility(GlobalValue::HiddenVisibility);
     }
+
+    if (Function *F = dyn_cast<Function>(&ExportGV)) {
+      // Create a local alias with the original name to avoid breaking
+      // references from inline assembly.
+      GlobalAlias *A =
+          GlobalAlias::create(F->getValueType(), F->getAddressSpace(),
+                              GlobalValue::InternalLinkage, Name, F, &ExportM);
+      appendToCompilerUsed(ExportM, A);
+    }
   }
 
   if (!RenamedComdats.empty())
diff --git a/llvm/test/Transforms/ThinLTOBitcodeWriter/cfi-icall-static-inline-asm.ll b/llvm/test/Transforms/ThinLTOBitcodeWriter/cfi-icall-static-inline-asm.ll
new file mode 100644
index 000000000000..70f5322faa52
--- /dev/null
+++ b/llvm/test/Transforms/ThinLTOBitcodeWriter/cfi-icall-static-inline-asm.ll
@@ -0,0 +1,19 @@
+; RUN: opt -thinlto-bc -thinlto-split-lto-unit -o - %s | llvm-modextract -b -n 0 -o - | llvm-dis | FileCheck %s
+
+; CHECK: @a = internal alias {{.*}}@a.[[HASH:[0-9a-f]+]]
+
+define void @b() {
+  %f = alloca void ()*, align 8
+  ; CHECK: store{{.*}} @a.[[HASH]],{{.*}} %f
+  store void ()* @a, void ()** %f, align 8
+  ; CHECK: %1 = call void ()* asm sideeffect "leaq a(%rip)
+  %1 = call void ()* asm sideeffect "leaq a(%rip), $0\0A\09", "=r,~{dirflag},~{fpsr},~{flags}"()
+  ret void
+}
+
+; CHECK: define{{.*}} @a.[[HASH]](){{.*}} !type
+define internal void @a() !type !0 {
+  ret void
+}
+
+!0 = !{i64 0, !"typeid1"}