Modernize the C++ APIs for creating LTO modules.

This is a continuation of r253367.

These functions return is owned by the caller, so they return
std::unique_ptr now.

The call can fail, so the return is wrapped in ErrorOr.

They have a context where to report diagnostics, so they don't need to
take a string out parameter.

With this there are no call to getGlobalContext in lib/LTO.

llvm-svn: 254721
This commit is contained in:
Rafael Espindola 2015-12-04 16:14:31 +00:00
parent bebd2f4028
commit a7612b4fac
4 changed files with 164 additions and 126 deletions

View File

@ -91,25 +91,24 @@ public:
/// InitializeAllTargetMCs();
/// InitializeAllAsmPrinters();
/// InitializeAllAsmParsers();
static LTOModule *createFromFile(const char *path, TargetOptions options,
std::string &errMsg);
static LTOModule *createFromOpenFile(int fd, const char *path, size_t size,
TargetOptions options,
std::string &errMsg);
static LTOModule *createFromOpenFileSlice(int fd, const char *path,
size_t map_size, off_t offset,
TargetOptions options,
std::string &errMsg);
static LTOModule *createFromBuffer(const void *mem, size_t length,
TargetOptions options, std::string &errMsg,
StringRef path = "");
static ErrorOr<std::unique_ptr<LTOModule>>
createFromFile(LLVMContext &Context, const char *path, TargetOptions options);
static ErrorOr<std::unique_ptr<LTOModule>>
createFromOpenFile(LLVMContext &Context, int fd, const char *path,
size_t size, TargetOptions options);
static ErrorOr<std::unique_ptr<LTOModule>>
createFromOpenFileSlice(LLVMContext &Context, int fd, const char *path,
size_t map_size, off_t offset, TargetOptions options);
static ErrorOr<std::unique_ptr<LTOModule>>
createFromBuffer(LLVMContext &Context, const void *mem, size_t length,
TargetOptions options, StringRef path = "");
static LTOModule *createInLocalContext(const void *mem, size_t length,
TargetOptions options,
std::string &errMsg, StringRef path);
static LTOModule *createInContext(const void *mem, size_t length,
TargetOptions options, std::string &errMsg,
StringRef path, LLVMContext *Context);
static ErrorOr<std::unique_ptr<LTOModule>>
createInLocalContext(const void *mem, size_t length, TargetOptions options,
StringRef path);
static ErrorOr<std::unique_ptr<LTOModule>>
createInContext(const void *mem, size_t length, TargetOptions options,
StringRef path, LLVMContext *Context);
const Module &getModule() const {
return const_cast<LTOModule*>(this)->getModule();
@ -207,8 +206,9 @@ private:
bool objcClassNameFromExpression(const Constant *c, std::string &name);
/// Create an LTOModule (private version).
static LTOModule *makeLTOModule(MemoryBufferRef Buffer, TargetOptions options,
std::string &errMsg, LLVMContext *Context);
static ErrorOr<std::unique_ptr<LTOModule>>
makeLTOModule(MemoryBufferRef Buffer, TargetOptions options,
LLVMContext *Context);
};
}
#endif

View File

@ -100,89 +100,72 @@ std::string LTOModule::getProducerString(MemoryBuffer *Buffer) {
return getBitcodeProducerString(*BCOrErr, Context);
}
LTOModule *LTOModule::createFromFile(const char *path, TargetOptions options,
std::string &errMsg) {
ErrorOr<std::unique_ptr<LTOModule>>
LTOModule::createFromFile(LLVMContext &Context, const char *path,
TargetOptions options) {
ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr =
MemoryBuffer::getFile(path);
if (std::error_code EC = BufferOrErr.getError()) {
errMsg = EC.message();
return nullptr;
}
if (std::error_code EC = BufferOrErr.getError())
return EC;
std::unique_ptr<MemoryBuffer> Buffer = std::move(BufferOrErr.get());
return makeLTOModule(Buffer->getMemBufferRef(), options, errMsg,
&getGlobalContext());
return makeLTOModule(Buffer->getMemBufferRef(), options, &Context);
}
LTOModule *LTOModule::createFromOpenFile(int fd, const char *path, size_t size,
TargetOptions options,
std::string &errMsg) {
return createFromOpenFileSlice(fd, path, size, 0, options, errMsg);
ErrorOr<std::unique_ptr<LTOModule>>
LTOModule::createFromOpenFile(LLVMContext &Context, int fd, const char *path,
size_t size, TargetOptions options) {
return createFromOpenFileSlice(Context, fd, path, size, 0, options);
}
LTOModule *LTOModule::createFromOpenFileSlice(int fd, const char *path,
size_t map_size, off_t offset,
TargetOptions options,
std::string &errMsg) {
ErrorOr<std::unique_ptr<LTOModule>>
LTOModule::createFromOpenFileSlice(LLVMContext &Context, int fd,
const char *path, size_t map_size,
off_t offset, TargetOptions options) {
ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr =
MemoryBuffer::getOpenFileSlice(fd, path, map_size, offset);
if (std::error_code EC = BufferOrErr.getError()) {
errMsg = EC.message();
return nullptr;
}
if (std::error_code EC = BufferOrErr.getError())
return EC;
std::unique_ptr<MemoryBuffer> Buffer = std::move(BufferOrErr.get());
return makeLTOModule(Buffer->getMemBufferRef(), options, errMsg,
&getGlobalContext());
return makeLTOModule(Buffer->getMemBufferRef(), options, &Context);
}
LTOModule *LTOModule::createFromBuffer(const void *mem, size_t length,
TargetOptions options,
std::string &errMsg, StringRef path) {
return createInContext(mem, length, options, errMsg, path,
&getGlobalContext());
ErrorOr<std::unique_ptr<LTOModule>>
LTOModule::createFromBuffer(LLVMContext &Context, const void *mem,
size_t length, TargetOptions options,
StringRef path) {
return createInContext(mem, length, options, path, &Context);
}
LTOModule *LTOModule::createInLocalContext(const void *mem, size_t length,
TargetOptions options,
std::string &errMsg,
StringRef path) {
return createInContext(mem, length, options, errMsg, path, nullptr);
ErrorOr<std::unique_ptr<LTOModule>>
LTOModule::createInLocalContext(const void *mem, size_t length,
TargetOptions options, StringRef path) {
return createInContext(mem, length, options, path, nullptr);
}
LTOModule *LTOModule::createInContext(const void *mem, size_t length,
TargetOptions options,
std::string &errMsg, StringRef path,
LLVMContext *Context) {
ErrorOr<std::unique_ptr<LTOModule>>
LTOModule::createInContext(const void *mem, size_t length,
TargetOptions options, StringRef path,
LLVMContext *Context) {
StringRef Data((const char *)mem, length);
MemoryBufferRef Buffer(Data, path);
return makeLTOModule(Buffer, options, errMsg, Context);
return makeLTOModule(Buffer, options, Context);
}
static std::unique_ptr<Module> parseBitcodeFileImpl(MemoryBufferRef Buffer,
LLVMContext &Context,
bool ShouldBeLazy,
std::string &ErrMsg) {
static ErrorOr<std::unique_ptr<Module>>
parseBitcodeFileImpl(MemoryBufferRef Buffer, LLVMContext &Context,
bool ShouldBeLazy) {
// Find the buffer.
ErrorOr<MemoryBufferRef> MBOrErr =
IRObjectFile::findBitcodeInMemBuffer(Buffer);
if (std::error_code EC = MBOrErr.getError()) {
ErrMsg = EC.message();
return nullptr;
}
std::function<void(const DiagnosticInfo &)> DiagnosticHandler =
[&ErrMsg](const DiagnosticInfo &DI) {
raw_string_ostream Stream(ErrMsg);
DiagnosticPrinterRawOStream DP(Stream);
DI.print(DP);
};
if (std::error_code EC = MBOrErr.getError())
return EC;
if (!ShouldBeLazy) {
// Parse the full file.
ErrorOr<std::unique_ptr<Module>> M =
parseBitcodeFile(*MBOrErr, Context, DiagnosticHandler);
if (!M)
return nullptr;
ErrorOr<std::unique_ptr<Module>> M = parseBitcodeFile(*MBOrErr, Context);
if (std::error_code EC = M.getError())
return EC;
return std::move(*M);
}
@ -190,16 +173,16 @@ static std::unique_ptr<Module> parseBitcodeFileImpl(MemoryBufferRef Buffer,
std::unique_ptr<MemoryBuffer> LightweightBuf =
MemoryBuffer::getMemBuffer(*MBOrErr, false);
ErrorOr<std::unique_ptr<Module>> M =
getLazyBitcodeModule(std::move(LightweightBuf), Context,
DiagnosticHandler, true /*ShouldLazyLoadMetadata*/);
if (!M)
return nullptr;
getLazyBitcodeModule(std::move(LightweightBuf), Context, nullptr,
true /*ShouldLazyLoadMetadata*/);
if (std::error_code EC = M.getError())
return EC;
return std::move(*M);
}
LTOModule *LTOModule::makeLTOModule(MemoryBufferRef Buffer,
TargetOptions options, std::string &errMsg,
LLVMContext *Context) {
ErrorOr<std::unique_ptr<LTOModule>>
LTOModule::makeLTOModule(MemoryBufferRef Buffer, TargetOptions options,
LLVMContext *Context) {
std::unique_ptr<LLVMContext> OwnedContext;
if (!Context) {
OwnedContext = llvm::make_unique<LLVMContext>();
@ -208,11 +191,12 @@ LTOModule *LTOModule::makeLTOModule(MemoryBufferRef Buffer,
// If we own a context, we know this is being used only for symbol
// extraction, not linking. Be lazy in that case.
std::unique_ptr<Module> M = parseBitcodeFileImpl(
Buffer, *Context,
/* ShouldBeLazy */ static_cast<bool>(OwnedContext), errMsg);
if (!M)
return nullptr;
ErrorOr<std::unique_ptr<Module>> MOrErr =
parseBitcodeFileImpl(Buffer, *Context,
/* ShouldBeLazy */ static_cast<bool>(OwnedContext));
if (std::error_code EC = MOrErr.getError())
return EC;
std::unique_ptr<Module> &M = *MOrErr;
std::string TripleStr = M->getTargetTriple();
if (TripleStr.empty())
@ -220,9 +204,10 @@ LTOModule *LTOModule::makeLTOModule(MemoryBufferRef Buffer,
llvm::Triple Triple(TripleStr);
// find machine architecture for this module
std::string errMsg;
const Target *march = TargetRegistry::lookupTarget(TripleStr, errMsg);
if (!march)
return nullptr;
return std::unique_ptr<LTOModule>(nullptr);
// construct LTOModule, hand over ownership of module and target
SubtargetFeatures Features;
@ -246,16 +231,16 @@ LTOModule *LTOModule::makeLTOModule(MemoryBufferRef Buffer,
std::unique_ptr<object::IRObjectFile> IRObj(
new object::IRObjectFile(Buffer, std::move(M)));
LTOModule *Ret;
std::unique_ptr<LTOModule> Ret;
if (OwnedContext)
Ret = new LTOModule(std::move(IRObj), target, std::move(OwnedContext));
Ret.reset(new LTOModule(std::move(IRObj), target, std::move(OwnedContext)));
else
Ret = new LTOModule(std::move(IRObj), target);
Ret.reset(new LTOModule(std::move(IRObj), target));
Ret->parseSymbols();
Ret->parseMetadata();
return Ret;
return std::move(Ret);
}
/// Create a MemoryBuffer from a memory range with an optional name.

View File

@ -124,23 +124,27 @@ static void handleDiagnostics(lto_codegen_diagnostic_severity_t Severity,
errs() << Msg << "\n";
}
static std::string CurrentActivity;
static void diagnosticHandler(const DiagnosticInfo &DI) {
raw_ostream &OS = errs();
OS << "llvm-lto: ";
switch (DI.getSeverity()) {
case DS_Error:
OS << "error: ";
OS << "error";
break;
case DS_Warning:
OS << "warning: ";
OS << "warning";
break;
case DS_Remark:
OS << "remark: ";
OS << "remark";
break;
case DS_Note:
OS << "note: ";
OS << "note";
break;
}
if (!CurrentActivity.empty())
OS << ' ' << CurrentActivity;
OS << ": ";
DiagnosticPrinterRawOStream DP(OS);
DI.print(DP);
@ -150,6 +154,11 @@ static void diagnosticHandler(const DiagnosticInfo &DI) {
exit(1);
}
static void diagnosticHandlerWithContenxt(const DiagnosticInfo &DI,
void *Context) {
diagnosticHandler(DI);
}
static void error(const Twine &Msg) {
errs() << "llvm-lto: " << Msg << '\n';
exit(1);
@ -172,12 +181,11 @@ getLocalLTOModule(StringRef Path, std::unique_ptr<MemoryBuffer> &Buffer,
MemoryBuffer::getFile(Path);
error(BufferOrErr, "error loading file '" + Path + "'");
Buffer = std::move(BufferOrErr.get());
std::string Error;
std::unique_ptr<LTOModule> Ret(LTOModule::createInLocalContext(
Buffer->getBufferStart(), Buffer->getBufferSize(), Options, Error, Path));
if (!Error.empty())
error("error loading file '" + Path + "' " + Error);
return Ret;
CurrentActivity = ("loading file '" + Path + "'").str();
ErrorOr<std::unique_ptr<LTOModule>> Ret = LTOModule::createInLocalContext(
Buffer->getBufferStart(), Buffer->getBufferSize(), Options, Path);
CurrentActivity = "";
return std::move(*Ret);
}
/// \brief List symbols in each IR file.
@ -207,10 +215,11 @@ static void createCombinedFunctionIndex() {
FunctionInfoIndex CombinedIndex;
uint64_t NextModuleId = 0;
for (auto &Filename : InputFilenames) {
CurrentActivity = "loading file '" + Filename + "'";
ErrorOr<std::unique_ptr<FunctionInfoIndex>> IndexOrErr =
llvm::getFunctionIndexForFile(Filename, diagnosticHandler);
error(IndexOrErr, "error loading file '" + Filename + "'");
std::unique_ptr<FunctionInfoIndex> Index = std::move(IndexOrErr.get());
CurrentActivity = "";
// Skip files without a function summary.
if (!Index)
continue;
@ -257,7 +266,10 @@ int main(int argc, char **argv) {
unsigned BaseArg = 0;
LTOCodeGenerator CodeGen(getGlobalContext());
LLVMContext Context;
Context.setDiagnosticHandler(diagnosticHandlerWithContenxt, nullptr, true);
LTOCodeGenerator CodeGen(Context);
if (UseDiagnosticHandler)
CodeGen.setDiagnosticHandler(handleDiagnostics, nullptr);
@ -274,14 +286,11 @@ int main(int argc, char **argv) {
std::vector<std::string> KeptDSOSyms;
for (unsigned i = BaseArg; i < InputFilenames.size(); ++i) {
std::string error;
std::unique_ptr<LTOModule> Module(
LTOModule::createFromFile(InputFilenames[i].c_str(), Options, error));
if (!error.empty()) {
errs() << argv[0] << ": error loading file '" << InputFilenames[i]
<< "': " << error << "\n";
return 1;
}
CurrentActivity = "loading file '" + InputFilenames[i] + "'";
ErrorOr<std::unique_ptr<LTOModule>> ModuleOrErr =
LTOModule::createFromFile(Context, InputFilenames[i].c_str(), Options);
std::unique_ptr<LTOModule> &Module = *ModuleOrErr;
CurrentActivity = "";
unsigned NumSyms = Module->getSymbolCount();
for (unsigned I = 0; I < NumSyms; ++I) {

View File

@ -15,6 +15,8 @@
#include "llvm-c/lto.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/CodeGen/CommandFlags.h"
#include "llvm/IR/DiagnosticInfo.h"
#include "llvm/IR/DiagnosticPrinter.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/LTO/LTOCodeGenerator.h"
#include "llvm/LTO/LTOModule.h"
@ -64,6 +66,24 @@ static bool initialized = false;
// Holds the command-line option parsing state of the LTO module.
static bool parsedOptions = false;
static LLVMContext *LTOContext = nullptr;
static void diagnosticHandler(const DiagnosticInfo &DI, void *Context) {
if (DI.getSeverity() != DS_Error) {
DiagnosticPrinterRawOStream DP(errs());
DI.print(DP);
errs() << '\n';
return;
}
sLastErrorString = "";
{
raw_string_ostream Stream(sLastErrorString);
DiagnosticPrinterRawOStream DP(Stream);
DI.print(DP);
}
sLastErrorString += '\n';
}
// Initialize the configured targets if they have not been initialized.
static void lto_initialize() {
if (!initialized) {
@ -79,6 +99,9 @@ static void lto_initialize() {
InitializeAllAsmParsers();
InitializeAllAsmPrinters();
InitializeAllDisassemblers();
LTOContext = &getGlobalContext();
LTOContext->setDiagnosticHandler(diagnosticHandler, nullptr, true);
initialized = true;
}
}
@ -95,7 +118,7 @@ static void handleLibLTODiagnostic(lto_codegen_diagnostic_severity_t Severity,
// libLTO API semantics, which require that the code generator owns the object
// file.
struct LibLTOCodeGenerator : LTOCodeGenerator {
LibLTOCodeGenerator() : LTOCodeGenerator(getGlobalContext()) {
LibLTOCodeGenerator() : LTOCodeGenerator(*LTOContext) {
setDiagnosticHandler(handleLibLTODiagnostic, nullptr); }
LibLTOCodeGenerator(std::unique_ptr<LLVMContext> Context)
: LTOCodeGenerator(*Context), OwnedContext(std::move(Context)) {
@ -166,14 +189,21 @@ lto_module_is_object_file_in_memory_for_target(const void* mem,
lto_module_t lto_module_create(const char* path) {
lto_initialize();
llvm::TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
return wrap(LTOModule::createFromFile(path, Options, sLastErrorString));
ErrorOr<std::unique_ptr<LTOModule>> M =
LTOModule::createFromFile(*LTOContext, path, Options);
if (!M)
return nullptr;
return wrap(M->release());
}
lto_module_t lto_module_create_from_fd(int fd, const char *path, size_t size) {
lto_initialize();
llvm::TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
return wrap(
LTOModule::createFromOpenFile(fd, path, size, Options, sLastErrorString));
ErrorOr<std::unique_ptr<LTOModule>> M =
LTOModule::createFromOpenFile(*LTOContext, fd, path, size, Options);
if (!M)
return nullptr;
return wrap(M->release());
}
lto_module_t lto_module_create_from_fd_at_offset(int fd, const char *path,
@ -182,14 +212,21 @@ lto_module_t lto_module_create_from_fd_at_offset(int fd, const char *path,
off_t offset) {
lto_initialize();
llvm::TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
return wrap(LTOModule::createFromOpenFileSlice(fd, path, map_size, offset,
Options, sLastErrorString));
ErrorOr<std::unique_ptr<LTOModule>> M = LTOModule::createFromOpenFileSlice(
*LTOContext, fd, path, map_size, offset, Options);
if (!M)
return nullptr;
return wrap(M->release());
}
lto_module_t lto_module_create_from_memory(const void* mem, size_t length) {
lto_initialize();
llvm::TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
return wrap(LTOModule::createFromBuffer(mem, length, Options, sLastErrorString));
ErrorOr<std::unique_ptr<LTOModule>> M =
LTOModule::createFromBuffer(*LTOContext, mem, length, Options);
if (!M)
return nullptr;
return wrap(M->release());
}
lto_module_t lto_module_create_from_memory_with_path(const void* mem,
@ -197,16 +234,22 @@ lto_module_t lto_module_create_from_memory_with_path(const void* mem,
const char *path) {
lto_initialize();
llvm::TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
return wrap(
LTOModule::createFromBuffer(mem, length, Options, sLastErrorString, path));
ErrorOr<std::unique_ptr<LTOModule>> M =
LTOModule::createFromBuffer(*LTOContext, mem, length, Options, path);
if (!M)
return nullptr;
return wrap(M->release());
}
lto_module_t lto_module_create_in_local_context(const void *mem, size_t length,
const char *path) {
lto_initialize();
llvm::TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
return wrap(LTOModule::createInLocalContext(mem, length, Options,
sLastErrorString, path));
ErrorOr<std::unique_ptr<LTOModule>> M =
LTOModule::createInLocalContext(mem, length, Options, path);
if (!M)
return nullptr;
return wrap(M->release());
}
lto_module_t lto_module_create_in_codegen_context(const void *mem,
@ -215,8 +258,9 @@ lto_module_t lto_module_create_in_codegen_context(const void *mem,
lto_code_gen_t cg) {
lto_initialize();
llvm::TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
return wrap(LTOModule::createInContext(mem, length, Options, sLastErrorString,
path, &unwrap(cg)->getContext()));
ErrorOr<std::unique_ptr<LTOModule>> M = LTOModule::createInContext(
mem, length, Options, path, &unwrap(cg)->getContext());
return wrap(M->release());
}
void lto_module_dispose(lto_module_t mod) { delete unwrap(mod); }