diff --git a/llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h b/llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h --- a/llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h @@ -41,6 +41,7 @@ class Constant; class ConstrainedFPIntrinsic; class DataLayout; +class DbgDeclareInst; class Instruction; class MachineBasicBlock; class MachineFunction; @@ -244,6 +245,14 @@ bool translateKnownIntrinsic(const CallInst &CI, Intrinsic::ID ID, MachineIRBuilder &MIRBuilder); + /// Returns the single livein physical register Arg was lowered to, if + /// possible. + std::optional getArgPhysReg(Argument &Arg); + + /// If DebugInst targets an Argument and its expression is an EntryValue, + /// lower it as an entry in the MF debug table. + bool translateIfEntryValueArgument(const DbgDeclareInst &DebugInst); + bool translateInlineAsm(const CallBase &CB, MachineIRBuilder &MIRBuilder); /// Common code for translating normal calls or invokes. diff --git a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp --- a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp +++ b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp @@ -1879,6 +1879,37 @@ return true; } +std::optional IRTranslator::getArgPhysReg(Argument &Arg) { + auto VRegs = getOrCreateVRegs(Arg); + if (VRegs.size() != 1) + return std::nullopt; + + // Arguments are lowered as a copy of a livein physical register. + auto *VRegDef = MF->getRegInfo().getVRegDef(VRegs[0]); + if (!VRegDef || !VRegDef->isCopy()) + return std::nullopt; + return VRegDef->getOperand(1).getReg().asMCReg(); +} + +bool IRTranslator::translateIfEntryValueArgument( + const DbgDeclareInst &DebugInst) { + auto *Arg = dyn_cast(DebugInst.getAddress()); + if (!Arg) + return false; + + const DIExpression *Expr = DebugInst.getExpression(); + if (!Expr->isEntryValue()) + return false; + + std::optional PhysReg = getArgPhysReg(*Arg); + if (!PhysReg) + return false; + + MF->setVariableDbgInfo(DebugInst.getVariable(), Expr, *PhysReg, + DebugInst.getDebugLoc()); + return true; +} + bool IRTranslator::translateKnownIntrinsic(const CallInst &CI, Intrinsic::ID ID, MachineIRBuilder &MIRBuilder) { if (auto *MI = dyn_cast(&CI)) { @@ -1945,12 +1976,16 @@ // instructions (in fact, they get ignored if they *do* exist). MF->setVariableDbgInfo(DI.getVariable(), DI.getExpression(), getOrCreateFrameIndex(*AI), DI.getDebugLoc()); - } else { - // A dbg.declare describes the address of a source variable, so lower it - // into an indirect DBG_VALUE. - MIRBuilder.buildIndirectDbgValue(getOrCreateVReg(*Address), - DI.getVariable(), DI.getExpression()); + return true; } + + if (translateIfEntryValueArgument(DI)) + return true; + + // A dbg.declare describes the address of a source variable, so lower it + // into an indirect DBG_VALUE. + MIRBuilder.buildIndirectDbgValue(getOrCreateVReg(*Address), + DI.getVariable(), DI.getExpression()); return true; } case Intrinsic::dbg_label: { diff --git a/llvm/test/CodeGen/AArch64/dbg-declare-swift-async.ll b/llvm/test/CodeGen/AArch64/dbg-declare-swift-async.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/dbg-declare-swift-async.ll @@ -0,0 +1,40 @@ +; RUN: llc -O0 -global-isel -stop-after=irtranslator -verify-machineinstrs %s -o - | FileCheck %s + +; CHECK: void @foo +; CHECK-NEXT: dbg.declare(metadata {{.*}}, metadata ![[VAR:.*]], metadata ![[EXPR:.*]]), !dbg ![[LOC:.*]] +; CHECK: entry_values: +; CHECK-NEXT: entry-value-register: '$x22', debug-info-variable: '![[VAR]]', debug-info-expression: '![[EXPR]]', +; CHECK-NEXT: debug-info-location: '![[LOC]] +; CHECK-NEXT: entry-value-register: '$x22', debug-info-variable: '![[VAR]]', debug-info-expression: '![[EXPR]]' +; CHECK-NEXT: debug-info-location: '![[LOC]] + +; CHECK-NOT: DBG_VALUE + +target triple="aarch64--" + +define void @foo(ptr %unused_arg, ptr swiftasync %async_arg) !dbg !6 { + call void @llvm.dbg.declare(metadata ptr %async_arg, metadata !12, metadata !DIExpression(DW_OP_LLVM_entry_value, 1)), !dbg !14 + call void @llvm.dbg.declare(metadata ptr %async_arg, metadata !12, metadata !DIExpression(DW_OP_LLVM_entry_value, 1)), !dbg !14 + call void @consume(ptr %async_arg) + ret void, !dbg !15 +} + +declare void @llvm.dbg.declare(metadata, metadata, metadata) +declare void @consume(ptr %ptr) + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!3, !4} + +!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug) +!1 = !DIFile(filename: "x.c", directory: "/") +!3 = !{i32 2, !"Dwarf Version", i32 4} +!4 = !{i32 2, !"Debug Info Version", i32 3} +!6 = distinct !DISubprogram(name: "f", scope: !1, file: !1, line: 1, type: !7, isLocal: false, isDefinition: true, scopeLine: 1, unit: !0) +!7 = !DISubroutineType(types: !8) +!8 = !{null, !9, !9, !9} +!9 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !10, size: 64) +!10 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !11) +!11 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char) +!12 = !DILocalVariable(name: "a", scope: !6, file: !1, line: 1, type: !9) +!14 = !DILocation(line: 1, column: 29, scope: !6) +!15 = !DILocation(line: 1, column: 37, scope: !6)