Make the C++ LTO API easier to use from C++ clients.
authorPeter Collingbourne <peter@pcc.me.uk>
Mon, 1 Jun 2015 20:08:30 +0000 (20:08 +0000)
committerPeter Collingbourne <peter@pcc.me.uk>
Mon, 1 Jun 2015 20:08:30 +0000 (20:08 +0000)
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
lib/LTO/LTOCodeGenerator.cpp
tools/llvm-lto/llvm-lto.cpp
tools/lto/lto.cpp

index 3b4be81b223ce49b3683eb1f49f6f4dc31ca30c8..0c46fc048a43b8772dd973d7d737081e675de80e 100644 (file)
@@ -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<MemoryBuffer> 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<MemoryBuffer> 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<MemoryBuffer> NativeObjectFile;
   std::vector<char *> CodegenOptions;
   std::string MCpu;
   std::string MAttr;
index 3cf13a0ef2cda4637418151b92a087689a909a1f..716d66abf1c2c7cd04642182292e46d37384d57b 100644 (file)
@@ -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<MemoryBuffer>
+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<MemoryBuffer>
+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) {
index 9cd6587c26223a8c4176e8b3532a64b8e3b3c69e..9678c8397e0e1688eb5c0ff797b35e01922f4311 100644 (file)
@@ -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<MemoryBuffer> 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<const char *>(Code), len);
+    FileStream.write(Code->getBufferStart(), Code->getBufferSize());
   } else {
     std::string ErrorInfo;
     const char *OutputName = nullptr;
index d6ceebed728fcb46bba13d1e921bf668e0cbd512..e55708c70f89158ed1ca08bb0af3945866122bf7 100644 (file)
@@ -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<LLVMContext> Context)
+      : LTOCodeGenerator(std::move(Context)) {}
+
+  std::unique_ptr<MemoryBuffer> 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<LLVMContext>())
-                     : new LTOCodeGenerator();
-  if (CodeGen)
-    CodeGen->setTargetOptions(Options);
+  LibLTOCodeGenerator *CodeGen =
+      InLocalContext ? new LibLTOCodeGenerator(make_unique<LLVMContext>())
+                     : 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) {