Index: include/llvm/CodeGen/AsmPrinter.h =================================================================== --- include/llvm/CodeGen/AsmPrinter.h +++ include/llvm/CodeGen/AsmPrinter.h @@ -23,6 +23,7 @@ #include "llvm/IR/InlineAsm.h" #include "llvm/Support/DataTypes.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/SourceMgr.h" namespace llvm { class AsmPrinterHandler; @@ -109,6 +110,9 @@ MCSymbol *CurrentFnEnd; MCSymbol *CurExceptionSym; + /// A SourceMgr for inline assembly. + mutable std::unique_ptr InlineSrcMgr; + // The garbage collection metadata printer table. void *GCMetadataPrinters; // Really a DenseMap. @@ -137,6 +141,27 @@ /// maintains ownership of the emitters. SmallVector Handlers; +public: + struct SrcMgrDiagInfo { + const MDNode *LocInfo; + LLVMContext::InlineAsmDiagHandlerTy DiagHandler; + void *DiagContext; + }; + +private: + mutable std::vector> DiagInfos; + + SourceMgr *getInlineSourceManager() const { + if (!InlineSrcMgr) + InlineSrcMgr = make_unique(); + + return InlineSrcMgr.get(); + } + + SrcMgrDiagInfo &getNewDiagInfo() const { + DiagInfos.push_back(make_unique()); + return *DiagInfos.back(); + } /// If the target supports dwarf debug info, this pointer is non-null. DwarfDebug *DD; Index: include/llvm/MC/MCContext.h =================================================================== --- include/llvm/MC/MCContext.h +++ include/llvm/MC/MCContext.h @@ -59,6 +59,9 @@ /// The SourceMgr for this object, if any. const SourceMgr *SrcMgr; + /// The SourceMgr for inline assembly, if any. + SourceMgr *InlineSrcMgr; + /// The MCAsmInfo for this target. const MCAsmInfo *MAI; @@ -240,6 +243,8 @@ const SourceMgr *getSourceManager() const { return SrcMgr; } + void setInlineSourceManager(SourceMgr *SM) { InlineSrcMgr = SM; } + const MCAsmInfo *getAsmInfo() const { return MAI; } const MCRegisterInfo *getRegisterInfo() const { return MRI; } Index: include/llvm/MC/MCParser/MCAsmParser.h =================================================================== --- include/llvm/MC/MCParser/MCAsmParser.h +++ include/llvm/MC/MCParser/MCAsmParser.h @@ -258,7 +258,7 @@ /// \brief Create an MCAsmParser instance. MCAsmParser *createMCAsmParser(SourceMgr &, MCContext &, MCStreamer &, - const MCAsmInfo &); + const MCAsmInfo &, unsigned CB = 0); } // End llvm namespace Index: lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp =================================================================== --- lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp +++ lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp @@ -40,19 +40,12 @@ #define DEBUG_TYPE "asm-printer" -namespace { - struct SrcMgrDiagInfo { - const MDNode *LocInfo; - LLVMContext::InlineAsmDiagHandlerTy DiagHandler; - void *DiagContext; - }; -} - /// 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) { - SrcMgrDiagInfo *DiagInfo = static_cast(diagInfo); + AsmPrinter::SrcMgrDiagInfo *DiagInfo = + static_cast(diagInfo); assert(DiagInfo && "Diagnostic context not passed down?"); // If the inline asm had metadata associated with it, pull out a location @@ -99,15 +92,17 @@ return; } - SourceMgr SrcMgr; + SourceMgr &SrcMgr = *getInlineSourceManager(); SrcMgr.setIncludeDirs(MCOptions.IASSearchPaths); - SrcMgrDiagInfo DiagInfo; + MCContext &Context = MMI->getContext(); + Context.setInlineSourceManager(&SrcMgr); // If the current LLVMContext has an inline asm handler, set it in SourceMgr. LLVMContext &LLVMCtx = MMI->getModule()->getContext(); bool HasDiagHandler = false; if (LLVMCtx.getInlineAsmDiagnosticHandler() != nullptr) { + SrcMgrDiagInfo &DiagInfo = getNewDiagInfo(); // If the source manager has an issue, we arrange for srcMgrDiagHandler // to be invoked, getting DiagInfo passed into it. DiagInfo.LocInfo = LocMDNode; @@ -118,16 +113,15 @@ } std::unique_ptr Buffer; - if (isNullTerminated) - Buffer = MemoryBuffer::getMemBuffer(Str, ""); - else - Buffer = MemoryBuffer::getMemBufferCopy(Str, ""); + // Always copy the inline assembly string into the memory buffer to preserve + // it until after finalization. + Buffer = MemoryBuffer::getMemBufferCopy(Str, ""); // Tell SrcMgr about this buffer, it takes ownership of the buffer. - SrcMgr.AddNewSourceBuffer(std::move(Buffer), SMLoc()); + unsigned BufNum = SrcMgr.AddNewSourceBuffer(std::move(Buffer), SMLoc()); std::unique_ptr Parser( - createMCAsmParser(SrcMgr, OutContext, *OutStreamer, *MAI)); + createMCAsmParser(SrcMgr, OutContext, *OutStreamer, *MAI, BufNum)); // We create a new MCInstrInfo here since we might be at the module level // and not have a MachineFunction to initialize the TargetInstrInfo from and Index: lib/MC/MCContext.cpp =================================================================== --- lib/MC/MCContext.cpp +++ lib/MC/MCContext.cpp @@ -510,13 +510,15 @@ void MCContext::reportError(SMLoc Loc, const Twine &Msg) { HadError = true; - // If we have a source manager use it. Otherwise just use the generic - // report_fatal_error(). - if (!SrcMgr) + // If we have a source manager use it. Otherwise, try using the inline source + // manager. + // If that fails, use the generic report_fatal_error(). + if (SrcMgr) + SrcMgr->PrintMessage(Loc, SourceMgr::DK_Error, Msg); + else if (InlineSrcMgr) + InlineSrcMgr->PrintMessage(Loc, SourceMgr::DK_Error, Msg); + else report_fatal_error(Msg, false); - - // Use the source manager to print the message. - SrcMgr->PrintMessage(Loc, SourceMgr::DK_Error, Msg); } void MCContext::reportFatalError(SMLoc Loc, const Twine &Msg) { Index: lib/MC/MCParser/AsmParser.cpp =================================================================== --- lib/MC/MCParser/AsmParser.cpp +++ lib/MC/MCParser/AsmParser.cpp @@ -209,7 +209,7 @@ public: AsmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out, - const MCAsmInfo &MAI); + const MCAsmInfo &MAI, unsigned CB); ~AsmParser() override; bool Run(bool NoInitialTextSection, bool NoFinalize = false) override; @@ -572,9 +572,9 @@ enum { DEFAULT_ADDRSPACE = 0 }; AsmParser::AsmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out, - const MCAsmInfo &MAI) + const MCAsmInfo &MAI, unsigned CB = 0) : Lexer(MAI), Ctx(Ctx), Out(Out), MAI(MAI), SrcMgr(SM), - PlatformParser(nullptr), CurBuffer(SM.getMainFileID()), + PlatformParser(nullptr), CurBuffer(CB ? CB : SM.getMainFileID()), MacrosEnabledFlag(true), CppHashInfo(), AssemblerDialect(~0U), IsDarwin(false), ParsingInlineAsm(false) { HadError = false; @@ -608,6 +608,10 @@ AsmParser::~AsmParser() { assert((HadError || ActiveMacros.empty()) && "Unexpected active macro instantiation!"); + + // Restore the saved diagnostics handler and context for use during + // finalization. + SrcMgr.setDiagHandler(SavedDiagHandler, SavedDiagContext); } void AsmParser::printMacroInstantiations() { @@ -5519,6 +5523,7 @@ /// \brief Create an MCAsmParser instance. MCAsmParser *llvm::createMCAsmParser(SourceMgr &SM, MCContext &C, - MCStreamer &Out, const MCAsmInfo &MAI) { - return new AsmParser(SM, C, Out, MAI); + MCStreamer &Out, const MCAsmInfo &MAI, + unsigned CB) { + return new AsmParser(SM, C, Out, MAI, CB); } Index: test/Assembler/inline-asm-diags.ll =================================================================== --- /dev/null +++ test/Assembler/inline-asm-diags.ll @@ -0,0 +1,9 @@ +; RUN: not llc -filetype=obj < %s 2>&1 -o /dev/null | FileCheck %s + +module asm ".word 0x10" +module asm ".word -bar" + +; CHECK: :2:7: error: expected relocatable expression + +module asm ".word -foo" +; CHECK: :3:7: error: expected relocatable expression