diff --git a/clang/lib/CodeGen/CodeGenAction.cpp b/clang/lib/CodeGen/CodeGenAction.cpp --- a/clang/lib/CodeGen/CodeGenAction.cpp +++ b/clang/lib/CodeGen/CodeGenAction.cpp @@ -304,14 +304,7 @@ if (!getModule()) return; - // Install an inline asm handler so that diagnostics get printed through - // our diagnostics hooks. LLVMContext &Ctx = getModule()->getContext(); - LLVMContext::InlineAsmDiagHandlerTy OldHandler = - Ctx.getInlineAsmDiagnosticHandler(); - void *OldContext = Ctx.getInlineAsmDiagnosticContext(); - Ctx.setInlineAsmDiagnosticHandler(InlineAsmDiagHandler, this); - std::unique_ptr OldDiagnosticHandler = Ctx.getDiagnosticHandler(); Ctx.setDiagnosticHandler(std::make_unique( @@ -345,8 +338,6 @@ LangOpts, C.getTargetInfo().getDataLayout(), getModule(), Action, std::move(AsmOutStream)); - Ctx.setInlineAsmDiagnosticHandler(OldHandler, OldContext); - Ctx.setDiagnosticHandler(std::move(OldDiagnosticHandler)); if (OptRecordFile) @@ -380,12 +371,6 @@ Gen->HandleVTable(RD); } - static void InlineAsmDiagHandler(const llvm::SMDiagnostic &SM,void *Context, - unsigned LocCookie) { - SourceLocation Loc = SourceLocation::getFromRawEncoding(LocCookie); - ((BackendConsumer*)Context)->InlineAsmDiagHandler2(SM, Loc); - } - /// Get the best possible source location to represent a diagnostic that /// may have associated debug info. const FullSourceLoc @@ -393,14 +378,12 @@ bool &BadDebugInfo, StringRef &Filename, unsigned &Line, unsigned &Column) const; - void InlineAsmDiagHandler2(const llvm::SMDiagnostic &, - SourceLocation LocCookie); - void DiagnosticHandlerImpl(const llvm::DiagnosticInfo &DI); /// Specialized handler for InlineAsm diagnostic. /// \return True if the diagnostic has been successfully reported, false /// otherwise. bool InlineAsmDiagHandler(const llvm::DiagnosticInfoInlineAsm &D); + bool InlineAsmDiagHandler(const llvm::DiagnosticInfoSrcMgr &D); /// Specialized handler for StackSize diagnostic. /// \return True if the diagnostic has been successfully reported, false /// otherwise. @@ -459,24 +442,9 @@ return FullSourceLoc(NewLoc, CSM); } - -/// InlineAsmDiagHandler2 - This function is invoked when the backend hits an -/// error parsing inline asm. The SMDiagnostic indicates the error relative to -/// the temporary memory buffer that the inline asm parser has set up. -void BackendConsumer::InlineAsmDiagHandler2(const llvm::SMDiagnostic &D, - SourceLocation LocCookie) { - // There are a couple of different kinds of errors we could get here. First, - // we re-format the SMDiagnostic in terms of a clang diagnostic. - - // Strip "error: " off the start of the message string. - StringRef Message = D.getMessage(); - if (Message.startswith("error: ")) - Message = Message.substr(7); - - // If the SMDiagnostic has an inline asm source location, translate it. - FullSourceLoc Loc; - if (D.getLoc() != SMLoc()) - Loc = ConvertBackendLocation(D, Context->getSourceManager()); +bool BackendConsumer::InlineAsmDiagHandler( + const llvm::DiagnosticInfoSrcMgr &DI) { + const llvm::SMDiagnostic &D = DI.getSMDiag(); unsigned DiagID; switch (D.getKind()) { @@ -492,29 +460,56 @@ case llvm::SourceMgr::DK_Remark: llvm_unreachable("remarks unexpected"); } + + // This is for the empty BackendConsumer that uses the clang diagnostic + // handler for IR input files. + if (!Context) { + D.print(nullptr, llvm::errs()); + Diags.Report(DiagID).AddString("cannot compile inline asm"); + return true; + } + + // There are a couple of different kinds of errors we could get here. + // First, we re-format the SMDiagnostic in terms of a clang diagnostic. + + // Strip "error: " off the start of the message string. + StringRef Message = D.getMessage(); + if (Message.startswith("error: ")) + Message = Message.substr(7); + + // If the SMDiagnostic has an inline asm source location, translate it. + FullSourceLoc Loc; + if (D.getLoc() != SMLoc()) + Loc = ConvertBackendLocation(D, Context->getSourceManager()); + // If this problem has clang-level source location information, report the // issue in the source with a note showing the instantiated // code. - if (LocCookie.isValid()) { - Diags.Report(LocCookie, DiagID).AddString(Message); - - if (D.getLoc().isValid()) { - DiagnosticBuilder B = Diags.Report(Loc, diag::note_fe_inline_asm_here); - // Convert the SMDiagnostic ranges into SourceRange and attach them - // to the diagnostic. - for (const std::pair &Range : D.getRanges()) { - unsigned Column = D.getColumnNo(); - B << SourceRange(Loc.getLocWithOffset(Range.first - Column), - Loc.getLocWithOffset(Range.second - Column)); + if (DI.isInlineAsmDiag()) { + SourceLocation LocCookie = + SourceLocation::getFromRawEncoding(DI.getLocCookie()); + if (LocCookie.isValid()) { + Diags.Report(LocCookie, DiagID).AddString(Message); + + if (D.getLoc().isValid()) { + DiagnosticBuilder B = Diags.Report(Loc, diag::note_fe_inline_asm_here); + // Convert the SMDiagnostic ranges into SourceRange and attach them + // to the diagnostic. + for (const std::pair &Range : D.getRanges()) { + unsigned Column = D.getColumnNo(); + B << SourceRange(Loc.getLocWithOffset(Range.first - Column), + Loc.getLocWithOffset(Range.second - Column)); + } } + return true; } - return; } // Otherwise, report the backend issue as occurring in the generated .s file. // If Loc is invalid, we still need to report the issue, it just gets no // location info. Diags.Report(Loc, DiagID).AddString(Message); + return true; } #define ComputeDiagID(Severity, GroupName, DiagID) \ @@ -791,6 +786,11 @@ return; ComputeDiagID(Severity, inline_asm, DiagID); break; + case llvm::DK_SrcMgr: + if (InlineAsmDiagHandler(cast(DI))) + return; + ComputeDiagID(Severity, inline_asm, DiagID); + break; case llvm::DK_StackSize: if (StackSizeDiagHandler(cast(DI))) return; @@ -987,30 +987,6 @@ return std::move(Result); } -static void BitcodeInlineAsmDiagHandler(const llvm::SMDiagnostic &SM, - void *Context, - unsigned LocCookie) { - SM.print(nullptr, llvm::errs()); - - auto Diags = static_cast(Context); - unsigned DiagID; - switch (SM.getKind()) { - case llvm::SourceMgr::DK_Error: - DiagID = diag::err_fe_inline_asm; - break; - case llvm::SourceMgr::DK_Warning: - DiagID = diag::warn_fe_inline_asm; - break; - case llvm::SourceMgr::DK_Note: - DiagID = diag::note_fe_inline_asm; - break; - case llvm::SourceMgr::DK_Remark: - llvm_unreachable("remarks unexpected"); - } - - Diags->Report(DiagID).AddString("cannot compile inline asm"); -} - std::unique_ptr CodeGenAction::loadModule(MemoryBufferRef MBRef) { CompilerInstance &CI = getCompilerInstance(); @@ -1113,7 +1089,6 @@ EmbedBitcode(TheModule.get(), CodeGenOpts, *MainFile); LLVMContext &Ctx = TheModule->getContext(); - Ctx.setInlineAsmDiagnosticHandler(BitcodeInlineAsmDiagHandler, &Diagnostics); // Restore any diagnostic handler previously set before returning from this // function. diff --git a/lldb/source/Expression/IRExecutionUnit.cpp b/lldb/source/Expression/IRExecutionUnit.cpp --- a/lldb/source/Expression/IRExecutionUnit.cpp +++ b/lldb/source/Expression/IRExecutionUnit.cpp @@ -9,6 +9,8 @@ #include "llvm/ExecutionEngine/ExecutionEngine.h" #include "llvm/ExecutionEngine/ObjectCache.h" #include "llvm/IR/Constants.h" +#include "llvm/IR/DiagnosticHandler.h" +#include "llvm/IR/DiagnosticInfo.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" #include "llvm/Support/SourceMgr.h" @@ -200,16 +202,26 @@ return ret; } -static void ReportInlineAsmError(const llvm::SMDiagnostic &diagnostic, - void *Context, unsigned LocCookie) { - Status *err = static_cast(Context); +namespace { +struct IRExecDiagnosticHandler : public llvm::DiagnosticHandler { + Status *err; + IRExecDiagnosticHandler(Status *err) : err(err) {} + bool handleDiagnostics(const llvm::DiagnosticInfo &DI) override { + if (DI.getKind() == llvm::DK_SrcMgr) { + const auto &DISM = llvm::cast(DI); + if (err && err->Success()) { + err->SetErrorToGenericError(); + err->SetErrorStringWithFormat( + "Inline assembly error: %s", + DISM.getSMDiag().getMessage().str().c_str()); + } + return true; + } - if (err && err->Success()) { - err->SetErrorToGenericError(); - err->SetErrorStringWithFormat("Inline assembly error: %s", - diagnostic.getMessage().str().c_str()); + return false; } -} +}; +} // namespace void IRExecutionUnit::ReportSymbolLookupError(ConstString name) { m_failed_lookups.push_back(name); @@ -257,8 +269,8 @@ LLDB_LOGF(log, "Module being sent to JIT: \n%s", s.c_str()); } - m_module_up->getContext().setInlineAsmDiagnosticHandler(ReportInlineAsmError, - &error); + m_module_up->getContext().setDiagnosticHandler( + std::make_unique(&error)); llvm::EngineBuilder builder(std::move(m_module_up)); llvm::Triple triple(m_module->getTargetTriple()); diff --git a/llvm/include/llvm/CodeGen/AsmPrinter.h b/llvm/include/llvm/CodeGen/AsmPrinter.h --- a/llvm/include/llvm/CodeGen/AsmPrinter.h +++ b/llvm/include/llvm/CodeGen/AsmPrinter.h @@ -185,14 +185,6 @@ std::vector Handlers; size_t NumUserHandlers = 0; -public: - struct SrcMgrDiagInfo { - SourceMgr SrcMgr; - std::vector LocInfos; - LLVMContext::InlineAsmDiagHandlerTy DiagHandler; - void *DiagContext; - }; - private: /// If generated on the fly this own the instance. std::unique_ptr OwnedMDT; @@ -200,10 +192,6 @@ /// If generated on the fly this own the instance. std::unique_ptr OwnedMLI; - /// Structure for generating diagnostics for inline assembly. Only initialised - /// when necessary. - mutable std::unique_ptr DiagInfo; - /// If the target supports dwarf debug info, this pointer is non-null. DwarfDebug *DD = nullptr; diff --git a/llvm/include/llvm/IR/DiagnosticInfo.h b/llvm/include/llvm/IR/DiagnosticInfo.h --- a/llvm/include/llvm/IR/DiagnosticInfo.h +++ b/llvm/include/llvm/IR/DiagnosticInfo.h @@ -78,6 +78,7 @@ DK_MIRParser, DK_PGOProfile, DK_Unsupported, + DK_SrcMgr, DK_FirstPluginKind // Must be last value to work with // getNextAvailablePluginDiagnosticKind }; @@ -1015,6 +1016,31 @@ void print(DiagnosticPrinter &DP) const override; }; +class DiagnosticInfoSrcMgr : public DiagnosticInfo { + const SMDiagnostic &Diagnostic; + bool InlineAsmDiag; + unsigned LocCookie; + +public: + DiagnosticInfoSrcMgr(const SMDiagnostic &Diagnostic, + bool InlineAsmDiag = true, unsigned LocCookie = 0, + DiagnosticSeverity Severity = DS_Error) + : DiagnosticInfo(DK_SrcMgr, Severity), Diagnostic(Diagnostic), + InlineAsmDiag(InlineAsmDiag), LocCookie(LocCookie) {} + + bool isInlineAsmDiag() const { return InlineAsmDiag; } + const SMDiagnostic &getSMDiag() const { return Diagnostic; } + unsigned getLocCookie() const { return LocCookie; } + + void print(DiagnosticPrinter &DP) const override { + llvm_unreachable("unimplemented"); + } + + static bool classof(const DiagnosticInfo *DI) { + return DI->getKind() == DK_SrcMgr; + } +}; + } // end namespace llvm #endif // LLVM_IR_DIAGNOSTICINFO_H diff --git a/llvm/include/llvm/IR/LLVMContext.h b/llvm/include/llvm/IR/LLVMContext.h --- a/llvm/include/llvm/IR/LLVMContext.h +++ b/llvm/include/llvm/IR/LLVMContext.h @@ -153,31 +153,10 @@ void enableDebugTypeODRUniquing(); void disableDebugTypeODRUniquing(); - using InlineAsmDiagHandlerTy = void (*)(const SMDiagnostic&, void *Context, - unsigned LocCookie); - /// Defines the type of a yield callback. /// \see LLVMContext::setYieldCallback. using YieldCallbackTy = void (*)(LLVMContext *Context, void *OpaqueHandle); - /// setInlineAsmDiagnosticHandler - This method sets a handler that is invoked - /// when problems with inline asm are detected by the backend. The first - /// argument is a function pointer and the second is a context pointer that - /// gets passed into the DiagHandler. - /// - /// LLVMContext doesn't take ownership or interpret either of these - /// pointers. - void setInlineAsmDiagnosticHandler(InlineAsmDiagHandlerTy DiagHandler, - void *DiagContext = nullptr); - - /// getInlineAsmDiagnosticHandler - Return the diagnostic handler set by - /// setInlineAsmDiagnosticHandler. - InlineAsmDiagHandlerTy getInlineAsmDiagnosticHandler() const; - - /// getInlineAsmDiagnosticContext - Return the diagnostic context set by - /// setInlineAsmDiagnosticHandler. - void *getInlineAsmDiagnosticContext() const; - /// setDiagnosticHandlerCallBack - This method sets a handler call back /// that is invoked when the backend needs to report anything to the user. /// The first argument is a function pointer and the second is a context pointer diff --git a/llvm/include/llvm/MC/MCContext.h b/llvm/include/llvm/MC/MCContext.h --- a/llvm/include/llvm/MC/MCContext.h +++ b/llvm/include/llvm/MC/MCContext.h @@ -30,11 +30,13 @@ #include "llvm/Support/Compiler.h" #include "llvm/Support/Error.h" #include "llvm/Support/MD5.h" +#include "llvm/Support/SourceMgr.h" #include "llvm/Support/raw_ostream.h" #include #include #include #include +#include #include #include #include @@ -59,6 +61,7 @@ class MCSymbolELF; class MCSymbolWasm; class MCSymbolXCOFF; + class MDNode; class SMLoc; class SourceMgr; @@ -68,13 +71,19 @@ class MCContext { public: using SymbolTable = StringMap; + using DiagHandlerTy = + std::function &)>; private: /// The SourceMgr for this object, if any. const SourceMgr *SrcMgr; /// The SourceMgr for inline assembly, if any. - SourceMgr *InlineSrcMgr; + std::unique_ptr InlineSrcMgr; + std::vector LocInfos; + + DiagHandlerTy DiagHandler = defaultDiagHandler; /// The MCAsmInfo for this target. const MCAsmInfo *MAI; @@ -299,6 +308,9 @@ bool HadError = false; + void reportCommon(SMLoc Loc, SourceMgr::DiagKind Kind, const Twine &Msg, + bool InlineAsm = false); + MCSymbol *createSymbolImpl(const StringMapEntry *Name, bool CanBeUnnamed); MCSymbol *createSymbol(StringRef Name, bool AlwaysAddSuffix, @@ -361,9 +373,26 @@ MCContext &operator=(const MCContext &) = delete; ~MCContext(); + static void defaultDiagHandler(const SMDiagnostic &SMD, bool, + const SourceMgr &, + std::vector &) { + SMD.print(nullptr, errs()); + } const SourceMgr *getSourceManager() const { return SrcMgr; } - void setInlineSourceManager(SourceMgr *SM) { InlineSrcMgr = SM; } + bool AsmParseMode = false; + void initInlineSourceManager() { + if (!InlineSrcMgr) + InlineSrcMgr.reset(new SourceMgr()); + } + SourceMgr *getInlineSourceManager() { + assert(InlineSrcMgr); + return InlineSrcMgr.get(); + } + std::vector &getLocInfos() { return LocInfos; } + void setDiagnosticHandler(DiagHandlerTy DiagHandler) { + this->DiagHandler = DiagHandler; + } const MCAsmInfo *getAsmInfo() const { return MAI; } @@ -748,13 +777,14 @@ void deallocate(void *Ptr) {} bool hadError() { return HadError; } - void reportError(SMLoc L, const Twine &Msg); - void reportWarning(SMLoc L, const Twine &Msg); + void diagnose(const SMDiagnostic &SMD); + void reportError(SMLoc L, const Twine &Msg, bool InlineAsm = false); + void reportWarning(SMLoc L, const Twine &Msg, bool InlineAsm = false); // Unrecoverable error has occurred. Display the best diagnostic we can // and bail via exit(1). For now, most MC backend errors are unrecoverable. // FIXME: We should really do something about that. - LLVM_ATTRIBUTE_NORETURN void reportFatalError(SMLoc L, - const Twine &Msg); + LLVM_ATTRIBUTE_NORETURN void reportFatalError(SMLoc L, const Twine &Msg, + bool InlineAsm = false); const MCAsmMacro *lookupMacro(StringRef Name) { StringMap::iterator I = MacroMap.find(Name); diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp @@ -39,54 +39,12 @@ #define DEBUG_TYPE "asm-printer" -/// srcMgrDiagHandler - This callback is invoked when the SourceMgr for an -/// inline asm has an error in it. diagInfo is a pointer to the SrcMgrDiagInfo -/// struct above. -static void srcMgrDiagHandler(const SMDiagnostic &Diag, void *diagInfo) { - AsmPrinter::SrcMgrDiagInfo *DiagInfo = - static_cast(diagInfo); - assert(DiagInfo && "Diagnostic context not passed down?"); - - // Look up a LocInfo for the buffer this diagnostic is coming from. - unsigned BufNum = DiagInfo->SrcMgr.FindBufferContainingLoc(Diag.getLoc()); - const MDNode *LocInfo = nullptr; - if (BufNum > 0 && BufNum <= DiagInfo->LocInfos.size()) - LocInfo = DiagInfo->LocInfos[BufNum-1]; - - // If the inline asm had metadata associated with it, pull out a location - // cookie corresponding to which line the error occurred on. - unsigned LocCookie = 0; - if (LocInfo) { - unsigned ErrorLine = Diag.getLineNo()-1; - if (ErrorLine >= LocInfo->getNumOperands()) - ErrorLine = 0; - - if (LocInfo->getNumOperands() != 0) - if (const ConstantInt *CI = - mdconst::dyn_extract(LocInfo->getOperand(ErrorLine))) - LocCookie = CI->getZExtValue(); - } - - DiagInfo->DiagHandler(Diag, DiagInfo->DiagContext, LocCookie); -} - unsigned AsmPrinter::addInlineAsmDiagBuffer(StringRef AsmStr, const MDNode *LocMDNode) const { - if (!DiagInfo) { - DiagInfo = std::make_unique(); - - MCContext &Context = MMI->getContext(); - Context.setInlineSourceManager(&DiagInfo->SrcMgr); - - LLVMContext &LLVMCtx = MMI->getModule()->getContext(); - if (LLVMCtx.getInlineAsmDiagnosticHandler()) { - DiagInfo->DiagHandler = LLVMCtx.getInlineAsmDiagnosticHandler(); - DiagInfo->DiagContext = LLVMCtx.getInlineAsmDiagnosticContext(); - DiagInfo->SrcMgr.setDiagHandler(srcMgrDiagHandler, DiagInfo.get()); - } - } - - SourceMgr &SrcMgr = DiagInfo->SrcMgr; + MCContext &Context = MMI->getContext(); + Context.initInlineSourceManager(); + SourceMgr &SrcMgr = *Context.getInlineSourceManager(); + std::vector &LocInfos = Context.getLocInfos(); std::unique_ptr Buffer; // The inline asm source manager will outlive AsmStr, so make a copy of the @@ -98,8 +56,8 @@ // Store LocMDNode in DiagInfo, using BufNum as an identifier. if (LocMDNode) { - DiagInfo->LocInfos.resize(BufNum); - DiagInfo->LocInfos[BufNum - 1] = LocMDNode; + LocInfos.resize(BufNum); + LocInfos[BufNum - 1] = LocMDNode; } return BufNum; @@ -134,10 +92,11 @@ } unsigned BufNum = addInlineAsmDiagBuffer(Str, LocMDNode); - DiagInfo->SrcMgr.setIncludeDirs(MCOptions.IASSearchPaths); + SourceMgr &SrcMgr = *MMI->getContext().getInlineSourceManager(); + SrcMgr.setIncludeDirs(MCOptions.IASSearchPaths); - std::unique_ptr Parser(createMCAsmParser( - DiagInfo->SrcMgr, OutContext, *OutStreamer, *MAI, BufNum)); + std::unique_ptr Parser( + createMCAsmParser(SrcMgr, OutContext, *OutStreamer, *MAI, BufNum)); // Do not use assembler-level information for parsing inline assembly. OutStreamer->setUseAssemblerInfoForParsing(false); @@ -162,12 +121,9 @@ emitInlineAsmStart(); // Don't implicitly switch to the text section before the asm. - int Res = Parser->Run(/*NoInitialTextSection*/ true, - /*NoFinalize*/ true); + (void)Parser->Run(/*NoInitialTextSection*/ true, + /*NoFinalize*/ true); emitInlineAsmEnd(STI, &TAP->getSTI()); - - if (Res && !DiagInfo->DiagHandler) - report_fatal_error("Error parsing inline asm\n"); } static void EmitMSInlineAsmStr(const char *AsmStr, const MachineInstr *MI, @@ -572,7 +528,7 @@ if (!RestrRegs.empty()) { unsigned BufNum = addInlineAsmDiagBuffer(OS.str(), LocMD); - auto &SrcMgr = DiagInfo->SrcMgr; + auto &SrcMgr = *MMI->getContext().getInlineSourceManager(); SMLoc Loc = SMLoc::getFromPointer( SrcMgr.getMemoryBuffer(BufNum)->getBuffer().begin()); diff --git a/llvm/lib/CodeGen/MachineModuleInfo.cpp b/llvm/lib/CodeGen/MachineModuleInfo.cpp --- a/llvm/lib/CodeGen/MachineModuleInfo.cpp +++ b/llvm/lib/CodeGen/MachineModuleInfo.cpp @@ -16,7 +16,9 @@ #include "llvm/CodeGen/Passes.h" #include "llvm/IR/BasicBlock.h" #include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/DiagnosticInfo.h" #include "llvm/IR/Instructions.h" +#include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" #include "llvm/IR/Value.h" #include "llvm/IR/ValueHandle.h" @@ -315,9 +317,44 @@ "Machine Module Information", false, false) char MachineModuleInfoWrapperPass::ID = 0; +static unsigned getLocCookie(const SMDiagnostic &SMD, const SourceMgr &SrcMgr, + std::vector &LocInfos) { + // Look up a LocInfo for the buffer this diagnostic is coming from. + unsigned BufNum = SrcMgr.FindBufferContainingLoc(SMD.getLoc()); + const MDNode *LocInfo = nullptr; + if (BufNum > 0 && BufNum <= LocInfos.size()) + LocInfo = LocInfos[BufNum - 1]; + + // If the inline asm had metadata associated with it, pull out a location + // cookie corresponding to which line the error occurred on. + unsigned LocCookie = 0; + if (LocInfo) { + unsigned ErrorLine = SMD.getLineNo() - 1; + if (ErrorLine >= LocInfo->getNumOperands()) + ErrorLine = 0; + + if (LocInfo->getNumOperands() != 0) + if (const ConstantInt *CI = + mdconst::dyn_extract(LocInfo->getOperand(ErrorLine))) + LocCookie = CI->getZExtValue(); + } + + return LocCookie; +} + bool MachineModuleInfoWrapperPass::doInitialization(Module &M) { MMI.initialize(); MMI.TheModule = &M; + // FIXME: Do this for new pass manager. + LLVMContext &Ctx = M.getContext(); + MMI.getContext().setDiagnosticHandler( + [&Ctx](const SMDiagnostic &SMD, bool IsInlineAsm, const SourceMgr &SrcMgr, + std::vector &LocInfos) { + unsigned LocCookie = 0; + if (IsInlineAsm) + LocCookie = getLocCookie(SMD, SrcMgr, LocInfos); + Ctx.diagnose(DiagnosticInfoSrcMgr(SMD, IsInlineAsm, LocCookie)); + }); MMI.DbgInfoAvailable = !M.debug_compile_units().empty(); return false; } diff --git a/llvm/lib/IR/LLVMContext.cpp b/llvm/lib/IR/LLVMContext.cpp --- a/llvm/lib/IR/LLVMContext.cpp +++ b/llvm/lib/IR/LLVMContext.cpp @@ -111,26 +111,6 @@ // Recoverable Backend Errors //===----------------------------------------------------------------------===// -void LLVMContext:: -setInlineAsmDiagnosticHandler(InlineAsmDiagHandlerTy DiagHandler, - void *DiagContext) { - pImpl->InlineAsmDiagHandler = DiagHandler; - pImpl->InlineAsmDiagContext = DiagContext; -} - -/// getInlineAsmDiagnosticHandler - Return the diagnostic handler set by -/// setInlineAsmDiagnosticHandler. -LLVMContext::InlineAsmDiagHandlerTy -LLVMContext::getInlineAsmDiagnosticHandler() const { - return pImpl->InlineAsmDiagHandler; -} - -/// getInlineAsmDiagnosticContext - Return the diagnostic context set by -/// setInlineAsmDiagnosticHandler. -void *LLVMContext::getInlineAsmDiagnosticContext() const { - return pImpl->InlineAsmDiagContext; -} - void LLVMContext::setDiagnosticHandlerCallBack( DiagnosticHandler::DiagnosticHandlerTy DiagnosticHandler, void *DiagnosticContext, bool RespectFilters) { diff --git a/llvm/lib/IR/LLVMContextImpl.h b/llvm/lib/IR/LLVMContextImpl.h --- a/llvm/lib/IR/LLVMContextImpl.h +++ b/llvm/lib/IR/LLVMContextImpl.h @@ -1314,9 +1314,6 @@ /// will be automatically deleted if this context is deleted. SmallPtrSet OwnedModules; - LLVMContext::InlineAsmDiagHandlerTy InlineAsmDiagHandler = nullptr; - void *InlineAsmDiagContext = nullptr; - /// The main remark streamer used by all the other streamers (e.g. IR, MIR, /// frontends, etc.). This should only be used by the specific streamers, and /// never directly. diff --git a/llvm/lib/MC/MCContext.cpp b/llvm/lib/MC/MCContext.cpp --- a/llvm/lib/MC/MCContext.cpp +++ b/llvm/lib/MC/MCContext.cpp @@ -85,6 +85,12 @@ //===----------------------------------------------------------------------===// void MCContext::reset() { + SrcMgr = nullptr; + InlineSrcMgr.release(); + LocInfos.clear(); + DiagHandler = defaultDiagHandler; + AsmParseMode = false; + // Call the destructors so the fragments are freed COFFAllocator.DestroyAll(); ELFAllocator.DestroyAll(); @@ -835,37 +841,68 @@ // Error Reporting //===----------------------------------------------------------------------===// -void MCContext::reportError(SMLoc Loc, const Twine &Msg) { - HadError = true; +void MCContext::diagnose(const SMDiagnostic &SMD) { + assert(DiagHandler && "MCContext::DiagHandler is not set"); + bool InlineAsm = false; + const SourceMgr *SMP = nullptr; + if (SrcMgr) { + SMP = SrcMgr; + } else if (InlineSrcMgr) { + // Fallback to use InlineSrcMgr when SrcMgr is not available. + SMP = InlineSrcMgr.get(); + InlineAsm = true; + } else + llvm_unreachable("Either SourceMgr should be available"); + DiagHandler(SMD, InlineAsm, *SMP, LocInfos); +} + +void MCContext::reportCommon(SMLoc Loc, SourceMgr::DiagKind Kind, + const Twine &Msg, bool InlineAsm) { + SourceMgr SM; + const SourceMgr *SMP = &SM; + InlineAsm = InlineAsm || AsmParseMode; + + // FIXME: Simplify these by combining InlineSrcMgr & SrcMgr. + // For MC-only execution, only SrcMgr is used; + // For non MC-only execution, only InlineSrcMgr is used. + if (InlineAsm) { + if (InlineSrcMgr) { + SMP = InlineSrcMgr.get(); + } else if (SrcMgr) { + SMP = SrcMgr; + InlineAsm = false; + } + } else { + if (SrcMgr) { + SMP = SrcMgr; + } else if (InlineSrcMgr) { + // Fallback to use InlineSrcMgr when SrcMgr is not available. + SMP = InlineSrcMgr.get(); + InlineAsm = true; + } + } - // If we have a source manager use it. Otherwise, try using the inline source - // manager. - // If that fails, construct a temporary SourceMgr. - if (SrcMgr) - SrcMgr->PrintMessage(Loc, SourceMgr::DK_Error, Msg); - else if (InlineSrcMgr) - InlineSrcMgr->PrintMessage(Loc, SourceMgr::DK_Error, Msg); - else - SourceMgr().PrintMessage(Loc, SourceMgr::DK_Error, Msg); + SMDiagnostic D = SMP->GetMessage(Loc, Kind, Msg); + DiagHandler(D, InlineAsm, *SMP, LocInfos); } -void MCContext::reportWarning(SMLoc Loc, const Twine &Msg) { +void MCContext::reportError(SMLoc Loc, const Twine &Msg, bool InlineAsm) { + HadError = true; + reportCommon(Loc, SourceMgr::DK_Error, Msg, InlineAsm); +} + +void MCContext::reportWarning(SMLoc Loc, const Twine &Msg, bool InlineAsm) { if (TargetOptions && TargetOptions->MCNoWarn) return; - if (TargetOptions && TargetOptions->MCFatalWarnings) - reportError(Loc, Msg); - else { - // If we have a source manager use it. Otherwise, try using the inline - // source manager. - if (SrcMgr) - SrcMgr->PrintMessage(Loc, SourceMgr::DK_Warning, Msg); - else if (InlineSrcMgr) - InlineSrcMgr->PrintMessage(Loc, SourceMgr::DK_Warning, Msg); + if (TargetOptions && TargetOptions->MCFatalWarnings) { + reportError(Loc, Msg, InlineAsm); + } else { + reportCommon(Loc, SourceMgr::DK_Warning, Msg, InlineAsm); } } -void MCContext::reportFatalError(SMLoc Loc, const Twine &Msg) { - reportError(Loc, Msg); +void MCContext::reportFatalError(SMLoc Loc, const Twine &Msg, bool InlineAsm) { + reportError(Loc, Msg, InlineAsm); // If we reached here, we are failing ungracefully. Run the interrupt handlers // to make sure any special cleanups get done, in particular that we remove diff --git a/llvm/lib/MC/MCParser/AsmParser.cpp b/llvm/lib/MC/MCParser/AsmParser.cpp --- a/llvm/lib/MC/MCParser/AsmParser.cpp +++ b/llvm/lib/MC/MCParser/AsmParser.cpp @@ -54,6 +54,7 @@ #include "llvm/Support/MathExtras.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/SMLoc.h" +#include "llvm/Support/SaveAndRestore.h" #include "llvm/Support/SourceMgr.h" #include "llvm/Support/raw_ostream.h" #include @@ -892,6 +893,8 @@ } bool AsmParser::Run(bool NoInitialTextSection, bool NoFinalize) { + SaveAndRestore TurnOnAsmParseDiag(Ctx.AsmParseMode, true); + // Create the initial section, if requested. if (!NoInitialTextSection) Out.InitSections(false); @@ -2348,7 +2351,7 @@ /// will use the last parsed cpp hash line filename comment /// for the Filename and LineNo if any in the diagnostic. void AsmParser::DiagHandler(const SMDiagnostic &Diag, void *Context) { - const AsmParser *Parser = static_cast(Context); + auto *Parser = static_cast(Context); raw_ostream &OS = errs(); const SourceMgr &DiagSrcMgr = *Diag.getSourceMgr(); @@ -2369,12 +2372,8 @@ // If we have not parsed a cpp hash line filename comment or the source // manager changed or buffer changed (like in a nested include) then just // print the normal diagnostic using its Filename and LineNo. - if (!Parser->CppHashInfo.LineNumber || &DiagSrcMgr != &Parser->SrcMgr || - DiagBuf != CppHashBuf) { - if (Parser->SavedDiagHandler) - Parser->SavedDiagHandler(Diag, Parser->SavedDiagContext); - else - Diag.print(nullptr, OS); + if (!Parser->CppHashInfo.LineNumber || DiagBuf != CppHashBuf) { + Parser->getContext().diagnose(Diag); return; } @@ -2393,10 +2392,7 @@ Diag.getColumnNo(), Diag.getKind(), Diag.getMessage(), Diag.getLineContents(), Diag.getRanges()); - if (Parser->SavedDiagHandler) - Parser->SavedDiagHandler(NewDiag, Parser->SavedDiagContext); - else - NewDiag.print(nullptr, OS); + Parser->getContext().diagnose(NewDiag); } // FIXME: This is mostly duplicated from the function in AsmLexer.cpp. The diff --git a/llvm/test/CodeGen/AMDGPU/lds-initializer.ll b/llvm/test/CodeGen/AMDGPU/lds-initializer.ll --- a/llvm/test/CodeGen/AMDGPU/lds-initializer.ll +++ b/llvm/test/CodeGen/AMDGPU/lds-initializer.ll @@ -1,5 +1,5 @@ -; RUN: llc -march=amdgcn -mcpu=tahiti < %s -o /dev/null 2>&1 | FileCheck %s -; RUN: llc -march=amdgcn -mcpu=tonga < %s -o /dev/null 2>&1 | FileCheck %s +; RUN: not llc -march=amdgcn -mcpu=tahiti < %s -o /dev/null 2>&1 | FileCheck %s +; RUN: not llc -march=amdgcn -mcpu=tonga < %s -o /dev/null 2>&1 | FileCheck %s ; CHECK: lds: unsupported initializer for address space diff --git a/llvm/test/CodeGen/AMDGPU/lds-zero-initializer.ll b/llvm/test/CodeGen/AMDGPU/lds-zero-initializer.ll --- a/llvm/test/CodeGen/AMDGPU/lds-zero-initializer.ll +++ b/llvm/test/CodeGen/AMDGPU/lds-zero-initializer.ll @@ -1,5 +1,5 @@ -; RUN: llc -march=amdgcn -mcpu=tahiti < %s -o /dev/null 2>&1 | FileCheck %s -; RUN: llc -march=amdgcn -mcpu=tonga < %s -o /dev/null 2>&1 | FileCheck %s +; RUN: not llc -march=amdgcn -mcpu=tahiti < %s -o /dev/null 2>&1 | FileCheck %s +; RUN: not llc -march=amdgcn -mcpu=tonga < %s -o /dev/null 2>&1 | FileCheck %s ; CHECK: lds: unsupported initializer for address space diff --git a/llvm/test/CodeGen/XCore/section-name.ll b/llvm/test/CodeGen/XCore/section-name.ll --- a/llvm/test/CodeGen/XCore/section-name.ll +++ b/llvm/test/CodeGen/XCore/section-name.ll @@ -1,4 +1,4 @@ -; RUN: llc < %s -march=xcore -o /dev/null 2>&1 | FileCheck %s +; RUN: not llc < %s -march=xcore -o /dev/null 2>&1 | FileCheck %s @bar = internal global i32 zeroinitializer diff --git a/llvm/tools/llc/llc.cpp b/llvm/tools/llc/llc.cpp --- a/llvm/tools/llc/llc.cpp +++ b/llvm/tools/llc/llc.cpp @@ -290,6 +290,22 @@ bool *HasError; LLCDiagnosticHandler(bool *HasErrorPtr) : HasError(HasErrorPtr) {} bool handleDiagnostics(const DiagnosticInfo &DI) override { + if (DI.getKind() == llvm::DK_SrcMgr) { + const auto &DISM = cast(DI); + const SMDiagnostic &SMD = DISM.getSMDiag(); + + if (SMD.getKind() == SourceMgr::DK_Error) + *HasError = true; + + SMD.print(nullptr, errs()); + + // For testing purposes, we print the LocCookie here. + if (DISM.isInlineAsmDiag() && DISM.getLocCookie()) + WithColor::note() << "!srcloc = " << DISM.getLocCookie() << "\n"; + + return true; + } + if (DI.getSeverity() == DS_Error) *HasError = true; @@ -305,19 +321,6 @@ } }; -static void InlineAsmDiagHandler(const SMDiagnostic &SMD, void *Context, - unsigned LocCookie) { - bool *HasError = static_cast(Context); - if (SMD.getKind() == SourceMgr::DK_Error) - *HasError = true; - - SMD.print(nullptr, errs()); - - // For testing purposes, we print the LocCookie here. - if (LocCookie) - WithColor::note() << "!srcloc = " << LocCookie << "\n"; -} - // main - Entry point for the llc compiler. // int main(int argc, char **argv) { @@ -367,7 +370,6 @@ bool HasError = false; Context.setDiagnosticHandler( std::make_unique(&HasError)); - Context.setInlineAsmDiagnosticHandler(InlineAsmDiagHandler, &HasError); Expected> RemarksFileOrErr = setupLLVMOptimizationRemarks(Context, RemarksFilename, RemarksPasses,