/// 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 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>>
+ 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 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();
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
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);
}
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>();
// 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())
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;
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.
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);
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);
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.
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;
unsigned BaseArg = 0;
- LTOCodeGenerator CodeGen(getGlobalContext());
+ LLVMContext Context;
+ Context.setDiagnosticHandler(diagnosticHandlerWithContenxt, nullptr, true);
+
+ LTOCodeGenerator CodeGen(Context);
if (UseDiagnosticHandler)
CodeGen.setDiagnosticHandler(handleDiagnostics, nullptr);
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) {
#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"
// 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) {
InitializeAllAsmParsers();
InitializeAllAsmPrinters();
InitializeAllDisassemblers();
+
+ LTOContext = &getGlobalContext();
+ LTOContext->setDiagnosticHandler(diagnosticHandler, nullptr, true);
initialized = true;
}
}
// 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)) {
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,
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,
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,
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); }