From 970f79c29a2a40f386b074e355f401a9181efa9c Mon Sep 17 00:00:00 2001
From: Steven Wu <stevenwu@apple.com>
Date: Fri, 13 May 2016 12:17:52 -0700
Subject: [PATCH] Fix embed-bitcode linkage type

---
 lib/CodeGen/BackendUtil.cpp | 45 ++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 38 insertions(+), 7 deletions(-)

diff --git a/lib/CodeGen/BackendUtil.cpp b/lib/CodeGen/BackendUtil.cpp
index bffa621..66c2a9c 100644
--- a/lib/CodeGen/BackendUtil.cpp
+++ b/lib/CodeGen/BackendUtil.cpp
@@ -797,6 +797,24 @@ void clang::EmbedBitcode(llvm::Module *M, const CodeGenOptions &CGOpts,
   if (CGOpts.getEmbedBitcode() == CodeGenOptions::Embed_Off)
     return;
 
+  // Re-create llvm.used list if needed.
+  SmallVector<Constant*, 2> UsedArray;
+  Type *UsedElementType = Type::getInt8Ty(M->getContext())->getPointerTo(0);
+  if (auto Used = M->getGlobalVariable("llvm.used")) {
+    auto UsedGlobals = cast<ConstantArray>(Used->getInitializer());
+    assert(UsedGlobals->getType()->getElementType() == UsedElementType &&
+           "Type must be the same");
+    for (auto &Op : UsedGlobals->operands()) {
+      if (auto Cast = dyn_cast<ConstantExpr>(Op)) {
+          if (Cast->getOperand(0)->getName() == "llvm.embedded.module" ||
+              Cast->getOperand(0)->getName() == "llvm.cmdline")
+            continue;
+      }
+      UsedArray.push_back(cast<llvm::Constant>(Op));
+    }
+    Used->eraseFromParent();
+  }
+
   // Embed the bitcode for the llvm module.
   std::string Data;
   ArrayRef<uint8_t> ModuleData;
@@ -820,14 +838,14 @@ void clang::EmbedBitcode(llvm::Module *M, const CodeGenOptions &CGOpts,
   }
   llvm::Constant *ModuleConstant =
       llvm::ConstantDataArray::get(M->getContext(), ModuleData);
-  // Use Appending linkage so it doesn't get optimized out.
   llvm::GlobalVariable *GV = new llvm::GlobalVariable(
-      *M, ModuleConstant->getType(), true, llvm::GlobalValue::AppendingLinkage,
+      *M, ModuleConstant->getType(), true, llvm::GlobalValue::PrivateLinkage,
       ModuleConstant);
   GV->setSection(getSectionNameForBitcode(T));
+  UsedArray.push_back(
+      ConstantExpr::getPointerBitCastOrAddrSpaceCast(GV, UsedElementType));
   if (llvm::GlobalVariable *Old =
-          M->getGlobalVariable("llvm.embedded.module")) {
-    assert(Old->use_empty() && "llvm.embedded.module must have no uses");
+          M->getGlobalVariable("llvm.embedded.module", true)) {
     GV->takeName(Old);
     Old->eraseFromParent();
   } else {
@@ -844,14 +862,27 @@ void clang::EmbedBitcode(llvm::Module *M, const CodeGenOptions &CGOpts,
   llvm::Constant *CmdConstant =
     llvm::ConstantDataArray::get(M->getContext(), CmdData);
   GV = new llvm::GlobalVariable(*M, CmdConstant->getType(), true,
-                                llvm::GlobalValue::AppendingLinkage,
+                                llvm::GlobalValue::PrivateLinkage,
                                 CmdConstant);
   GV->setSection(getSectionNameForCommandline(T));
-  if (llvm::GlobalVariable *Old = M->getGlobalVariable("llvm.cmdline")) {
-    assert(Old->use_empty() && "llvm.cmdline must have no uses");
+  UsedArray.push_back(
+      ConstantExpr::getPointerBitCastOrAddrSpaceCast(GV, UsedElementType));
+  if (llvm::GlobalVariable *Old = M->getGlobalVariable("llvm.cmdline", true)) {
     GV->takeName(Old);
     Old->eraseFromParent();
   } else {
     GV->setName("llvm.cmdline");
   }
+
+  if (UsedArray.empty())
+    return;
+
+  // Recreate llvm.used.
+  ArrayType *ATy = ArrayType::get(UsedElementType, UsedArray.size());
+  // FIXME: Change LinkageType when llvm.used is moved away from
+  // AppendingLinkage.
+  auto *NewUsed =
+      new GlobalVariable(*M, ATy, false, llvm::GlobalValue::AppendingLinkage,
+                         llvm::ConstantArray::get(ATy, UsedArray), "llvm.used");
+  NewUsed->setSection("llvm.metadata");
 }
-- 
2.7.4 (Apple Git-66)

