https://github.com/GkvJwa updated https://github.com/llvm/llvm-project/pull/193007
>From 7086f8496e2e0a3a1f42468c9eabfc88df0d0e03 Mon Sep 17 00:00:00 2001 From: GkvJwa <[email protected]> Date: Mon, 20 Apr 2026 23:55:36 +0800 Subject: [PATCH] [CodeView] Add line entries for instructions in MS inline asm Teach Clang to preserve per-line source locations for MS inline asm in srcloc metadata, and teach the CodeView path to emit those locations while the integrated assembler parses the inline asm body. This allows debuggers such as WinDbg to step through individual instructions inside __asm blocks instead of stepping over the whole block Fixes #91861 --- clang/lib/CodeGen/CGStmt.cpp | 91 ++++++++++++++++--- clang/test/CodeGen/ms-inline-asm-codeview.cpp | 15 +++ llvm/include/llvm/CodeGen/AsmPrinterHandler.h | 5 + llvm/include/llvm/CodeGen/MachineInstr.h | 5 + llvm/include/llvm/MC/MCStreamer.h | 11 +++ .../AsmPrinter/AsmPrinterInlineAsm.cpp | 44 +++++++++ llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp | 13 +++ llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h | 4 + llvm/lib/CodeGen/MachineInstr.cpp | 32 +++++++ llvm/lib/CodeGen/MachineModuleInfo.cpp | 21 ++++- llvm/lib/MC/MCAsmStreamer.cpp | 2 + llvm/lib/MC/MCStreamer.cpp | 7 ++ .../DebugInfo/COFF/inline-asm-source-loc.ll | 34 +++++++ 13 files changed, 268 insertions(+), 16 deletions(-) create mode 100644 clang/test/CodeGen/ms-inline-asm-codeview.cpp create mode 100644 llvm/test/DebugInfo/COFF/inline-asm-source-loc.ll diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp index b70667d04d1f6..9f259881aa3ff 100644 --- a/clang/lib/CodeGen/CGStmt.cpp +++ b/clang/lib/CodeGen/CGStmt.cpp @@ -26,6 +26,7 @@ #include "clang/Basic/PrettyStackTrace.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/TargetInfo.h" +#include "clang/Lex/Token.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallSet.h" @@ -2574,16 +2575,43 @@ CodeGenFunction::EmitAsmInput(const TargetInfo::ConstraintInfo &Info, InputExpr->getExprLoc()); } +static llvm::MDNode *getAsmSrcLocInfo(ArrayRef<SourceLocation> SourceLocs, + CodeGenFunction &CGF) { + SmallVector<llvm::Metadata *, 8> Locs; + llvm::LLVMContext &Ctx = CGF.getLLVMContext(); + + for (SourceLocation Loc : SourceLocs) { + llvm::Constant *RawLoc = + llvm::ConstantInt::get(CGF.Int64Ty, Loc.getRawEncoding()); + Locs.push_back(llvm::ConstantAsMetadata::get(RawLoc)); + } + + if (CGF.getDebugInfo() && CGF.CGM.getCodeGenOpts().EmitCodeView) { + SmallVector<llvm::Metadata *, 16> DebugLocs; + DebugLocs.push_back(llvm::MDString::get(Ctx, "inlineasm.dbg.line")); + llvm::Type *Int32Ty = llvm::Type::getInt32Ty(Ctx); + for (SourceLocation Loc : SourceLocs) { + llvm::DebugLoc DL = CGF.SourceLocToDebugLoc(Loc); + DebugLocs.push_back(llvm::ConstantAsMetadata::get( + llvm::ConstantInt::get(Int32Ty, DL ? DL.getLine() : 0))); + DebugLocs.push_back(llvm::ConstantAsMetadata::get( + llvm::ConstantInt::get(Int32Ty, DL ? DL.getCol() : 0))); + } + Locs.push_back(llvm::MDNode::get(Ctx, DebugLocs)); + } + + return llvm::MDNode::get(Ctx, Locs); +} + /// getAsmSrcLocInfo - Return the !srcloc metadata node to attach to an inline /// asm call instruction. The !srcloc MDNode contains a list of constant /// integers which are the source locations of the start of each line in the /// asm. -static llvm::MDNode *getAsmSrcLocInfo(const StringLiteral *Str, - CodeGenFunction &CGF) { - SmallVector<llvm::Metadata *, 8> Locs; +static llvm::MDNode *getGCCAsmSrcLocInfo(const StringLiteral *Str, + CodeGenFunction &CGF) { + SmallVector<SourceLocation, 8> Locs; // Add the location of the first line to the MDNode. - Locs.push_back(llvm::ConstantAsMetadata::get(llvm::ConstantInt::get( - CGF.Int64Ty, Str->getBeginLoc().getRawEncoding()))); + Locs.push_back(Str->getBeginLoc()); StringRef StrVal = Str->getString(); if (!StrVal.empty()) { const SourceManager &SM = CGF.CGM.getContext().getSourceManager(); @@ -2597,12 +2625,47 @@ static llvm::MDNode *getAsmSrcLocInfo(const StringLiteral *Str, if (StrVal[i] != '\n') continue; SourceLocation LineLoc = Str->getLocationOfByte( i + 1, SM, LangOpts, CGF.getTarget(), &StartToken, &ByteOffset); - Locs.push_back(llvm::ConstantAsMetadata::get( - llvm::ConstantInt::get(CGF.Int64Ty, LineLoc.getRawEncoding()))); + Locs.push_back(LineLoc); + } + } + + return getAsmSrcLocInfo(Locs, CGF); +} + +static llvm::MDNode *getMSAsmSrcLocInfo(const MSAsmStmt &S, StringRef AsmString, + CodeGenFunction &CGF) { + SmallVector<SourceLocation, 8> Locs; + + MSAsmStmt &NonConstS = const_cast<MSAsmStmt &>(S); + ArrayRef<Token> AsmToks(NonConstS.getAsmToks(), NonConstS.getNumAsmToks()); + bool IsNewStatement = true; + for (const Token &Tok : AsmToks) { + if (!IsNewStatement && (Tok.is(tok::kw_asm) || Tok.isAtStartOfLine())) + IsNewStatement = true; + + if (IsNewStatement) { + if (Tok.is(tok::kw_asm)) + continue; + + Locs.push_back(Tok.getLocation()); + IsNewStatement = false; + continue; } + + if (!Tok.is(tok::kw_asm)) + IsNewStatement = false; } - return llvm::MDNode::get(CGF.getLLVMContext(), Locs); + if (Locs.empty()) + Locs.push_back(S.getAsmLoc()); + + size_t ExpectedLocs = AsmString.empty() ? 1 : AsmString.count('\n') + 1; + if (Locs.size() > ExpectedLocs) + Locs.truncate(ExpectedLocs); + while (Locs.size() < ExpectedLocs) + Locs.push_back(Locs.back()); + + return getAsmSrcLocInfo(Locs, CGF); } void CodeGenFunction::UpdateAsmCallInst( @@ -2638,15 +2701,15 @@ void CodeGenFunction::UpdateAsmCallInst( if (const auto *gccAsmStmt = dyn_cast<GCCAsmStmt>(&S); gccAsmStmt && (SL = dyn_cast<StringLiteral>(gccAsmStmt->getAsmStringExpr()))) { - Result.setMetadata("srcloc", getAsmSrcLocInfo(SL, *this)); + Result.setMetadata("srcloc", getGCCAsmSrcLocInfo(SL, *this)); + } else if (const auto *msAsmStmt = dyn_cast<MSAsmStmt>(&S)) { + Result.setMetadata( + "srcloc", + getMSAsmSrcLocInfo(*msAsmStmt, msAsmStmt->getAsmString(), *this)); } else { // At least put the line number on MS inline asm blobs and GCC asm constexpr // strings. - llvm::Constant *Loc = - llvm::ConstantInt::get(Int64Ty, S.getAsmLoc().getRawEncoding()); - Result.setMetadata("srcloc", - llvm::MDNode::get(getLLVMContext(), - llvm::ConstantAsMetadata::get(Loc))); + Result.setMetadata("srcloc", getAsmSrcLocInfo({S.getAsmLoc()}, *this)); } // Make inline-asm calls Key for the debug info feature Key Instructions. diff --git a/clang/test/CodeGen/ms-inline-asm-codeview.cpp b/clang/test/CodeGen/ms-inline-asm-codeview.cpp new file mode 100644 index 0000000000000..04c6f15b566ad --- /dev/null +++ b/clang/test/CodeGen/ms-inline-asm-codeview.cpp @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -triple i386-pc-windows-msvc -fasm-blocks -gcodeview \ +// RUN: -debug-info-kind=limited -emit-llvm -o - %s | FileCheck %s + +#line 100 "t.cpp" +void f() { + __asm { + nop + nop + } +} + +// CHECK: call void asm sideeffect inteldialect +// CHECK-SAME: !srcloc ![[SRCLOC:[0-9]+]] +// CHECK: ![[SRCLOC]] = !{i64 {{[0-9]+}}, i64 {{[0-9]+}}, ![[DBGLOCS:[0-9]+]]} +// CHECK: ![[DBGLOCS]] = !{!"inlineasm.dbg.line", i32 102, i32 5, i32 103, i32 5} diff --git a/llvm/include/llvm/CodeGen/AsmPrinterHandler.h b/llvm/include/llvm/CodeGen/AsmPrinterHandler.h index ab737fa00ce14..ed15f6c23fe6d 100644 --- a/llvm/include/llvm/CodeGen/AsmPrinterHandler.h +++ b/llvm/include/llvm/CodeGen/AsmPrinterHandler.h @@ -20,6 +20,7 @@ namespace llvm { class AsmPrinter; +class DILocation; class MachineBasicBlock; class MachineFunction; class MachineInstr; @@ -72,6 +73,10 @@ class LLVM_ABI AsmPrinterHandler { /// Process beginning of an instruction. virtual void beginInstruction(const MachineInstr *MI) {} + /// Process beginning of an instruction parsed from an inline asm blob. + virtual void beginInlineAsmInstruction(const MachineInstr *MI, + const DILocation *Loc) {} + /// Process end of an instruction. virtual void endInstruction() {} diff --git a/llvm/include/llvm/CodeGen/MachineInstr.h b/llvm/include/llvm/CodeGen/MachineInstr.h index 0a7dd3f4eef65..d687a0ab29236 100644 --- a/llvm/include/llvm/CodeGen/MachineInstr.h +++ b/llvm/include/llvm/CodeGen/MachineInstr.h @@ -585,6 +585,11 @@ class MachineInstr /// the loc cookie from it. LLVM_ABI const MDNode *getLocCookieMD() const; + /// For inline asm, get the nested source line metadata in !srcloc, if + /// present. Operand 0 is a tag, and subsequent operands are line/column pairs + /// for inline asm source lines. + LLVM_ABI const MDNode *getInlineAsmSourceLocMD() const; + /// Emit an error referring to the source location of this instruction. This /// should only be used for inline assembly that is somehow impossible to /// compile. Other errors should have been handled much earlier. diff --git a/llvm/include/llvm/MC/MCStreamer.h b/llvm/include/llvm/MC/MCStreamer.h index 3d249408d07a8..c6f8758840d35 100644 --- a/llvm/include/llvm/MC/MCStreamer.h +++ b/llvm/include/llvm/MC/MCStreamer.h @@ -31,6 +31,7 @@ #include "llvm/TargetParser/ARMTargetParser.h" #include <cassert> #include <cstdint> +#include <functional> #include <memory> #include <optional> #include <string> @@ -244,6 +245,10 @@ class LLVM_ABI MCStreamer { /// locations for diagnostics. const SMLoc *StartTokLocPtr = nullptr; + /// Callback used by inline asm parsing to give AsmPrinter a chance to emit + /// source location directives immediately before each parsed instruction. + std::function<void(SMLoc)> InlineAsmSourceLocCallback; + /// The next unique ID to use when creating a WinCFI-related section (.pdata /// or .xdata). This ID ensures that we have a one-to-one mapping from /// code section to unwind info section, which MSVC's incremental linker @@ -290,6 +295,8 @@ class LLVM_ABI MCStreamer { virtual void emitRawTextImpl(StringRef String); + void emitInlineAsmSourceLoc(SMLoc Loc); + /// Returns true if the .cv_loc directive is in the right section. bool checkCVLocSection(unsigned FuncId, unsigned FileNo, SMLoc Loc); @@ -312,6 +319,10 @@ class LLVM_ABI MCStreamer { return StartTokLocPtr ? *StartTokLocPtr : SMLoc(); } + void setInlineAsmSourceLocCallback(std::function<void(SMLoc)> Callback) { + InlineAsmSourceLocCallback = std::move(Callback); + } + void setLFIRewriter(std::unique_ptr<MCLFIRewriter> Rewriter); MCLFIRewriter *getLFIRewriter() { return LFIRewriter.get(); } diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp index b3bcfc08643f1..9109f7d362c21 100644 --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp @@ -15,6 +15,7 @@ #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/Twine.h" #include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/CodeGen/AsmPrinterHandler.h" #include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineModuleInfo.h" @@ -22,6 +23,7 @@ #include "llvm/CodeGen/TargetSubtargetInfo.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DataLayout.h" +#include "llvm/IR/DebugInfoMetadata.h" #include "llvm/IR/DiagnosticInfo.h" #include "llvm/IR/InlineAsm.h" #include "llvm/IR/LLVMContext.h" @@ -131,9 +133,51 @@ void AsmPrinter::emitInlineAsm(StringRef Str, const MCSubtargetInfo &STI, Parser->setTargetParser(*TAP); emitInlineAsmStart(); + const MDNode *InlineAsmSourceLocs = + MI ? MI->getInlineAsmSourceLocMD() : nullptr; + if (InlineAsmSourceLocs) { + unsigned SyntheticLineOffset = + TM.getTargetTriple().isX86() && Dialect == InlineAsm::AD_Intel ? 1 : 0; + OutStreamer->setInlineAsmSourceLocCallback( + [this, &SrcMgr, BufNum, SyntheticLineOffset, InlineAsmSourceLocs, + MI](SMLoc Loc) { + if (!Loc.isValid() || SrcMgr.FindBufferContainingLoc(Loc) != BufNum) + return; + + unsigned ParserLine = SrcMgr.FindLineNumber(Loc, BufNum); + if (ParserLine <= SyntheticLineOffset) + return; + + unsigned SourceLine = ParserLine - SyntheticLineOffset; + unsigned LocIdx = (SourceLine - 1) * 2 + 1; + if (LocIdx + 1 >= InlineAsmSourceLocs->getNumOperands()) + return; + + const auto *Line = mdconst::dyn_extract<ConstantInt>( + InlineAsmSourceLocs->getOperand(LocIdx)); + const auto *Column = mdconst::dyn_extract<ConstantInt>( + InlineAsmSourceLocs->getOperand(LocIdx + 1)); + if (!Line || !Column || Line->isZero()) + return; + + DebugLoc BaseDL = MI->getDebugLoc(); + if (!BaseDL) + return; + + auto *DIL = DILocation::get( + MI->getMF()->getFunction().getContext(), Line->getZExtValue(), + Column->getZExtValue(), BaseDL->getScope(), + BaseDL->getInlinedAt(), BaseDL->isImplicitCode(), + BaseDL->getAtomGroup(), BaseDL->getAtomRank()); + for (auto &Handler : Handlers) + Handler->beginInlineAsmInstruction(MI, DIL); + }); + } // Don't implicitly switch to the text section before the asm. (void)Parser->Run(/*NoInitialTextSection*/ true, /*NoFinalize*/ true); + if (InlineAsmSourceLocs) + OutStreamer->setInlineAsmSourceLocCallback(nullptr); emitInlineAsmEnd(STI, &TAP->getSTI(), MI); } diff --git a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp index ccec0b5910658..8b425ee9ceeae 100644 --- a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp @@ -3145,6 +3145,11 @@ static bool isUsableDebugLoc(DebugLoc DL) { void CodeViewDebug::beginInstruction(const MachineInstr *MI) { DebugHandlerBase::beginInstruction(MI); + if (MI->isInlineAsm() && MI->getInlineAsmSourceLocMD()) { + PrevInstBB = MI->getParent(); + return; + } + // Ignore DBG_VALUE and DBG_LABEL locations and function prologue. if (!Asm || !CurFn || MI->isDebugInstr() || MI->getFlag(MachineInstr::FrameSetup)) @@ -3173,6 +3178,14 @@ void CodeViewDebug::beginInstruction(const MachineInstr *MI) { maybeRecordLocation(DL, Asm->MF); } +void CodeViewDebug::beginInlineAsmInstruction(const MachineInstr *MI, + const DILocation *Loc) { + if (!Asm || !CurFn || !MI || !Loc) + return; + + maybeRecordLocation(DebugLoc(Loc), Asm->MF); +} + MCSymbol *CodeViewDebug::beginCVSubsection(DebugSubsectionKind Kind) { MCSymbol *BeginLabel = MMI->getContext().createTempSymbol(), *EndLabel = MMI->getContext().createTempSymbol(); diff --git a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h index b4dcadde18e8f..162cf4afd66de 100644 --- a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h +++ b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h @@ -551,6 +551,10 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public DebugHandlerBase { /// Process beginning of an instruction. void beginInstruction(const MachineInstr *MI) override; + + /// Process beginning of an instruction parsed from an inline asm blob. + void beginInlineAsmInstruction(const MachineInstr *MI, + const DILocation *Loc) override; }; template <> struct DenseMapInfo<CodeViewDebug::LocalVarDef> { diff --git a/llvm/lib/CodeGen/MachineInstr.cpp b/llvm/lib/CodeGen/MachineInstr.cpp index cc3dae91c16d2..ea69636d730e0 100644 --- a/llvm/lib/CodeGen/MachineInstr.cpp +++ b/llvm/lib/CodeGen/MachineInstr.cpp @@ -2359,6 +2359,38 @@ const MDNode *MachineInstr::getLocCookieMD() const { return nullptr; } +static bool isInlineAsmSourceLocMD(const MDNode *Locs) { + if (!Locs || Locs->getNumOperands() < 3 || Locs->getNumOperands() % 2 == 0) + return false; + + const auto *Tag = dyn_cast_or_null<MDString>(Locs->getOperand(0)); + if (!Tag || Tag->getString() != "inlineasm.dbg.line") + return false; + + return true; +} + +const MDNode *MachineInstr::getInlineAsmSourceLocMD() const { + for (unsigned I = getNumOperands(); I != 0; --I) { + if (!getOperand(I - 1).isMetadata()) + continue; + + const MDNode *LocMD = getOperand(I - 1).getMetadata(); + if (isInlineAsmSourceLocMD(LocMD)) + return LocMD; + + if (!LocMD) + continue; + for (const MDOperand &Op : LocMD->operands()) { + const auto *Locs = dyn_cast_or_null<MDNode>(Op); + if (isInlineAsmSourceLocMD(Locs)) + return Locs; + } + } + + return nullptr; +} + void MachineInstr::emitInlineAsmError(const Twine &Msg) const { assert(isInlineAsm()); const MDNode *LocMD = getLocCookieMD(); diff --git a/llvm/lib/CodeGen/MachineModuleInfo.cpp b/llvm/lib/CodeGen/MachineModuleInfo.cpp index 6b7a8cdfd2951..88aeff59acde2 100644 --- a/llvm/lib/CodeGen/MachineModuleInfo.cpp +++ b/llvm/lib/CodeGen/MachineModuleInfo.cpp @@ -12,6 +12,7 @@ #include "llvm/IR/Constants.h" #include "llvm/IR/DiagnosticInfo.h" #include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Metadata.h" #include "llvm/IR/Module.h" #include "llvm/InitializePasses.h" #include "llvm/Target/TargetLoweringObjectFile.h" @@ -21,6 +22,19 @@ using namespace llvm; using namespace llvm::dwarf; +static bool isInlineAsmSourceLocMD(const MDNode *LocInfo) { + if (!LocInfo || LocInfo->getNumOperands() == 0) + return false; + + const auto *Locs = dyn_cast_or_null<MDNode>( + LocInfo->getOperand(LocInfo->getNumOperands() - 1)); + if (!Locs || Locs->getNumOperands() < 3 || Locs->getNumOperands() % 2 == 0) + return false; + + const auto *Tag = dyn_cast_or_null<MDString>(Locs->getOperand(0)); + return Tag && Tag->getString() == "inlineasm.dbg.line"; +} + // Out of line virtual method. MachineModuleInfoImpl::~MachineModuleInfoImpl() = default; @@ -176,10 +190,13 @@ static uint64_t getLocCookie(const SMDiagnostic &SMD, const SourceMgr &SrcMgr, uint64_t LocCookie = 0; if (LocInfo) { unsigned ErrorLine = SMD.getLineNo() - 1; - if (ErrorLine >= LocInfo->getNumOperands()) + unsigned NumRawLocs = LocInfo->getNumOperands(); + if (isInlineAsmSourceLocMD(LocInfo)) + --NumRawLocs; + if (ErrorLine >= NumRawLocs) ErrorLine = 0; - if (LocInfo->getNumOperands() != 0) + if (NumRawLocs != 0) if (const ConstantInt *CI = mdconst::dyn_extract<ConstantInt>(LocInfo->getOperand(ErrorLine))) LocCookie = CI->getZExtValue(); diff --git a/llvm/lib/MC/MCAsmStreamer.cpp b/llvm/lib/MC/MCAsmStreamer.cpp index 05e3dc28a502b..6a1bf0c9be910 100644 --- a/llvm/lib/MC/MCAsmStreamer.cpp +++ b/llvm/lib/MC/MCAsmStreamer.cpp @@ -2595,6 +2595,8 @@ void MCAsmStreamer::emitInstruction(const MCInst &Inst, if (LFIRewriter && LFIRewriter->rewriteInst(Inst, *this, STI)) return; + emitInlineAsmSourceLoc(getStartTokLoc()); + if (CurFrag) { MCSection *Sec = getCurrentSectionOnly(); Sec->setHasInstructions(true); diff --git a/llvm/lib/MC/MCStreamer.cpp b/llvm/lib/MC/MCStreamer.cpp index 29e2b73a217bf..32278c087837a 100644 --- a/llvm/lib/MC/MCStreamer.cpp +++ b/llvm/lib/MC/MCStreamer.cpp @@ -1268,7 +1268,14 @@ void MCStreamer::visitUsedExpr(const MCExpr &Expr) { } } +void MCStreamer::emitInlineAsmSourceLoc(SMLoc Loc) { + if (InlineAsmSourceLocCallback) + InlineAsmSourceLocCallback(Loc); +} + void MCStreamer::emitInstruction(const MCInst &Inst, const MCSubtargetInfo &) { + emitInlineAsmSourceLoc(getStartTokLoc()); + // Scan for values. for (unsigned i = Inst.getNumOperands(); i--;) if (Inst.getOperand(i).isExpr()) diff --git a/llvm/test/DebugInfo/COFF/inline-asm-source-loc.ll b/llvm/test/DebugInfo/COFF/inline-asm-source-loc.ll new file mode 100644 index 0000000000000..dda873b91d35e --- /dev/null +++ b/llvm/test/DebugInfo/COFF/inline-asm-source-loc.ll @@ -0,0 +1,34 @@ +; RUN: llc -mtriple=i386-windows-msvc -filetype=asm < %s | FileCheck %s + +; CHECK: #APP +; CHECK: {{[ \t]*}}.cv_loc{{[ \t]+}}0 1 6 9 +; CHECK-NEXT: {{[ \t]*}}nop +; CHECK-NEXT: {{[ \t]*}}.cv_loc{{[ \t]+}}0 1 7 9 +; CHECK-NEXT: {{[ \t]*}}nop +; CHECK: #NO_APP + +target triple = "i386-pc-windows-msvc" + +define dso_local i32 @main() !dbg !8 { +entry: + ; The inline asm string is two source instructions: "nop\n\tnop". + call void asm sideeffect inteldialect "nop\0A\09nop", "~{dirflag},~{fpsr},~{flags}"(), !srcloc !12, !dbg !13 + ret i32 0, !dbg !15 +} + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!3, !4} + +!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug) +!1 = !DIFile(filename: "t.cpp", directory: "/") +!2 = !{} +!3 = !{i32 2, !"CodeView", i32 1} +!4 = !{i32 2, !"Debug Info Version", i32 3} +!5 = !DISubroutineType(types: !6) +!6 = !{!7} +!7 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!8 = distinct !DISubprogram(name: "main", scope: !1, file: !1, line: 3, type: !5, scopeLine: 3, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2) +!12 = !{i64 0, i64 0, !14} +!13 = !DILocation(line: 4, column: 5, scope: !8) +!14 = !{!"inlineasm.dbg.line", i32 6, i32 9, i32 7, i32 9} +!15 = !DILocation(line: 8, column: 3, scope: !8) _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
