| OLD | NEW |
| 1 //===-- gold-plugin.cpp - Plugin to gold for Link Time Optimization ------===// | 1 //===-- gold-plugin.cpp - Plugin to gold for Link Time Optimization ------===// |
| 2 // | 2 // |
| 3 // The LLVM Compiler Infrastructure | 3 // The LLVM Compiler Infrastructure |
| 4 // | 4 // |
| 5 // This file is distributed under the University of Illinois Open Source | 5 // This file is distributed under the University of Illinois Open Source |
| 6 // License. See LICENSE.TXT for details. | 6 // License. See LICENSE.TXT for details. |
| 7 // | 7 // |
| 8 //===----------------------------------------------------------------------===// | 8 //===----------------------------------------------------------------------===// |
| 9 // | 9 // |
| 10 // This is a gold plugin for LLVM. It provides an LLVM implementation of the | 10 // This is a gold plugin for LLVM. It provides an LLVM implementation of the |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 71 static ld_plugin_add_input_file add_input_file = nullptr; | 71 static ld_plugin_add_input_file add_input_file = nullptr; |
| 72 static ld_plugin_set_extra_library_path set_extra_library_path = nullptr; | 72 static ld_plugin_set_extra_library_path set_extra_library_path = nullptr; |
| 73 static ld_plugin_get_view get_view = nullptr; | 73 static ld_plugin_get_view get_view = nullptr; |
| 74 static ld_plugin_message message = discard_message; | 74 static ld_plugin_message message = discard_message; |
| 75 static Reloc::Model RelocationModel = Reloc::Default; | 75 static Reloc::Model RelocationModel = Reloc::Default; |
| 76 static std::string output_name = ""; | 76 static std::string output_name = ""; |
| 77 static std::list<claimed_file> Modules; | 77 static std::list<claimed_file> Modules; |
| 78 static std::vector<std::string> Cleanup; | 78 static std::vector<std::string> Cleanup; |
| 79 static llvm::TargetOptions TargetOpts; | 79 static llvm::TargetOptions TargetOpts; |
| 80 | 80 |
| 81 // @LOCALMOD-BEGIN |
| 82 // Callback for getting the number of --wrap'd symbols. |
| 83 static ld_plugin_get_num_wrapped get_num_wrapped = NULL; |
| 84 |
| 85 // Callback for getting the name of a wrapped symbol. |
| 86 static ld_plugin_get_wrapped get_wrapped = NULL; |
| 87 // @LOCALMOD-END |
| 88 |
| 81 namespace options { | 89 namespace options { |
| 82 enum OutputType { | 90 enum OutputType { |
| 83 OT_NORMAL, | 91 OT_NORMAL, |
| 84 OT_DISABLE, | 92 OT_DISABLE, |
| 85 OT_BC_ONLY, | 93 OT_BC_ONLY, |
| 86 OT_SAVE_TEMPS | 94 OT_SAVE_TEMPS |
| 87 }; | 95 }; |
| 88 static bool generate_api_file = false; | 96 static bool generate_api_file = false; |
| 89 static OutputType TheOutputType = OT_NORMAL; | 97 static OutputType TheOutputType = OT_NORMAL; |
| 90 static std::string obj_path; | 98 static std::string obj_path; |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 216 break; | 224 break; |
| 217 case LDPT_ADD_INPUT_FILE: | 225 case LDPT_ADD_INPUT_FILE: |
| 218 add_input_file = tv->tv_u.tv_add_input_file; | 226 add_input_file = tv->tv_u.tv_add_input_file; |
| 219 break; | 227 break; |
| 220 case LDPT_SET_EXTRA_LIBRARY_PATH: | 228 case LDPT_SET_EXTRA_LIBRARY_PATH: |
| 221 set_extra_library_path = tv->tv_u.tv_set_extra_library_path; | 229 set_extra_library_path = tv->tv_u.tv_set_extra_library_path; |
| 222 break; | 230 break; |
| 223 case LDPT_GET_VIEW: | 231 case LDPT_GET_VIEW: |
| 224 get_view = tv->tv_u.tv_get_view; | 232 get_view = tv->tv_u.tv_get_view; |
| 225 break; | 233 break; |
| 234 // @LOCALMOD-BEGIN |
| 235 case LDPT_GET_WRAPPED: |
| 236 get_wrapped = tv->tv_u.tv_get_wrapped; |
| 237 break; |
| 238 case LDPT_GET_NUM_WRAPPED: |
| 239 get_num_wrapped = tv->tv_u.tv_get_num_wrapped; |
| 240 break; |
| 241 // @LOCALMOD-END |
| 226 case LDPT_MESSAGE: | 242 case LDPT_MESSAGE: |
| 227 message = tv->tv_u.tv_message; | 243 message = tv->tv_u.tv_message; |
| 228 break; | 244 break; |
| 229 default: | 245 default: |
| 230 break; | 246 break; |
| 231 } | 247 } |
| 232 } | 248 } |
| 233 | 249 |
| 234 if (!registeredClaimFile) { | 250 if (!registeredClaimFile) { |
| 235 message(LDPL_ERROR, "register_claim_file not passed to LLVMgold."); | 251 message(LDPL_ERROR, "register_claim_file not passed to LLVMgold."); |
| (...skipping 300 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 536 assert(!isa<GlobalAlias>(GV) && "Found alias point to weak alias."); | 552 assert(!isa<GlobalAlias>(GV) && "Found alias point to weak alias."); |
| 537 return makeInternalReplacement(cast<GlobalObject>(GV)); | 553 return makeInternalReplacement(cast<GlobalObject>(GV)); |
| 538 } | 554 } |
| 539 | 555 |
| 540 static Constant *mapConstantToLocalCopy(Constant *C, ValueToValueMapTy &VM, | 556 static Constant *mapConstantToLocalCopy(Constant *C, ValueToValueMapTy &VM, |
| 541 LocalValueMaterializer *Materializer) { | 557 LocalValueMaterializer *Materializer) { |
| 542 return MapValue(C, VM, RF_IgnoreMissingEntries, nullptr, Materializer); | 558 return MapValue(C, VM, RF_IgnoreMissingEntries, nullptr, Materializer); |
| 543 } | 559 } |
| 544 | 560 |
| 545 static std::unique_ptr<Module> | 561 static std::unique_ptr<Module> |
| 546 getModuleForFile(LLVMContext &Context, claimed_file &F, raw_fd_ostream *ApiFile, | 562 getModuleForFile(LLVMContext &Context, claimed_file &F, |
| 563 off_t Filesize, raw_fd_ostream *ApiFile, |
| 547 StringSet<> &Internalize, StringSet<> &Maybe) { | 564 StringSet<> &Internalize, StringSet<> &Maybe) { |
| 548 ld_plugin_input_file File; | |
| 549 if (get_input_file(F.handle, &File) != LDPS_OK) | |
| 550 message(LDPL_FATAL, "Failed to get file information"); | |
| 551 | 565 |
| 552 if (get_symbols(F.handle, F.syms.size(), &F.syms[0]) != LDPS_OK) | 566 if (get_symbols(F.handle, F.syms.size(), &F.syms[0]) != LDPS_OK) |
| 553 message(LDPL_FATAL, "Failed to get symbol information"); | 567 message(LDPL_FATAL, "Failed to get symbol information"); |
| 554 | 568 |
| 555 const void *View; | 569 const void *View; |
| 556 if (get_view(F.handle, &View) != LDPS_OK) | 570 if (get_view(F.handle, &View) != LDPS_OK) |
| 557 message(LDPL_FATAL, "Failed to get a view of file"); | 571 message(LDPL_FATAL, "Failed to get a view of file"); |
| 558 | 572 |
| 559 llvm::ErrorOr<MemoryBufferRef> MBOrErr = | 573 llvm::ErrorOr<MemoryBufferRef> MBOrErr = |
| 560 object::IRObjectFile::findBitcodeInMemBuffer( | 574 object::IRObjectFile::findBitcodeInMemBuffer( |
| 561 MemoryBufferRef(StringRef((const char *)View, File.filesize), "")); | 575 MemoryBufferRef(StringRef((const char *)View, Filesize), "")); |
| 562 if (std::error_code EC = MBOrErr.getError()) | 576 if (std::error_code EC = MBOrErr.getError()) |
| 563 message(LDPL_FATAL, "Could not read bitcode from file : %s", | 577 message(LDPL_FATAL, "Could not read bitcode from file : %s", |
| 564 EC.message().c_str()); | 578 EC.message().c_str()); |
| 565 | 579 |
| 566 std::unique_ptr<MemoryBuffer> Buffer = | 580 std::unique_ptr<MemoryBuffer> Buffer = |
| 567 MemoryBuffer::getMemBuffer(MBOrErr->getBuffer(), "", false); | 581 MemoryBuffer::getMemBuffer(MBOrErr->getBuffer(), "", false); |
| 568 | 582 |
| 569 if (release_input_file(F.handle) != LDPS_OK) | |
| 570 message(LDPL_FATAL, "Failed to release file information"); | |
| 571 | |
| 572 ErrorOr<Module *> MOrErr = getLazyBitcodeModule(std::move(Buffer), Context); | 583 ErrorOr<Module *> MOrErr = getLazyBitcodeModule(std::move(Buffer), Context); |
| 573 | 584 |
| 574 if (std::error_code EC = MOrErr.getError()) | 585 if (std::error_code EC = MOrErr.getError()) |
| 575 message(LDPL_FATAL, "Could not read bitcode from file : %s", | 586 message(LDPL_FATAL, "Could not read bitcode from file : %s", |
| 576 EC.message().c_str()); | 587 EC.message().c_str()); |
| 577 | 588 |
| 578 std::unique_ptr<Module> M(MOrErr.get()); | 589 std::unique_ptr<Module> M(MOrErr.get()); |
| 579 | 590 |
| 580 SmallPtrSet<GlobalValue *, 8> Used; | 591 SmallPtrSet<GlobalValue *, 8> Used; |
| 581 collectUsedGlobalVariables(*M, Used, /*CompilerUsed*/ false); | 592 collectUsedGlobalVariables(*M, Used, /*CompilerUsed*/ false); |
| (...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 753 | 764 |
| 754 if (add_input_file(Filename.c_str()) != LDPS_OK) | 765 if (add_input_file(Filename.c_str()) != LDPS_OK) |
| 755 message(LDPL_FATAL, | 766 message(LDPL_FATAL, |
| 756 "Unable to add .o file to the link. File left behind in: %s", | 767 "Unable to add .o file to the link. File left behind in: %s", |
| 757 Filename.c_str()); | 768 Filename.c_str()); |
| 758 | 769 |
| 759 if (options::obj_path.empty()) | 770 if (options::obj_path.empty()) |
| 760 Cleanup.push_back(Filename.c_str()); | 771 Cleanup.push_back(Filename.c_str()); |
| 761 } | 772 } |
| 762 | 773 |
| 774 // @LOCALMOD-BEGIN |
| 775 static void wrapSymbol(Module *M, const char *sym) { |
| 776 std::string wrapSymName("__wrap_"); |
| 777 wrapSymName += sym; |
| 778 std::string realSymName("__real_"); |
| 779 realSymName += sym; |
| 780 |
| 781 Constant *SymGV = M->getNamedValue(sym); |
| 782 |
| 783 // Replace uses of "sym" with "__wrap_sym". |
| 784 if (SymGV) { |
| 785 Constant *WrapGV = M->getNamedValue(wrapSymName); |
| 786 if (!WrapGV) |
| 787 WrapGV = M->getOrInsertGlobal(wrapSymName, SymGV->getType()); |
| 788 SymGV->replaceAllUsesWith( |
| 789 ConstantExpr::getBitCast(WrapGV, SymGV->getType())); |
| 790 } |
| 791 |
| 792 // Replace uses of "__real_sym" with "sym". |
| 793 if (Constant *RealGV = M->getNamedValue(realSymName)) { |
| 794 if (!SymGV) |
| 795 SymGV = M->getOrInsertGlobal(sym, RealGV->getType()); |
| 796 RealGV->replaceAllUsesWith( |
| 797 ConstantExpr::getBitCast(SymGV, RealGV->getType())); |
| 798 } |
| 799 } |
| 800 // @LOCALMOD-END |
| 801 |
| 763 /// gold informs us that all symbols have been read. At this point, we use | 802 /// gold informs us that all symbols have been read. At this point, we use |
| 764 /// get_symbols to see if any of our definitions have been overridden by a | 803 /// get_symbols to see if any of our definitions have been overridden by a |
| 765 /// native object file. Then, perform optimization and codegen. | 804 /// native object file. Then, perform optimization and codegen. |
| 766 static ld_plugin_status allSymbolsReadHook(raw_fd_ostream *ApiFile) { | 805 static ld_plugin_status allSymbolsReadHook(raw_fd_ostream *ApiFile) { |
| 767 if (Modules.empty()) | 806 if (Modules.empty()) |
| 768 return LDPS_OK; | 807 return LDPS_OK; |
| 769 | 808 |
| 770 LLVMContext Context; | 809 LLVMContext Context; |
| 771 std::unique_ptr<Module> Combined(new Module("ld-temp.o", Context)); | 810 std::unique_ptr<Module> Combined(new Module("ld-temp.o", Context)); |
| 772 Linker L(Combined.get()); | 811 Linker L(Combined.get()); |
| 773 | 812 |
| 774 std::string DefaultTriple = sys::getDefaultTargetTriple(); | 813 std::string DefaultTriple = sys::getDefaultTargetTriple(); |
| 775 | 814 |
| 776 StringSet<> Internalize; | 815 StringSet<> Internalize; |
| 777 StringSet<> Maybe; | 816 StringSet<> Maybe; |
| 778 for (claimed_file &F : Modules) { | 817 for (claimed_file &F : Modules) { |
| 818 ld_plugin_input_file File; |
| 819 if (get_input_file(F.handle, &File) != LDPS_OK) |
| 820 message(LDPL_FATAL, "Failed to get file information"); |
| 779 std::unique_ptr<Module> M = | 821 std::unique_ptr<Module> M = |
| 780 getModuleForFile(Context, F, ApiFile, Internalize, Maybe); | 822 getModuleForFile(Context, F, File.filesize, ApiFile, |
| 823 Internalize, Maybe); |
| 781 if (!options::triple.empty()) | 824 if (!options::triple.empty()) |
| 782 M->setTargetTriple(options::triple.c_str()); | 825 M->setTargetTriple(options::triple.c_str()); |
| 783 else if (M->getTargetTriple().empty()) { | 826 else if (M->getTargetTriple().empty()) { |
| 784 M->setTargetTriple(DefaultTriple); | 827 M->setTargetTriple(DefaultTriple); |
| 785 } | 828 } |
| 786 | 829 |
| 787 if (L.linkInModule(M.get())) | 830 if (L.linkInModule(M.get())) |
| 788 message(LDPL_FATAL, "Failed to link module"); | 831 message(LDPL_FATAL, "Failed to link module"); |
| 832 if (release_input_file(F.handle) != LDPS_OK) |
| 833 message(LDPL_FATAL, "Failed to release file information"); |
| 789 } | 834 } |
| 790 | 835 |
| 791 for (const auto &Name : Internalize) { | 836 for (const auto &Name : Internalize) { |
| 792 GlobalValue *GV = Combined->getNamedValue(Name.first()); | 837 GlobalValue *GV = Combined->getNamedValue(Name.first()); |
| 793 if (GV) | 838 if (GV) |
| 794 internalize(*GV); | 839 internalize(*GV); |
| 795 } | 840 } |
| 796 | 841 |
| 797 for (const auto &Name : Maybe) { | 842 for (const auto &Name : Maybe) { |
| 798 GlobalValue *GV = Combined->getNamedValue(Name.first()); | 843 GlobalValue *GV = Combined->getNamedValue(Name.first()); |
| 799 if (!GV) | 844 if (!GV) |
| 800 continue; | 845 continue; |
| 801 GV->setLinkage(GlobalValue::LinkOnceODRLinkage); | 846 GV->setLinkage(GlobalValue::LinkOnceODRLinkage); |
| 802 if (canBeOmittedFromSymbolTable(GV)) | 847 if (canBeOmittedFromSymbolTable(GV)) |
| 803 internalize(*GV); | 848 internalize(*GV); |
| 804 } | 849 } |
| 805 | 850 |
| 851 // @LOCALMOD-BEGIN |
| 852 // Perform symbol wrapping. |
| 853 unsigned num_wrapped; |
| 854 if ((*get_num_wrapped)(&num_wrapped) != LDPS_OK) { |
| 855 (*message)(LDPL_ERROR, "Unable to get the number of wrapped symbols."); |
| 856 return LDPS_ERR; |
| 857 } |
| 858 for (unsigned i = 0; i < num_wrapped; ++i) { |
| 859 const char *sym; |
| 860 if ((*get_wrapped)(i, &sym) != LDPS_OK) { |
| 861 (*message)(LDPL_ERROR, "Unable to wrap symbol %u/%u.", i, num_wrapped); |
| 862 return LDPS_ERR; |
| 863 } |
| 864 wrapSymbol(Combined.get(), sym); |
| 865 } |
| 866 // @LOCALMOD-END |
| 867 |
| 806 if (options::TheOutputType == options::OT_DISABLE) | 868 if (options::TheOutputType == options::OT_DISABLE) |
| 807 return LDPS_OK; | 869 return LDPS_OK; |
| 808 | 870 |
| 809 if (options::TheOutputType != options::OT_NORMAL) { | 871 if (options::TheOutputType != options::OT_NORMAL) { |
| 810 std::string path; | 872 std::string path; |
| 811 if (options::TheOutputType == options::OT_BC_ONLY) | 873 if (options::TheOutputType == options::OT_BC_ONLY) |
| 812 path = output_name; | 874 path = output_name; |
| 813 else | 875 else |
| 814 path = output_name + ".bc"; | 876 path = output_name + ".bc"; |
| 815 saveBCFile(path, *L.getModule()); | 877 saveBCFile(path, *L.getModule()); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 851 static ld_plugin_status cleanup_hook(void) { | 913 static ld_plugin_status cleanup_hook(void) { |
| 852 for (std::string &Name : Cleanup) { | 914 for (std::string &Name : Cleanup) { |
| 853 std::error_code EC = sys::fs::remove(Name); | 915 std::error_code EC = sys::fs::remove(Name); |
| 854 if (EC) | 916 if (EC) |
| 855 message(LDPL_ERROR, "Failed to delete '%s': %s", Name.c_str(), | 917 message(LDPL_ERROR, "Failed to delete '%s': %s", Name.c_str(), |
| 856 EC.message().c_str()); | 918 EC.message().c_str()); |
| 857 } | 919 } |
| 858 | 920 |
| 859 return LDPS_OK; | 921 return LDPS_OK; |
| 860 } | 922 } |
| OLD | NEW |