Replace also-emit-llvm with save-temps.
[oota-llvm.git] / tools / gold / gold-plugin.cpp
index 110433aefe3ddcfae2cd219cdb280cea6b2dd9da..fb1566ca396744a99dfe8a9e5a9104a0f04bd92e 100644 (file)
@@ -78,10 +78,9 @@ static std::vector<std::string> Cleanup;
 static llvm::TargetOptions TargetOpts;
 
 namespace options {
-  enum generate_bc { BC_NO, BC_ALSO, BC_ONLY };
+  enum generate_bc { BC_NO, BC_ONLY, BC_SAVE_TEMPS };
   static bool generate_api_file = false;
   static generate_bc generate_bc_file = BC_NO;
-  static std::string bc_path;
   static std::string obj_path;
   static std::string extra_library_path;
   static std::string triple;
@@ -111,18 +110,8 @@ namespace options {
       obj_path = opt.substr(strlen("obj-path="));
     } else if (opt == "emit-llvm") {
       generate_bc_file = BC_ONLY;
-    } else if (opt == "also-emit-llvm") {
-      generate_bc_file = BC_ALSO;
-    } else if (opt.startswith("also-emit-llvm=")) {
-      llvm::StringRef path = opt.substr(strlen("also-emit-llvm="));
-      generate_bc_file = BC_ALSO;
-      if (!bc_path.empty()) {
-        message(LDPL_WARNING, "Path to the output IL file specified twice. "
-                              "Discarding %s",
-                opt_);
-      } else {
-        bc_path = path;
-      }
+    } else if (opt == "save-temps") {
+      generate_bc_file = BC_SAVE_TEMPS;
     } else {
       // Save this option to pass to the code generator.
       // ParseCommandLineOptions() expects argv[0] to be program name. Lazily
@@ -278,7 +267,7 @@ static ld_plugin_status claim_file_hook(const ld_plugin_input_file *file,
       message(LDPL_ERROR, "Failed to get a view of %s", file->name);
       return LDPS_ERR;
     }
-    BufferRef = MemoryBufferRef(StringRef((char *)view, file->filesize), "");
+    BufferRef = MemoryBufferRef(StringRef((const char *)view, file->filesize), "");
   } else {
     int64_t offset = 0;
     // Gold has found what might be IR part-way inside of a file, such as
@@ -300,7 +289,9 @@ static ld_plugin_status claim_file_hook(const ld_plugin_input_file *file,
   ErrorOr<std::unique_ptr<object::IRObjectFile>> ObjOrErr =
       object::IRObjectFile::createIRObjectFile(BufferRef, Context);
   std::error_code EC = ObjOrErr.getError();
-  if (EC == BitcodeError::InvalidBitcodeSignature)
+  if (EC == BitcodeError::InvalidBitcodeSignature ||
+      EC == object::object_error::invalid_file_type ||
+      EC == object::object_error::bitcode_section_not_found)
     return LDPS_OK;
 
   *claimed = 1;
@@ -416,18 +407,8 @@ static void keepGlobalValue(GlobalValue &GV,
   assert(!GV.isDiscardableIfUnused());
 }
 
-static bool isDeclaration(const GlobalValue &V) {
-  if (V.hasAvailableExternallyLinkage())
-    return true;
-
-  if (V.isMaterializable())
-    return false;
-
-  return V.isDeclaration();
-}
-
 static void internalize(GlobalValue &GV) {
-  if (isDeclaration(GV))
+  if (GV.isDeclarationForLinker())
     return; // We get here if there is a matching asm definition.
   if (!GV.hasLocalLinkage())
     GV.setLinkage(GlobalValue::InternalLinkage);
@@ -457,6 +438,7 @@ static void drop(GlobalValue &GV) {
                          /*Initializer*/ nullptr);
   Var->takeName(&Alias);
   Alias.replaceAllUsesWith(Var);
+  Alias.eraseFromParent();
 }
 
 static const char *getResolutionName(ld_plugin_symbol_resolution R) {
@@ -482,27 +464,49 @@ static const char *getResolutionName(ld_plugin_symbol_resolution R) {
   case LDPR_PREVAILING_DEF_IRONLY_EXP:
     return "PREVAILING_DEF_IRONLY_EXP";
   }
+  llvm_unreachable("Unknown resolution");
 }
 
 static GlobalObject *makeInternalReplacement(GlobalObject *GO) {
   Module *M = GO->getParent();
   GlobalObject *Ret;
   if (auto *F = dyn_cast<Function>(GO)) {
-    auto *NewF = Function::Create(
-        F->getFunctionType(), GlobalValue::InternalLinkage, F->getName(), M);
+    if (F->isMaterializable()) {
+      if (F->materialize())
+        message(LDPL_FATAL, "LLVM gold plugin has failed to read a function");
+
+    }
+
+    auto *NewF = Function::Create(F->getFunctionType(), F->getLinkage(),
+                                  F->getName(), M);
+
+    ValueToValueMapTy VM;
+    Function::arg_iterator NewI = NewF->arg_begin();
+    for (auto &Arg : F->args()) {
+      NewI->setName(Arg.getName());
+      VM[&Arg] = NewI;
+      ++NewI;
+    }
+
     NewF->getBasicBlockList().splice(NewF->end(), F->getBasicBlockList());
+    for (auto &BB : *NewF) {
+      for (auto &Inst : BB)
+        RemapInstruction(&Inst, VM, RF_IgnoreMissingEntries);
+    }
+
     Ret = NewF;
     F->deleteBody();
   } else {
     auto *Var = cast<GlobalVariable>(GO);
     Ret = new GlobalVariable(
         *M, Var->getType()->getElementType(), Var->isConstant(),
-        GlobalValue::InternalLinkage, Var->getInitializer(), Var->getName(),
+        Var->getLinkage(), Var->getInitializer(), Var->getName(),
         nullptr, Var->getThreadLocalMode(), Var->getType()->getAddressSpace(),
         Var->isExternallyInitialized());
     Var->setInitializer(nullptr);
   }
   Ret->copyAttributesFrom(GO);
+  Ret->setLinkage(GlobalValue::InternalLinkage);
   Ret->setComdat(GO->getComdat());
 
   return Ret;
@@ -547,8 +551,15 @@ getModuleForFile(LLVMContext &Context, claimed_file &F, raw_fd_ostream *ApiFile,
   if (get_view(F.handle, &View) != LDPS_OK)
     message(LDPL_FATAL, "Failed to get a view of file");
 
-  std::unique_ptr<MemoryBuffer> Buffer = MemoryBuffer::getMemBuffer(
-      StringRef((char *)View, File.filesize), "", false);
+  llvm::ErrorOr<MemoryBufferRef> MBOrErr =
+      object::IRObjectFile::findBitcodeInMemBuffer(
+          MemoryBufferRef(StringRef((const char *)View, File.filesize), ""));
+  if (std::error_code EC = MBOrErr.getError())
+    message(LDPL_FATAL, "Could not read bitcode from file : %s",
+            EC.message().c_str());
+
+  std::unique_ptr<MemoryBuffer> Buffer =
+      MemoryBuffer::getMemBuffer(MBOrErr->getBuffer(), "", false);
 
   if (release_input_file(F.handle) != LDPS_OK)
     message(LDPL_FATAL, "Failed to release file information");
@@ -577,10 +588,12 @@ getModuleForFile(LLVMContext &Context, claimed_file &F, raw_fd_ostream *ApiFile,
     if (!GV)
       continue; // Asm symbol.
 
-    if (GV->hasCommonLinkage()) {
+    if (Resolution != LDPR_PREVAILING_DEF_IRONLY && GV->hasCommonLinkage()) {
       // Common linkage is special. There is no single symbol that wins the
       // resolution. Instead we have to collect the maximum alignment and size.
       // The IR linker does that for us if we just pass it every common GV.
+      // We still have to keep track of LDPR_PREVAILING_DEF_IRONLY so we
+      // internalize once the IR linker has done its job.
       continue;
     }
 
@@ -592,7 +605,7 @@ getModuleForFile(LLVMContext &Context, claimed_file &F, raw_fd_ostream *ApiFile,
     case LDPR_RESOLVED_EXEC:
     case LDPR_RESOLVED_DYN:
     case LDPR_UNDEF:
-      assert(isDeclaration(*GV));
+      assert(GV->isDeclarationForLinker());
       break;
 
     case LDPR_PREVAILING_DEF_IRONLY: {
@@ -610,8 +623,14 @@ getModuleForFile(LLVMContext &Context, claimed_file &F, raw_fd_ostream *ApiFile,
       keepGlobalValue(*GV, KeptAliases);
       break;
 
-    case LDPR_PREEMPTED_REG:
     case LDPR_PREEMPTED_IR:
+      // Gold might have selected a linkonce_odr and preempted a weak_odr.
+      // In that case we have to make sure we don't end up internalizing it.
+      if (!GV->isDiscardableIfUnused())
+        Maybe.erase(Sym.name);
+
+      // fall-through
+    case LDPR_PREEMPTED_REG:
       Drop.insert(GV);
       break;
 
@@ -633,12 +652,6 @@ getModuleForFile(LLVMContext &Context, claimed_file &F, raw_fd_ostream *ApiFile,
     Sym.comdat_key = nullptr;
   }
 
-  if (!Drop.empty())
-    // This is horrible. Given how lazy loading is implemented, dropping
-    // the body while there is a materializer present doesn't work, the
-    // linker will just read the body back.
-    M->materializeAllPermanently();
-
   ValueToValueMapTy VM;
   LocalValueMaterializer Materializer(Drop);
   for (GlobalAlias *GA : KeptAliases) {
@@ -667,6 +680,14 @@ static void runLTOPasses(Module &M, TargetMachine &TM) {
   passes.run(M);
 }
 
+static void saveBCFile(StringRef Path, Module &M) {
+  std::error_code EC;
+  raw_fd_ostream OS(Path, EC, sys::fs::OpenFlags::F_None);
+  if (EC)
+    message(LDPL_FATAL, "Failed to write the output file.");
+  WriteBitcodeToFile(&M, OS);
+}
+
 static void codegen(Module &M) {
   const std::string &TripleStr = M.getTargetTriple();
   Triple TheTriple(TripleStr);
@@ -691,8 +712,11 @@ static void codegen(Module &M) {
 
   runLTOPasses(M, *TM);
 
+  if (options::generate_bc_file == options::BC_SAVE_TEMPS)
+    saveBCFile(output_name + ".opt.bc", M);
+
   PassManager CodeGenPasses;
-  CodeGenPasses.add(new DataLayoutPass(&M));
+  CodeGenPasses.add(new DataLayoutPass());
 
   SmallString<128> Filename;
   int FD;
@@ -753,9 +777,8 @@ static ld_plugin_status allSymbolsReadHook(raw_fd_ostream *ApiFile) {
       M->setTargetTriple(DefaultTriple);
     }
 
-    std::string ErrMsg;
-    if (L.linkInModule(M.get(), &ErrMsg))
-      message(LDPL_FATAL, "Failed to link module: %s", ErrMsg.c_str());
+    if (L.linkInModule(M.get()))
+      message(LDPL_FATAL, "Failed to link module");
   }
 
   for (const auto &Name : Internalize) {
@@ -777,17 +800,9 @@ static ld_plugin_status allSymbolsReadHook(raw_fd_ostream *ApiFile) {
     std::string path;
     if (options::generate_bc_file == options::BC_ONLY)
       path = output_name;
-    else if (!options::bc_path.empty())
-      path = options::bc_path;
     else
       path = output_name + ".bc";
-    {
-      std::error_code EC;
-      raw_fd_ostream OS(path, EC, sys::fs::OpenFlags::F_None);
-      if (EC)
-        message(LDPL_FATAL, "Failed to write the output file.");
-      WriteBitcodeToFile(L.getModule(), OS);
-    }
+    saveBCFile(path, *L.getModule());
     if (options::generate_bc_file == options::BC_ONLY)
       return LDPS_OK;
   }