Make it easier to pass a custom diagnostic handler to the IR linker.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@220732 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Rafael Espindola
2014-10-27 23:02:10 +00:00
parent 68aeef61f4
commit 0660f174cf
3 changed files with 46 additions and 32 deletions

View File

@ -12,8 +12,10 @@
#include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallPtrSet.h"
namespace llvm { #include <functional>
namespace llvm {
class DiagnosticInfo;
class Module; class Module;
class StructType; class StructType;
@ -28,6 +30,10 @@ class Linker {
PreserveSource = 1 // Preserve the source module. PreserveSource = 1 // Preserve the source module.
}; };
typedef std::function<void(const DiagnosticInfo &)>
DiagnosticHandlerFunction;
Linker(Module *M, DiagnosticHandlerFunction DiagnosticHandler);
Linker(Module *M); Linker(Module *M);
~Linker(); ~Linker();
@ -44,11 +50,18 @@ class Linker {
return linkInModule(Src, Linker::DestroySource); return linkInModule(Src, Linker::DestroySource);
} }
static bool LinkModules(Module *Dest, Module *Src, unsigned Mode); static bool
LinkModules(Module *Dest, Module *Src, unsigned Mode,
DiagnosticHandlerFunction DiagnosticHandler);
static bool
LinkModules(Module *Dest, Module *Src, unsigned Mode);
private: private:
Module *Composite; Module *Composite;
SmallPtrSet<StructType*, 32> IdentifiedStructTypes; SmallPtrSet<StructType*, 32> IdentifiedStructTypes;
DiagnosticHandlerFunction DiagnosticHandler;
}; };
} // End llvm namespace } // End llvm namespace

View File

@ -418,10 +418,14 @@ namespace {
// Vector of functions to lazily link in. // Vector of functions to lazily link in.
std::vector<Function*> LazilyLinkFunctions; std::vector<Function*> LazilyLinkFunctions;
Linker::DiagnosticHandlerFunction DiagnosticHandler;
public: public:
ModuleLinker(Module *dstM, TypeSet &Set, Module *srcM, unsigned mode) ModuleLinker(Module *dstM, TypeSet &Set, Module *srcM, unsigned mode,
Linker::DiagnosticHandlerFunction DiagnosticHandler)
: DstM(dstM), SrcM(srcM), TypeMap(Set), : DstM(dstM), SrcM(srcM), TypeMap(Set),
ValMaterializer(TypeMap, DstM, LazilyLinkFunctions), Mode(mode) {} ValMaterializer(TypeMap, DstM, LazilyLinkFunctions), Mode(mode),
DiagnosticHandler(DiagnosticHandler) {}
bool run(); bool run();
@ -431,12 +435,12 @@ namespace {
/// Helper method for setting a message and returning an error code. /// Helper method for setting a message and returning an error code.
bool emitError(const Twine &Message) { bool emitError(const Twine &Message) {
DstM->getContext().diagnose(LinkDiagnosticInfo(DS_Error, Message)); DiagnosticHandler(LinkDiagnosticInfo(DS_Error, Message));
return true; return true;
} }
void emitWarning(const Twine &Message) { void emitWarning(const Twine &Message) {
DstM->getContext().diagnose(LinkDiagnosticInfo(DS_Warning, Message)); DiagnosticHandler(LinkDiagnosticInfo(DS_Warning, Message));
} }
bool getComdatLeader(Module *M, StringRef ComdatName, bool getComdatLeader(Module *M, StringRef ComdatName,
@ -1721,7 +1725,13 @@ bool ModuleLinker::run() {
return false; return false;
} }
Linker::Linker(Module *M) : Composite(M) { Linker::Linker(Module *M, DiagnosticHandlerFunction DiagnosticHandler)
: Composite(M), DiagnosticHandler(DiagnosticHandler) {}
Linker::Linker(Module *M)
: Composite(M), DiagnosticHandler([this](const DiagnosticInfo &DI) {
Composite->getContext().diagnose(DI);
}) {
TypeFinder StructTypes; TypeFinder StructTypes;
StructTypes.run(*M, true); StructTypes.run(*M, true);
IdentifiedStructTypes.insert(StructTypes.begin(), StructTypes.end()); IdentifiedStructTypes.insert(StructTypes.begin(), StructTypes.end());
@ -1736,7 +1746,7 @@ void Linker::deleteModule() {
} }
bool Linker::linkInModule(Module *Src, unsigned Mode) { bool Linker::linkInModule(Module *Src, unsigned Mode) {
ModuleLinker TheLinker(Composite, IdentifiedStructTypes, Src, Mode); ModuleLinker TheLinker(Composite, IdentifiedStructTypes, Src, Mode, DiagnosticHandler);
return TheLinker.run(); return TheLinker.run();
} }
@ -1749,6 +1759,12 @@ bool Linker::linkInModule(Module *Src, unsigned Mode) {
/// true is returned and ErrorMsg (if not null) is set to indicate the problem. /// true is returned and ErrorMsg (if not null) is set to indicate the problem.
/// Upon failure, the Dest module could be in a modified state, and shouldn't be /// Upon failure, the Dest module could be in a modified state, and shouldn't be
/// relied on to be consistent. /// relied on to be consistent.
bool Linker::LinkModules(Module *Dest, Module *Src, unsigned Mode,
DiagnosticHandlerFunction DiagnosticHandler) {
Linker L(Dest, DiagnosticHandler);
return L.linkInModule(Src, Mode);
}
bool Linker::LinkModules(Module *Dest, Module *Src, unsigned Mode) { bool Linker::LinkModules(Module *Dest, Module *Src, unsigned Mode) {
Linker L(Dest); Linker L(Dest);
return L.linkInModule(Src, Mode); return L.linkInModule(Src, Mode);
@ -1758,31 +1774,15 @@ bool Linker::LinkModules(Module *Dest, Module *Src, unsigned Mode) {
// C API. // C API.
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
static void bindingDiagnosticHandler(const llvm::DiagnosticInfo &DI,
void *Context) {
if (DI.getSeverity() != DS_Error)
return;
std::string *Message = (std::string *)Context;
{
raw_string_ostream Stream(*Message);
DiagnosticPrinterRawOStream DP(Stream);
DI.print(DP);
}
}
LLVMBool LLVMLinkModules(LLVMModuleRef Dest, LLVMModuleRef Src, LLVMBool LLVMLinkModules(LLVMModuleRef Dest, LLVMModuleRef Src,
LLVMLinkerMode Mode, char **OutMessages) { LLVMLinkerMode Mode, char **OutMessages) {
Module *D = unwrap(Dest); Module *D = unwrap(Dest);
LLVMContext &Ctx = D->getContext();
LLVMContext::DiagnosticHandlerTy OldHandler = Ctx.getDiagnosticHandler();
void *OldDiagnosticContext = Ctx.getDiagnosticContext();
std::string Message; std::string Message;
Ctx.setDiagnosticHandler(bindingDiagnosticHandler, &Message); raw_string_ostream Stream(Message);
LLVMBool Result = Linker::LinkModules(D, unwrap(Src), Mode); DiagnosticPrinterRawOStream DP(Stream);
Ctx.setDiagnosticHandler(OldHandler, OldDiagnosticContext);
LLVMBool Result = Linker::LinkModules(
D, unwrap(Src), Mode, [&](const DiagnosticInfo &DI) { DI.print(DP); });
if (OutMessages && Result) if (OutMessages && Result)
*OutMessages = strdup(Message.c_str()); *OutMessages = strdup(Message.c_str());

View File

@ -71,11 +71,12 @@ loadFile(const char *argv0, const std::string &FN, LLVMContext &Context) {
return Result; return Result;
} }
static void diagnosticHandler(const DiagnosticInfo &DI, void *Context) { static void diagnosticHandler(const DiagnosticInfo &DI) {
unsigned Severity = DI.getSeverity(); unsigned Severity = DI.getSeverity();
switch (Severity) { switch (Severity) {
case DS_Error: case DS_Error:
errs() << "ERROR: "; errs() << "ERROR: ";
break;
case DS_Warning: case DS_Warning:
if (SuppressWarnings) if (SuppressWarnings)
return; return;
@ -88,6 +89,7 @@ static void diagnosticHandler(const DiagnosticInfo &DI, void *Context) {
DiagnosticPrinterRawOStream DP(errs()); DiagnosticPrinterRawOStream DP(errs());
DI.print(DP); DI.print(DP);
errs() << '\n';
} }
int main(int argc, char **argv) { int main(int argc, char **argv) {
@ -100,9 +102,8 @@ int main(int argc, char **argv) {
cl::ParseCommandLineOptions(argc, argv, "llvm linker\n"); cl::ParseCommandLineOptions(argc, argv, "llvm linker\n");
auto Composite = make_unique<Module>("llvm-link", Context); auto Composite = make_unique<Module>("llvm-link", Context);
Linker L(Composite.get()); Linker L(Composite.get(), diagnosticHandler);
Context.setDiagnosticHandler(diagnosticHandler);
for (unsigned i = 0; i < InputFilenames.size(); ++i) { for (unsigned i = 0; i < InputFilenames.size(); ++i) {
std::unique_ptr<Module> M = loadFile(argv[0], InputFilenames[i], Context); std::unique_ptr<Module> M = loadFile(argv[0], InputFilenames[i], Context);
if (!M.get()) { if (!M.get()) {