Skip to content

Commit

Permalink
[LTO] Add a hook to map LLVM diagnostics into the clients of LTO.
Browse files Browse the repository at this point in the history
Add a hook in the C API of LTO so that clients of the code generator can set
their own handler for the LLVM diagnostics.
The handler is defined like this:
typedef void (*lto_diagnostic_handler_t)(lto_codegen_diagnostic_severity_t
severity, const char *diag, void *ctxt)
- severity says how bad this is.
- diag is a string that contains the diagnostic message.
- ctxt is the registered context for this handler.

This hook is more general than the lto_get_error_message, since this function
keeps only the latest message and can only be queried when something went wrong
(no warning for instance).

<rdar://problem/15517596>


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@199338 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
Quentin Colombet committed Jan 15, 2014
1 parent 7fa843c commit 4c831d9
Show file tree
Hide file tree
Showing 5 changed files with 94 additions and 2 deletions.
29 changes: 28 additions & 1 deletion include/llvm-c/lto.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ typedef bool lto_bool_t;
* @{
*/

#define LTO_API_VERSION 6
#define LTO_API_VERSION 7

typedef enum {
LTO_SYMBOL_ALIGNMENT_MASK = 0x0000001F, /* log2 of alignment */
Expand Down Expand Up @@ -204,6 +204,33 @@ lto_module_get_symbol_name(lto_module_t mod, unsigned int index);
extern lto_symbol_attributes
lto_module_get_symbol_attribute(lto_module_t mod, unsigned int index);

/**
* Diagnostic severity.
*/
typedef enum {
LTO_DS_ERROR,
LTO_DS_WARNING,
LTO_DS_NOTE
} lto_codegen_diagnostic_severity_t;

/**
* Diagnostic handler type.
* \p severity defines the severity.
* \p diag is the actual diagnostic.
* The diagnostic is not prefixed by any of severity keyword, e.g., 'error: '.
* \p ctxt is used to pass the context set with the diagnostic handler.
*/
typedef void (*lto_diagnostic_handler_t)(
lto_codegen_diagnostic_severity_t severity, const char *diag, void *ctxt);

/**
* Set a diagnostic handler and the related context (void *).
* This is more general than lto_get_error_message, as the diagnostic handler
* can be called at anytime within lto.
*/
extern void lto_codegen_set_diagnostic_handler(lto_code_gen_t,
lto_diagnostic_handler_t,
void *);

/**
* Instantiates a code generator.
Expand Down
9 changes: 9 additions & 0 deletions include/llvm/LTO/LTOCodeGenerator.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@

namespace llvm {
class LLVMContext;
class DiagnosticInfo;
class GlobalValue;
class Mangler;
class MemoryBuffer;
Expand Down Expand Up @@ -115,6 +116,8 @@ struct LTOCodeGenerator {
bool disableGVNLoadPRE,
std::string &errMsg);

void setDiagnosticHandler(lto_diagnostic_handler_t, void *);

bool shouldInternalize() const {
return InternalizeStrategy != LTO_INTERNALIZE_NONE;
}
Expand All @@ -139,6 +142,10 @@ struct LTOCodeGenerator {
llvm::Mangler &Mangler);
bool determineTarget(std::string &errMsg);

static void DiagnosticHandler(const llvm::DiagnosticInfo &DI, void *Context);

void DiagnosticHandler2(const llvm::DiagnosticInfo &DI);

typedef llvm::StringMap<uint8_t> StringSet;

llvm::LLVMContext &Context;
Expand All @@ -155,6 +162,8 @@ struct LTOCodeGenerator {
std::string MCpu;
std::string NativeObjectPath;
llvm::TargetOptions Options;
lto_diagnostic_handler_t DiagHandler;
void *DiagContext;
};

#endif // LTO_CODE_GENERATOR_H
50 changes: 49 additions & 1 deletion lib/LTO/LTOCodeGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
#include "llvm/IR/Constants.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/DiagnosticInfo.h"
#include "llvm/IR/DiagnosticPrinter.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Mangler.h"
#include "llvm/IR/Module.h"
Expand All @@ -37,6 +39,7 @@
#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/Host.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/Signals.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/TargetSelect.h"
Expand All @@ -63,7 +66,8 @@ LTOCodeGenerator::LTOCodeGenerator()
: Context(getGlobalContext()), Linker(new Module("ld-temp.o", Context)),
TargetMach(NULL), EmitDwarfDebugInfo(false), ScopeRestrictionsDone(false),
CodeModel(LTO_CODEGEN_PIC_MODEL_DYNAMIC),
InternalizeStrategy(LTO_INTERNALIZE_FULL), NativeObjectFile(NULL) {
InternalizeStrategy(LTO_INTERNALIZE_FULL), NativeObjectFile(NULL),
DiagHandler(NULL), DiagContext(NULL) {
initializeLTOPasses();
}

Expand Down Expand Up @@ -536,3 +540,47 @@ void LTOCodeGenerator::parseCodeGenDebugOptions() {
cl::ParseCommandLineOptions(CodegenOptions.size(),
const_cast<char **>(&CodegenOptions[0]));
}

void LTOCodeGenerator::DiagnosticHandler(const DiagnosticInfo &DI,
void *Context) {
((LTOCodeGenerator *)Context)->DiagnosticHandler2(DI);
}

void LTOCodeGenerator::DiagnosticHandler2(const DiagnosticInfo &DI) {
// Map the LLVM internal diagnostic severity to the LTO diagnostic severity.
lto_codegen_diagnostic_severity_t Severity;
switch (DI.getSeverity()) {
case DS_Error:
Severity = LTO_DS_ERROR;
break;
case DS_Warning:
Severity = LTO_DS_WARNING;
break;
case DS_Note:
Severity = LTO_DS_NOTE;
break;
}
// Create the string that will be reported to the external diagnostic handler.
std::string MsgStorage;
raw_string_ostream Stream(MsgStorage);
DiagnosticPrinterRawOStream DP(Stream);
DI.print(DP);
Stream.flush();

// If this method has been called it means someone has set up an external
// diagnostic handler. Assert on that.
assert(DiagHandler && "Invalid diagnostic handler");
(*DiagHandler)(Severity, MsgStorage.c_str(), DiagContext);
}

void
LTOCodeGenerator::setDiagnosticHandler(lto_diagnostic_handler_t DiagHandler,
void *Ctxt) {
this->DiagHandler = DiagHandler;
this->DiagContext = Ctxt;
if (!DiagHandler)
return Context.setDiagnosticHandler(NULL, NULL);
// Register the LTOCodeGenerator stub in the LLVMContext to forward the
// diagnostic to the external DiagHandler.
Context.setDiagnosticHandler(LTOCodeGenerator::DiagnosticHandler, this);
}
7 changes: 7 additions & 0 deletions tools/lto/lto.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,13 @@ lto_symbol_attributes lto_module_get_symbol_attribute(lto_module_t mod,
return mod->getSymbolAttributes(index);
}

/// Set a diagnostic handler.
void lto_codegen_set_diagnostic_handler(lto_code_gen_t cg,
lto_diagnostic_handler_t diag_handler,
void *ctxt) {
cg->setDiagnosticHandler(diag_handler, ctxt);
}

/// lto_codegen_create - Instantiates a code generator. Returns NULL if there
/// is an error.
lto_code_gen_t lto_codegen_create(void) {
Expand Down
1 change: 1 addition & 0 deletions tools/lto/lto.exports
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ lto_module_is_object_file_for_target
lto_module_is_object_file_in_memory
lto_module_is_object_file_in_memory_for_target
lto_module_dispose
lto_codegen_set_diagnostic_handler
lto_codegen_add_module
lto_codegen_add_must_preserve_symbol
lto_codegen_compile
Expand Down

0 comments on commit 4c831d9

Please sign in to comment.