From 3fcf5a99cbe7d7c18d235787ff8d44823754f21b Mon Sep 17 00:00:00 2001 From: Peter Collingbourne Date: Mon, 1 Jun 2015 20:08:30 +0000 Subject: [PATCH] Make the C++ LTO API easier to use from C++ clients. Start using C++ types such as StringRef and MemoryBuffer in the C++ LTO API. In doing so, clarify the ownership of the native object file: the caller now owns it, not the LTOCodeGenerator. The C libLTO library has been modified to use a derived class of LTOCodeGenerator that owns the object file. Differential Revision: http://reviews.llvm.org/D10114 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@238776 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/LTO/LTOCodeGenerator.h | 14 ++++------ lib/LTO/LTOCodeGenerator.cpp | 21 +++++--------- tools/llvm-lto/llvm-lto.cpp | 8 ++---- tools/lto/lto.cpp | 43 ++++++++++++++++++++++------- 4 files changed, 49 insertions(+), 37 deletions(-) diff --git a/include/llvm/LTO/LTOCodeGenerator.h b/include/llvm/LTO/LTOCodeGenerator.h index 3b4be81b223..0c46fc048a4 100644 --- a/include/llvm/LTO/LTOCodeGenerator.h +++ b/include/llvm/LTO/LTOCodeGenerator.h @@ -82,7 +82,7 @@ struct LTOCodeGenerator { void setShouldInternalize(bool Value) { ShouldInternalize = Value; } void setShouldEmbedUselists(bool Value) { ShouldEmbedUselists = Value; } - void addMustPreserveSymbol(const char *sym) { MustPreserveSymbols[sym] = 1; } + void addMustPreserveSymbol(StringRef sym) { MustPreserveSymbols[sym] = 1; } // To pass options to the driver and optimization passes. These options are // not necessarily for debugging purpose (The function name is misleading). @@ -117,11 +117,10 @@ struct LTOCodeGenerator { // (linker), it brings the object to a buffer, and return the buffer to the // caller. This function should delete intermediate object file once its content // is brought to memory. Return NULL if the compilation was not successful. - const void *compile(size_t *length, - bool disableInline, - bool disableGVNLoadPRE, - bool disableVectorization, - std::string &errMsg); + std::unique_ptr compile(bool disableInline, + bool disableGVNLoadPRE, + bool disableVectorization, + std::string &errMsg); // Optimizes the merged module. Returns true on success. bool optimize(bool disableInline, @@ -132,7 +131,7 @@ struct LTOCodeGenerator { // Compiles the merged optimized module into a single object file. It brings // the object to a buffer, and returns the buffer to the caller. Return NULL // if the compilation was not successful. - const void *compileOptimized(size_t *length, std::string &errMsg); + std::unique_ptr compileOptimized(std::string &errMsg); void setDiagnosticHandler(lto_diagnostic_handler_t, void *); @@ -166,7 +165,6 @@ private: lto_codegen_model CodeModel = LTO_CODEGEN_PIC_MODEL_DEFAULT; StringSet MustPreserveSymbols; StringSet AsmUndefinedRefs; - std::unique_ptr NativeObjectFile; std::vector CodegenOptions; std::string MCpu; std::string MAttr; diff --git a/lib/LTO/LTOCodeGenerator.cpp b/lib/LTO/LTOCodeGenerator.cpp index 3cf13a0ef2c..716d66abf1c 100644 --- a/lib/LTO/LTOCodeGenerator.cpp +++ b/lib/LTO/LTOCodeGenerator.cpp @@ -250,8 +250,8 @@ bool LTOCodeGenerator::compileOptimizedToFile(const char **name, return true; } -const void *LTOCodeGenerator::compileOptimized(size_t *length, - std::string &errMsg) { +std::unique_ptr +LTOCodeGenerator::compileOptimized(std::string &errMsg) { const char *name; if (!compileOptimizedToFile(&name, errMsg)) return nullptr; @@ -264,16 +264,11 @@ const void *LTOCodeGenerator::compileOptimized(size_t *length, sys::fs::remove(NativeObjectPath); return nullptr; } - NativeObjectFile = std::move(*BufferOrErr); // remove temp files sys::fs::remove(NativeObjectPath); - // return buffer, unless error - if (!NativeObjectFile) - return nullptr; - *length = NativeObjectFile->getBufferSize(); - return NativeObjectFile->getBufferStart(); + return std::move(*BufferOrErr); } @@ -289,16 +284,14 @@ bool LTOCodeGenerator::compile_to_file(const char **name, return compileOptimizedToFile(name, errMsg); } -const void* LTOCodeGenerator::compile(size_t *length, - bool disableInline, - bool disableGVNLoadPRE, - bool disableVectorization, - std::string &errMsg) { +std::unique_ptr +LTOCodeGenerator::compile(bool disableInline, bool disableGVNLoadPRE, + bool disableVectorization, std::string &errMsg) { if (!optimize(disableInline, disableGVNLoadPRE, disableVectorization, errMsg)) return nullptr; - return compileOptimized(length, errMsg); + return compileOptimized(errMsg); } bool LTOCodeGenerator::determineTarget(std::string &errMsg) { diff --git a/tools/llvm-lto/llvm-lto.cpp b/tools/llvm-lto/llvm-lto.cpp index 9cd6587c262..9678c8397e0 100644 --- a/tools/llvm-lto/llvm-lto.cpp +++ b/tools/llvm-lto/llvm-lto.cpp @@ -253,11 +253,9 @@ int main(int argc, char **argv) { CodeGen.setAttr(attrs.c_str()); if (!OutputFilename.empty()) { - size_t len = 0; std::string ErrorInfo; - const void *Code = - CodeGen.compile(&len, DisableInline, DisableGVNLoadPRE, - DisableLTOVectorization, ErrorInfo); + std::unique_ptr Code = CodeGen.compile( + DisableInline, DisableGVNLoadPRE, DisableLTOVectorization, ErrorInfo); if (!Code) { errs() << argv[0] << ": error compiling the code: " << ErrorInfo << "\n"; @@ -272,7 +270,7 @@ int main(int argc, char **argv) { return 1; } - FileStream.write(reinterpret_cast(Code), len); + FileStream.write(Code->getBufferStart(), Code->getBufferSize()); } else { std::string ErrorInfo; const char *OutputName = nullptr; diff --git a/tools/lto/lto.cpp b/tools/lto/lto.cpp index d6ceebed728..e55708c70f8 100644 --- a/tools/lto/lto.cpp +++ b/tools/lto/lto.cpp @@ -73,7 +73,22 @@ static void lto_initialize() { } } -DEFINE_SIMPLE_CONVERSION_FUNCTIONS(LTOCodeGenerator, lto_code_gen_t) +namespace { + +// This derived class owns the native object file. This helps implement the +// libLTO API semantics, which require that the code generator owns the object +// file. +struct LibLTOCodeGenerator : LTOCodeGenerator { + LibLTOCodeGenerator() {} + LibLTOCodeGenerator(std::unique_ptr Context) + : LTOCodeGenerator(std::move(Context)) {} + + std::unique_ptr NativeObjectFile; +}; + +} + +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(LibLTOCodeGenerator, lto_code_gen_t) DEFINE_SIMPLE_CONVERSION_FUNCTIONS(LTOModule, lto_module_t) // Convert the subtarget features into a string to pass to LTOCodeGenerator. @@ -235,11 +250,10 @@ static lto_code_gen_t createCodeGen(bool InLocalContext) { TargetOptions Options = InitTargetOptionsFromCodeGenFlags(); - LTOCodeGenerator *CodeGen = - InLocalContext ? new LTOCodeGenerator(make_unique()) - : new LTOCodeGenerator(); - if (CodeGen) - CodeGen->setTargetOptions(Options); + LibLTOCodeGenerator *CodeGen = + InLocalContext ? new LibLTOCodeGenerator(make_unique()) + : new LibLTOCodeGenerator(); + CodeGen->setTargetOptions(Options); return wrap(CodeGen); } @@ -304,9 +318,13 @@ bool lto_codegen_write_merged_modules(lto_code_gen_t cg, const char *path) { const void *lto_codegen_compile(lto_code_gen_t cg, size_t *length) { maybeParseOptions(cg); - return unwrap(cg)->compile(length, DisableInline, - DisableGVNLoadPRE, DisableLTOVectorization, - sLastErrorString); + LibLTOCodeGenerator *CG = unwrap(cg); + CG->NativeObjectFile = CG->compile(DisableInline, DisableGVNLoadPRE, + DisableLTOVectorization, sLastErrorString); + if (!CG->NativeObjectFile) + return nullptr; + *length = CG->NativeObjectFile->getBufferSize(); + return CG->NativeObjectFile->getBufferStart(); } bool lto_codegen_optimize(lto_code_gen_t cg) { @@ -318,7 +336,12 @@ bool lto_codegen_optimize(lto_code_gen_t cg) { const void *lto_codegen_compile_optimized(lto_code_gen_t cg, size_t *length) { maybeParseOptions(cg); - return unwrap(cg)->compileOptimized(length, sLastErrorString); + LibLTOCodeGenerator *CG = unwrap(cg); + CG->NativeObjectFile = CG->compileOptimized(sLastErrorString); + if (!CG->NativeObjectFile) + return nullptr; + *length = CG->NativeObjectFile->getBufferSize(); + return CG->NativeObjectFile->getBufferStart(); } bool lto_codegen_compile_to_file(lto_code_gen_t cg, const char **name) {