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 |