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
This commit is contained in:
Peter Collingbourne 2015-06-01 20:08:30 +00:00
parent 9be6a55ba0
commit 3fcf5a99cb
4 changed files with 49 additions and 37 deletions

View 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;

View 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) {

View 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;

View 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) {