https://github.com/vogelsgesang updated https://github.com/llvm/llvm-project/pull/141937
>From 8fe2bd74609cf0c14466ff82a9c966c07eecd6c8 Mon Sep 17 00:00:00 2001 From: Adrian Vogelsgesang <avogelsges...@salesforce.com> Date: Tue, 27 May 2025 19:36:42 +0000 Subject: [PATCH 1/5] [debuginfo][coro] Emit debug info labels for coroutine resume points With this commit, we add `DILabel` debug infos (lowering to DW_TAG_label in DWARF) to the various resume points of a coroutine. Those labels use the naming convention `__coro_resume_<N>` where `<N>` is the suspension point id. That way, debugging scripts can figure out the exact line / column at which a coroutine was suspended by looking up current `__coro_index` value inside the coroutines frame, and then searching for the corresponding `__coro_resume_<N>` inside the coroutine's resume function. While this is an artificial compiler-generated label, I did not apply the DW_AT_artificial tag to it. The DWARFv5 standard only allows that tag on type and variable definitions, but not on labels. In gdb, those line numebers can then be looked up using the command `info line -function my_coroutine -label __coro_resume_1`. LLDB unfortunately does not parse DW_TAG_label debug information, yet. As such, this debug information is currently not useful in LLDB. --- clang/docs/DebuggingCoroutines.rst | 24 ++++++++++------ llvm/lib/Transforms/Coroutines/CoroFrame.cpp | 6 ++-- llvm/lib/Transforms/Coroutines/CoroSplit.cpp | 29 +++++++++++++++++++- 3 files changed, 47 insertions(+), 12 deletions(-) diff --git a/clang/docs/DebuggingCoroutines.rst b/clang/docs/DebuggingCoroutines.rst index 80df321340724..9fc3785a0622b 100644 --- a/clang/docs/DebuggingCoroutines.rst +++ b/clang/docs/DebuggingCoroutines.rst @@ -311,17 +311,25 @@ variables in the C++ source. Get the suspended points ======================== -An important requirement for debugging coroutines is to understand suspended -points, which are where the coroutine is currently suspended and awaiting. +An important requirement for debugging coroutines is to understand at which +point a coroutine is currently suspended and awaiting. -For simple cases like the above, inspecting the value of the `__coro_index` -variable in the coroutine frame works well. +The value of the `__coro_index` inside a couroutine frame indicates the current +suspension point. To map this id back to a source code location, you can lookup +the source location of a special, compiler-generated label `__coro_suspend_<N>`. -However, it is not quite so simple in really complex situations. In these -cases, it is necessary to use the coroutine libraries to insert the -line-number. +:: -For example: + (gdb) info line -function coro_task -label __coro_resume_2 + Line 45 of "llvm-example.cpp" starts at address 0x1b1b <_ZL9coro_taski.resume+555> and ends at 0x1b46 <_ZL9coro_taski.resume+598>. + Line 45 of "llvm-example.cpp" starts at address 0x201b <_ZL9coro_taski.destroy+555> and ends at 0x2046 <_ZL9coro_taski.destroy+598>. + Line 45 of "llvm-example.cpp" starts at address 0x253b <_ZL9coro_taski.cleanup+555> and ends at 0x2566 <_ZL9coro_taski.cleanup+598>. + +Older versions of LLVM/clang might not yet emit those labels, though. For +simple cases, you might still be able to guess the suspension point correctly. + +Alternatively, you might also want to modify your coroutine library to store +the line number of the current suspension point in the promise: .. code-block:: c++ diff --git a/llvm/lib/Transforms/Coroutines/CoroFrame.cpp b/llvm/lib/Transforms/Coroutines/CoroFrame.cpp index 1acd9139fe26e..42f8bf91118ae 100644 --- a/llvm/lib/Transforms/Coroutines/CoroFrame.cpp +++ b/llvm/lib/Transforms/Coroutines/CoroFrame.cpp @@ -688,9 +688,9 @@ static DIType *solveDIType(DIBuilder &Builder, Type *Ty, static void buildFrameDebugInfo(Function &F, coro::Shape &Shape, FrameDataInfo &FrameData) { DISubprogram *DIS = F.getSubprogram(); - // If there is no DISubprogram for F, it implies the Function are not compiled - // with debug info. So we also don't need to generate debug info for the frame - // neither. + // If there is no DISubprogram for F, it implies the function is compiled + // without debug info. So we also don't generate debug info for the frame, + // either. if (!DIS || !DIS->getUnit() || !dwarf::isCPlusPlus( (dwarf::SourceLanguage)DIS->getUnit()->getSourceLanguage()) || diff --git a/llvm/lib/Transforms/Coroutines/CoroSplit.cpp b/llvm/lib/Transforms/Coroutines/CoroSplit.cpp index 8813f91e9060c..1348d785f4f85 100644 --- a/llvm/lib/Transforms/Coroutines/CoroSplit.cpp +++ b/llvm/lib/Transforms/Coroutines/CoroSplit.cpp @@ -42,6 +42,7 @@ #include "llvm/IR/CFG.h" #include "llvm/IR/CallingConv.h" #include "llvm/IR/Constants.h" +#include "llvm/IR/DIBuilder.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/DebugInfo.h" #include "llvm/IR/DerivedTypes.h" @@ -302,7 +303,7 @@ static void replaceFallthroughCoroEnd(AnyCoroEndInst *End, } // Mark a coroutine as done, which implies that the coroutine is finished and -// never get resumed. +// never gets resumed. // // In resume-switched ABI, the done state is represented by storing zero in // ResumeFnAddr. @@ -1478,6 +1479,18 @@ struct SwitchCoroutineSplitter { static void createResumeEntryBlock(Function &F, coro::Shape &Shape) { LLVMContext &C = F.getContext(); + DIBuilder DBuilder(*F.getParent(), /*AllowUnresolved*/ false); + DISubprogram *DIS = F.getSubprogram(); + // If there is no DISubprogram for F, it implies the function is compiled + // without debug info. So we also don't generate debug info for the + // suspension points, either. + bool AddDebugLabels = + (DIS && DIS->getUnit() && + (DIS->getUnit()->getEmissionKind() == + DICompileUnit::DebugEmissionKind::FullDebug || + DIS->getUnit()->getEmissionKind() == + DICompileUnit::DebugEmissionKind::LineTablesOnly)); + // resume.entry: // %index.addr = getelementptr inbounds %f.Frame, %f.Frame* %FramePtr, i32 // 0, i32 2 % index = load i32, i32* %index.addr switch i32 %index, label @@ -1500,6 +1513,7 @@ struct SwitchCoroutineSplitter { Builder.CreateSwitch(Index, UnreachBB, Shape.CoroSuspends.size()); Shape.SwitchLowering.ResumeSwitch = Switch; + // Split all coro.suspend calls size_t SuspendIndex = 0; for (auto *AnyS : Shape.CoroSuspends) { auto *S = cast<CoroSuspendInst>(AnyS); @@ -1538,6 +1552,7 @@ struct SwitchCoroutineSplitter { // br label %resume.0.landing // // resume.0: ; <--- jump from the switch in the resume.entry + // XXX: label // %0 = tail call i8 @llvm.coro.suspend(token none, i1 false) // br label %resume.0.landing // @@ -1560,11 +1575,23 @@ struct SwitchCoroutineSplitter { PN->addIncoming(Builder.getInt8(-1), SuspendBB); PN->addIncoming(S, ResumeBB); + if (AddDebugLabels) { + if (DebugLoc SuspendLoc = S->getDebugLoc()) { + std::string LabelName = + ("__coro_resume_" + Twine(SuspendIndex)).str(); + DILocation& DILoc = *SuspendLoc.get(); + DILabel *ResumeLabel = DBuilder.createLabel( + DIS, LabelName, DILoc.getFile(), SuspendLoc.getLine()); + DBuilder.insertLabel(ResumeLabel, &DILoc, ResumeBB->begin()); + } + } + ++SuspendIndex; } Builder.SetInsertPoint(UnreachBB); Builder.CreateUnreachable(); + DBuilder.finalize(); Shape.SwitchLowering.ResumeEntryBlock = NewEntry; } >From d4633fb146f35665c3eff717c2ceeabe8e9d555f Mon Sep 17 00:00:00 2001 From: Adrian Vogelsgesang <avogelsges...@salesforce.com> Date: Wed, 11 Jun 2025 11:24:03 +0000 Subject: [PATCH 2/5] Add column, DW_AT_artificial & llvm-coro-suspension point --- clang/lib/CodeGen/CGDebugInfo.cpp | 2 +- clang/test/CodeGen/debug-label-inline.c | 2 +- clang/test/CodeGen/debug-label.c | 2 +- llvm/docs/LangRef.rst | 18 ++++++--- llvm/include/llvm/BinaryFormat/Dwarf.def | 1 + llvm/include/llvm/IR/DIBuilder.h | 4 +- llvm/include/llvm/IR/DebugInfoMetadata.h | 37 ++++++++++++++----- llvm/lib/AsmParser/LLParser.cpp | 11 ++++-- llvm/lib/Bitcode/Reader/MetadataLoader.cpp | 19 +++++++++- llvm/lib/Bitcode/Writer/BitcodeWriter.cpp | 5 ++- .../CodeGen/AsmPrinter/DwarfCompileUnit.cpp | 9 ++++- llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp | 17 +++++---- llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h | 2 +- llvm/lib/CodeGen/LiveDebugVariables.cpp | 1 + llvm/lib/IR/AsmWriter.cpp | 4 ++ llvm/lib/IR/DIBuilder.cpp | 6 ++- llvm/lib/IR/DebugInfo.cpp | 3 +- llvm/lib/IR/DebugInfoMetadata.cpp | 17 ++++++--- llvm/lib/IR/LLVMContextImpl.h | 15 +++++--- llvm/lib/Transforms/Coroutines/CoroSplit.cpp | 5 ++- llvm/lib/Transforms/Utils/CodeExtractor.cpp | 5 ++- llvm/unittests/IR/IRBuilderTest.cpp | 4 +- 22 files changed, 136 insertions(+), 53 deletions(-) diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index 7ab0e2fdaa731..674ac22516271 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -5293,7 +5293,7 @@ void CGDebugInfo::EmitLabel(const LabelDecl *D, CGBuilderTy &Builder) { // Create the descriptor for the label. auto *L = - DBuilder.createLabel(Scope, Name, Unit, Line, CGM.getLangOpts().Optimize); + DBuilder.createLabel(Scope, Name, Unit, Line, Column, /*IsArtificial=*/false, /*CoroSuspendIdx=*/std::nullopt, CGM.getLangOpts().Optimize); // Insert an llvm.dbg.label into the current block. DBuilder.insertLabel(L, diff --git a/clang/test/CodeGen/debug-label-inline.c b/clang/test/CodeGen/debug-label-inline.c index 972a32b5af32d..9d92ffb5ef61f 100644 --- a/clang/test/CodeGen/debug-label-inline.c +++ b/clang/test/CodeGen/debug-label-inline.c @@ -23,6 +23,6 @@ int f2(void) { // CHECK: distinct !DISubprogram(name: "f1", {{.*}}, retainedNodes: [[ELEMENTS:!.*]]) // CHECK: [[ELEMENTS]] = !{{{.*}}, [[LABEL_METADATA]]} -// CHECK: [[LABEL_METADATA]] = !DILabel({{.*}}, name: "top", {{.*}}, line: 8) +// CHECK: [[LABEL_METADATA]] = !DILabel({{.*}}, name: "top", {{.*}}, line: 8, column: 1) // CHECK: [[INLINEDAT:!.*]] = distinct !DILocation(line: 18, // CHECK: [[LABEL_LOCATION]] = !DILocation(line: 8, {{.*}}, inlinedAt: [[INLINEDAT]]) diff --git a/clang/test/CodeGen/debug-label.c b/clang/test/CodeGen/debug-label.c index 662b1a7dd2062..308d664ab712b 100644 --- a/clang/test/CodeGen/debug-label.c +++ b/clang/test/CodeGen/debug-label.c @@ -12,5 +12,5 @@ int f1(int a, int b) { return sum; } -// CHECK: [[LABEL_METADATA]] = !DILabel({{.*}}, name: "top", {{.*}}, line: 9) +// CHECK: [[LABEL_METADATA]] = !DILabel({{.*}}, name: "top", {{.*}}, line: 9, column: 1) // CHECK: [[LABEL_LOCATION]] = !DILocation(line: 9, diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst index d77c659055236..5f95b30652b2d 100644 --- a/llvm/docs/LangRef.rst +++ b/llvm/docs/LangRef.rst @@ -6975,16 +6975,22 @@ appear in the included source file. DILabel """"""" -``DILabel`` nodes represent labels within a :ref:`DISubprogram`. All fields of -a ``DILabel`` are mandatory. The ``scope:`` field must be one of either a -:ref:`DILexicalBlockFile`, a :ref:`DILexicalBlock`, or a :ref:`DISubprogram`. -The ``name:`` field is the label identifier. The ``file:`` field is the -:ref:`DIFile` the label is present in. The ``line:`` field is the source line +``DILabel`` nodes represent labels within a :ref:`DISubprogram`. The ``scope:`` +field must be one of either a :ref:`DILexicalBlockFile`, a +:ref:`DILexicalBlock`, or a :ref:`DISubprogram`. The ``name:`` field is the +label identifier. The ``file:`` field is the :ref:`DIFile` the label is +present in. The ``line:`` and ``column:`` field are the source line and column within the file where the label is declared. +Furthermore, a label can be marked as artificial, i.e. compiler-generated, +using ``isArtificial:``. Such artitificial labels are generated, e.g., by +the ``CoroSplit`` pass. In addition, the ``CoroSplit`` pass also uses the +``coroSuspendIdx:`` field to identify the coroutine suspend points. + .. code-block:: text - !2 = !DILabel(scope: !0, name: "foo", file: !1, line: 7) + !2 = !DILabel(scope: !0, name: "foo", file: !1, line: 7, column: 4) + !3 = !DILabel(scope: !0, name: "__coro_resume_3", file: !1, line: 9, column: 3, isArtificial: true, coroSuspendIdx: 3) DICommonBlock """"""""""""" diff --git a/llvm/include/llvm/BinaryFormat/Dwarf.def b/llvm/include/llvm/BinaryFormat/Dwarf.def index 9cccea4fcaa58..48b33478d5045 100644 --- a/llvm/include/llvm/BinaryFormat/Dwarf.def +++ b/llvm/include/llvm/BinaryFormat/Dwarf.def @@ -624,6 +624,7 @@ HANDLE_DW_AT(0x3e09, LLVM_ptrauth_authenticates_null_values, 0, LLVM) HANDLE_DW_AT(0x3e0a, LLVM_ptrauth_authentication_mode, 0, LLVM) HANDLE_DW_AT(0x3e0b, LLVM_num_extra_inhabitants, 0, LLVM) HANDLE_DW_AT(0x3e0c, LLVM_stmt_sequence, 0, LLVM) +HANDLE_DW_AT(0x3e0d, LLVM_coro_suspend_idx, 0, LLVM) // Apple extensions. diff --git a/llvm/include/llvm/IR/DIBuilder.h b/llvm/include/llvm/IR/DIBuilder.h index 99f7491b1b9b5..66aa562ea8212 100644 --- a/llvm/include/llvm/IR/DIBuilder.h +++ b/llvm/include/llvm/IR/DIBuilder.h @@ -901,7 +901,9 @@ namespace llvm { /// \c Scope must be a \a DILocalScope, and thus its scope chain eventually /// leads to a \a DISubprogram. LLVM_ABI DILabel *createLabel(DIScope *Scope, StringRef Name, DIFile *File, - unsigned LineNo, bool AlwaysPreserve = false); + unsigned LineNo, unsigned Column, bool IsArtificial, + std::optional<unsigned> CoroSuspendIdx, + bool AlwaysPreserve = false); /// Create a new descriptor for a parameter variable. /// diff --git a/llvm/include/llvm/IR/DebugInfoMetadata.h b/llvm/include/llvm/IR/DebugInfoMetadata.h index f80e44ce3abbc..363fa0a7c083f 100644 --- a/llvm/include/llvm/IR/DebugInfoMetadata.h +++ b/llvm/include/llvm/IR/DebugInfoMetadata.h @@ -4104,35 +4104,49 @@ class DILabel : public DINode { friend class LLVMContextImpl; friend class MDNode; - DILabel(LLVMContext &C, StorageType Storage, unsigned Line, + unsigned Column; + std::optional<unsigned> CoroSuspendIdx; + bool IsArtificial; + + DILabel(LLVMContext &C, StorageType Storage, unsigned Line, unsigned Column, + bool IsArtificial, std::optional<unsigned> CoroSuspendIdx, ArrayRef<Metadata *> Ops); ~DILabel() = default; static DILabel *getImpl(LLVMContext &Context, DIScope *Scope, StringRef Name, - DIFile *File, unsigned Line, StorageType Storage, - bool ShouldCreate = true) { + DIFile *File, unsigned Line, unsigned Column, + bool IsArtificial, std::optional<unsigned> CoroSuspendIdx, + StorageType Storage, bool ShouldCreate = true) { return getImpl(Context, Scope, getCanonicalMDString(Context, Name), File, - Line, Storage, ShouldCreate); + Line, Column, IsArtificial, CoroSuspendIdx, Storage, + ShouldCreate); } LLVM_ABI static DILabel *getImpl(LLVMContext &Context, Metadata *Scope, MDString *Name, Metadata *File, - unsigned Line, StorageType Storage, + unsigned Line, unsigned Column, + bool IsArtificial, std::optional<unsigned> CoroSuspendIdx, + StorageType Storage, bool ShouldCreate = true); TempDILabel cloneImpl() const { return getTemporary(getContext(), getScope(), getName(), getFile(), - getLine()); + getLine(), getColumn(), isArtificial(), + getCoroSuspendIdx()); } public: DEFINE_MDNODE_GET(DILabel, (DILocalScope * Scope, StringRef Name, DIFile *File, - unsigned Line), - (Scope, Name, File, Line)) + unsigned Line, unsigned Column, bool IsArtificial, + std::optional<unsigned> CoroSuspendIdx), + (Scope, Name, File, Line, Column, IsArtificial, + CoroSuspendIdx)) DEFINE_MDNODE_GET(DILabel, (Metadata * Scope, MDString *Name, Metadata *File, - unsigned Line), - (Scope, Name, File, Line)) + unsigned Line, unsigned Column, bool IsArtificial, + std::optional<unsigned> CoroSuspendIdx), + (Scope, Name, File, Line, Column, IsArtificial, + CoroSuspendIdx)) TempDILabel clone() const { return cloneImpl(); } @@ -4143,8 +4157,11 @@ class DILabel : public DINode { return cast_or_null<DILocalScope>(getRawScope()); } unsigned getLine() const { return SubclassData32; } + unsigned getColumn() const { return Column; } StringRef getName() const { return getStringOperand(1); } DIFile *getFile() const { return cast_or_null<DIFile>(getRawFile()); } + bool isArtificial() const { return IsArtificial; } + std::optional<unsigned> getCoroSuspendIdx() const { return CoroSuspendIdx; } Metadata *getRawScope() const { return getOperand(0); } MDString *getRawName() const { return getOperandAs<MDString>(1); } diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp index c5e166cef6da6..e69eb7d51d86b 100644 --- a/llvm/lib/AsmParser/LLParser.cpp +++ b/llvm/lib/AsmParser/LLParser.cpp @@ -6116,18 +6116,23 @@ bool LLParser::parseDILocalVariable(MDNode *&Result, bool IsDistinct) { } /// parseDILabel: -/// ::= !DILabel(scope: !0, name: "foo", file: !1, line: 7) +/// ::= !DILabel(scope: !0, name: "foo", file: !1, line: 7, column: 4) bool LLParser::parseDILabel(MDNode *&Result, bool IsDistinct) { #define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ REQUIRED(scope, MDField, (/* AllowNull */ false)); \ REQUIRED(name, MDStringField, ); \ REQUIRED(file, MDField, ); \ - REQUIRED(line, LineField, ); + REQUIRED(line, LineField, ); \ + OPTIONAL(column, ColumnField, ); \ + OPTIONAL(isArtificial, MDBoolField, ); \ + OPTIONAL(coroSuspendIdx, MDUnsignedField, ); PARSE_MD_FIELDS(); #undef VISIT_MD_FIELDS + std::optional<unsigned> CoroSuspendIdx = coroSuspendIdx.Seen ? std::optional<unsigned>(coroSuspendIdx.Val) : std::nullopt; + Result = GET_OR_DISTINCT(DILabel, - (Context, scope.Val, name.Val, file.Val, line.Val)); + (Context, scope.Val, name.Val, file.Val, line.Val, column.Val, isArtificial.Val, CoroSuspendIdx)); return false; } diff --git a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp index a9467d16c9a14..694d446fb2f04 100644 --- a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp +++ b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp @@ -1133,6 +1133,7 @@ Error MetadataLoader::MetadataLoaderImpl::parseMetadata(bool ModuleLevel) { ++NumMDRecordLoaded; if (Expected<unsigned> MaybeCode = Stream.readRecord(Entry.ID, Record, &Blob)) { + // Crashes called from here! if (Error Err = parseOneMetadata(Record, MaybeCode.get(), Placeholders, Blob, NextMetadataNo)) return Err; @@ -1319,6 +1320,7 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata( unsigned Size = Record.size(); NamedMDNode *NMD = TheModule.getOrInsertNamedMetadata(Name); for (unsigned i = 0; i != Size; ++i) { + // Crashes here! MDNode *MD = MetadataList.getMDNodeFwdRefOrNull(Record[i]); if (!MD) return error("Invalid named metadata: expect fwd ref to MDNode"); @@ -2240,14 +2242,27 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata( break; } case bitc::METADATA_LABEL: { - if (Record.size() != 5) + if (Record.size() < 5 || Record.size() > 7) return error("Invalid record"); IsDistinct = Record[0] & 1; + uint64_t Line = Record[4]; + uint64_t Column = Record.size() > 5 ? Record[5] : 0; + bool IsArtificial = Record[0] & 2; + std::optional<unsigned> CoroSuspendIdx; + if (Record.size() > 6) { + unsigned RawSuspendIdx = Record[6]; + if (RawSuspendIdx != std::numeric_limits<unsigned>::max()) { + if (RawSuspendIdx > (uint64_t)std::numeric_limits<unsigned>::max()) + return error("CoroSuspendIdx value is too large"); + CoroSuspendIdx = RawSuspendIdx; + } + } + MetadataList.assignValue( GET_OR_DISTINCT(DILabel, (Context, getMDOrNull(Record[1]), getMDString(Record[2]), - getMDOrNull(Record[3]), Record[4])), + getMDOrNull(Record[3]), Line, Column, IsArtificial, CoroSuspendIdx)), NextMetadataNo); NextMetadataNo++; break; diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp index 2a2dd085a9461..ceaf804087d82 100644 --- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -2344,11 +2344,14 @@ void ModuleBitcodeWriter::writeDILocalVariable( void ModuleBitcodeWriter::writeDILabel( const DILabel *N, SmallVectorImpl<uint64_t> &Record, unsigned Abbrev) { - Record.push_back((uint64_t)N->isDistinct()); + uint64_t IsArtificialFlag = uint64_t(N->isArtificial()) << 1; + Record.push_back((uint64_t)N->isDistinct() | IsArtificialFlag); Record.push_back(VE.getMetadataOrNullID(N->getScope())); Record.push_back(VE.getMetadataOrNullID(N->getRawName())); Record.push_back(VE.getMetadataOrNullID(N->getFile())); Record.push_back(N->getLine()); + Record.push_back(N->getColumn()); + Record.push_back(N->getCoroSuspendIdx().value_or(std::numeric_limits<uint64_t>::max())); Stream.EmitRecord(bitc::METADATA_LABEL, Record, Abbrev); Record.clear(); diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp index a20c374e08935..8e8cda4eef573 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp @@ -429,7 +429,7 @@ DIE *DwarfCompileUnit::getOrCreateCommonBlock( addString(NDie, dwarf::DW_AT_name, Name); addGlobalName(Name, NDie, CB->getScope()); if (CB->getFile()) - addSourceLine(NDie, CB->getLineNo(), CB->getFile()); + addSourceLine(NDie, CB->getLineNo(), /*Column*/ 0, CB->getFile()); if (DIGlobalVariable *V = CB->getDecl()) getCU().addLocationAttribute(&NDie, V, GlobalExprs); return &NDie; @@ -1404,7 +1404,7 @@ DIE *DwarfCompileUnit::constructImportedEntityDIE( else EntityDie = getDIE(Entity); assert(EntityDie); - addSourceLine(*IMDie, Module->getLine(), Module->getFile()); + addSourceLine(*IMDie, Module->getLine(), /*Column*/ 0, Module->getFile()); addDIEEntry(*IMDie, dwarf::DW_AT_import, *EntityDie); StringRef Name = Module->getName(); if (!Name.empty()) { @@ -1701,6 +1701,11 @@ void DwarfCompileUnit::applyLabelAttributes(const DbgLabel &Label, addString(LabelDie, dwarf::DW_AT_name, Name); const auto *DILabel = Label.getLabel(); addSourceLine(LabelDie, DILabel); + if (DILabel->isArtificial()) + addFlag(LabelDie, dwarf::DW_AT_artificial); + if (DILabel->getCoroSuspendIdx()) + addUInt(LabelDie, dwarf::DW_AT_LLVM_coro_suspend_idx, std::nullopt, + *DILabel->getCoroSuspendIdx()); } /// Add a Dwarf expression attribute data and value. diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp index 9bd337a962b86..3d4fed7a8d68d 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp @@ -442,49 +442,52 @@ void DwarfUnit::addBlock(DIE &Die, dwarf::Attribute Attribute, addBlock(Die, Attribute, Block->BestForm(), Block); } -void DwarfUnit::addSourceLine(DIE &Die, unsigned Line, const DIFile *File) { +void DwarfUnit::addSourceLine(DIE &Die, unsigned Line, unsigned Column, const DIFile *File) { if (Line == 0) return; unsigned FileID = getOrCreateSourceID(File); addUInt(Die, dwarf::DW_AT_decl_file, std::nullopt, FileID); addUInt(Die, dwarf::DW_AT_decl_line, std::nullopt, Line); + + if (Column != 0) + addUInt(Die, dwarf::DW_AT_decl_column, std::nullopt, Column); } void DwarfUnit::addSourceLine(DIE &Die, const DILocalVariable *V) { assert(V); - addSourceLine(Die, V->getLine(), V->getFile()); + addSourceLine(Die, V->getLine(), /*Column*/ 0, V->getFile()); } void DwarfUnit::addSourceLine(DIE &Die, const DIGlobalVariable *G) { assert(G); - addSourceLine(Die, G->getLine(), G->getFile()); + addSourceLine(Die, G->getLine(), /*Column*/ 0, G->getFile()); } void DwarfUnit::addSourceLine(DIE &Die, const DISubprogram *SP) { assert(SP); - addSourceLine(Die, SP->getLine(), SP->getFile()); + addSourceLine(Die, SP->getLine(), /*Column*/ 0, SP->getFile()); } void DwarfUnit::addSourceLine(DIE &Die, const DILabel *L) { assert(L); - addSourceLine(Die, L->getLine(), L->getFile()); + addSourceLine(Die, L->getLine(), L->getColumn(), L->getFile()); } void DwarfUnit::addSourceLine(DIE &Die, const DIType *Ty) { assert(Ty); - addSourceLine(Die, Ty->getLine(), Ty->getFile()); + addSourceLine(Die, Ty->getLine(), /*Column*/ 0, Ty->getFile()); } void DwarfUnit::addSourceLine(DIE &Die, const DIObjCProperty *Ty) { assert(Ty); - addSourceLine(Die, Ty->getLine(), Ty->getFile()); + addSourceLine(Die, Ty->getLine(), /*Column*/ 0, Ty->getFile()); } void DwarfUnit::addConstantFPValue(DIE &Die, const ConstantFP *CFP) { diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h index 43bf197563867..c01fb6c6c29d9 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h @@ -216,7 +216,7 @@ class DwarfUnit : public DIEUnit { DIEBlock *Block); /// Add location information to specified debug information entry. - void addSourceLine(DIE &Die, unsigned Line, const DIFile *File); + void addSourceLine(DIE &Die, unsigned Line, unsigned Column, const DIFile *File); void addSourceLine(DIE &Die, const DILocalVariable *V); void addSourceLine(DIE &Die, const DIGlobalVariable *G); void addSourceLine(DIE &Die, const DISubprogram *SP); diff --git a/llvm/lib/CodeGen/LiveDebugVariables.cpp b/llvm/lib/CodeGen/LiveDebugVariables.cpp index f12f437c493e1..83b179499decb 100644 --- a/llvm/lib/CodeGen/LiveDebugVariables.cpp +++ b/llvm/lib/CodeGen/LiveDebugVariables.cpp @@ -715,6 +715,7 @@ static void printExtendedName(raw_ostream &OS, const DINode *Node, Res = V->getName(); Line = V->getLine(); } else if (const auto *L = dyn_cast<const DILabel>(Node)) { + // XXX what are we doing here? Adjust it? Res = L->getName(); Line = L->getLine(); } diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp index 7828ba45ec27f..d6a67a68c66d3 100644 --- a/llvm/lib/IR/AsmWriter.cpp +++ b/llvm/lib/IR/AsmWriter.cpp @@ -2611,6 +2611,10 @@ static void writeDILabel(raw_ostream &Out, const DILabel *N, Printer.printString("name", N->getName()); Printer.printMetadata("file", N->getRawFile()); Printer.printInt("line", N->getLine()); + Printer.printInt("column", N->getColumn()); + Printer.printBool("isArtificial", N->isArtificial(), false); + if (N->getCoroSuspendIdx()) + Printer.printInt("coroSuspendIdx", *N->getCoroSuspendIdx(), /* ShouldSkipZero */ false); Out << ")"; } diff --git a/llvm/lib/IR/DIBuilder.cpp b/llvm/lib/IR/DIBuilder.cpp index 6001ed421183b..0ba2b050035b8 100644 --- a/llvm/lib/IR/DIBuilder.cpp +++ b/llvm/lib/IR/DIBuilder.cpp @@ -946,9 +946,11 @@ DILocalVariable *DIBuilder::createParameterVariable( } DILabel *DIBuilder::createLabel(DIScope *Context, StringRef Name, DIFile *File, - unsigned LineNo, bool AlwaysPreserve) { + unsigned LineNo, unsigned Column, bool IsArtificial, + std::optional<unsigned> CoroSuspendIdx, + bool AlwaysPreserve) { auto *Scope = cast<DILocalScope>(Context); - auto *Node = DILabel::get(VMContext, Scope, Name, File, LineNo); + auto *Node = DILabel::get(VMContext, Scope, Name, File, LineNo, Column, IsArtificial, CoroSuspendIdx); if (AlwaysPreserve) { /// The optimizer may remove labels. If there is an interest diff --git a/llvm/lib/IR/DebugInfo.cpp b/llvm/lib/IR/DebugInfo.cpp index 5c645ffe3f3f7..947550cce043e 100644 --- a/llvm/lib/IR/DebugInfo.cpp +++ b/llvm/lib/IR/DebugInfo.cpp @@ -1837,7 +1837,8 @@ LLVMMetadataRef LLVMDIBuilderCreateLabel(LLVMDIBuilderRef Builder, LLVMBool AlwaysPreserve) { return wrap(unwrap(Builder)->createLabel( unwrapDI<DIScope>(Context), StringRef(Name, NameLen), - unwrapDI<DIFile>(File), LineNo, AlwaysPreserve)); + unwrapDI<DIFile>(File), LineNo, /*Column*/ 0, /*IsArtificial*/ false, + /*CoroSuspendIdx*/ std::nullopt, AlwaysPreserve)); } LLVMDbgRecordRef LLVMDIBuilderInsertLabelBefore(LLVMDIBuilderRef Builder, diff --git a/llvm/lib/IR/DebugInfoMetadata.cpp b/llvm/lib/IR/DebugInfoMetadata.cpp index 44b0f0d50067c..c975b99877635 100644 --- a/llvm/lib/IR/DebugInfoMetadata.cpp +++ b/llvm/lib/IR/DebugInfoMetadata.cpp @@ -1616,18 +1616,25 @@ std::optional<uint64_t> DIVariable::getSizeInBits() const { } DILabel::DILabel(LLVMContext &C, StorageType Storage, unsigned Line, + unsigned Column, bool IsArtificial, std::optional<unsigned> CoroSuspendIdx, ArrayRef<Metadata *> Ops) : DINode(C, DILabelKind, Storage, dwarf::DW_TAG_label, Ops) { - SubclassData32 = Line; + this->SubclassData32 = Line; + this->Column = Column; + this->IsArtificial = IsArtificial; + this->CoroSuspendIdx = CoroSuspendIdx; } DILabel *DILabel::getImpl(LLVMContext &Context, Metadata *Scope, MDString *Name, - Metadata *File, unsigned Line, StorageType Storage, - bool ShouldCreate) { + Metadata *File, unsigned Line, unsigned Column, + bool IsArtificial, std::optional<unsigned> CoroSuspendIdx, + StorageType Storage, bool ShouldCreate) { assert(Scope && "Expected scope"); assert(isCanonical(Name) && "Expected canonical MDString"); - DEFINE_GETIMPL_LOOKUP(DILabel, (Scope, Name, File, Line)); + DEFINE_GETIMPL_LOOKUP(DILabel, (Scope, Name, File, Line, Column, IsArtificial, + CoroSuspendIdx)); Metadata *Ops[] = {Scope, Name, File}; - DEFINE_GETIMPL_STORE(DILabel, (Line), Ops); + DEFINE_GETIMPL_STORE(DILabel, (Line, Column, IsArtificial, CoroSuspendIdx), + Ops); } DIExpression *DIExpression::getImpl(LLVMContext &Context, diff --git a/llvm/lib/IR/LLVMContextImpl.h b/llvm/lib/IR/LLVMContextImpl.h index 4446f47d323d2..170e2f3143a8b 100644 --- a/llvm/lib/IR/LLVMContextImpl.h +++ b/llvm/lib/IR/LLVMContextImpl.h @@ -1329,20 +1329,25 @@ template <> struct MDNodeKeyImpl<DILabel> { MDString *Name; Metadata *File; unsigned Line; + unsigned Column; + bool IsArtificial; + std::optional<unsigned> CoroSuspendIdx; - MDNodeKeyImpl(Metadata *Scope, MDString *Name, Metadata *File, unsigned Line) - : Scope(Scope), Name(Name), File(File), Line(Line) {} + MDNodeKeyImpl(Metadata *Scope, MDString *Name, Metadata *File, unsigned Line, unsigned Column, bool IsArtificial, std::optional<unsigned> CoroSuspendIdx) + : Scope(Scope), Name(Name), File(File), Line(Line), Column(Column), IsArtificial(IsArtificial), CoroSuspendIdx(CoroSuspendIdx) {} MDNodeKeyImpl(const DILabel *N) : Scope(N->getRawScope()), Name(N->getRawName()), File(N->getRawFile()), - Line(N->getLine()) {} + Line(N->getLine()), Column(N->getColumn()), IsArtificial(N->isArtificial()), CoroSuspendIdx(N->getCoroSuspendIdx()) {} bool isKeyOf(const DILabel *RHS) const { return Scope == RHS->getRawScope() && Name == RHS->getRawName() && - File == RHS->getRawFile() && Line == RHS->getLine(); + File == RHS->getRawFile() && Line == RHS->getLine() && + Column == RHS->getColumn() && IsArtificial == RHS->isArtificial() && + CoroSuspendIdx == RHS->getCoroSuspendIdx(); } /// Using name and line to get hash value. It should already be mostly unique. - unsigned getHashValue() const { return hash_combine(Scope, Name, Line); } + unsigned getHashValue() const { return hash_combine(Scope, Name, Line, Column, IsArtificial, CoroSuspendIdx); } }; template <> struct MDNodeKeyImpl<DIExpression> { diff --git a/llvm/lib/Transforms/Coroutines/CoroSplit.cpp b/llvm/lib/Transforms/Coroutines/CoroSplit.cpp index 1348d785f4f85..1a9833b306a0e 100644 --- a/llvm/lib/Transforms/Coroutines/CoroSplit.cpp +++ b/llvm/lib/Transforms/Coroutines/CoroSplit.cpp @@ -1581,7 +1581,10 @@ struct SwitchCoroutineSplitter { ("__coro_resume_" + Twine(SuspendIndex)).str(); DILocation& DILoc = *SuspendLoc.get(); DILabel *ResumeLabel = DBuilder.createLabel( - DIS, LabelName, DILoc.getFile(), SuspendLoc.getLine()); + DIS, LabelName, DILoc.getFile(), SuspendLoc.getLine(), SuspendLoc.getCol(), + /*IsArtificial=*/true, + /*CoroSuspendIdx=*/SuspendIndex, + /*AlwaysPreserve=*/false); DBuilder.insertLabel(ResumeLabel, &DILoc, ResumeBB->begin()); } } diff --git a/llvm/lib/Transforms/Utils/CodeExtractor.cpp b/llvm/lib/Transforms/Utils/CodeExtractor.cpp index 242cf6d811b66..52a3e7acb5bbd 100644 --- a/llvm/lib/Transforms/Utils/CodeExtractor.cpp +++ b/llvm/lib/Transforms/Utils/CodeExtractor.cpp @@ -1348,7 +1348,10 @@ static void fixupDebugInfoPostExtraction(Function &OldFunc, Function &NewFunc, DILocalScope *NewScope = DILocalScope::cloneScopeForSubprogram( *OldLabel->getScope(), *NewSP, Ctx, Cache); NewLabel = DILabel::get(Ctx, NewScope, OldLabel->getName(), - OldLabel->getFile(), OldLabel->getLine()); + OldLabel->getFile(), OldLabel->getLine(), + OldLabel->getColumn(), + OldLabel->isArtificial(), + OldLabel->getCoroSuspendIdx()); } LabelRecord->setLabel(cast<DILabel>(NewLabel)); }; diff --git a/llvm/unittests/IR/IRBuilderTest.cpp b/llvm/unittests/IR/IRBuilderTest.cpp index 520735dfc3268..6f38c6d72dab4 100644 --- a/llvm/unittests/IR/IRBuilderTest.cpp +++ b/llvm/unittests/IR/IRBuilderTest.cpp @@ -920,9 +920,9 @@ TEST_F(IRBuilderTest, DIBuilder) { // -------------------------- DILocation *LabelLoc = DILocation::get(Ctx, 1, 0, BarScope); DILabel *AlwaysPreserveLabel = DIB.createLabel( - BarScope, "meles_meles", File, 1, /*AlwaysPreserve*/ true); + BarScope, "meles_meles", File, 1, /*Column*/ 0, /*IsArtificial*/ false, /*CoroSuspendIdx*/ std::nullopt, /*AlwaysPreserve*/ true); DILabel *Label = - DIB.createLabel(BarScope, "badger", File, 1, /*AlwaysPreserve*/ false); + DIB.createLabel(BarScope, "badger", File, 1, /*Column*/ 0, /*IsArtificial*/ false, /*CoroSuspendIdx*/ std::nullopt, /*AlwaysPreserve*/ false); { /* dbg.label | DbgLabelRecord */ // Insert before I and check order. >From b2475e22c56fd324c7b99d18064d1c3642bef286 Mon Sep 17 00:00:00 2001 From: Adrian Vogelsgesang <avogelsges...@salesforce.com> Date: Fri, 27 Jun 2025 02:29:58 +0000 Subject: [PATCH 3/5] Test cases --- llvm/test/DebugInfo/Generic/debug-label.ll | 4 +- .../Coroutines/coro-debug-dbg.values.ll | 2 +- llvm/test/Transforms/Coroutines/coro-debug.ll | 32 ++-- .../Coroutines/coro-split-dbg-labels.ll | 148 ++++++++++++++++++ ...-lieftime.ll => coro-split-no-lifetime.ll} | 0 5 files changed, 171 insertions(+), 15 deletions(-) create mode 100644 llvm/test/Transforms/Coroutines/coro-split-dbg-labels.ll rename llvm/test/Transforms/Coroutines/{coro-split-no-lieftime.ll => coro-split-no-lifetime.ll} (100%) diff --git a/llvm/test/DebugInfo/Generic/debug-label.ll b/llvm/test/DebugInfo/Generic/debug-label.ll index eff482a25ee0f..0adb0608fafb6 100644 --- a/llvm/test/DebugInfo/Generic/debug-label.ll +++ b/llvm/test/DebugInfo/Generic/debug-label.ll @@ -5,6 +5,7 @@ ; CHECK-NEXT: DW_AT_name {{.*}}"top" ; CHECK-NEXT: DW_AT_decl_file [DW_FORM_data1] {{.*}}debug-label.c ; CHECK-NEXT: DW_AT_decl_line [DW_FORM_data1] {{.*}}4 +; CHECK-NEXT: DW_AT_decl_column [DW_FORM_data1] {{.*}}9 ; CHECK-NEXT: DW_AT_low_pc [DW_FORM_addr] {{.*}}{{0x[0-9a-f]+}} ; CHECK: DW_TAG_label ; CHECK-NEXT: DW_AT_name {{.*}}"done" @@ -22,6 +23,7 @@ ; ASM-NEXT: DW_AT_name ; ASM: 1 {{.*}} DW_AT_decl_file ; ASM-NEXT: 4 {{.*}} DW_AT_decl_line +; ASM-NEXT: 9 {{.*}} DW_AT_decl_column ; ASM-NEXT: [[TOP_LOW_PC]]{{.*}} DW_AT_low_pc ; ASM: DW_TAG_label ; ASM-NEXT: DW_AT_name @@ -68,7 +70,7 @@ declare void @llvm.dbg.label(metadata) !7 = !DISubroutineType(types: !8) !8 = !{!9, !9, !9} !9 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) -!10 = !DILabel(scope: !6, name: "top", file: !1, line: 4) +!10 = !DILabel(scope: !6, name: "top", file: !1, line: 4, column: 9) !11 = !DILocation(line: 4, column: 1, scope: !6) !12 = !DILabel(scope: !15, name: "done", file: !1, line: 7) !13 = !DILocation(line: 7, column: 1, scope: !6) diff --git a/llvm/test/Transforms/Coroutines/coro-debug-dbg.values.ll b/llvm/test/Transforms/Coroutines/coro-debug-dbg.values.ll index 5f7701c357ec3..0934393a667ee 100644 --- a/llvm/test/Transforms/Coroutines/coro-debug-dbg.values.ll +++ b/llvm/test/Transforms/Coroutines/coro-debug-dbg.values.ll @@ -1,4 +1,4 @@ -; Tests whether resume function would remain dbg.value infomation. +; Tests whether resume function retains dbg.value information. ; RUN: opt < %s -passes='module(coro-early),cgscc(coro-split,coro-split)' -S | FileCheck %s ; ; This file is based on coro-debug-frame-variable.ll. diff --git a/llvm/test/Transforms/Coroutines/coro-debug.ll b/llvm/test/Transforms/Coroutines/coro-debug.ll index a220073248ba3..5f8e9c9c1d16d 100644 --- a/llvm/test/Transforms/Coroutines/coro-debug.ll +++ b/llvm/test/Transforms/Coroutines/coro-debug.ll @@ -19,7 +19,6 @@ entry: %3 = call i8 @llvm.coro.suspend(token none, i1 false), !dbg !17 %conv = sext i8 %3 to i32, !dbg !17 %late_local = alloca i32, align 4 - call void @coro.devirt.trigger(ptr null) switch i32 %conv, label %sw.default [ i32 0, label %sw.bb i32 1, label %sw.bb1 @@ -113,12 +112,6 @@ declare ptr @llvm.coro.free(token, ptr nocapture readonly) #2 ; Function Attrs: nounwind declare i1 @llvm.coro.end(ptr, i1, token) #5 -; Function Attrs: alwaysinline -define private void @coro.devirt.trigger(ptr) #6 { -entry: - ret void -} - ; Function Attrs: argmemonly nounwind readonly declare ptr @llvm.coro.subfn.addr(ptr nocapture readonly, i8) #2 @@ -170,15 +163,20 @@ attributes #7 = { noduplicate } !31 = !DILocalVariable(name: "allocated", scope: !6, file: !7, line: 55, type: !11) !32 = !DILocalVariable(name: "inline_asm", scope: !6, file: !7, line: 55, type: !11) +; Check that the original function is visible and capture its debug info id. ; CHECK: define ptr @flink(i32 %x) #0 personality i32 0 !dbg ![[ORIG:[0-9]+]] + +; Check that the resume function is present and capture its debug info id. +; Also check that it contains `#dbg_declare` and `#dbg_value` debug instructions +; making the debug variables available to the debugger. +; ; CHECK: define internal fastcc void @flink.resume(ptr noundef nonnull align 8 dereferenceable(40) %0) #0 personality i32 0 !dbg ![[RESUME:[0-9]+]] ; CHECK: entry.resume: ; CHECK: %[[DBG_PTR:.*]] = alloca ptr -; CHECK: #dbg_declare(ptr %[[DBG_PTR]], ![[RESUME_COROHDL:[0-9]+]], !DIExpression(DW_OP_deref, DW_OP_plus_uconst, -; CHECK: #dbg_declare(ptr %[[DBG_PTR]], ![[RESUME_X:[0-9]+]], !DIExpression(DW_OP_deref, DW_OP_plus_uconst, [[EXPR_TAIL:.*]]) -; CHECK: store ptr {{.*}}, ptr %[[DBG_PTR]] +; CHECK-NEXT: #dbg_declare(ptr %[[DBG_PTR]], ![[RESUME_COROHDL:[0-9]+]], !DIExpression(DW_OP_deref, DW_OP_plus_uconst, +; CHECK-NEXT: #dbg_declare(ptr %[[DBG_PTR]], ![[RESUME_X:[0-9]+]], !DIExpression(DW_OP_deref, DW_OP_plus_uconst, [[EXPR_TAIL:.*]]) +; CHECK-NEXT: store ptr {{.*}}, ptr %[[DBG_PTR]] ; CHECK-NOT: alloca ptr -; CHECK: call void @coro.devirt.trigger(ptr null) ; CHECK: #dbg_value(i8 0, ![[RESUME_CONST:[0-9]+]], !DIExpression(DW_OP_LLVM_convert, 8, DW_ATE_signed, DW_OP_LLVM_convert, 32, DW_ATE_signed), ; CHECK: #dbg_value(ptr %[[DBG_PTR]], ![[RESUME_DIRECT:[0-9]+]], !DIExpression(DW_OP_deref, DW_OP_plus_uconst, {{[0-9]+}}, DW_OP_deref), ; Note that keeping the undef value here could be acceptable, too. @@ -194,18 +192,26 @@ attributes #7 = { noduplicate } ; CHECK: [[DEFAULT_DEST]]: ; CHECK-NOT: {{.*}}: ; CHECK: #dbg_value(i32 %[[CALLBR_RES]] + +; Check that the destroy and cleanup functions are present and capture their debug info id. +; ; CHECK: define internal fastcc void @flink.destroy(ptr noundef nonnull align 8 dereferenceable(40) %0) #0 personality i32 0 !dbg ![[DESTROY:[0-9]+]] ; CHECK: define internal fastcc void @flink.cleanup(ptr noundef nonnull align 8 dereferenceable(40) %0) #0 personality i32 0 !dbg ![[CLEANUP:[0-9]+]] +; Check that the linkage name of the original function is set correctly. +; ; CHECK: ![[ORIG]] = distinct !DISubprogram(name: "f", linkageName: "flink" - ; CHECK: ![[RESUME]] = distinct !DISubprogram(name: "f", linkageName: "flink.resume" + +; Check that metadata for local variables in the resume function is set correctly. +; ; CHECK: ![[RESUME_COROHDL]] = !DILocalVariable(name: "coro_hdl", scope: ![[RESUME]] ; CHECK: ![[RESUME_X]] = !DILocalVariable(name: "x", arg: 1, scope: ![[RESUME]] ; CHECK: ![[RESUME_CONST]] = !DILocalVariable(name: "direct_const", scope: ![[RESUME]] ; CHECK: ![[RESUME_DIRECT]] = !DILocalVariable(name: "direct_mem", scope: ![[RESUME]] ; CHECK: ![[RESUME_DIRECT_VALUE]] = !DILocalVariable(name: "direct_value", scope: ![[RESUME]] +; Check that the linkage names are set correctly for the destroy and cleanup functions. +; ; CHECK: ![[DESTROY]] = distinct !DISubprogram(name: "f", linkageName: "flink.destroy" - ; CHECK: ![[CLEANUP]] = distinct !DISubprogram(name: "f", linkageName: "flink.cleanup" diff --git a/llvm/test/Transforms/Coroutines/coro-split-dbg-labels.ll b/llvm/test/Transforms/Coroutines/coro-split-dbg-labels.ll new file mode 100644 index 0000000000000..48642ffa97b4d --- /dev/null +++ b/llvm/test/Transforms/Coroutines/coro-split-dbg-labels.ll @@ -0,0 +1,148 @@ +; Tests that we add DILabels for the suspend points. +; +; We check both the generated LLVM: +; RUN: opt < %s -passes='cgscc(coro-split)' -S | FileCheck %s +; +; And the debug info: +; RUN: opt < %s -passes='cgscc(coro-split),coro-cleanup' \ +; RUN: | llc -O0 -filetype=obj -o - \ +; RUN: | llvm-dwarfdump - \ +; RUN: | FileCheck %s -check-prefix=DWARF + +source_filename = "coro.c" +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +declare void @bar(...) local_unnamed_addr #2 +declare void @baz(...) local_unnamed_addr #2 + +; Roughly equivalent to: +; +; task f() { +; while (true) { +; bar(); +; co_await std::suspend_always{}; +; baz(); +; co_await std::suspend_always{}; +; } +; } + +; Function Attrs: nounwind uwtable +define ptr @f() #3 !dbg !16 { +entry: + %0 = tail call token @llvm.coro.id(i32 0, ptr null, ptr @f, ptr null), !dbg !26 + %1 = tail call i64 @llvm.coro.size.i64(), !dbg !26 + %frame = tail call ptr @malloc(i64 %1), !dbg !26 + %2 = tail call ptr @llvm.coro.begin(token %0, ptr %frame) #4, !dbg !26 + br label %loop1, !dbg !27 + +loop1: ; preds = %for.cond, %entry + tail call void (...) @bar() #7, !dbg !33 + %3 = tail call token @llvm.coro.save(ptr null), !dbg !34 + %4 = tail call i8 @llvm.coro.suspend(token %3, i1 false), !dbg !34 + switch i8 %4, label %coro_Suspend [ + i8 0, label %loop2 + i8 1, label %coro_Cleanup + ], !dbg !34 + +loop2: ; preds = %for.cond, %entry + tail call void (...) @baz() #7, !dbg !35 + %5 = tail call token @llvm.coro.save(ptr null), !dbg !36 + %6 = tail call i8 @llvm.coro.suspend(token %5, i1 false), !dbg !36 + switch i8 %6, label %coro_Suspend [ + i8 0, label %loop1 + i8 1, label %coro_Cleanup + ], !dbg !36 + +coro_Cleanup: ; preds = %for.cond + %7 = tail call ptr @llvm.coro.free(token %0, ptr %2), !dbg !37 + tail call void @free(ptr nonnull %7), !dbg !37 + br label %coro_Suspend, !dbg !37 + +coro_Suspend: ; preds = %for.cond, %if.then, %coro_Cleanup + tail call i1 @llvm.coro.end(ptr null, i1 false, token none) #4, !dbg !40 + ret ptr %2, !dbg !41 +} + +; Check that the resume function contains the `#dbg_label` instructions. +; CHECK-LABEL: define ptr @f() #1 !dbg !6 { +; CHECK: resume.0: ; preds = %resume.entry +; CHECK-NEXT: #dbg_label(![[RESUME_0:[0-9]+]], !{{[0-9]+}}) +; CHECK: resume.1: ; preds = %resume.entry +; CHECK-NEXT: #dbg_label(![[RESUME_1:[0-9]+]], !{{[0-9]+}}) + +; Check that the destroy function contains the `#dbg_label` instructions. +; CHECK-LABEL: define internal fastcc void @f.destroy({{.*}}) #1 !dbg !38 { +; CHECK: resume.0: ; preds = %resume.entry +; CHECK-NEXT: #dbg_label(![[DESTROY_0:[0-9]+]], !{{[0-9]+}}) +; CHECK: resume.1: ; preds = %resume.entry +; CHECK-NEXT: #dbg_label(![[DESTROY_1:[0-9]+]], !{{[0-9]+}}) + +; Check that the DILabels are correct. +; CHECK: ![[RESUME_0]] = !DILabel(scope: !{{[0-9]+}}, name: "__coro_resume_0", file: !{{[0-9]*}}, line: 12, column: 6, isArtificial: true, coroSuspendIdx: 0) +; CHECK: ![[RESUME_1]] = !DILabel(scope: !{{[0-9]+}}, name: "__coro_resume_1", file: !{{[0-9]*}}, line: 14, column: 6, isArtificial: true, coroSuspendIdx: 1) +; CHECK: ![[DESTROY_0]] = !DILabel(scope: !{{[0-9]+}}, name: "__coro_resume_0", file: !{{[0-9]*}}, line: 12, column: 6, isArtificial: true, coroSuspendIdx: 0) +; CHECK: ![[DESTROY_1]] = !DILabel(scope: !{{[0-9]+}}, name: "__coro_resume_1", file: !{{[0-9]*}}, line: 14, column: 6, isArtificial: true, coroSuspendIdx: 1) + +; DWARF: {{.*}}DW_TAG_label +; DWARF-LABEL: DW_AT_name ("__coro_resume_0") +; DWARF-NEXT: DW_AT_decl_file +; DWARF-NEXT: DW_AT_decl_line (12) +; DWARF-NEXT: DW_AT_decl_column (6) +; DWARF-NEXT: DW_AT_artificial (true) +; DWARF-NEXT: DW_AT_LLVM_coro_suspend_idx (0x00) +; DWARF-NEXT: DW_AT_low_pc + + +; Function Attrs: argmemonly nounwind readonly +declare token @llvm.coro.id(i32, ptr readnone, ptr nocapture readonly, ptr) #5 + +; Function Attrs: nounwind +declare noalias ptr @malloc(i64) local_unnamed_addr #6 +declare i64 @llvm.coro.size.i64() #1 +declare ptr @llvm.coro.begin(token, ptr writeonly) #7 +declare token @llvm.coro.save(ptr) #7 +declare i8 @llvm.coro.suspend(token, i1) #7 +declare ptr @llvm.coro.free(token, ptr nocapture readonly) #5 +declare void @free(ptr nocapture) local_unnamed_addr #6 +declare i1 @llvm.coro.end(ptr, i1, token) #7 + +attributes #0 = { nounwind uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "frame-pointer"="none" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #1 = { nounwind readnone } +attributes #2 = { "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "frame-pointer"="none" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #3 = { nounwind uwtable presplitcoroutine "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "frame-pointer"="none" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #4 = { noduplicate } +attributes #5 = { argmemonly nounwind readonly } +attributes #6 = { nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "frame-pointer"="none" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #7 = { nounwind } +attributes #8 = { alwaysinline nounwind } + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!3, !4} +!llvm.ident = !{!5} + +!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 4.0.0 - manually edited", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2) +!1 = !DIFile(filename: "coro.c", directory: "/home/gor/build/bin") +!2 = !{} +!3 = !{i32 2, !"Dwarf Version", i32 4} +!4 = !{i32 2, !"Debug Info Version", i32 3} +!5 = !{!"clang version 4.0.0 - manually edited"} +!9 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed) +!16 = distinct !DISubprogram(name: "f", scope: !1, file: !1, line: 8, type: !17, isLocal: false, isDefinition: true, scopeLine: 8, isOptimized: true, unit: !0, retainedNodes: !20) +!17 = !DISubroutineType(types: !18) +!18 = !{!19} +!19 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: null, size: 64, align: 64) +!20 = !{!21, !22, !24} +!21 = !DILocalVariable(name: "coro_hdl", scope: !16, file: !1, line: 9, type: !19) +!22 = !DILocalVariable(name: "i", scope: !23, file: !1, line: 11, type: !9) +!23 = distinct !DILexicalBlock(scope: !16, file: !1, line: 11, column: 3) +!24 = !DILocalVariable(name: "coro_mem", scope: !16, file: !1, line: 16, type: !19) +!26 = !DILocation(line: 9, column: 3, scope: !16) +!27 = !DILocation(line: 10, column: 8, scope: !23) +!33 = !DILocation(line: 11, column: 6, scope: !23) +!34 = !DILocation(line: 12, column: 6, scope: !23) +!35 = !DILocation(line: 13, column: 6, scope: !23) +!36 = !DILocation(line: 14, column: 6, scope: !23) +!37 = !DILocation(line: 16, column: 3, scope: !16) +!40 = !DILocation(line: 16, column: 3, scope: !16) +!41 = !DILocation(line: 17, column: 1, scope: !16) diff --git a/llvm/test/Transforms/Coroutines/coro-split-no-lieftime.ll b/llvm/test/Transforms/Coroutines/coro-split-no-lifetime.ll similarity index 100% rename from llvm/test/Transforms/Coroutines/coro-split-no-lieftime.ll rename to llvm/test/Transforms/Coroutines/coro-split-no-lifetime.ll >From a251525e1a0340b6b94b689d625c72318557c7f0 Mon Sep 17 00:00:00 2001 From: Adrian Vogelsgesang <avogelsges...@salesforce.com> Date: Fri, 27 Jun 2025 05:21:09 +0000 Subject: [PATCH 4/5] Formatting --- clang/lib/CodeGen/CGDebugInfo.cpp | 5 +++-- llvm/include/llvm/IR/DIBuilder.h | 3 ++- llvm/include/llvm/IR/DebugInfoMetadata.h | 14 +++++++------- llvm/lib/AsmParser/LLParser.cpp | 7 +++++-- llvm/lib/Bitcode/Reader/MetadataLoader.cpp | 7 ++++--- llvm/lib/Bitcode/Writer/BitcodeWriter.cpp | 3 ++- llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp | 3 ++- llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h | 3 ++- llvm/lib/IR/AsmWriter.cpp | 3 ++- llvm/lib/IR/DIBuilder.cpp | 10 ++++++---- llvm/lib/IR/DebugInfoMetadata.cpp | 10 ++++++---- llvm/lib/IR/LLVMContextImpl.h | 16 ++++++++++++---- llvm/lib/Transforms/Coroutines/CoroSplit.cpp | 13 +++++++------ llvm/lib/Transforms/Utils/CodeExtractor.cpp | 9 ++++----- llvm/unittests/IR/IRBuilderTest.cpp | 8 +++++--- 15 files changed, 69 insertions(+), 45 deletions(-) diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index 674ac22516271..3ff189297c546 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -5292,8 +5292,9 @@ void CGDebugInfo::EmitLabel(const LabelDecl *D, CGBuilderTy &Builder) { StringRef Name = D->getName(); // Create the descriptor for the label. - auto *L = - DBuilder.createLabel(Scope, Name, Unit, Line, Column, /*IsArtificial=*/false, /*CoroSuspendIdx=*/std::nullopt, CGM.getLangOpts().Optimize); + auto *L = DBuilder.createLabel( + Scope, Name, Unit, Line, Column, /*IsArtificial=*/false, + /*CoroSuspendIdx=*/std::nullopt, CGM.getLangOpts().Optimize); // Insert an llvm.dbg.label into the current block. DBuilder.insertLabel(L, diff --git a/llvm/include/llvm/IR/DIBuilder.h b/llvm/include/llvm/IR/DIBuilder.h index 66aa562ea8212..17a4e237342e1 100644 --- a/llvm/include/llvm/IR/DIBuilder.h +++ b/llvm/include/llvm/IR/DIBuilder.h @@ -901,7 +901,8 @@ namespace llvm { /// \c Scope must be a \a DILocalScope, and thus its scope chain eventually /// leads to a \a DISubprogram. LLVM_ABI DILabel *createLabel(DIScope *Scope, StringRef Name, DIFile *File, - unsigned LineNo, unsigned Column, bool IsArtificial, + unsigned LineNo, unsigned Column, + bool IsArtificial, std::optional<unsigned> CoroSuspendIdx, bool AlwaysPreserve = false); diff --git a/llvm/include/llvm/IR/DebugInfoMetadata.h b/llvm/include/llvm/IR/DebugInfoMetadata.h index 363fa0a7c083f..559a18033ad81 100644 --- a/llvm/include/llvm/IR/DebugInfoMetadata.h +++ b/llvm/include/llvm/IR/DebugInfoMetadata.h @@ -4115,18 +4115,18 @@ class DILabel : public DINode { static DILabel *getImpl(LLVMContext &Context, DIScope *Scope, StringRef Name, DIFile *File, unsigned Line, unsigned Column, - bool IsArtificial, std::optional<unsigned> CoroSuspendIdx, + bool IsArtificial, + std::optional<unsigned> CoroSuspendIdx, StorageType Storage, bool ShouldCreate = true) { return getImpl(Context, Scope, getCanonicalMDString(Context, Name), File, Line, Column, IsArtificial, CoroSuspendIdx, Storage, ShouldCreate); } - LLVM_ABI static DILabel *getImpl(LLVMContext &Context, Metadata *Scope, - MDString *Name, Metadata *File, - unsigned Line, unsigned Column, - bool IsArtificial, std::optional<unsigned> CoroSuspendIdx, - StorageType Storage, - bool ShouldCreate = true); + LLVM_ABI static DILabel * + getImpl(LLVMContext &Context, Metadata *Scope, MDString *Name, Metadata *File, + unsigned Line, unsigned Column, bool IsArtificial, + std::optional<unsigned> CoroSuspendIdx, StorageType Storage, + bool ShouldCreate = true); TempDILabel cloneImpl() const { return getTemporary(getContext(), getScope(), getName(), getFile(), diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp index e69eb7d51d86b..168ad5a575064 100644 --- a/llvm/lib/AsmParser/LLParser.cpp +++ b/llvm/lib/AsmParser/LLParser.cpp @@ -6129,10 +6129,13 @@ bool LLParser::parseDILabel(MDNode *&Result, bool IsDistinct) { PARSE_MD_FIELDS(); #undef VISIT_MD_FIELDS - std::optional<unsigned> CoroSuspendIdx = coroSuspendIdx.Seen ? std::optional<unsigned>(coroSuspendIdx.Val) : std::nullopt; + std::optional<unsigned> CoroSuspendIdx = + coroSuspendIdx.Seen ? std::optional<unsigned>(coroSuspendIdx.Val) + : std::nullopt; Result = GET_OR_DISTINCT(DILabel, - (Context, scope.Val, name.Val, file.Val, line.Val, column.Val, isArtificial.Val, CoroSuspendIdx)); + (Context, scope.Val, name.Val, file.Val, line.Val, + column.Val, isArtificial.Val, CoroSuspendIdx)); return false; } diff --git a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp index 694d446fb2f04..eed35d8d38440 100644 --- a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp +++ b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp @@ -2260,9 +2260,10 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata( } MetadataList.assignValue( - GET_OR_DISTINCT(DILabel, (Context, getMDOrNull(Record[1]), - getMDString(Record[2]), - getMDOrNull(Record[3]), Line, Column, IsArtificial, CoroSuspendIdx)), + GET_OR_DISTINCT(DILabel, + (Context, getMDOrNull(Record[1]), + getMDString(Record[2]), getMDOrNull(Record[3]), Line, + Column, IsArtificial, CoroSuspendIdx)), NextMetadataNo); NextMetadataNo++; break; diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp index ceaf804087d82..0e962056b8dbd 100644 --- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -2351,7 +2351,8 @@ void ModuleBitcodeWriter::writeDILabel( Record.push_back(VE.getMetadataOrNullID(N->getFile())); Record.push_back(N->getLine()); Record.push_back(N->getColumn()); - Record.push_back(N->getCoroSuspendIdx().value_or(std::numeric_limits<uint64_t>::max())); + Record.push_back( + N->getCoroSuspendIdx().value_or(std::numeric_limits<uint64_t>::max())); Stream.EmitRecord(bitc::METADATA_LABEL, Record, Abbrev); Record.clear(); diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp index 3d4fed7a8d68d..b03fac2d22a52 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp @@ -442,7 +442,8 @@ void DwarfUnit::addBlock(DIE &Die, dwarf::Attribute Attribute, addBlock(Die, Attribute, Block->BestForm(), Block); } -void DwarfUnit::addSourceLine(DIE &Die, unsigned Line, unsigned Column, const DIFile *File) { +void DwarfUnit::addSourceLine(DIE &Die, unsigned Line, unsigned Column, + const DIFile *File) { if (Line == 0) return; diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h index c01fb6c6c29d9..fe05766cf36e1 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h @@ -216,7 +216,8 @@ class DwarfUnit : public DIEUnit { DIEBlock *Block); /// Add location information to specified debug information entry. - void addSourceLine(DIE &Die, unsigned Line, unsigned Column, const DIFile *File); + void addSourceLine(DIE &Die, unsigned Line, unsigned Column, + const DIFile *File); void addSourceLine(DIE &Die, const DILocalVariable *V); void addSourceLine(DIE &Die, const DIGlobalVariable *G); void addSourceLine(DIE &Die, const DISubprogram *SP); diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp index d6a67a68c66d3..306c684431b5c 100644 --- a/llvm/lib/IR/AsmWriter.cpp +++ b/llvm/lib/IR/AsmWriter.cpp @@ -2614,7 +2614,8 @@ static void writeDILabel(raw_ostream &Out, const DILabel *N, Printer.printInt("column", N->getColumn()); Printer.printBool("isArtificial", N->isArtificial(), false); if (N->getCoroSuspendIdx()) - Printer.printInt("coroSuspendIdx", *N->getCoroSuspendIdx(), /* ShouldSkipZero */ false); + Printer.printInt("coroSuspendIdx", *N->getCoroSuspendIdx(), + /* ShouldSkipZero */ false); Out << ")"; } diff --git a/llvm/lib/IR/DIBuilder.cpp b/llvm/lib/IR/DIBuilder.cpp index 0ba2b050035b8..c871edaaec973 100644 --- a/llvm/lib/IR/DIBuilder.cpp +++ b/llvm/lib/IR/DIBuilder.cpp @@ -946,11 +946,13 @@ DILocalVariable *DIBuilder::createParameterVariable( } DILabel *DIBuilder::createLabel(DIScope *Context, StringRef Name, DIFile *File, - unsigned LineNo, unsigned Column, bool IsArtificial, - std::optional<unsigned> CoroSuspendIdx, - bool AlwaysPreserve) { + unsigned LineNo, unsigned Column, + bool IsArtificial, + std::optional<unsigned> CoroSuspendIdx, + bool AlwaysPreserve) { auto *Scope = cast<DILocalScope>(Context); - auto *Node = DILabel::get(VMContext, Scope, Name, File, LineNo, Column, IsArtificial, CoroSuspendIdx); + auto *Node = DILabel::get(VMContext, Scope, Name, File, LineNo, Column, + IsArtificial, CoroSuspendIdx); if (AlwaysPreserve) { /// The optimizer may remove labels. If there is an interest diff --git a/llvm/lib/IR/DebugInfoMetadata.cpp b/llvm/lib/IR/DebugInfoMetadata.cpp index c975b99877635..0c8f1d78e4933 100644 --- a/llvm/lib/IR/DebugInfoMetadata.cpp +++ b/llvm/lib/IR/DebugInfoMetadata.cpp @@ -1616,7 +1616,8 @@ std::optional<uint64_t> DIVariable::getSizeInBits() const { } DILabel::DILabel(LLVMContext &C, StorageType Storage, unsigned Line, - unsigned Column, bool IsArtificial, std::optional<unsigned> CoroSuspendIdx, + unsigned Column, bool IsArtificial, + std::optional<unsigned> CoroSuspendIdx, ArrayRef<Metadata *> Ops) : DINode(C, DILabelKind, Storage, dwarf::DW_TAG_label, Ops) { this->SubclassData32 = Line; @@ -1626,12 +1627,13 @@ DILabel::DILabel(LLVMContext &C, StorageType Storage, unsigned Line, } DILabel *DILabel::getImpl(LLVMContext &Context, Metadata *Scope, MDString *Name, Metadata *File, unsigned Line, unsigned Column, - bool IsArtificial, std::optional<unsigned> CoroSuspendIdx, + bool IsArtificial, + std::optional<unsigned> CoroSuspendIdx, StorageType Storage, bool ShouldCreate) { assert(Scope && "Expected scope"); assert(isCanonical(Name) && "Expected canonical MDString"); - DEFINE_GETIMPL_LOOKUP(DILabel, (Scope, Name, File, Line, Column, IsArtificial, - CoroSuspendIdx)); + DEFINE_GETIMPL_LOOKUP( + DILabel, (Scope, Name, File, Line, Column, IsArtificial, CoroSuspendIdx)); Metadata *Ops[] = {Scope, Name, File}; DEFINE_GETIMPL_STORE(DILabel, (Line, Column, IsArtificial, CoroSuspendIdx), Ops); diff --git a/llvm/lib/IR/LLVMContextImpl.h b/llvm/lib/IR/LLVMContextImpl.h index 170e2f3143a8b..ae7c926502fe6 100644 --- a/llvm/lib/IR/LLVMContextImpl.h +++ b/llvm/lib/IR/LLVMContextImpl.h @@ -1333,11 +1333,16 @@ template <> struct MDNodeKeyImpl<DILabel> { bool IsArtificial; std::optional<unsigned> CoroSuspendIdx; - MDNodeKeyImpl(Metadata *Scope, MDString *Name, Metadata *File, unsigned Line, unsigned Column, bool IsArtificial, std::optional<unsigned> CoroSuspendIdx) - : Scope(Scope), Name(Name), File(File), Line(Line), Column(Column), IsArtificial(IsArtificial), CoroSuspendIdx(CoroSuspendIdx) {} + MDNodeKeyImpl(Metadata *Scope, MDString *Name, Metadata *File, unsigned Line, + unsigned Column, bool IsArtificial, + std::optional<unsigned> CoroSuspendIdx) + : Scope(Scope), Name(Name), File(File), Line(Line), Column(Column), + IsArtificial(IsArtificial), CoroSuspendIdx(CoroSuspendIdx) {} MDNodeKeyImpl(const DILabel *N) : Scope(N->getRawScope()), Name(N->getRawName()), File(N->getRawFile()), - Line(N->getLine()), Column(N->getColumn()), IsArtificial(N->isArtificial()), CoroSuspendIdx(N->getCoroSuspendIdx()) {} + Line(N->getLine()), Column(N->getColumn()), + IsArtificial(N->isArtificial()), + CoroSuspendIdx(N->getCoroSuspendIdx()) {} bool isKeyOf(const DILabel *RHS) const { return Scope == RHS->getRawScope() && Name == RHS->getRawName() && @@ -1347,7 +1352,10 @@ template <> struct MDNodeKeyImpl<DILabel> { } /// Using name and line to get hash value. It should already be mostly unique. - unsigned getHashValue() const { return hash_combine(Scope, Name, Line, Column, IsArtificial, CoroSuspendIdx); } + unsigned getHashValue() const { + return hash_combine(Scope, Name, Line, Column, IsArtificial, + CoroSuspendIdx); + } }; template <> struct MDNodeKeyImpl<DIExpression> { diff --git a/llvm/lib/Transforms/Coroutines/CoroSplit.cpp b/llvm/lib/Transforms/Coroutines/CoroSplit.cpp index 1a9833b306a0e..1f0aa106cec63 100644 --- a/llvm/lib/Transforms/Coroutines/CoroSplit.cpp +++ b/llvm/lib/Transforms/Coroutines/CoroSplit.cpp @@ -1579,12 +1579,13 @@ struct SwitchCoroutineSplitter { if (DebugLoc SuspendLoc = S->getDebugLoc()) { std::string LabelName = ("__coro_resume_" + Twine(SuspendIndex)).str(); - DILocation& DILoc = *SuspendLoc.get(); - DILabel *ResumeLabel = DBuilder.createLabel( - DIS, LabelName, DILoc.getFile(), SuspendLoc.getLine(), SuspendLoc.getCol(), - /*IsArtificial=*/true, - /*CoroSuspendIdx=*/SuspendIndex, - /*AlwaysPreserve=*/false); + DILocation &DILoc = *SuspendLoc.get(); + DILabel *ResumeLabel = + DBuilder.createLabel(DIS, LabelName, DILoc.getFile(), + SuspendLoc.getLine(), SuspendLoc.getCol(), + /*IsArtificial=*/true, + /*CoroSuspendIdx=*/SuspendIndex, + /*AlwaysPreserve=*/false); DBuilder.insertLabel(ResumeLabel, &DILoc, ResumeBB->begin()); } } diff --git a/llvm/lib/Transforms/Utils/CodeExtractor.cpp b/llvm/lib/Transforms/Utils/CodeExtractor.cpp index 52a3e7acb5bbd..25d3db9431bda 100644 --- a/llvm/lib/Transforms/Utils/CodeExtractor.cpp +++ b/llvm/lib/Transforms/Utils/CodeExtractor.cpp @@ -1347,11 +1347,10 @@ static void fixupDebugInfoPostExtraction(Function &OldFunc, Function &NewFunc, if (!NewLabel) { DILocalScope *NewScope = DILocalScope::cloneScopeForSubprogram( *OldLabel->getScope(), *NewSP, Ctx, Cache); - NewLabel = DILabel::get(Ctx, NewScope, OldLabel->getName(), - OldLabel->getFile(), OldLabel->getLine(), - OldLabel->getColumn(), - OldLabel->isArtificial(), - OldLabel->getCoroSuspendIdx()); + NewLabel = + DILabel::get(Ctx, NewScope, OldLabel->getName(), OldLabel->getFile(), + OldLabel->getLine(), OldLabel->getColumn(), + OldLabel->isArtificial(), OldLabel->getCoroSuspendIdx()); } LabelRecord->setLabel(cast<DILabel>(NewLabel)); }; diff --git a/llvm/unittests/IR/IRBuilderTest.cpp b/llvm/unittests/IR/IRBuilderTest.cpp index 6f38c6d72dab4..4f2ede3321080 100644 --- a/llvm/unittests/IR/IRBuilderTest.cpp +++ b/llvm/unittests/IR/IRBuilderTest.cpp @@ -920,9 +920,11 @@ TEST_F(IRBuilderTest, DIBuilder) { // -------------------------- DILocation *LabelLoc = DILocation::get(Ctx, 1, 0, BarScope); DILabel *AlwaysPreserveLabel = DIB.createLabel( - BarScope, "meles_meles", File, 1, /*Column*/ 0, /*IsArtificial*/ false, /*CoroSuspendIdx*/ std::nullopt, /*AlwaysPreserve*/ true); - DILabel *Label = - DIB.createLabel(BarScope, "badger", File, 1, /*Column*/ 0, /*IsArtificial*/ false, /*CoroSuspendIdx*/ std::nullopt, /*AlwaysPreserve*/ false); + BarScope, "meles_meles", File, 1, /*Column*/ 0, /*IsArtificial*/ false, + /*CoroSuspendIdx*/ std::nullopt, /*AlwaysPreserve*/ true); + DILabel *Label = DIB.createLabel( + BarScope, "badger", File, 1, /*Column*/ 0, /*IsArtificial*/ false, + /*CoroSuspendIdx*/ std::nullopt, /*AlwaysPreserve*/ false); { /* dbg.label | DbgLabelRecord */ // Insert before I and check order. >From 7d34cac0b26d04b970daa09fd20d30350fc80184 Mon Sep 17 00:00:00 2001 From: Adrian Vogelsgesang <avogelsges...@salesforce.com> Date: Fri, 27 Jun 2025 06:13:01 +0000 Subject: [PATCH 5/5] Fix MLIR build --- mlir/lib/Target/LLVMIR/DebugTranslation.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mlir/lib/Target/LLVMIR/DebugTranslation.cpp b/mlir/lib/Target/LLVMIR/DebugTranslation.cpp index 2af3ae0bd7f4f..e8304ae4dc168 100644 --- a/mlir/lib/Target/LLVMIR/DebugTranslation.cpp +++ b/mlir/lib/Target/LLVMIR/DebugTranslation.cpp @@ -221,7 +221,9 @@ llvm::DIFile *DebugTranslation::translateImpl(DIFileAttr attr) { llvm::DILabel *DebugTranslation::translateImpl(DILabelAttr attr) { return llvm::DILabel::get(llvmCtx, translate(attr.getScope()), getMDStringOrNull(attr.getName()), - translate(attr.getFile()), attr.getLine()); + translate(attr.getFile()), attr.getLine(), + /*Column=*/0, /*IsArtificial=*/true, + /*CoroSuspendIdx=*/std::nullopt); } llvm::DILexicalBlock *DebugTranslation::translateImpl(DILexicalBlockAttr attr) { _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits