diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def index e26ea56e02acfb..9340f668ecf3af 100644 --- a/clang/include/clang/Basic/CodeGenOptions.def +++ b/clang/include/clang/Basic/CodeGenOptions.def @@ -30,8 +30,6 @@ CODEGENOPT(Name, Bits, Default) CODEGENOPT(DisableIntegratedAS, 1, 0) ///< -no-integrated-as CODEGENOPT(RelaxELFRelocations, 1, 1) ///< -Wa,-mrelax-relocations={yes,no} CODEGENOPT(AsmVerbose , 1, 0) ///< -dA, -fverbose-asm. -CODEGENOPT(HeterogeneousDwarf, 1, 0) ///< Enable DWARF extensions for - ///< heterogeneous debugging. CODEGENOPT(PreserveAsmComments, 1, 1) ///< -dA, -fno-preserve-as-comments. CODEGENOPT(AssumeSaneOperatorNew , 1, 1) ///< implicit __attribute__((malloc)) operator new CODEGENOPT(AssumeUniqueVTables , 1, 1) ///< Assume a class has only one vtable. diff --git a/clang/include/clang/Basic/CodeGenOptions.h b/clang/include/clang/Basic/CodeGenOptions.h index 6952b48e898a81..3de22ac3b4d087 100644 --- a/clang/include/clang/Basic/CodeGenOptions.h +++ b/clang/include/clang/Basic/CodeGenOptions.h @@ -158,6 +158,21 @@ class CodeGenOptions : public CodeGenOptionsBase { Never, // No loop is assumed to be finite. }; + enum class HeterogeneousDwarfOpts { + Disabled, //< Do not emit any heterogeneous dwarf metadata. + DIExpr, //< Enable DIExpr-based metadata. + DIExpression, //< Enable DIExpression-based metadata. + }; + bool isHeterogeneousDwarfEnabled() const { + return getHeterogeneousDwarfMode() != HeterogeneousDwarfOpts::Disabled; + } + bool isHeterogeneousDwarfDIExpr() const { + return getHeterogeneousDwarfMode() == HeterogeneousDwarfOpts::DIExpr; + } + bool isHeterogeneousDwarfDIExpression() const { + return getHeterogeneousDwarfMode() == HeterogeneousDwarfOpts::DIExpression; + } + enum AssignmentTrackingOpts { Disabled, Enabled, diff --git a/clang/include/clang/Basic/DebugOptions.def b/clang/include/clang/Basic/DebugOptions.def index 7cd3edf08a17ea..98b6a74c2e0551 100644 --- a/clang/include/clang/Basic/DebugOptions.def +++ b/clang/include/clang/Basic/DebugOptions.def @@ -69,6 +69,10 @@ BENIGN_DEBUGOPT(NoInlineLineTables, 1, 0) ///< Whether debug info should contain DEBUGOPT(DebugStrictDwarf, 1, 1) ///< Whether or not to use strict DWARF info. +/// Control DWARF extensions for heterogeneous debugging enablement and approach. +BENIGN_ENUM_DEBUGOPT(HeterogeneousDwarfMode, HeterogeneousDwarfOpts, 2, + HeterogeneousDwarfOpts::Disabled) + /// Control the Assignment Tracking debug info feature. BENIGN_ENUM_DEBUGOPT(AssignmentTrackingMode, AssignmentTrackingOpts, 2, AssignmentTrackingOpts::Disabled) diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index a84caee29ef9cf..12c14cf57fc6e7 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -4211,12 +4211,23 @@ def gdwarf64 : Flag<["-"], "gdwarf64">, Group, def gdwarf32 : Flag<["-"], "gdwarf32">, Group, Visibility<[ClangOption, CC1Option, CC1AsOption]>, HelpText<"Enables DWARF32 format for ELF binaries, if debug information emission is enabled.">; -def gheterogeneous_dwarf : Flag<["-"], "gheterogeneous-dwarf">, + +def gheterogeneous_dwarf_EQ : Joined<["-"], "gheterogeneous-dwarf=">, Group, Visibility<[ClangOption, CC1Option]>, - HelpText<"Enable DWARF extensions for heterogeneous debugging">, - MarshallingInfoFlag>; + HelpText<"Control DWARF extensions for heterogeneous debugging">, + Values<"disabled,diexpr,diexpression">, + NormalizedValuesScope<"CodeGenOptions::HeterogeneousDwarfOpts">, + NormalizedValues<["Disabled","DIExpr","DIExpression"]>, + MarshallingInfoEnum, "Disabled">; +def gheterogeneous_dwarf : Flag<["-"], "gheterogeneous-dwarf">, Group, + Visibility<[ClangOption, CC1Option]>, + HelpText<"Enable DIExpr-based DWARF extensions for heterogeneous debugging">, + Alias, AliasArgs<["diexpr"]>; def gno_heterogeneous_dwarf : Flag<["-"], "gno-heterogeneous-dwarf">, - Group, HelpText<"Disable DWARF extensions for heterogeneous debugging">; + Visibility<[ClangOption, CC1Option]>, + Group, + HelpText<"Disable DWARF extensions for heterogeneous debugging">, + Alias, AliasArgs<["disabled"]>; def gcodeview : Flag<["-"], "gcodeview">, HelpText<"Generate CodeView debug information">, diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index ea15be272a40a8..f360aebc9a7f29 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -4642,7 +4642,7 @@ llvm::DILocalVariable *CGDebugInfo::EmitDeclare(const VarDecl *VD, std::optional ArgNo, CGBuilderTy &Builder, const bool UsePointerValue) { - if (CGM.getCodeGenOpts().HeterogeneousDwarf) + if (CGM.getCodeGenOpts().isHeterogeneousDwarfEnabled()) return EmitDef(VD, Storage, ArgNo, Builder, UsePointerValue); assert(CGM.getCodeGenOpts().hasReducedDebugInfo()); @@ -4848,7 +4848,10 @@ llvm::DILocalVariable *CGDebugInfo::EmitDef(const BindingDecl *BD, CGM.getTypes().ConvertTypeForMem(BD->getDecomposedDecl()->getType()); llvm::DIExprBuilder ExprBuilder(CGM.getLLVMContext()); - ExprBuilder.append(Storage->getType()); + if (CGM.getCodeGenOpts().isHeterogeneousDwarfDIExpr()) + ExprBuilder.append(Storage->getType()); + else + ExprBuilder.append(0u, Storage->getType()); ExprBuilder.append(DecomposedTy); if (UsePointerValue) { @@ -4898,11 +4901,17 @@ llvm::DILocalVariable *CGDebugInfo::EmitDef(const BindingDecl *BD, } } - DBuilder.insertDef(DBuilder.createBoundedLifetime(D, ExprBuilder.intoExpr()), - Storage, - llvm::DILocation::get(CGM.getLLVMContext(), Line, Column, - Scope, CurInlinedAt), - Builder.GetInsertBlock()); + if (CGM.getCodeGenOpts().isHeterogeneousDwarfDIExpr()) + DBuilder.insertDef( + DBuilder.createBoundedLifetime(D, ExprBuilder.intoExpr()), Storage, + llvm::DILocation::get(CGM.getLLVMContext(), Line, Column, Scope, + CurInlinedAt), + Builder.GetInsertBlock()); + else + DBuilder.insertDeclare(Storage, D, ExprBuilder.intoExpression(), + llvm::DILocation::get(CGM.getLLVMContext(), Line, + Column, Scope, CurInlinedAt), + Builder.GetInsertBlock()); return D; } @@ -4913,12 +4922,16 @@ llvm::DILocalVariable *CGDebugInfo::EmitDef(const VarDecl *VD, const bool UsePointerValue) { assert(CGM.getCodeGenOpts().hasReducedDebugInfo() && "Call to EmitDef below ReducedDebugInfo"); - assert(CGM.getCodeGenOpts().HeterogeneousDwarf && + assert(CGM.getCodeGenOpts().isHeterogeneousDwarfEnabled() && "Call to EmitDef without HeterogeneousDwarf enabled"); assert(!LexicalBlockStack.empty() && "Region stack mismatch, stack empty!"); if (VD->hasAttr()) return nullptr; + // Debug intrinsics expect to take an alloca directly, not an addrspace cast + // thereof. + Storage = Storage->stripPointerCasts(); + bool Unwritten = VD->isImplicit() || (isa(VD->getDeclContext()) && cast(VD->getDeclContext())->isImplicit()); @@ -4962,10 +4975,16 @@ llvm::DILocalVariable *CGDebugInfo::EmitDef(const VarDecl *VD, CGM.getLLVMContext()); llvm::DIExprBuilder ExprBuilder(CGM.getLLVMContext()); - ExprBuilder.append(Storage->getType()); + if (CGM.getCodeGenOpts().isHeterogeneousDwarfDIExpr()) + ExprBuilder.append(Storage->getType()); + else + ExprBuilder.append(0u, Storage->getType()); llvm::Type *ReferrerPointeeTy = (!Name.empty() && VD->isEscapingByref()) ? BlockPtrTy : VDMemTy; - ExprBuilder.append(ReferrerPointeeTy); + if (UsePointerValue) + ExprBuilder.append(Storage->getType()); + else + ExprBuilder.append(ReferrerPointeeTy); // If this is implicit parameter of CXXThis or ObjCSelf kind, then give it an // object pointer flag. @@ -5002,7 +5021,13 @@ llvm::DILocalVariable *CGDebugInfo::EmitDef(const VarDecl *VD, const RecordDecl *RD = RT->getDecl(); if (RD->isUnion() && RD->isAnonymousStructOrUnion()) { llvm::DIExprBuilder UnionExprBuilder{ExprBuilder}; - llvm::DIExpr *UnionExpr = UnionExprBuilder.intoExpr(); + llvm::DIExpr *UnionDIExpr = nullptr; + llvm::DIExpression *UnionDIExpression = nullptr; + if (CGM.getCodeGenOpts().isHeterogeneousDwarfDIExpr()) + UnionDIExpr = UnionExprBuilder.intoExpr(); + else + UnionDIExpression = UnionExprBuilder.intoExpression(); + // GDB has trouble finding local variables in anonymous unions, so we emit // artificial local variables for each of the members. // @@ -5024,12 +5049,19 @@ llvm::DILocalVariable *CGDebugInfo::EmitDef(const VarDecl *VD, Scope, FieldName, Unit, Line, FieldTy, /*AlwaysPreserve=*/true, Flags | llvm::DINode::FlagArtificial, MS, FieldAlign); - // Insert an llvm.dbg.def into the current block. - DBuilder.insertDef(DBuilder.createBoundedLifetime(D, UnionExpr), - Storage, - llvm::DILocation::get(CGM.getLLVMContext(), Line, - Column, Scope, CurInlinedAt), - Builder.GetInsertBlock()); + // Insert an intrinsic into the current block. + if (CGM.getCodeGenOpts().isHeterogeneousDwarfDIExpr()) + DBuilder.insertDef(DBuilder.createBoundedLifetime(D, UnionDIExpr), + Storage, + llvm::DILocation::get(CGM.getLLVMContext(), Line, + Column, Scope, CurInlinedAt), + Builder.GetInsertBlock()); + else + DBuilder.insertDeclare(Storage, D, UnionDIExpression, + llvm::DILocation::get(CGM.getLLVMContext(), + Line, Column, Scope, + CurInlinedAt), + Builder.GetInsertBlock()); } } } @@ -5088,12 +5120,18 @@ llvm::DILocalVariable *CGDebugInfo::EmitDef(const VarDecl *VD, /*AlwaysPreserve=*/true, Flags, MS, Align); } - // Insert an llvm.dbg.def into the current block. - DBuilder.insertDef(DBuilder.createBoundedLifetime(D, ExprBuilder.intoExpr()), - Storage, - llvm::DILocation::get(CGM.getLLVMContext(), Line, Column, - Scope, CurInlinedAt), - Builder.GetInsertBlock()); + // Insert an intrinsic into the current block. + if (CGM.getCodeGenOpts().isHeterogeneousDwarfDIExpr()) + DBuilder.insertDef( + DBuilder.createBoundedLifetime(D, ExprBuilder.intoExpr()), Storage, + llvm::DILocation::get(CGM.getLLVMContext(), Line, Column, Scope, + CurInlinedAt), + Builder.GetInsertBlock()); + else + DBuilder.insertDeclare(Storage, D, ExprBuilder.intoExpression(), + llvm::DILocation::get(CGM.getLLVMContext(), Line, + Column, Scope, CurInlinedAt), + Builder.GetInsertBlock()); llvm::Function *Parent = Builder.GetInsertBlock()->getParent(); assert(Parent->getSubprogram() && "expected DISubprogram"); @@ -5141,7 +5179,7 @@ llvm::DILocalVariable *CGDebugInfo::EmitDeclare(const BindingDecl *BD, CGBuilderTy &Builder, const bool UsePointerValue) { - if (CGM.getCodeGenOpts().HeterogeneousDwarf) + if (CGM.getCodeGenOpts().isHeterogeneousDwarfEnabled()) return EmitDef(BD, Storage, ArgNo, Builder, UsePointerValue); assert(CGM.getCodeGenOpts().hasReducedDebugInfo()); @@ -5585,11 +5623,11 @@ llvm::DIGlobalVariableExpression *CGDebugInfo::CollectAnonRecordDecls( } llvm::DIGlobalVariable * -CGDebugInfo::CollectAnonRecordDeclsForHeterogeneousDwarf( +CGDebugInfo::CollectAnonRecordDeclsForHeterogeneousDwarfDIExpr( const RecordDecl *RD, llvm::DIFile *Unit, unsigned LineNo, StringRef LinkageName, llvm::dwarf::MemorySpace MS, llvm::GlobalVariable *Var, llvm::DIScope *DContext) { - assert(CGM.getCodeGenOpts().HeterogeneousDwarf); + assert(CGM.getCodeGenOpts().isHeterogeneousDwarfDIExpr()); llvm::DIGlobalVariable *GV = nullptr; @@ -5600,7 +5638,7 @@ CGDebugInfo::CollectAnonRecordDeclsForHeterogeneousDwarf( // Ignore unnamed fields, but recurse into anonymous records. if (FieldName.empty()) { if (const auto *RT = dyn_cast(Field->getType())) - GV = CollectAnonRecordDeclsForHeterogeneousDwarf( + GV = CollectAnonRecordDeclsForHeterogeneousDwarfDIExpr( RT->getDecl(), Unit, LineNo, LinkageName, MS, Var, DContext); continue; } @@ -5613,6 +5651,35 @@ CGDebugInfo::CollectAnonRecordDeclsForHeterogeneousDwarf( return GV; } +llvm::DIGlobalVariableExpression * +CGDebugInfo::CollectAnonRecordDeclsForHeterogeneousDwarfDIExpression( + const RecordDecl *RD, llvm::DIFile *Unit, unsigned LineNo, + StringRef LinkageName, llvm::dwarf::MemorySpace MS, + llvm::GlobalVariable *Var, llvm::DIScope *DContext) { + assert(CGM.getCodeGenOpts().isHeterogeneousDwarfDIExpression()); + + llvm::DIGlobalVariableExpression *GVE = nullptr; + + for (const auto *Field : RD->fields()) { + llvm::DIType *FieldTy = getOrCreateType(Field->getType(), Unit); + StringRef FieldName = Field->getName(); + + // Ignore unnamed fields, but recurse into anonymous records. + if (FieldName.empty()) { + if (const auto *RT = dyn_cast(Field->getType())) + GVE = CollectAnonRecordDeclsForHeterogeneousDwarfDIExpression( + RT->getDecl(), Unit, LineNo, LinkageName, MS, Var, DContext); + continue; + } + // Use VarDecl's Tag, Scope and Line number. + GVE = DBuilder.createGlobalVariableExpression( + DContext, FieldName, LinkageName, Unit, LineNo, FieldTy, + Var->hasLocalLinkage(), true, nullptr, nullptr, nullptr, MS); + Var->addDebugInfo(GVE); + } + return GVE; +} + static bool ReferencesAnonymousEntity(ArrayRef Args); static bool ReferencesAnonymousEntity(RecordType *RT) { // Unnamed classes/lambdas can't be reconstituted due to a lack of column @@ -5842,7 +5909,7 @@ std::string CGDebugInfo::GetName(const Decl *D, bool Qualified) const { void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var, const VarDecl *D) { - if (CGM.getCodeGenOpts().HeterogeneousDwarf) + if (CGM.getCodeGenOpts().isHeterogeneousDwarfEnabled()) return EmitGlobalVariableForHeterogeneousDwarf(Var, D); assert(CGM.getCodeGenOpts().hasReducedDebugInfo()); @@ -5914,7 +5981,7 @@ void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var, void CGDebugInfo::EmitGlobalVariableForHeterogeneousDwarf( llvm::GlobalVariable *Var, const VarDecl *D) { assert(CGM.getCodeGenOpts().hasReducedDebugInfo()); - assert(CGM.getCodeGenOpts().HeterogeneousDwarf); + assert(CGM.getCodeGenOpts().isHeterogeneousDwarfEnabled()); if (D->hasAttr()) return; @@ -5950,6 +6017,7 @@ void CGDebugInfo::EmitGlobalVariableForHeterogeneousDwarf( // Attempt to store one global variable for the declaration - even if we // emit a lot of fields. llvm::DIGlobalVariable *DGV = nullptr; + llvm::DIGlobalVariableExpression *GVE = nullptr; // If this is an anonymous union then we'll want to emit a global // variable for each member of the anonymous union so that it's possible @@ -5960,38 +6028,58 @@ void CGDebugInfo::EmitGlobalVariableForHeterogeneousDwarf( assert(RD->isAnonymousStructOrUnion() && "unnamed non-anonymous struct or union?"); // FIXME(KZHURAVL): No tests for this path. - DGV = CollectAnonRecordDeclsForHeterogeneousDwarf( - RD, Unit, LineNo, LinkageName, MS, Var, DContext); + if (CGM.getCodeGenOpts().isHeterogeneousDwarfDIExpr()) + DGV = CollectAnonRecordDeclsForHeterogeneousDwarfDIExpr( + RD, Unit, LineNo, LinkageName, MS, Var, DContext); + else + GVE = CollectAnonRecordDeclsForHeterogeneousDwarfDIExpression( + RD, Unit, LineNo, LinkageName, MS, Var, DContext); } else { + auto Align = getDeclAlignIfRequired(D, CGM.getContext()); + // Create DIExpr. llvm::DIExprBuilder ExprBuilder(CGM.getLLVMContext()); - ExprBuilder.append(0, Var->getType()); + ExprBuilder.append(0u, Var->getType()); ExprBuilder.append(Var->getValueType()); - // Create DIGlobalVariable. - DGV = DBuilder.createGlobalVariable( - DContext, DeclName, LinkageName, Unit, LineNo, getOrCreateType(T, Unit), - Var->hasLocalLinkage(), true, - getOrCreateStaticDataMemberDeclarationOrNull(D), TemplateParameters, MS, - getDeclAlignIfRequired(D, CGM.getContext())); + llvm::DINodeArray Annotations = CollectBTFDeclTagAnnotations(D); - // Create DIFragment. - llvm::DIFragment *Fragment = DBuilder.createFragment(); - SmallVector LifetimeArgs; - LifetimeArgs.push_back(Fragment); + if (CGM.getCodeGenOpts().isHeterogeneousDwarfDIExpr()) { + DGV = DBuilder.createGlobalVariable( + DContext, DeclName, LinkageName, Unit, LineNo, + getOrCreateType(T, Unit), Var->hasLocalLinkage(), true, + getOrCreateStaticDataMemberDeclarationOrNull(D), TemplateParameters, + MS, getDeclAlignIfRequired(D, CGM.getContext())); - // Create DILifetime and add to llvm.dbg.retainedNodes named metadata. - DBuilder.createComputedLifetime(DGV, ExprBuilder.intoExpr(), LifetimeArgs); + // Create DIFragment. + llvm::DIFragment *Fragment = DBuilder.createFragment(); + SmallVector LifetimeArgs; + LifetimeArgs.push_back(Fragment); - // Attach metadata to GlobalVariable. - Var->setDbgDef(Fragment); - } + // Create DILifetime and add to llvm.dbg.retainedNodes named metadata. + DBuilder.createComputedLifetime(DGV, ExprBuilder.intoExpr(), + LifetimeArgs); + + Var->setDbgDef(Fragment); - GV.reset(DGV); + } else { + GVE = DBuilder.createGlobalVariableExpression( + DContext, DeclName, LinkageName, Unit, LineNo, + getOrCreateType(T, Unit), Var->hasLocalLinkage(), true, + ExprBuilder.intoExpression(), + getOrCreateStaticDataMemberDeclarationOrNull(D), TemplateParameters, + MS, Align, Annotations); + Var->addDebugInfo(GVE); + } + } + if (CGM.getCodeGenOpts().isHeterogeneousDwarfDIExpr()) + GV.reset(DGV); + else + DeclCache[D->getCanonicalDecl()].reset(GVE); } void CGDebugInfo::EmitGlobalVariable(const ValueDecl *VD, const APValue &Init) { - if (CGM.getCodeGenOpts().HeterogeneousDwarf) + if (CGM.getCodeGenOpts().isHeterogeneousDwarfEnabled()) return EmitGlobalVariableForHeterogeneousDwarf(VD, Init); assert(CGM.getCodeGenOpts().hasReducedDebugInfo()); @@ -6151,14 +6239,22 @@ void CGDebugInfo::EmitGlobalVariableForHeterogeneousDwarf( ExprBuilder.append( llvm::ConstantFP::get(CGM.getLLVMContext(), Init.getFloat())); - llvm::DIGlobalVariable *DGV = DBuilder.createGlobalVariable( - DContext, Name, StringRef(), Unit, getLineNumber(VD->getLocation()), Ty, - true, true, getOrCreateStaticDataMemberDeclarationOrNull(VarD), - TemplateParameters, MS, Align); + if (CGM.getCodeGenOpts().isHeterogeneousDwarfDIExpr()) { + llvm::DIGlobalVariable *DGV = DBuilder.createGlobalVariable( + DContext, Name, StringRef(), Unit, getLineNumber(VD->getLocation()), Ty, + true, true, getOrCreateStaticDataMemberDeclarationOrNull(VarD), + TemplateParameters, MS, Align); - DBuilder.createComputedLifetime(DGV, ExprBuilder.intoExpr(), {}); + DBuilder.createComputedLifetime(DGV, ExprBuilder.intoExpr(), {}); - GV.reset(DGV); + GV.reset(DGV); + } else { + GV.reset(DBuilder.createGlobalVariableExpression( + DContext, Name, StringRef(), Unit, getLineNumber(VD->getLocation()), Ty, + true, true, ExprBuilder.intoExpression(), + getOrCreateStaticDataMemberDeclarationOrNull(VarD), TemplateParameters, + MS, Align)); + } } void CGDebugInfo::EmitExternalVariable(llvm::GlobalVariable *Var, @@ -6225,7 +6321,7 @@ void CGDebugInfo::EmitGlobalAlias(const llvm::GlobalValue *GV, void CGDebugInfo::AddStringLiteralDebugInfo(llvm::GlobalVariable *GV, const StringLiteral *S) { // FIXME: Implement for heterogeneous debug info - if (CGM.getCodeGenOpts().HeterogeneousDwarf) + if (CGM.getCodeGenOpts().isHeterogeneousDwarfEnabled()) return; SourceLocation Loc = S->getStrTokenLoc(0); diff --git a/clang/lib/CodeGen/CGDebugInfo.h b/clang/lib/CodeGen/CGDebugInfo.h index 5e7e91e70595c6..5c3a3a077003c0 100644 --- a/clang/lib/CodeGen/CGDebugInfo.h +++ b/clang/lib/CodeGen/CGDebugInfo.h @@ -777,7 +777,20 @@ class CGDebugInfo { /// anonymous decl and create static variables for them. The first /// time this is called it needs to be on a union and then from /// there we can have additional unnamed fields. - llvm::DIGlobalVariable *CollectAnonRecordDeclsForHeterogeneousDwarf( + llvm::DIGlobalVariable *CollectAnonRecordDeclsForHeterogeneousDwarfDIExpr( + const RecordDecl *RD, llvm::DIFile *Unit, unsigned LineNo, + StringRef LinkageName, llvm::dwarf::MemorySpace MS, + llvm::GlobalVariable *Var, llvm::DIScope *DContext); + + /// Return a global variable that represents one of the collection of global + /// variables created for an anonmyous union (-gheterogeneous-dwarf). + /// + /// Recursively collect all of the member fields of a global + /// anonymous decl and create static variables for them. The first + /// time this is called it needs to be on a union and then from + /// there we can have additional unnamed fields. + llvm::DIGlobalVariableExpression * + CollectAnonRecordDeclsForHeterogeneousDwarfDIExpression( const RecordDecl *RD, llvm::DIFile *Unit, unsigned LineNo, StringRef LinkageName, llvm::dwarf::MemorySpace MS, llvm::GlobalVariable *Var, llvm::DIScope *DContext); diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index d715aaa2a886b1..0d9b02453e48bb 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -985,7 +985,7 @@ void CodeGenModule::Release() { // We support a single version in the linked module. The LLVM // parser will drop debug info with a different version number // (and warn about it, too). - if (CodeGenOpts.HeterogeneousDwarf) { + if (CodeGenOpts.isHeterogeneousDwarfDIExpr()) { getModule().addModuleFlag(llvm::Module::Override, "Debug Info Version", llvm::DEBUG_METADATA_VERSION_HETEROGENEOUS_DWARF); } else { diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 5281d829e17468..ba0405a679d22e 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -4590,9 +4590,30 @@ renderDebugOptions(const ToolChain &TC, const Driver &D, const llvm::Triple &T, bool EmitDwarfForAMDGCN = EmitDwarf && T.isAMDGCN(); if (EmitDwarfForAMDGCN) CmdArgs.append({"-mllvm", "-amdgpu-spill-cfi-saved-regs"}); - if (Args.hasFlag(options::OPT_gheterogeneous_dwarf, - options::OPT_gno_heterogeneous_dwarf, EmitDwarfForAMDGCN)) - CmdArgs.push_back("-gheterogeneous-dwarf"); + if (Arg *A = Args.getLastArg(options::OPT_gheterogeneous_dwarf_EQ)) { + A->render(Args, CmdArgs); + } else if (EmitDwarfForAMDGCN) { +#ifndef NDEBUG + // There doesn't seem to be a straightforward way to "render" an option + // acquired from the OptTable into a string we can append to CmdArgs. + // All of the logic is buried in "accept" which works directly in terms + // of an ArgList. + // + // Instead, assert that the static string we are adding to CmdArgs has + // the same shape as what a bare -gheterogeneous-dwarf would alias to + // if the user has provided it in ArgList. + const Option GHeterogeneousDwarf = + getDriverOptTable().getOption(options::OPT_gheterogeneous_dwarf); + const Option Aliased = GHeterogeneousDwarf.getAlias(); + assert(Aliased.isValid() && "gheterogeneous-dwarf must be an alias"); + assert(Aliased.getName() == "gheterogeneous-dwarf=" && + "gheterogeneous-dwarf must alias gheterogeneous-dwarf="); + assert(StringRef(GHeterogeneousDwarf.getAliasArgs()) == "diexpr" && + GHeterogeneousDwarf.getAliasArgs()[strlen("diexpr") + 1] == '\0' && + "gheterogeneous-dwarf must alias gheterogeneous-dwarf=diexpr"); +#endif + CmdArgs.push_back("-gheterogeneous-dwarf=diexpr"); + } // This controls whether or not we perform JustMyCode instrumentation. if (Args.hasFlag(options::OPT_fjmc, options::OPT_fno_jmc, false)) { diff --git a/clang/test/CodeGen/debug-info-block-expr-heterogeneous-dwarf.c b/clang/test/CodeGen/debug-info-block-expr-heterogeneous-dwarf.c index cee228a20cae4e..dd78bb3aea7822 100644 --- a/clang/test/CodeGen/debug-info-block-expr-heterogeneous-dwarf.c +++ b/clang/test/CodeGen/debug-info-block-expr-heterogeneous-dwarf.c @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -fblocks -debug-info-kind=limited -gheterogeneous-dwarf -emit-llvm -disable-llvm-verifier -o - %s | FileCheck %s -// RUN: %clang_cc1 -DDEAD_CODE -fblocks -debug-info-kind=limited -gheterogeneous-dwarf -emit-llvm -disable-llvm-verifier -o - %s | FileCheck %s +// RUN: %clang_cc1 -fblocks -debug-info-kind=limited -gheterogeneous-dwarf=diexpr -emit-llvm -disable-llvm-verifier -o - %s | FileCheck %s +// RUN: %clang_cc1 -DDEAD_CODE -fblocks -debug-info-kind=limited -gheterogeneous-dwarf=diexpr -emit-llvm -disable-llvm-verifier -o - %s | FileCheck %s typedef void (^BlockTy)(); void escapeFunc(BlockTy); diff --git a/clang/test/CodeGen/debug-info-global-constant-heterogeneous-dwarf.c b/clang/test/CodeGen/debug-info-global-constant-heterogeneous-dwarf.c index bf58b535a51cab..9824c5ae4e4b81 100644 --- a/clang/test/CodeGen/debug-info-global-constant-heterogeneous-dwarf.c +++ b/clang/test/CodeGen/debug-info-global-constant-heterogeneous-dwarf.c @@ -1,12 +1,12 @@ -// RUN: %clang_cc1 -D ARG_TYPE=int -D PTR_ARG='&g' -D VAL_ARG=g -emit-llvm -debug-info-kind=standalone -gheterogeneous-dwarf %s -o - | FileCheck --check-prefix=INT-ADDROF-VAL %s -// RUN: %clang_cc1 -D ARG_TYPE=int -D PTR_ARG='&g' -D VAL_ARG=0 -emit-llvm -debug-info-kind=standalone -gheterogeneous-dwarf %s -o - | FileCheck --check-prefix=INT-ADDROF-NOVAL %s -// RUN: %clang_cc1 -D ARG_TYPE=int -D PTR_ARG=0 -D VAL_ARG=g -emit-llvm -debug-info-kind=standalone -gheterogeneous-dwarf %s -o - | FileCheck --check-prefix=INT-NOADDROF-VAL %s -// RUN: %clang_cc1 -D ARG_TYPE=int -D PTR_ARG=0 -D VAL_ARG=0 -emit-llvm -debug-info-kind=standalone -gheterogeneous-dwarf %s -o - | FileCheck --check-prefix=INT-NOADDROF-NOVAL %s +// RUN: %clang_cc1 -D ARG_TYPE=int -D PTR_ARG='&g' -D VAL_ARG=g -emit-llvm -debug-info-kind=standalone -gheterogeneous-dwarf=diexpr %s -o - | FileCheck --check-prefix=INT-ADDROF-VAL %s +// RUN: %clang_cc1 -D ARG_TYPE=int -D PTR_ARG='&g' -D VAL_ARG=0 -emit-llvm -debug-info-kind=standalone -gheterogeneous-dwarf=diexpr %s -o - | FileCheck --check-prefix=INT-ADDROF-NOVAL %s +// RUN: %clang_cc1 -D ARG_TYPE=int -D PTR_ARG=0 -D VAL_ARG=g -emit-llvm -debug-info-kind=standalone -gheterogeneous-dwarf=diexpr %s -o - | FileCheck --check-prefix=INT-NOADDROF-VAL %s +// RUN: %clang_cc1 -D ARG_TYPE=int -D PTR_ARG=0 -D VAL_ARG=0 -emit-llvm -debug-info-kind=standalone -gheterogeneous-dwarf=diexpr %s -o - | FileCheck --check-prefix=INT-NOADDROF-NOVAL %s // -// RUN: %clang_cc1 -D ARG_TYPE=float -D PTR_ARG='&g' -D VAL_ARG=g -emit-llvm -debug-info-kind=standalone -gheterogeneous-dwarf %s -o - | FileCheck --check-prefix=FLOAT-ADDROF-VAL %s -// RUN: %clang_cc1 -D ARG_TYPE=float -D PTR_ARG='&g' -D VAL_ARG=0 -emit-llvm -debug-info-kind=standalone -gheterogeneous-dwarf %s -o - | FileCheck --check-prefix=FLOAT-ADDROF-NOVAL %s -// RUN: %clang_cc1 -D ARG_TYPE=float -D PTR_ARG=0 -D VAL_ARG=g -emit-llvm -debug-info-kind=standalone -gheterogeneous-dwarf %s -o - | FileCheck --check-prefix=FLOAT-NOADDROF-VAL %s -// RUN: %clang_cc1 -D ARG_TYPE=float -D PTR_ARG=0 -D VAL_ARG=0 -emit-llvm -debug-info-kind=standalone -gheterogeneous-dwarf %s -o - | FileCheck --check-prefix=FLOAT-NOADDROF-NOVAL %s +// RUN: %clang_cc1 -D ARG_TYPE=float -D PTR_ARG='&g' -D VAL_ARG=g -emit-llvm -debug-info-kind=standalone -gheterogeneous-dwarf=diexpr %s -o - | FileCheck --check-prefix=FLOAT-ADDROF-VAL %s +// RUN: %clang_cc1 -D ARG_TYPE=float -D PTR_ARG='&g' -D VAL_ARG=0 -emit-llvm -debug-info-kind=standalone -gheterogeneous-dwarf=diexpr %s -o - | FileCheck --check-prefix=FLOAT-ADDROF-NOVAL %s +// RUN: %clang_cc1 -D ARG_TYPE=float -D PTR_ARG=0 -D VAL_ARG=g -emit-llvm -debug-info-kind=standalone -gheterogeneous-dwarf=diexpr %s -o - | FileCheck --check-prefix=FLOAT-NOADDROF-VAL %s +// RUN: %clang_cc1 -D ARG_TYPE=float -D PTR_ARG=0 -D VAL_ARG=0 -emit-llvm -debug-info-kind=standalone -gheterogeneous-dwarf=diexpr %s -o - | FileCheck --check-prefix=FLOAT-NOADDROF-NOVAL %s // INT-ADDROF-VAL: @g = internal constant i32 1, align 4{{$}} // INT-ADDROF-VAL-DAG: !llvm.dbg.retainedNodes = !{![[#LIFETIME:]]} diff --git a/clang/test/CodeGen/debug-info-version-heterogeneous-dwarf.c b/clang/test/CodeGen/debug-info-version-heterogeneous-dwarf.c index 285226686ba811..180d646775ffc2 100644 --- a/clang/test/CodeGen/debug-info-version-heterogeneous-dwarf.c +++ b/clang/test/CodeGen/debug-info-version-heterogeneous-dwarf.c @@ -1,4 +1,4 @@ -// RUN: %clang -g -gheterogeneous-dwarf -S -emit-llvm -o - %s | FileCheck %s +// RUN: %clang -g -gheterogeneous-dwarf=diexpr -S -emit-llvm -o - %s | FileCheck %s // RUN: %clang -S -emit-llvm -o - %s | FileCheck %s --check-prefix=NO_DEBUG int main (void) { return 0; diff --git a/clang/test/CodeGenCUDA/debug-info-memory-space.cu b/clang/test/CodeGenCUDA/debug-info-memory-space.cu index d0cb40b96cdf19..7a71049162c2bc 100644 --- a/clang/test/CodeGenCUDA/debug-info-memory-space.cu +++ b/clang/test/CodeGenCUDA/debug-info-memory-space.cu @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple nvptx-unknown-unknown -emit-llvm -fcuda-is-device -debug-info-kind=limited -gheterogeneous-dwarf -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple nvptx-unknown-unknown -emit-llvm -fcuda-is-device -debug-info-kind=limited -gheterogeneous-dwarf=diexpr -o - %s | FileCheck %s // CHECK-DAG: !DIGlobalVariable(name: "GlobalShared", scope: !{{[0-9]+}}, file: !{{[0-9]+}}, line: {{[0-9]+}}, type: !{{[0-9]+}}, isLocal: false, isDefinition: true, memorySpace: DW_MSPACE_LLVM_group) // CHECK-DAG: !DIGlobalVariable(name: "GlobalDevice", scope: !{{[0-9]+}}, file: !{{[0-9]+}}, line: {{[0-9]+}}, type: !{{[0-9]+}}, isLocal: false, isDefinition: true, memorySpace: DW_MSPACE_LLVM_global) // CHECK-DAG: !DIGlobalVariable(name: "GlobalConstant", scope: !{{[0-9]+}}, file: !{{[0-9]+}}, line: {{[0-9]+}}, type: !{{[0-9]+}}, isLocal: false, isDefinition: true, memorySpace: DW_MSPACE_LLVM_constant) diff --git a/clang/test/CodeGenCXX/heterogeneous-debug-info-structured-binding-bitfield.cpp b/clang/test/CodeGenCXX/heterogeneous-debug-info-structured-binding-bitfield.cpp index 906cafba2fe609..aa884192e836ad 100644 --- a/clang/test/CodeGenCXX/heterogeneous-debug-info-structured-binding-bitfield.cpp +++ b/clang/test/CodeGenCXX/heterogeneous-debug-info-structured-binding-bitfield.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple amdgcn-amd-amdhsa -x c++ -emit-llvm -fcuda-is-device -debug-info-kind=limited -gheterogeneous-dwarf -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple amdgcn-amd-amdhsa -x c++ -emit-llvm -fcuda-is-device -debug-info-kind=limited -gheterogeneous-dwarf=diexpr -o - %s | FileCheck %s struct S0 { unsigned int x : 16; diff --git a/clang/test/CodeGenCXX/heterogeneous-debug-info-structured-binding.cpp b/clang/test/CodeGenCXX/heterogeneous-debug-info-structured-binding.cpp index 857c57f34f7aa7..6815ff5667a9c7 100644 --- a/clang/test/CodeGenCXX/heterogeneous-debug-info-structured-binding.cpp +++ b/clang/test/CodeGenCXX/heterogeneous-debug-info-structured-binding.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple amdgcn-amd-amdhsa -x c++ -emit-llvm -fcuda-is-device -debug-info-kind=limited -gheterogeneous-dwarf -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple amdgcn-amd-amdhsa -x c++ -emit-llvm -fcuda-is-device -debug-info-kind=limited -gheterogeneous-dwarf=diexpr -o - %s | FileCheck %s // // first def for 'a' // CHECK-LABEL: @_Z1fv() diff --git a/clang/test/CodeGenHIP/debug-info-address-class-heterogeneous-dwarf.hip b/clang/test/CodeGenHIP/debug-info-address-class-heterogeneous-dwarf.hip index 58fb91a3e147db..586d2227bb29c6 100644 --- a/clang/test/CodeGenHIP/debug-info-address-class-heterogeneous-dwarf.hip +++ b/clang/test/CodeGenHIP/debug-info-address-class-heterogeneous-dwarf.hip @@ -1,5 +1,5 @@ // REQUIRES: amdgpu-registered-target -// RUN: %clang_cc1 -triple amdgcn-amd-amdhsa -x hip -emit-llvm -fcuda-is-device -debug-info-kind=limited -gheterogeneous-dwarf -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple amdgcn-amd-amdhsa -x hip -emit-llvm -fcuda-is-device -debug-info-kind=limited -gheterogeneous-dwarf=diexpr -o - %s | FileCheck %s #define __device__ __attribute__((device)) diff --git a/clang/test/CodeGenHIP/debug-info-amdgcn-abi-heterogeneous-dwarf.hip b/clang/test/CodeGenHIP/debug-info-amdgcn-abi-heterogeneous-dwarf.hip index a2997f16a7e825..0de8daf955f1d9 100644 --- a/clang/test/CodeGenHIP/debug-info-amdgcn-abi-heterogeneous-dwarf.hip +++ b/clang/test/CodeGenHIP/debug-info-amdgcn-abi-heterogeneous-dwarf.hip @@ -1,5 +1,5 @@ // REQUIRES: amdgpu-registered-target -// RUN: %clang_cc1 -O0 -debug-info-kind=limited -gheterogeneous-dwarf -triple amdgcn-amd-amdhsa -x hip -emit-llvm -fcuda-is-device -o - %s | FileCheck %s +// RUN: %clang_cc1 -O0 -debug-info-kind=limited -gheterogeneous-dwarf=diexpr -triple amdgcn-amd-amdhsa -x hip -emit-llvm -fcuda-is-device -o - %s | FileCheck %s // Notes: // * There is no test involving transparent_union, as this isn't supported in diff --git a/clang/test/CodeGenHIP/debug-info-anonymous-union-heterogeneous-dwarf.hip b/clang/test/CodeGenHIP/debug-info-anonymous-union-heterogeneous-dwarf.hip index 17ae6daa315c50..c2e51df9bb726d 100644 --- a/clang/test/CodeGenHIP/debug-info-anonymous-union-heterogeneous-dwarf.hip +++ b/clang/test/CodeGenHIP/debug-info-anonymous-union-heterogeneous-dwarf.hip @@ -1,5 +1,5 @@ // REQUIRES: amdgpu-registered-target -// RUN: %clang_cc1 -triple amdgcn-amd-amdhsa -x hip -emit-llvm -fcuda-is-device -debug-info-kind=limited -gheterogeneous-dwarf -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple amdgcn-amd-amdhsa -x hip -emit-llvm -fcuda-is-device -debug-info-kind=limited -gheterogeneous-dwarf=diexpr -o - %s | FileCheck %s #define __device__ __attribute__((device)) diff --git a/clang/test/CodeGenHIP/debug-info-cc1-option.hip b/clang/test/CodeGenHIP/debug-info-cc1-option.hip new file mode 100644 index 00000000000000..ef54f476389c66 --- /dev/null +++ b/clang/test/CodeGenHIP/debug-info-cc1-option.hip @@ -0,0 +1,12 @@ +// REQUIRES: amdgpu-registered-target +// RUN: %clang_cc1 -triple amdgcn-amd-amdhsa -x hip -emit-llvm -fcuda-is-device -debug-info-kind=limited -gheterogeneous-dwarf -o - %s | FileCheck %s + +// Check that -gheterogeneous-dwarf without an `=OPTION` suffix remains valid +// and aliases the new default. This is needed for transitioning flang-legacy +// as it depends on the -cc1 interface. + +// CHECK: call void @llvm.dbg.def +// CHECK: !DIExpr( +__attribute__((device)) void kernel1(int Arg) { + int FuncVar; +} diff --git a/clang/test/CodeGenHIP/debug-info-diop-in-diexpression_dwarf.hip b/clang/test/CodeGenHIP/debug-info-diop-in-diexpression_dwarf.hip new file mode 100644 index 00000000000000..f88c95ca576234 --- /dev/null +++ b/clang/test/CodeGenHIP/debug-info-diop-in-diexpression_dwarf.hip @@ -0,0 +1,213 @@ +// REQUIRES: amdgpu-registered-target +// RUN: %clang_cc1 -x hip -triple amdgcn-amd-amdhsa -emit-obj -fcuda-is-device -debug-info-kind=limited -gheterogeneous-dwarf=diexpr -o - %s | llvm-dwarfdump --diff - | FileCheck --check-prefixes=CHECK,CHECK-DIEXPR %s +// RUN: %clang_cc1 -x hip -triple amdgcn-amd-amdhsa -emit-obj -fcuda-is-device -debug-info-kind=limited -gheterogeneous-dwarf=diexpr -mllvm -stop-after=amdgpu-isel -o - %s | llc -x mir -verify-machineinstrs -start-after=amdgpu-isel -filetype=obj -o - - | llvm-dwarfdump --diff - | FileCheck --check-prefixes=CHECK,CHECK-DIEXPR %s +// RUN: %clang_cc1 -x hip -triple amdgcn-amd-amdhsa -emit-obj -fcuda-is-device -debug-info-kind=limited -gheterogeneous-dwarf=diexpression -o - %s | llvm-dwarfdump --diff - | FileCheck --check-prefixes=CHECK,CHECK-DIEXPRESSION %s +// RUN: %clang_cc1 -x hip -triple amdgcn-amd-amdhsa -emit-obj -fcuda-is-device -debug-info-kind=limited -gheterogeneous-dwarf=diexpression -mllvm -stop-after=amdgpu-isel -o - %s | llc -x mir -verify-machineinstrs -start-after=amdgpu-isel -filetype=obj -o - - | llvm-dwarfdump --diff - | FileCheck --check-prefixes=CHECK,CHECK-DIEXPRESSION %s + +#define __global__ __attribute__((global)) +#define __device__ __attribute__((device)) +#define __shared__ __attribute__((shared)) +#define __constant__ __attribute__((constant)) + +__shared__ int GlobalSharedA; +__shared__ int GlobalSharedB; +__device__ int GlobalDeviceA; +__device__ int GlobalDeviceB; +__constant__ int GlobalConstantA; +__constant__ int GlobalConstantB; + +__global__ void kernel1(int Arg) { + __shared__ int KernelVarSharedA; + __shared__ int KernelVarSharedB; + int KernelVarA; + int KernelVarB; + + auto *KernelVarSharedAPointer = &KernelVarSharedA; + auto *KernelVarSharedBPointer = &KernelVarSharedB; + auto *KernelVarAPointer = &KernelVarA; + auto *KernelVarBPointer = &KernelVarB; +} + +__device__ void func1(int Arg) { + int FuncVarA; + int FuncVarB; + + auto *FuncVarAPointer = &FuncVarA; + auto *FuncVarBPointer = &FuncVarB; +} + + +// CHECK: .debug_info contents: +// CHECK: DW_TAG_compile_unit + +// CHECK: DW_TAG_variable +// CHECK: DW_AT_name ("GlobalSharedA") +// CHECK: DW_AT_type ("int") +// CHECK: DW_AT_external (true) +// CHECK: DW_AT_LLVM_memory_space (DW_MSPACE_LLVM_group) +// CHECK-DIEXPR: DW_AT_location () +// CHECK-DIEXPRESSION-NOT: DW_AT_location + +// CHECK: DW_TAG_base_type +// CHECK: DW_AT_name ("int") +// CHECK: DW_AT_encoding (DW_ATE_signed) +// CHECK: DW_AT_byte_size (0x04) + +// CHECK: DW_TAG_variable +// CHECK: DW_AT_name ("GlobalSharedB") +// CHECK: DW_AT_type ("int") +// CHECK: DW_AT_external (true) +// CHECK: DW_AT_LLVM_memory_space (DW_MSPACE_LLVM_group) +// CHECK-DIEXPR: DW_AT_location () +// CHECK-DIEXPRESSION-NOT: DW_AT_location + +// CHECK: DW_TAG_variable +// CHECK: DW_AT_name ("GlobalDeviceA") +// CHECK: DW_AT_type ("int") +// CHECK: DW_AT_external (true) +// CHECK: DW_AT_LLVM_memory_space (DW_MSPACE_LLVM_global) +// CHECK-DIEXPR: DW_AT_location (DW_OP_addr 0x0, DW_OP_stack_value, DW_OP_deref_size 0x8, DW_OP_constu 0x0, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address) +// CHECK-DIEXPRESSION: DW_AT_location (DW_OP_addr 0x0, DW_OP_stack_value, DW_OP_deref_size 0x8, DW_OP_lit0, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address) + +// CHECK: DW_TAG_variable +// CHECK: DW_AT_name ("GlobalDeviceB") +// CHECK: DW_AT_type ("int") +// CHECK: DW_AT_external (true) +// CHECK: DW_AT_LLVM_memory_space (DW_MSPACE_LLVM_global) +// CHECK-DIEXPR: DW_AT_location (DW_OP_addr 0x0, DW_OP_stack_value, DW_OP_deref_size 0x8, DW_OP_constu 0x0, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address) +// CHECK-DIEXPRESSION: DW_AT_location (DW_OP_addr 0x0, DW_OP_stack_value, DW_OP_deref_size 0x8, DW_OP_lit0, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address) + +// CHECK: DW_TAG_variable +// CHECK: DW_AT_name ("GlobalConstantA") +// CHECK: DW_AT_type ("int") +// CHECK: DW_AT_external (true) +// CHECK: DW_AT_LLVM_memory_space (DW_MSPACE_LLVM_constant) +// CHECK-DIEXPR: DW_AT_location (DW_OP_addr 0x0, DW_OP_stack_value, DW_OP_deref_size 0x8, DW_OP_constu 0x0, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address) +// CHECK-DIEXPRESSION: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_deref_size 0x8, DW_OP_lit0, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address) + +// CHECK: DW_TAG_variable +// CHECK: DW_AT_name ("GlobalConstantB") +// CHECK: DW_AT_type ("int") +// CHECK: DW_AT_external (true) +// CHECK: DW_AT_LLVM_memory_space (DW_MSPACE_LLVM_constant) +// CHECK-DIEXPR: DW_AT_location (DW_OP_addr 0x0, DW_OP_stack_value, DW_OP_deref_size 0x8, DW_OP_constu 0x0, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address) +// CHECK-DIEXPRESSION: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_deref_size 0x8, DW_OP_lit0, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address) + +// CHECK: DW_TAG_subprogram +// CHECK: DW_AT_linkage_name ("_Z7kernel1i") +// CHECK: DW_AT_name ("kernel1") +// CHECK: DW_AT_external (true) + +// CHECK: DW_TAG_variable +// CHECK: DW_AT_name ("KernelVarSharedA") +// CHECK: DW_AT_type ("int") +// CHECK: DW_AT_LLVM_memory_space (DW_MSPACE_LLVM_group) +// CHECK-DIEXPR: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x3, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_LLVM_user DW_OP_LLVM_offset) +// CHECK-DIEXPRESSION: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_lit0, DW_OP_plus, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_lit3, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address) + +// CHECK: DW_TAG_variable +// CHECK: DW_AT_name ("KernelVarSharedB") +// CHECK: DW_AT_type ("int") +// CHECK: DW_AT_LLVM_memory_space (DW_MSPACE_LLVM_group) +// CHECK-DIEXPR: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x3, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_LLVM_user DW_OP_LLVM_offset) +// CHECK-DIEXPRESSION: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_lit4, DW_OP_plus, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_lit3, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address) + +// CHECK: DW_TAG_formal_parameter +// CHECK-DIEXPR: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_LLVM_user DW_OP_LLVM_offset) +// CHECK-DIEXPRESSION: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_lit4, DW_OP_plus, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_lit5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address) +// CHECK: DW_AT_name ("Arg") +// CHECK: DW_AT_type ("int") + +// CHECK-DIEXPR: DW_TAG_variable +// CHECK-DIEXPR: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit24, DW_OP_LLVM_user DW_OP_LLVM_offset) +// CHECK-DIEXPR: DW_AT_name ("KernelVarSharedBPointer") +// CHECK-DIEXPR: DW_AT_type ("int *") + +// CHECK-DIEXPR: DW_TAG_variable +// CHECK-DIEXPR: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit8, DW_OP_LLVM_user DW_OP_LLVM_offset) +// CHECK-DIEXPR: DW_AT_name ("KernelVarA") +// CHECK-DIEXPR: DW_AT_type ("int") + +// CHECK-DIEXPR: DW_TAG_variable +// CHECK-DIEXPR: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit12, DW_OP_LLVM_user DW_OP_LLVM_offset) +// CHECK-DIEXPR: DW_AT_name ("KernelVarB") +// CHECK-DIEXPR: DW_AT_type ("int") + +// CHECK-DIEXPR: DW_TAG_variable +// CHECK-DIEXPR: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit16, DW_OP_LLVM_user DW_OP_LLVM_offset) +// CHECK-DIEXPR: DW_AT_name ("KernelVarSharedAPointer") +// CHECK-DIEXPR: DW_AT_type ("int *") + +// CHECK-DIEXPRESSION: DW_TAG_variable +// CHECK-DIEXPRESSION: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_lit8, DW_OP_plus, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_lit5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address) +// CHECK-DIEXPRESSION: DW_AT_name ("KernelVarA") +// CHECK-DIEXPRESSION: DW_AT_type ("int") + +// CHECK-DIEXPRESSION: DW_TAG_variable +// CHECK-DIEXPRESSION: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_lit12, DW_OP_plus, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_lit5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address) +// CHECK-DIEXPRESSION: DW_AT_name ("KernelVarB") +// CHECK-DIEXPRESSION: DW_AT_type ("int") + +// CHECK-DIEXPRESSION: DW_TAG_variable +// CHECK-DIEXPRESSION: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_lit16, DW_OP_plus, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_lit5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address) +// CHECK-DIEXPRESSION: DW_AT_name ("KernelVarSharedAPointer") +// CHECK-DIEXPRESSION: DW_AT_type ("int *") + +// CHECK-DIEXPRESSION: DW_TAG_variable +// CHECK-DIEXPRESSION: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_lit24, DW_OP_plus, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_lit5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address) +// CHECK-DIEXPRESSION: DW_AT_name ("KernelVarSharedBPointer") +// CHECK-DIEXPRESSION: DW_AT_type ("int *") + +// CHECK: DW_TAG_variable +// CHECK-DIEXPR: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_constu 0x20, DW_OP_LLVM_user DW_OP_LLVM_offset) +// CHECK-DIEXPRESSION: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_constu 0x20, DW_OP_plus, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_lit5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address) +// CHECK: DW_AT_name ("KernelVarAPointer") +// CHECK: DW_AT_type ("int *") + +// CHECK: DW_TAG_variable +// CHECK-DIEXPR: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_constu 0x28, DW_OP_LLVM_user DW_OP_LLVM_offset) +// CHECK-DIEXPRESSION: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_constu 0x28, DW_OP_plus, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_lit5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address) +// CHECK: DW_AT_name ("KernelVarBPointer") +// CHECK: DW_AT_type ("int *") +// CHECK: NULL + +// CHECK: DW_TAG_subprogram +// CHECK-DIEXPR: DW_AT_frame_base (DW_OP_regx 0x40) +// CHECK: DW_AT_linkage_name ("_Z5func1i") +// CHECK: DW_AT_name ("func1") +// CHECK: DW_AT_external (true) + +// CHECK: DW_TAG_formal_parameter +// CHECK-DIEXPR: DW_AT_location (DW_OP_regx 0x40, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_LLVM_user DW_OP_LLVM_offset) +// CHECK-DIEXPRESSION: DW_AT_location (DW_OP_regx 0x40, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_lit0, DW_OP_plus, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_lit5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address) +// CHECK: DW_AT_name ("Arg") +// CHECK: DW_AT_type ("int") + +// CHECK: DW_TAG_variable +// CHECK-DIEXPR: DW_AT_location (DW_OP_regx 0x40, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_LLVM_user DW_OP_LLVM_offset) +// CHECK-DIEXPRESSION: DW_AT_location (DW_OP_regx 0x40, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_lit4, DW_OP_plus, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_lit5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address) +// CHECK: DW_AT_name ("FuncVarA") +// CHECK: DW_AT_type ("int") + +// CHECK: DW_TAG_variable +// CHECK-DIEXPR: DW_AT_location (DW_OP_regx 0x40, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit8, DW_OP_LLVM_user DW_OP_LLVM_offset) +// CHECK-DIEXPRESSION: DW_AT_location (DW_OP_regx 0x40, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_lit8, DW_OP_plus, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_lit5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address) +// CHECK: DW_AT_name ("FuncVarB") +// CHECK: DW_AT_type ("int") + +// CHECK: DW_TAG_variable +// CHECK-DIEXPR: DW_AT_location (DW_OP_regx 0x40, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit16, DW_OP_LLVM_user DW_OP_LLVM_offset) +// CHECK-DIEXPRESSION: DW_AT_location (DW_OP_regx 0x40, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_lit16, DW_OP_plus, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_lit5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address) +// CHECK: DW_AT_name ("FuncVarAPointer") +// CHECK: DW_AT_type ("int *") + +// CHECK: DW_TAG_variable +// CHECK-DIEXPR: DW_AT_location (DW_OP_regx 0x40, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit24, DW_OP_LLVM_user DW_OP_LLVM_offset) +// CHECK-DIEXPRESSION: DW_AT_location (DW_OP_regx 0x40, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_lit24, DW_OP_plus, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_lit5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address) +// CHECK: DW_AT_name ("FuncVarBPointer") +// CHECK: DW_AT_type ("int *") +// CHECK: NULL + +// CHECK: DW_TAG_pointer_type +// CHECK: DW_AT_type ("int") +// CHECK: NULL diff --git a/clang/test/CodeGenHIP/debug-info-diop-in-diexpression_ir.hip b/clang/test/CodeGenHIP/debug-info-diop-in-diexpression_ir.hip new file mode 100644 index 00000000000000..48dfbec1bad9c5 --- /dev/null +++ b/clang/test/CodeGenHIP/debug-info-diop-in-diexpression_ir.hip @@ -0,0 +1,290 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --check-globals smart +// FIXME: Edited after utils/update_cc_test_checks.py to fix !DIFile checks +// REQUIRES: amdgpu-registered-target +// RUN: %clang_cc1 -x hip -triple amdgcn-amd-amdhsa -emit-llvm -fcuda-is-device -debug-info-kind=limited -gheterogeneous-dwarf=diexpr -o - %s | FileCheck --check-prefix=DIEXPR-IR %s +// RUN: %clang_cc1 -x hip -triple amdgcn-amd-amdhsa -emit-llvm -fcuda-is-device -debug-info-kind=limited -gheterogeneous-dwarf=diexpression -o - %s | FileCheck --check-prefix=DIEXPRESSION-IR %s + +#define __global__ __attribute__((global)) +#define __device__ __attribute__((device)) +#define __shared__ __attribute__((shared)) +#define __constant__ __attribute__((constant)) + +__shared__ int GlobalSharedA; +__shared__ int GlobalSharedB; +__device__ int GlobalDeviceA; +__device__ int GlobalDeviceB; +__constant__ int GlobalConstantA; +__constant__ int GlobalConstantB; + +// DIEXPR-IR-LABEL: @_Z7kernel1i( +// DIEXPR-IR-NEXT: entry: +// DIEXPR-IR-NEXT: [[ARG_ADDR:%.*]] = alloca i32, align 4, addrspace(5) +// DIEXPR-IR-NEXT: [[KERNELVARA:%.*]] = alloca i32, align 4, addrspace(5) +// DIEXPR-IR-NEXT: [[KERNELVARB:%.*]] = alloca i32, align 4, addrspace(5) +// DIEXPR-IR-NEXT: [[KERNELVARSHAREDAPOINTER:%.*]] = alloca ptr, align 8, addrspace(5) +// DIEXPR-IR-NEXT: [[KERNELVARSHAREDBPOINTER:%.*]] = alloca ptr, align 8, addrspace(5) +// DIEXPR-IR-NEXT: [[KERNELVARAPOINTER:%.*]] = alloca ptr, align 8, addrspace(5) +// DIEXPR-IR-NEXT: [[KERNELVARBPOINTER:%.*]] = alloca ptr, align 8, addrspace(5) +// DIEXPR-IR-NEXT: [[ARG_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[ARG_ADDR]] to ptr +// DIEXPR-IR-NEXT: [[KERNELVARA_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[KERNELVARA]] to ptr +// DIEXPR-IR-NEXT: [[KERNELVARB_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[KERNELVARB]] to ptr +// DIEXPR-IR-NEXT: [[KERNELVARSHAREDAPOINTER_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[KERNELVARSHAREDAPOINTER]] to ptr +// DIEXPR-IR-NEXT: [[KERNELVARSHAREDBPOINTER_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[KERNELVARSHAREDBPOINTER]] to ptr +// DIEXPR-IR-NEXT: [[KERNELVARAPOINTER_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[KERNELVARAPOINTER]] to ptr +// DIEXPR-IR-NEXT: [[KERNELVARBPOINTER_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[KERNELVARBPOINTER]] to ptr +// DIEXPR-IR-NEXT: store i32 [[ARG:%.*]], ptr [[ARG_ADDR_ASCAST]], align 4 +// DIEXPR-IR-NEXT: call void @llvm.dbg.def(metadata [[META45:![0-9]+]], metadata ptr addrspace(5) [[ARG_ADDR]]), !dbg [[DBG46:![0-9]+]] +// DIEXPR-IR-NEXT: call void @llvm.dbg.def(metadata [[META47:![0-9]+]], metadata ptr addrspace(5) [[KERNELVARA]]), !dbg [[DBG48:![0-9]+]] +// DIEXPR-IR-NEXT: call void @llvm.dbg.def(metadata [[META49:![0-9]+]], metadata ptr addrspace(5) [[KERNELVARB]]), !dbg [[DBG50:![0-9]+]] +// DIEXPR-IR-NEXT: call void @llvm.dbg.def(metadata [[META51:![0-9]+]], metadata ptr addrspace(5) [[KERNELVARSHAREDAPOINTER]]), !dbg [[DBG52:![0-9]+]] +// DIEXPR-IR-NEXT: store ptr addrspacecast (ptr addrspace(3) @_ZZ7kernel1iE16KernelVarSharedA to ptr), ptr [[KERNELVARSHAREDAPOINTER_ASCAST]], align 8, !dbg [[DBG52]] +// DIEXPR-IR-NEXT: call void @llvm.dbg.def(metadata [[META53:![0-9]+]], metadata ptr addrspace(5) [[KERNELVARSHAREDBPOINTER]]), !dbg [[DBG54:![0-9]+]] +// DIEXPR-IR-NEXT: store ptr addrspacecast (ptr addrspace(3) @_ZZ7kernel1iE16KernelVarSharedB to ptr), ptr [[KERNELVARSHAREDBPOINTER_ASCAST]], align 8, !dbg [[DBG54]] +// DIEXPR-IR-NEXT: call void @llvm.dbg.def(metadata [[META55:![0-9]+]], metadata ptr addrspace(5) [[KERNELVARAPOINTER]]), !dbg [[DBG56:![0-9]+]] +// DIEXPR-IR-NEXT: store ptr [[KERNELVARA_ASCAST]], ptr [[KERNELVARAPOINTER_ASCAST]], align 8, !dbg [[DBG56]] +// DIEXPR-IR-NEXT: call void @llvm.dbg.def(metadata [[META57:![0-9]+]], metadata ptr addrspace(5) [[KERNELVARBPOINTER]]), !dbg [[DBG58:![0-9]+]] +// DIEXPR-IR-NEXT: store ptr [[KERNELVARB_ASCAST]], ptr [[KERNELVARBPOINTER_ASCAST]], align 8, !dbg [[DBG58]] +// DIEXPR-IR-NEXT: ret void, !dbg [[DBG59:![0-9]+]] +// +// DIEXPRESSION-IR-LABEL: @_Z7kernel1i( +// DIEXPRESSION-IR-NEXT: entry: +// DIEXPRESSION-IR-NEXT: [[ARG_ADDR:%.*]] = alloca i32, align 4, addrspace(5) +// DIEXPRESSION-IR-NEXT: [[KERNELVARA:%.*]] = alloca i32, align 4, addrspace(5) +// DIEXPRESSION-IR-NEXT: [[KERNELVARB:%.*]] = alloca i32, align 4, addrspace(5) +// DIEXPRESSION-IR-NEXT: [[KERNELVARSHAREDAPOINTER:%.*]] = alloca ptr, align 8, addrspace(5) +// DIEXPRESSION-IR-NEXT: [[KERNELVARSHAREDBPOINTER:%.*]] = alloca ptr, align 8, addrspace(5) +// DIEXPRESSION-IR-NEXT: [[KERNELVARAPOINTER:%.*]] = alloca ptr, align 8, addrspace(5) +// DIEXPRESSION-IR-NEXT: [[KERNELVARBPOINTER:%.*]] = alloca ptr, align 8, addrspace(5) +// DIEXPRESSION-IR-NEXT: [[ARG_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[ARG_ADDR]] to ptr +// DIEXPRESSION-IR-NEXT: [[KERNELVARA_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[KERNELVARA]] to ptr +// DIEXPRESSION-IR-NEXT: [[KERNELVARB_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[KERNELVARB]] to ptr +// DIEXPRESSION-IR-NEXT: [[KERNELVARSHAREDAPOINTER_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[KERNELVARSHAREDAPOINTER]] to ptr +// DIEXPRESSION-IR-NEXT: [[KERNELVARSHAREDBPOINTER_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[KERNELVARSHAREDBPOINTER]] to ptr +// DIEXPRESSION-IR-NEXT: [[KERNELVARAPOINTER_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[KERNELVARAPOINTER]] to ptr +// DIEXPRESSION-IR-NEXT: [[KERNELVARBPOINTER_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[KERNELVARBPOINTER]] to ptr +// DIEXPRESSION-IR-NEXT: store i32 [[ARG:%.*]], ptr [[ARG_ADDR_ASCAST]], align 4 +// DIEXPRESSION-IR-NEXT: call void @llvm.dbg.declare(metadata ptr addrspace(5) [[ARG_ADDR]], metadata [[META23:![0-9]+]], metadata !DIExpression(DIOpArg(0, ptr addrspace(5)), DIOpDeref(i32))), !dbg [[DBG38:![0-9]+]] +// DIEXPRESSION-IR-NEXT: call void @llvm.dbg.declare(metadata ptr addrspace(5) [[KERNELVARA]], metadata [[META24:![0-9]+]], metadata !DIExpression(DIOpArg(0, ptr addrspace(5)), DIOpDeref(i32))), !dbg [[DBG39:![0-9]+]] +// DIEXPRESSION-IR-NEXT: call void @llvm.dbg.declare(metadata ptr addrspace(5) [[KERNELVARB]], metadata [[META25:![0-9]+]], metadata !DIExpression(DIOpArg(0, ptr addrspace(5)), DIOpDeref(i32))), !dbg [[DBG40:![0-9]+]] +// DIEXPRESSION-IR-NEXT: call void @llvm.dbg.declare(metadata ptr addrspace(5) [[KERNELVARSHAREDAPOINTER]], metadata [[META26:![0-9]+]], metadata !DIExpression(DIOpArg(0, ptr addrspace(5)), DIOpDeref(ptr))), !dbg [[DBG41:![0-9]+]] +// DIEXPRESSION-IR-NEXT: store ptr addrspacecast (ptr addrspace(3) @_ZZ7kernel1iE16KernelVarSharedA to ptr), ptr [[KERNELVARSHAREDAPOINTER_ASCAST]], align 8, !dbg [[DBG41]] +// DIEXPRESSION-IR-NEXT: call void @llvm.dbg.declare(metadata ptr addrspace(5) [[KERNELVARSHAREDBPOINTER]], metadata [[META28:![0-9]+]], metadata !DIExpression(DIOpArg(0, ptr addrspace(5)), DIOpDeref(ptr))), !dbg [[DBG42:![0-9]+]] +// DIEXPRESSION-IR-NEXT: store ptr addrspacecast (ptr addrspace(3) @_ZZ7kernel1iE16KernelVarSharedB to ptr), ptr [[KERNELVARSHAREDBPOINTER_ASCAST]], align 8, !dbg [[DBG42]] +// DIEXPRESSION-IR-NEXT: call void @llvm.dbg.declare(metadata ptr addrspace(5) [[KERNELVARAPOINTER]], metadata [[META29:![0-9]+]], metadata !DIExpression(DIOpArg(0, ptr addrspace(5)), DIOpDeref(ptr))), !dbg [[DBG43:![0-9]+]] +// DIEXPRESSION-IR-NEXT: store ptr [[KERNELVARA_ASCAST]], ptr [[KERNELVARAPOINTER_ASCAST]], align 8, !dbg [[DBG43]] +// DIEXPRESSION-IR-NEXT: call void @llvm.dbg.declare(metadata ptr addrspace(5) [[KERNELVARBPOINTER]], metadata [[META30:![0-9]+]], metadata !DIExpression(DIOpArg(0, ptr addrspace(5)), DIOpDeref(ptr))), !dbg [[DBG44:![0-9]+]] +// DIEXPRESSION-IR-NEXT: store ptr [[KERNELVARB_ASCAST]], ptr [[KERNELVARBPOINTER_ASCAST]], align 8, !dbg [[DBG44]] +// DIEXPRESSION-IR-NEXT: ret void, !dbg [[DBG45:![0-9]+]] +// +__global__ void kernel1(int Arg) { + __shared__ int KernelVarSharedA; + __shared__ int KernelVarSharedB; + int KernelVarA; + int KernelVarB; + + auto *KernelVarSharedAPointer = &KernelVarSharedA; + auto *KernelVarSharedBPointer = &KernelVarSharedB; + auto *KernelVarAPointer = &KernelVarA; + auto *KernelVarBPointer = &KernelVarB; +} + +// DIEXPR-IR-LABEL: @_Z5func1i( +// DIEXPR-IR-NEXT: entry: +// DIEXPR-IR-NEXT: [[ARG_ADDR:%.*]] = alloca i32, align 4, addrspace(5) +// DIEXPR-IR-NEXT: [[FUNCVARA:%.*]] = alloca i32, align 4, addrspace(5) +// DIEXPR-IR-NEXT: [[FUNCVARB:%.*]] = alloca i32, align 4, addrspace(5) +// DIEXPR-IR-NEXT: [[FUNCVARAPOINTER:%.*]] = alloca ptr, align 8, addrspace(5) +// DIEXPR-IR-NEXT: [[FUNCVARBPOINTER:%.*]] = alloca ptr, align 8, addrspace(5) +// DIEXPR-IR-NEXT: [[ARG_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[ARG_ADDR]] to ptr +// DIEXPR-IR-NEXT: [[FUNCVARA_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[FUNCVARA]] to ptr +// DIEXPR-IR-NEXT: [[FUNCVARB_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[FUNCVARB]] to ptr +// DIEXPR-IR-NEXT: [[FUNCVARAPOINTER_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[FUNCVARAPOINTER]] to ptr +// DIEXPR-IR-NEXT: [[FUNCVARBPOINTER_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[FUNCVARBPOINTER]] to ptr +// DIEXPR-IR-NEXT: store i32 [[ARG:%.*]], ptr [[ARG_ADDR_ASCAST]], align 4 +// DIEXPR-IR-NEXT: call void @llvm.dbg.def(metadata [[META67:![0-9]+]], metadata ptr addrspace(5) [[ARG_ADDR]]), !dbg [[DBG68:![0-9]+]] +// DIEXPR-IR-NEXT: call void @llvm.dbg.def(metadata [[META69:![0-9]+]], metadata ptr addrspace(5) [[FUNCVARA]]), !dbg [[DBG70:![0-9]+]] +// DIEXPR-IR-NEXT: call void @llvm.dbg.def(metadata [[META71:![0-9]+]], metadata ptr addrspace(5) [[FUNCVARB]]), !dbg [[DBG72:![0-9]+]] +// DIEXPR-IR-NEXT: call void @llvm.dbg.def(metadata [[META73:![0-9]+]], metadata ptr addrspace(5) [[FUNCVARAPOINTER]]), !dbg [[DBG74:![0-9]+]] +// DIEXPR-IR-NEXT: store ptr [[FUNCVARA_ASCAST]], ptr [[FUNCVARAPOINTER_ASCAST]], align 8, !dbg [[DBG74]] +// DIEXPR-IR-NEXT: call void @llvm.dbg.def(metadata [[META75:![0-9]+]], metadata ptr addrspace(5) [[FUNCVARBPOINTER]]), !dbg [[DBG76:![0-9]+]] +// DIEXPR-IR-NEXT: store ptr [[FUNCVARB_ASCAST]], ptr [[FUNCVARBPOINTER_ASCAST]], align 8, !dbg [[DBG76]] +// DIEXPR-IR-NEXT: ret void, !dbg [[DBG77:![0-9]+]] +// +// DIEXPRESSION-IR-LABEL: @_Z5func1i( +// DIEXPRESSION-IR-NEXT: entry: +// DIEXPRESSION-IR-NEXT: [[ARG_ADDR:%.*]] = alloca i32, align 4, addrspace(5) +// DIEXPRESSION-IR-NEXT: [[FUNCVARA:%.*]] = alloca i32, align 4, addrspace(5) +// DIEXPRESSION-IR-NEXT: [[FUNCVARB:%.*]] = alloca i32, align 4, addrspace(5) +// DIEXPRESSION-IR-NEXT: [[FUNCVARAPOINTER:%.*]] = alloca ptr, align 8, addrspace(5) +// DIEXPRESSION-IR-NEXT: [[FUNCVARBPOINTER:%.*]] = alloca ptr, align 8, addrspace(5) +// DIEXPRESSION-IR-NEXT: [[ARG_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[ARG_ADDR]] to ptr +// DIEXPRESSION-IR-NEXT: [[FUNCVARA_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[FUNCVARA]] to ptr +// DIEXPRESSION-IR-NEXT: [[FUNCVARB_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[FUNCVARB]] to ptr +// DIEXPRESSION-IR-NEXT: [[FUNCVARAPOINTER_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[FUNCVARAPOINTER]] to ptr +// DIEXPRESSION-IR-NEXT: [[FUNCVARBPOINTER_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[FUNCVARBPOINTER]] to ptr +// DIEXPRESSION-IR-NEXT: store i32 [[ARG:%.*]], ptr [[ARG_ADDR_ASCAST]], align 4 +// DIEXPRESSION-IR-NEXT: call void @llvm.dbg.declare(metadata ptr addrspace(5) [[ARG_ADDR]], metadata [[META48:![0-9]+]], metadata !DIExpression(DIOpArg(0, ptr addrspace(5)), DIOpDeref(i32))), !dbg [[DBG53:![0-9]+]] +// DIEXPRESSION-IR-NEXT: call void @llvm.dbg.declare(metadata ptr addrspace(5) [[FUNCVARA]], metadata [[META49:![0-9]+]], metadata !DIExpression(DIOpArg(0, ptr addrspace(5)), DIOpDeref(i32))), !dbg [[DBG54:![0-9]+]] +// DIEXPRESSION-IR-NEXT: call void @llvm.dbg.declare(metadata ptr addrspace(5) [[FUNCVARB]], metadata [[META50:![0-9]+]], metadata !DIExpression(DIOpArg(0, ptr addrspace(5)), DIOpDeref(i32))), !dbg [[DBG55:![0-9]+]] +// DIEXPRESSION-IR-NEXT: call void @llvm.dbg.declare(metadata ptr addrspace(5) [[FUNCVARAPOINTER]], metadata [[META51:![0-9]+]], metadata !DIExpression(DIOpArg(0, ptr addrspace(5)), DIOpDeref(ptr))), !dbg [[DBG56:![0-9]+]] +// DIEXPRESSION-IR-NEXT: store ptr [[FUNCVARA_ASCAST]], ptr [[FUNCVARAPOINTER_ASCAST]], align 8, !dbg [[DBG56]] +// DIEXPRESSION-IR-NEXT: call void @llvm.dbg.declare(metadata ptr addrspace(5) [[FUNCVARBPOINTER]], metadata [[META52:![0-9]+]], metadata !DIExpression(DIOpArg(0, ptr addrspace(5)), DIOpDeref(ptr))), !dbg [[DBG57:![0-9]+]] +// DIEXPRESSION-IR-NEXT: store ptr [[FUNCVARB_ASCAST]], ptr [[FUNCVARBPOINTER_ASCAST]], align 8, !dbg [[DBG57]] +// DIEXPRESSION-IR-NEXT: ret void, !dbg [[DBG58:![0-9]+]] +// +__device__ void func1(int Arg) { + int FuncVarA; + int FuncVarB; + + auto *FuncVarAPointer = &FuncVarA; + auto *FuncVarBPointer = &FuncVarB; +} + +struct pair { int first, second; }; +// DIEXPR-IR-LABEL: @_Z5func14pair( +// DIEXPR-IR-NEXT: entry: +// DIEXPR-IR-NEXT: [[P:%.*]] = alloca [[STRUCT_PAIR:%.*]], align 4, addrspace(5) +// DIEXPR-IR-NEXT: [[P1:%.*]] = addrspacecast ptr addrspace(5) [[P]] to ptr +// DIEXPR-IR-NEXT: store [2 x i32] [[P_COERCE:%.*]], ptr [[P1]], align 4 +// DIEXPR-IR-NEXT: call void @llvm.dbg.def(metadata [[META87:![0-9]+]], metadata ptr addrspace(5) [[P]]), !dbg [[DBG88:![0-9]+]] +// DIEXPR-IR-NEXT: ret void, !dbg [[DBG89:![0-9]+]] +// +// DIEXPRESSION-IR-LABEL: @_Z5func14pair( +// DIEXPRESSION-IR-NEXT: entry: +// DIEXPRESSION-IR-NEXT: [[P:%.*]] = alloca [[STRUCT_PAIR:%.*]], align 4, addrspace(5) +// DIEXPRESSION-IR-NEXT: [[P1:%.*]] = addrspacecast ptr addrspace(5) [[P]] to ptr +// DIEXPRESSION-IR-NEXT: store [2 x i32] [[P_COERCE:%.*]], ptr [[P1]], align 4 +// DIEXPRESSION-IR-NEXT: call void @llvm.dbg.declare(metadata ptr addrspace(5) [[P]], metadata [[META67:![0-9]+]], metadata !DIExpression(DIOpArg(0, ptr addrspace(5)), DIOpDeref([[STRUCT_PAIR]]))), !dbg [[DBG68:![0-9]+]] +// DIEXPRESSION-IR-NEXT: ret void, !dbg [[DBG69:![0-9]+]] +// +__device__ void func1(pair p) {} + +//. +// DIEXPR-IR: [[META8:![0-9]+]] = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: [[META9:![0-9]+]], producer: "{{.*}}clang version {{.*}}", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None) +// DIEXPR-IR: [[META9]] = !DIFile(filename: "{{.*}}", directory: {{.*}}) +// DIEXPR-IR: [[META12:![0-9]+]] = !DIFile(filename: "{{.*}}", directory: {{.*}}) +// DIEXPR-IR: [[META13:![0-9]+]] = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +// DIEXPR-IR: [[META26:![0-9]+]] = distinct !DISubprogram(name: "kernel1", linkageName: "_Z7kernel1i", scope: [[META12]], file: [[META12]], line: 79, type: [[META27:![0-9]+]], scopeLine: 79, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: [[META8]], retainedNodes: [[META29:![0-9]+]]) +// DIEXPR-IR: [[META27]] = !DISubroutineType(types: [[META28:![0-9]+]]) +// DIEXPR-IR: [[META28]] = !{null, [[META13]]} +// DIEXPR-IR: [[META29]] = !{[[META30:![0-9]+]], [[META31:![0-9]+]], [[META32:![0-9]+]], [[META33:![0-9]+]], [[META35:![0-9]+]], [[META36:![0-9]+]], [[META37:![0-9]+]]} +// DIEXPR-IR: [[META30]] = !DILocalVariable(name: "Arg", arg: 1, scope: [[META26]], file: [[META12]], line: 79, type: [[META13]]) +// DIEXPR-IR: [[META31]] = !DILocalVariable(name: "KernelVarA", scope: [[META26]], file: [[META12]], line: 82, type: [[META13]]) +// DIEXPR-IR: [[META32]] = !DILocalVariable(name: "KernelVarB", scope: [[META26]], file: [[META12]], line: 83, type: [[META13]]) +// DIEXPR-IR: [[META33]] = !DILocalVariable(name: "KernelVarSharedAPointer", scope: [[META26]], file: [[META12]], line: 85, type: [[META34:![0-9]+]]) +// DIEXPR-IR: [[META34]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: [[META13]], size: 64) +// DIEXPR-IR: [[META35]] = !DILocalVariable(name: "KernelVarSharedBPointer", scope: [[META26]], file: [[META12]], line: 86, type: [[META34]]) +// DIEXPR-IR: [[META36]] = !DILocalVariable(name: "KernelVarAPointer", scope: [[META26]], file: [[META12]], line: 87, type: [[META34]]) +// DIEXPR-IR: [[META37]] = !DILocalVariable(name: "KernelVarBPointer", scope: [[META26]], file: [[META12]], line: 88, type: [[META34]]) +// DIEXPR-IR: [[META45]] = distinct !DILifetime(object: [[META30]], location: !DIExpr(DIOpReferrer(ptr addrspace(5)), DIOpDeref(i32))) +// DIEXPR-IR: [[DBG46]] = !DILocation(line: 79, column: 29, scope: [[META26]]) +// DIEXPR-IR: [[META47]] = distinct !DILifetime(object: [[META31]], location: !DIExpr(DIOpReferrer(ptr addrspace(5)), DIOpDeref(i32))) +// DIEXPR-IR: [[DBG48]] = !DILocation(line: 82, column: 7, scope: [[META26]]) +// DIEXPR-IR: [[META49]] = distinct !DILifetime(object: [[META32]], location: !DIExpr(DIOpReferrer(ptr addrspace(5)), DIOpDeref(i32))) +// DIEXPR-IR: [[DBG50]] = !DILocation(line: 83, column: 7, scope: [[META26]]) +// DIEXPR-IR: [[META51]] = distinct !DILifetime(object: [[META33]], location: !DIExpr(DIOpReferrer(ptr addrspace(5)), DIOpDeref(ptr))) +// DIEXPR-IR: [[DBG52]] = !DILocation(line: 85, column: 9, scope: [[META26]]) +// DIEXPR-IR: [[META53]] = distinct !DILifetime(object: [[META35]], location: !DIExpr(DIOpReferrer(ptr addrspace(5)), DIOpDeref(ptr))) +// DIEXPR-IR: [[DBG54]] = !DILocation(line: 86, column: 9, scope: [[META26]]) +// DIEXPR-IR: [[META55]] = distinct !DILifetime(object: [[META36]], location: !DIExpr(DIOpReferrer(ptr addrspace(5)), DIOpDeref(ptr))) +// DIEXPR-IR: [[DBG56]] = !DILocation(line: 87, column: 9, scope: [[META26]]) +// DIEXPR-IR: [[META57]] = distinct !DILifetime(object: [[META37]], location: !DIExpr(DIOpReferrer(ptr addrspace(5)), DIOpDeref(ptr))) +// DIEXPR-IR: [[DBG58]] = !DILocation(line: 88, column: 9, scope: [[META26]]) +// DIEXPR-IR: [[DBG59]] = !DILocation(line: 89, column: 1, scope: [[META26]]) +// DIEXPR-IR: [[META60:![0-9]+]] = distinct !DISubprogram(name: "func1", linkageName: "_Z5func1i", scope: [[META12]], file: [[META12]], line: 135, type: [[META27]], scopeLine: 135, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: [[META8]], retainedNodes: [[META61:![0-9]+]]) +// DIEXPR-IR: [[META61]] = !{[[META62:![0-9]+]], [[META63:![0-9]+]], [[META64:![0-9]+]], [[META65:![0-9]+]], [[META66:![0-9]+]]} +// DIEXPR-IR: [[META62]] = !DILocalVariable(name: "Arg", arg: 1, scope: [[META60]], file: [[META12]], line: 135, type: [[META13]]) +// DIEXPR-IR: [[META63]] = !DILocalVariable(name: "FuncVarA", scope: [[META60]], file: [[META12]], line: 136, type: [[META13]]) +// DIEXPR-IR: [[META64]] = !DILocalVariable(name: "FuncVarB", scope: [[META60]], file: [[META12]], line: 137, type: [[META13]]) +// DIEXPR-IR: [[META65]] = !DILocalVariable(name: "FuncVarAPointer", scope: [[META60]], file: [[META12]], line: 139, type: [[META34]]) +// DIEXPR-IR: [[META66]] = !DILocalVariable(name: "FuncVarBPointer", scope: [[META60]], file: [[META12]], line: 140, type: [[META34]]) +// DIEXPR-IR: [[META67]] = distinct !DILifetime(object: [[META62]], location: !DIExpr(DIOpReferrer(ptr addrspace(5)), DIOpDeref(i32))) +// DIEXPR-IR: [[DBG68]] = !DILocation(line: 135, column: 27, scope: [[META60]]) +// DIEXPR-IR: [[META69]] = distinct !DILifetime(object: [[META63]], location: !DIExpr(DIOpReferrer(ptr addrspace(5)), DIOpDeref(i32))) +// DIEXPR-IR: [[DBG70]] = !DILocation(line: 136, column: 7, scope: [[META60]]) +// DIEXPR-IR: [[META71]] = distinct !DILifetime(object: [[META64]], location: !DIExpr(DIOpReferrer(ptr addrspace(5)), DIOpDeref(i32))) +// DIEXPR-IR: [[DBG72]] = !DILocation(line: 137, column: 7, scope: [[META60]]) +// DIEXPR-IR: [[META73]] = distinct !DILifetime(object: [[META65]], location: !DIExpr(DIOpReferrer(ptr addrspace(5)), DIOpDeref(ptr))) +// DIEXPR-IR: [[DBG74]] = !DILocation(line: 139, column: 9, scope: [[META60]]) +// DIEXPR-IR: [[META75]] = distinct !DILifetime(object: [[META66]], location: !DIExpr(DIOpReferrer(ptr addrspace(5)), DIOpDeref(ptr))) +// DIEXPR-IR: [[DBG76]] = !DILocation(line: 140, column: 9, scope: [[META60]]) +// DIEXPR-IR: [[DBG77]] = !DILocation(line: 141, column: 1, scope: [[META60]]) +// DIEXPR-IR: [[META78:![0-9]+]] = distinct !DISubprogram(name: "func1", linkageName: "_Z5func14pair", scope: [[META12]], file: [[META12]], line: 160, type: [[META79:![0-9]+]], scopeLine: 160, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: [[META8]], retainedNodes: [[META85:![0-9]+]]) +// DIEXPR-IR: [[META79]] = !DISubroutineType(types: [[META80:![0-9]+]]) +// DIEXPR-IR: [[META80]] = !{null, [[META81:![0-9]+]]} +// DIEXPR-IR: [[META81]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "pair", file: [[META12]], line: 143, size: 64, flags: DIFlagTypePassByValue, elements: [[META82:![0-9]+]], identifier: "_ZTS4pair") +// DIEXPR-IR: [[META82]] = !{[[META83:![0-9]+]], [[META84:![0-9]+]]} +// DIEXPR-IR: [[META83]] = !DIDerivedType(tag: DW_TAG_member, name: "first", scope: [[META81]], file: [[META12]], line: 143, baseType: [[META13]], size: 32) +// DIEXPR-IR: [[META84]] = !DIDerivedType(tag: DW_TAG_member, name: "second", scope: [[META81]], file: [[META12]], line: 143, baseType: [[META13]], size: 32, offset: 32) +// DIEXPR-IR: [[META85]] = !{[[META86:![0-9]+]]} +// DIEXPR-IR: [[META86]] = !DILocalVariable(name: "p", arg: 1, scope: [[META78]], file: [[META12]], line: 160, type: [[META81]]) +// DIEXPR-IR: [[META87]] = distinct !DILifetime(object: [[META86]], location: !DIExpr(DIOpReferrer(ptr addrspace(5)), DIOpDeref(%struct.pair))) +// DIEXPR-IR: [[DBG88]] = !DILocation(line: 160, column: 28, scope: [[META78]]) +// DIEXPR-IR: [[DBG89]] = !DILocation(line: 160, column: 32, scope: [[META78]]) +//. +// DIEXPRESSION-IR: [[META0:![0-9]+]] = !DIGlobalVariableExpression(var: [[META1:![0-9]+]], expr: !DIExpression(DIOpArg(0, ptr addrspace(3)), DIOpDeref(i32))) +// DIEXPRESSION-IR: [[META1]] = distinct !DIGlobalVariable(name: "GlobalSharedA", scope: [[META2:![0-9]+]], file: [[META7:![0-9]+]], line: 12, type: [[META8:![0-9]+]], isLocal: false, isDefinition: true, memorySpace: DW_MSPACE_LLVM_group) +// DIEXPRESSION-IR: [[META2]] = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: [[META3:![0-9]+]], producer: "{{.*}}clang version {{.*}}", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, globals: [[META4:![0-9]+]], splitDebugInlining: false, nameTableKind: None) +// DIEXPRESSION-IR: [[META3]] = !DIFile(filename: "{{.*}}", directory: {{.*}}) +// DIEXPRESSION-IR: [[META4]] = !{[[META0]], [[META5:![0-9]+]], [[META9:![0-9]+]], [[META11:![0-9]+]], [[META13:![0-9]+]], [[META15:![0-9]+]], [[META17:![0-9]+]], [[META31:![0-9]+]]} +// DIEXPRESSION-IR: [[META5]] = !DIGlobalVariableExpression(var: [[META6:![0-9]+]], expr: !DIExpression(DIOpArg(0, ptr addrspace(3)), DIOpDeref(i32))) +// DIEXPRESSION-IR: [[META6]] = distinct !DIGlobalVariable(name: "GlobalSharedB", scope: [[META2]], file: [[META7]], line: 13, type: [[META8]], isLocal: false, isDefinition: true, memorySpace: DW_MSPACE_LLVM_group) +// DIEXPRESSION-IR: [[META7]] = !DIFile(filename: "{{.*}}", directory: {{.*}}) +// DIEXPRESSION-IR: [[META8]] = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +// DIEXPRESSION-IR: [[META9]] = !DIGlobalVariableExpression(var: [[META10:![0-9]+]], expr: !DIExpression(DIOpArg(0, ptr addrspace(1)), DIOpDeref(i32))) +// DIEXPRESSION-IR: [[META10]] = distinct !DIGlobalVariable(name: "GlobalDeviceA", scope: [[META2]], file: [[META7]], line: 14, type: [[META8]], isLocal: false, isDefinition: true, memorySpace: DW_MSPACE_LLVM_global) +// DIEXPRESSION-IR: [[META11]] = !DIGlobalVariableExpression(var: [[META12:![0-9]+]], expr: !DIExpression(DIOpArg(0, ptr addrspace(1)), DIOpDeref(i32))) +// DIEXPRESSION-IR: [[META12]] = distinct !DIGlobalVariable(name: "GlobalDeviceB", scope: [[META2]], file: [[META7]], line: 15, type: [[META8]], isLocal: false, isDefinition: true, memorySpace: DW_MSPACE_LLVM_global) +// DIEXPRESSION-IR: [[META13]] = !DIGlobalVariableExpression(var: [[META14:![0-9]+]], expr: !DIExpression(DIOpArg(0, ptr addrspace(4)), DIOpDeref(i32))) +// DIEXPRESSION-IR: [[META14]] = distinct !DIGlobalVariable(name: "GlobalConstantA", scope: [[META2]], file: [[META7]], line: 16, type: [[META8]], isLocal: false, isDefinition: true, memorySpace: DW_MSPACE_LLVM_constant) +// DIEXPRESSION-IR: [[META15]] = !DIGlobalVariableExpression(var: [[META16:![0-9]+]], expr: !DIExpression(DIOpArg(0, ptr addrspace(4)), DIOpDeref(i32))) +// DIEXPRESSION-IR: [[META16]] = distinct !DIGlobalVariable(name: "GlobalConstantB", scope: [[META2]], file: [[META7]], line: 17, type: [[META8]], isLocal: false, isDefinition: true, memorySpace: DW_MSPACE_LLVM_constant) +// DIEXPRESSION-IR: [[META17]] = !DIGlobalVariableExpression(var: [[META18:![0-9]+]], expr: !DIExpression(DIOpArg(0, ptr addrspace(3)), DIOpDeref(i32))) +// DIEXPRESSION-IR: [[META18]] = distinct !DIGlobalVariable(name: "KernelVarSharedA", scope: [[META19:![0-9]+]], file: [[META7]], line: 80, type: [[META8]], isLocal: true, isDefinition: true, memorySpace: DW_MSPACE_LLVM_group) +// DIEXPRESSION-IR: [[META19]] = distinct !DISubprogram(name: "kernel1", linkageName: "_Z7kernel1i", scope: [[META7]], file: [[META7]], line: 79, type: [[META20:![0-9]+]], scopeLine: 79, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: [[META2]], retainedNodes: [[META22:![0-9]+]]) +// DIEXPRESSION-IR: [[META20]] = !DISubroutineType(types: [[META21:![0-9]+]]) +// DIEXPRESSION-IR: [[META21]] = !{null, [[META8]]} +// DIEXPRESSION-IR: [[META22]] = !{[[META23]], [[META24]], [[META25]], [[META26]], [[META28]], [[META29]], [[META30]]} +// DIEXPRESSION-IR: [[META23]] = !DILocalVariable(name: "Arg", arg: 1, scope: [[META19]], file: [[META7]], line: 79, type: [[META8]]) +// DIEXPRESSION-IR: [[META24]] = !DILocalVariable(name: "KernelVarA", scope: [[META19]], file: [[META7]], line: 82, type: [[META8]]) +// DIEXPRESSION-IR: [[META25]] = !DILocalVariable(name: "KernelVarB", scope: [[META19]], file: [[META7]], line: 83, type: [[META8]]) +// DIEXPRESSION-IR: [[META26]] = !DILocalVariable(name: "KernelVarSharedAPointer", scope: [[META19]], file: [[META7]], line: 85, type: [[META27:![0-9]+]]) +// DIEXPRESSION-IR: [[META27]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: [[META8]], size: 64) +// DIEXPRESSION-IR: [[META28]] = !DILocalVariable(name: "KernelVarSharedBPointer", scope: [[META19]], file: [[META7]], line: 86, type: [[META27]]) +// DIEXPRESSION-IR: [[META29]] = !DILocalVariable(name: "KernelVarAPointer", scope: [[META19]], file: [[META7]], line: 87, type: [[META27]]) +// DIEXPRESSION-IR: [[META30]] = !DILocalVariable(name: "KernelVarBPointer", scope: [[META19]], file: [[META7]], line: 88, type: [[META27]]) +// DIEXPRESSION-IR: [[META31]] = !DIGlobalVariableExpression(var: [[META32:![0-9]+]], expr: !DIExpression(DIOpArg(0, ptr addrspace(3)), DIOpDeref(i32))) +// DIEXPRESSION-IR: [[META32]] = distinct !DIGlobalVariable(name: "KernelVarSharedB", scope: [[META19]], file: [[META7]], line: 81, type: [[META8]], isLocal: true, isDefinition: true, memorySpace: DW_MSPACE_LLVM_group) +// DIEXPRESSION-IR: [[DBG38]] = !DILocation(line: 79, column: 29, scope: [[META19]]) +// DIEXPRESSION-IR: [[DBG39]] = !DILocation(line: 82, column: 7, scope: [[META19]]) +// DIEXPRESSION-IR: [[DBG40]] = !DILocation(line: 83, column: 7, scope: [[META19]]) +// DIEXPRESSION-IR: [[DBG41]] = !DILocation(line: 85, column: 9, scope: [[META19]]) +// DIEXPRESSION-IR: [[DBG42]] = !DILocation(line: 86, column: 9, scope: [[META19]]) +// DIEXPRESSION-IR: [[DBG43]] = !DILocation(line: 87, column: 9, scope: [[META19]]) +// DIEXPRESSION-IR: [[DBG44]] = !DILocation(line: 88, column: 9, scope: [[META19]]) +// DIEXPRESSION-IR: [[DBG45]] = !DILocation(line: 89, column: 1, scope: [[META19]]) +// DIEXPRESSION-IR: [[META46:![0-9]+]] = distinct !DISubprogram(name: "func1", linkageName: "_Z5func1i", scope: [[META7]], file: [[META7]], line: 135, type: [[META20]], scopeLine: 135, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: [[META2]], retainedNodes: [[META47:![0-9]+]]) +// DIEXPRESSION-IR: [[META47]] = !{[[META48]], [[META49]], [[META50]], [[META51]], [[META52]]} +// DIEXPRESSION-IR: [[META48]] = !DILocalVariable(name: "Arg", arg: 1, scope: [[META46]], file: [[META7]], line: 135, type: [[META8]]) +// DIEXPRESSION-IR: [[META49]] = !DILocalVariable(name: "FuncVarA", scope: [[META46]], file: [[META7]], line: 136, type: [[META8]]) +// DIEXPRESSION-IR: [[META50]] = !DILocalVariable(name: "FuncVarB", scope: [[META46]], file: [[META7]], line: 137, type: [[META8]]) +// DIEXPRESSION-IR: [[META51]] = !DILocalVariable(name: "FuncVarAPointer", scope: [[META46]], file: [[META7]], line: 139, type: [[META27]]) +// DIEXPRESSION-IR: [[META52]] = !DILocalVariable(name: "FuncVarBPointer", scope: [[META46]], file: [[META7]], line: 140, type: [[META27]]) +// DIEXPRESSION-IR: [[DBG53]] = !DILocation(line: 135, column: 27, scope: [[META46]]) +// DIEXPRESSION-IR: [[DBG54]] = !DILocation(line: 136, column: 7, scope: [[META46]]) +// DIEXPRESSION-IR: [[DBG55]] = !DILocation(line: 137, column: 7, scope: [[META46]]) +// DIEXPRESSION-IR: [[DBG56]] = !DILocation(line: 139, column: 9, scope: [[META46]]) +// DIEXPRESSION-IR: [[DBG57]] = !DILocation(line: 140, column: 9, scope: [[META46]]) +// DIEXPRESSION-IR: [[DBG58]] = !DILocation(line: 141, column: 1, scope: [[META46]]) +// DIEXPRESSION-IR: [[META59:![0-9]+]] = distinct !DISubprogram(name: "func1", linkageName: "_Z5func14pair", scope: [[META7]], file: [[META7]], line: 160, type: [[META60:![0-9]+]], scopeLine: 160, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: [[META2]], retainedNodes: [[META66:![0-9]+]]) +// DIEXPRESSION-IR: [[META60]] = !DISubroutineType(types: [[META61:![0-9]+]]) +// DIEXPRESSION-IR: [[META61]] = !{null, [[META62:![0-9]+]]} +// DIEXPRESSION-IR: [[META62]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "pair", file: [[META7]], line: 143, size: 64, flags: DIFlagTypePassByValue, elements: [[META63:![0-9]+]], identifier: "_ZTS4pair") +// DIEXPRESSION-IR: [[META63]] = !{[[META64:![0-9]+]], [[META65:![0-9]+]]} +// DIEXPRESSION-IR: [[META64]] = !DIDerivedType(tag: DW_TAG_member, name: "first", scope: [[META62]], file: [[META7]], line: 143, baseType: [[META8]], size: 32) +// DIEXPRESSION-IR: [[META65]] = !DIDerivedType(tag: DW_TAG_member, name: "second", scope: [[META62]], file: [[META7]], line: 143, baseType: [[META8]], size: 32, offset: 32) +// DIEXPRESSION-IR: [[META66]] = !{[[META67]]} +// DIEXPRESSION-IR: [[META67]] = !DILocalVariable(name: "p", arg: 1, scope: [[META59]], file: [[META7]], line: 160, type: [[META62]]) +// DIEXPRESSION-IR: [[DBG68]] = !DILocation(line: 160, column: 28, scope: [[META59]]) +// DIEXPRESSION-IR: [[DBG69]] = !DILocation(line: 160, column: 32, scope: [[META59]]) +//. diff --git a/clang/test/CodeGenHIP/debug-info-disubprogram-retained-nodes-heterogeneous-dwarf.hip b/clang/test/CodeGenHIP/debug-info-disubprogram-retained-nodes-heterogeneous-dwarf.hip index 514dbf45626932..60cf42ef6144ed 100644 --- a/clang/test/CodeGenHIP/debug-info-disubprogram-retained-nodes-heterogeneous-dwarf.hip +++ b/clang/test/CodeGenHIP/debug-info-disubprogram-retained-nodes-heterogeneous-dwarf.hip @@ -1,5 +1,5 @@ // REQUIRES: amdgpu-registered-target -// RUN: %clang_cc1 -triple amdgcn-amd-amdhsa -x hip -emit-llvm -fcuda-is-device -debug-info-kind=limited -gheterogeneous-dwarf -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple amdgcn-amd-amdhsa -x hip -emit-llvm -fcuda-is-device -debug-info-kind=limited -gheterogeneous-dwarf=diexpr -o - %s | FileCheck %s #define __device__ __attribute__((device)) #define __shared__ __attribute__((shared)) diff --git a/clang/test/CodeGenHIP/debug-info-memory-space.hip b/clang/test/CodeGenHIP/debug-info-memory-space.hip index 28e52ceeee9b1a..6a272db9a33a0e 100644 --- a/clang/test/CodeGenHIP/debug-info-memory-space.hip +++ b/clang/test/CodeGenHIP/debug-info-memory-space.hip @@ -1,5 +1,5 @@ // REQUIRES: amdgpu-registered-target -// RUN: %clang_cc1 -triple amdgcn-amd-amdhsa -x hip -emit-llvm -fcuda-is-device -debug-info-kind=limited -gheterogeneous-dwarf -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple amdgcn-amd-amdhsa -x hip -emit-llvm -fcuda-is-device -debug-info-kind=limited -gheterogeneous-dwarf=diexpr -o - %s | FileCheck %s // CHECK-DAG: !DIGlobalVariable(name: "GlobalShared", scope: !{{[0-9]+}}, file: !{{[0-9]+}}, line: {{[0-9]+}}, type: !{{[0-9]+}}, isLocal: false, isDefinition: true, memorySpace: DW_MSPACE_LLVM_group) // CHECK-DAG: !DIGlobalVariable(name: "GlobalDevice", scope: !{{[0-9]+}}, file: !{{[0-9]+}}, line: {{[0-9]+}}, type: !{{[0-9]+}}, isLocal: false, isDefinition: true, memorySpace: DW_MSPACE_LLVM_global) // CHECK-DAG: !DIGlobalVariable(name: "GlobalConstant", scope: !{{[0-9]+}}, file: !{{[0-9]+}}, line: {{[0-9]+}}, type: !{{[0-9]+}}, isLocal: false, isDefinition: true, memorySpace: DW_MSPACE_LLVM_constant) diff --git a/clang/test/CodeGenOpenCL/amdgpu-debug-info-variable-expression-heterogeneous-dwarf.cl b/clang/test/CodeGenOpenCL/amdgpu-debug-info-variable-expression-heterogeneous-dwarf.cl index af0704032bc1a3..710300a197e77b 100644 --- a/clang/test/CodeGenOpenCL/amdgpu-debug-info-variable-expression-heterogeneous-dwarf.cl +++ b/clang/test/CodeGenOpenCL/amdgpu-debug-info-variable-expression-heterogeneous-dwarf.cl @@ -1,6 +1,6 @@ // REQUIRES: amdgpu-registered-target -// RUN: %clang -Xclang -cl-std=CL2.0 -emit-llvm -fno-discard-value-names -g -gheterogeneous-dwarf -O0 -S -nogpulib -target amdgcn-amd-amdhsa -mcpu=fiji -o - %s | FileCheck %s -// RUN: %clang -Xclang -cl-std=CL2.0 -emit-llvm -fno-discard-value-names -g -gheterogeneous-dwarf -O0 -S -nogpulib -target amdgcn-amd-amdhsa-opencl -mcpu=fiji -o - %s | FileCheck %s +// RUN: %clang -Xclang -cl-std=CL2.0 -emit-llvm -fno-discard-value-names -g -gheterogeneous-dwarf=diexpr -O0 -S -nogpulib -target amdgcn-amd-amdhsa -mcpu=fiji -o - %s | FileCheck %s +// RUN: %clang -Xclang -cl-std=CL2.0 -emit-llvm -fno-discard-value-names -g -gheterogeneous-dwarf=diexpr -O0 -S -nogpulib -target amdgcn-amd-amdhsa-opencl -mcpu=fiji -o - %s | FileCheck %s // CHECK-DAG: @FileVar0 = hidden addrspace(1) global ptr addrspace(1) null, align 8, !dbg.def ![[FILEVAR0_F:[0-9]+]] // CHECK-DAG: ![[FILEVAR0_GV:[0-9]+]] = distinct !DIGlobalVariable(name: "FileVar0", scope: !{{[0-9]+}}, file: !{{[0-9]+}}, line: {{[0-9]+}}, type: !{{[0-9]+}}, isLocal: false, isDefinition: true, memorySpace: DW_MSPACE_LLVM_global) diff --git a/clang/test/Driver/amdgpu-debug.cl b/clang/test/Driver/amdgpu-debug.cl index 9dea047309b15d..b3719a87e787a2 100644 --- a/clang/test/Driver/amdgpu-debug.cl +++ b/clang/test/Driver/amdgpu-debug.cl @@ -7,7 +7,7 @@ // CHECK-SIMPLE-NOT: "-disable-O0-optnone" // CHECK-SIMPLE-NOT: "-debug-info-kind=line-tables-only" // CHECK-SIMPLE-DAG: "-mllvm" "-amdgpu-spill-cfi-saved-regs" -// CHECK-SIMPLE-DAG: "-gheterogeneous-dwarf" +// CHECK-SIMPLE-DAG: "-gheterogeneous-dwarf=diexpr" // CHECK-SIMPLE-DAG: "-debugger-tuning=gdb" // CHECK-SIMPLE-NOT: "-disable-O0-optnone" // CHECK-SIMPLE-NOT: "-debug-info-kind=line-tables-only" @@ -18,7 +18,31 @@ // CHECK-NO-G-NOT: "-amdgpu-spill-cfi-saved-regs" // CHECK-NO-G-NOT: "-gheterogeneous-dwarf" +// Check that -gheterogeneous-dwarf can be enabled for non-AMDGCN +// RUN: %clang -### -target x86_64-linux-gnu -x cl -c -nogpuinc -nogpulib -emit-llvm -gheterogeneous-dwarf %s 2>&1 | FileCheck -check-prefix=CHECK-EXPLICIT-HETEROGENEOUS %s +// CHECK-EXPLICIT-HETEROGENEOUS: "-cc1" +// CHECK-EXPLICIT-HETEROGENEOUS: "-gheterogeneous-dwarf=diexpr" + // Check that -gheterogeneous-dwarf can be disabled for AMDGCN // RUN: %clang -### -target amdgcn-amd-amdhsa -x cl -c -nogpuinc -nogpulib -emit-llvm -g -gno-heterogeneous-dwarf %s 2>&1 | FileCheck -check-prefix=CHECK-NO-HETEROGENEOUS %s // CHECK-NO-HETEROGENEOUS: "-cc1" -// CHECK-NO-HETEROGENEOUS-NOT: "-gheterogeneous-dwarf" +// CHECK-NO-HETEROGENEOUS: "-gheterogeneous-dwarf=disabled" + +// Check that -gheterogeneous-dwarf= works for disabling +// RUN: %clang -### -target amdgcn-amd-amdhsa -x cl -c -nogpuinc -nogpulib -emit-llvm -g -gheterogeneous-dwarf=disabled %s 2>&1 | FileCheck -check-prefix=CHECK-DISABLED %s +// CHECK-DISABLED: "-cc1" +// CHECK-DISABLED: "-gheterogeneous-dwarf=disabled" + +// Check that -gheterogeneous-dwarf= works for diexpr +// RUN: %clang -### -target amdgcn-amd-amdhsa -x cl -c -nogpuinc -nogpulib -emit-llvm -g -gheterogeneous-dwarf=diexpr %s 2>&1 | FileCheck -check-prefix=CHECK-DIEXPR %s +// CHECK-DIEXPR: "-cc1" +// CHECK-DIEXPR: "-gheterogeneous-dwarf=diexpr" + +// Check that -gheterogeneous-dwarf= works for diexpression +// RUN: %clang -### -target amdgcn-amd-amdhsa -x cl -c -nogpuinc -nogpulib -emit-llvm -g -gheterogeneous-dwarf=diexpression %s 2>&1 | FileCheck -check-prefix=CHECK-DIEXPRESSION %s +// CHECK-DIEXPRESSION: "-cc1" +// CHECK-DIEXPRESSION: "-gheterogeneous-dwarf=diexpression" + +// Check that -gheterogeneous-dwarf= fails for unknown option +// RUN: not %clang -target amdgcn-amd-amdhsa -x cl -c -nogpuinc -nogpulib -emit-llvm -g -gheterogeneous-dwarf=unknown %s 2>&1 | FileCheck -check-prefix=CHECK-UNKNOWN %s +// CHECK-UNKNOWN: error: invalid value diff --git a/llvm/docs/AMDGPULLVMExtensionsForHeterogeneousDebugging.rst b/llvm/docs/AMDGPULLVMExtensionsForHeterogeneousDebugging.rst index 6dc4be1f1081d0..7fc8bcedac15c3 100644 --- a/llvm/docs/AMDGPULLVMExtensionsForHeterogeneousDebugging.rst +++ b/llvm/docs/AMDGPULLVMExtensionsForHeterogeneousDebugging.rst @@ -920,7 +920,9 @@ specifies implicit location storage ``ILS`` and offset 0. ``ILS`` has value ``L'`` comprises one implicit location description ``IL``. ``IL`` specifies implicit location storage ``ILS`` and offset 0. ``ILS`` has value ``V`` and size -``bitsizeof(T')``. +``bitsizeof(T')``. If ``bitsizeof(T')`` is greater than ``bitsizeof(T)`` and +``T'`` and ``T`` are both integral types, then the expression is not +well-formed. ``V`` is the value ``read(L, T)`` converted to type ``T'``. @@ -929,6 +931,41 @@ debug format. For example, when the target debug format is DWARF, the conversions used should be limited to those supported by the* ``DW_OP_convert`` *operation.]* +*[Note: The restriction on extending integral types can be resolved by using +either ``DIOpSExt(T')`` or ``DIOpZExt(T')``.]* + +``DIOpZExt`` +^^^^^^^^^^^^ + +.. code:: llvm + + DIOpZExt(T':type) + { (L:T) -> (L':T') } + +``L'`` comprises one implicit location description ``IL``. ``IL`` specifies +implicit location storage ``ILS`` and offset 0. ``ILS`` has value ``V`` and size +``bitsizeof(T')``. If ``T`` and ``T'`` are not integral types, or if +``bitsizeof(T')`` is less than or equal to ``bitsizeof(T)`` then the expression +is not well-formed. + +``V`` is the value ``read(L, T)`` zero-extended to type ``T'``. + +``DIOpSExt`` +^^^^^^^^^^^^ + +.. code:: llvm + + DIOpSExt(T':type) + { (L:T) -> (L':T') } + +``L'`` comprises one implicit location description ``IL``. ``IL`` specifies +implicit location storage ``ILS`` and offset 0. ``ILS`` has value ``V`` and size +``bitsizeof(T')``. If ``T`` and ``T'`` are not integral types, or if +``bitsizeof(T')`` is less than or equal to ``bitsizeof(T)`` then the expression +is not well-formed. + +``V`` is the value ``read(L, T)`` sign-extended to type ``T'``. + ``DIOpReinterpret`` ^^^^^^^^^^^^^^^^^^^ @@ -1136,19 +1173,33 @@ implicit location storage ``ILS`` and offset 0. ``ILS`` has value ``read(V2, T) implicit location storage ``ILS`` and offset 0. ``ILS`` has value ``read(V2, T) / read(V1, T)`` and size ``bitsizeof(T)``. -``DIOpShr`` -^^^^^^^^^^^ +``DIOpLShr`` +^^^^^^^^^^^^ .. code:: llvm - DIOpShr() + DIOpLShr() { (L1:T) (L2:T) -> (L:T) } ``L`` comprises one implicit location description ``IL``. ``IL`` specifies implicit location storage ``ILS`` and offset 0. ``ILS`` has value ``read(V2, T) ->> read(V1, t)`` and size ``bitsizeof(T)``. If ``T`` is an unsigned integral -type, then the result is filled with 0 bits. If ``T`` is a signed integral type, -then the result is filled with the sign bit of ``V1``. +>> read(V1, T)`` and size ``bitsizeof(T)``. The higher order bits are filled +with zeros. + +If ``T`` is not an integral type, then the expression is not well-formed. + +``DIOpAShr`` +^^^^^^^^^^^^ + +.. code:: llvm + + DIOpAShr() + { (L1:T) (L2:T) -> (L:T) } + +``L`` comprises one implicit location description ``IL``. ``IL`` specifies +implicit location storage ``ILS`` and offset 0. ``ILS`` has value ``read(V2, T) +>> read(V1, T)`` and size ``bitsizeof(T)``. The higher order bits are filled +with the value of the sign bit. If ``T`` is not an integral type, then the expression is not well-formed. @@ -1183,6 +1234,18 @@ model. If ``T`` is not an integral type or the source language is not implemented using a SIMD or SIMT execution model, then the expression is not well-formed. +``DIOpFragment`` +^^^^^^^^^^^^^^^^ + +.. code:: llvm + + DIOpFragment(O:unsigned, S:unsigned) + { -> } + +An operation with no effect, used only as a means to encode the "fragment" +position of the debug intrinsic or metadata which refers to the expression in +terms of an bit offset ``O`` and bit size ``S``. + Intrinsics ---------- diff --git a/llvm/include/llvm/AsmParser/LLParser.h b/llvm/include/llvm/AsmParser/LLParser.h index ee68d6b92a1e79..d7bfc401b9bb82 100644 --- a/llvm/include/llvm/AsmParser/LLParser.h +++ b/llvm/include/llvm/AsmParser/LLParser.h @@ -197,6 +197,9 @@ namespace llvm { bool parseTypeAtBeginning(Type *&Ty, unsigned &Read, const SlotMapping *Slots); + bool parseDIExpressionBodyAtBeginning(MDNode *&Result, unsigned &Read, + const SlotMapping *Slots); + LLVMContext &getContext() { return Context; } private: @@ -577,6 +580,9 @@ namespace llvm { template bool parseMDFieldsImpl(ParserTy ParseField, LocTy &ClosingLoc); bool parseSpecializedMDNode(MDNode *&N, bool IsDistinct = false); + bool parseDIExpressionBody(MDNode *&Result, bool IsDistinct); + + bool parseDIOpExpression(MDNode *&Result, bool IsDIExpr); #define HANDLE_SPECIALIZED_MDNODE_LEAF(CLASS) \ bool parse##CLASS(MDNode *&Result, bool IsDistinct); diff --git a/llvm/include/llvm/AsmParser/Parser.h b/llvm/include/llvm/AsmParser/Parser.h index b3adfd7fd76cfb..15cc7b5af837c8 100644 --- a/llvm/include/llvm/AsmParser/Parser.h +++ b/llvm/include/llvm/AsmParser/Parser.h @@ -21,6 +21,7 @@ namespace llvm { class Constant; +class DIExpression; class LLVMContext; class MemoryBufferRef; class Module; @@ -202,6 +203,11 @@ Type *parseType(StringRef Asm, SMDiagnostic &Err, const Module &M, Type *parseTypeAtBeginning(StringRef Asm, unsigned &Read, SMDiagnostic &Err, const Module &M, const SlotMapping *Slots = nullptr); +DIExpression *parseDIExpressionBodyAtBeginning(StringRef Asm, unsigned &Read, + SMDiagnostic &Err, + const Module &M, + const SlotMapping *Slots); + } // End llvm namespace #endif diff --git a/llvm/include/llvm/BinaryFormat/Dwarf.h b/llvm/include/llvm/BinaryFormat/Dwarf.h index fa8162be430cc8..a1d582d6b5b831 100644 --- a/llvm/include/llvm/BinaryFormat/Dwarf.h +++ b/llvm/include/llvm/BinaryFormat/Dwarf.h @@ -144,6 +144,9 @@ enum LocationAtom { DW_OP_LLVM_entry_value = 0x1003, ///< Only used in LLVM metadata. DW_OP_LLVM_implicit_pointer = 0x1004, ///< Only used in LLVM metadata. DW_OP_LLVM_arg = 0x1005, ///< Only used in LLVM metadata. + //DW_OP_LLVM_extract_bits_sext = 0x1006, ///< Only used in LLVM metadata. + //DW_OP_LLVM_extract_bits_zext = 0x1007, ///< Only used in LLVM metadata. + DW_OP_LLVM_poisoned = 0x1008, ///< Only used in LLVM metadata. }; enum LlvmUserLocationAtom { @@ -162,6 +165,17 @@ inline std::optional getUserOp(uint8_t Op) { } } +inline std::optional getNonUserOp(uint8_t UserOp) { + switch (UserOp) { +#define HANDLE_HETEROGENEOUS_OP(NAME) \ + case DW_OP_LLVM_USER_##NAME: \ + return DW_OP_LLVM_##NAME; +#include "llvm/BinaryFormat/Dwarf.def" + default: + return std::nullopt; + } +} + enum TypeKind : uint8_t { #define HANDLE_DW_ATE(ID, NAME, VERSION, VENDOR) DW_ATE_##NAME = ID, #include "llvm/BinaryFormat/Dwarf.def" diff --git a/llvm/include/llvm/CodeGen/TargetFrameLowering.h b/llvm/include/llvm/CodeGen/TargetFrameLowering.h index 6cd7f5f4f91cc3..9ef7e0ddc18c87 100644 --- a/llvm/include/llvm/CodeGen/TargetFrameLowering.h +++ b/llvm/include/llvm/CodeGen/TargetFrameLowering.h @@ -327,6 +327,11 @@ class TargetFrameLowering { insertFrameLocation(const MachineFunction &MF, DIExprBuilder &Builder, DIExprBuilder::Iterator BI, Type *ResultType) const; + virtual DIExpression *lowerFIArgToFPArg(const MachineFunction &MF, + const DIExpression *Expr, + uint64_t ArgIndex, + StackOffset Offset) const; + /// Same as \c getFrameIndexReference, except that the stack pointer (as /// opposed to the frame pointer) will be the preferred value for \p /// FrameReg. This is generally used for emitting statepoint or EH tables that diff --git a/llvm/include/llvm/IR/DIExprOps.def b/llvm/include/llvm/IR/DIExprOps.def index bea67a3653ae91..9f743a7ace5ab3 100644 --- a/llvm/include/llvm/IR/DIExprOps.def +++ b/llvm/include/llvm/IR/DIExprOps.def @@ -86,6 +86,10 @@ HANDLE_OP1(Constant, ConstantData *, LiteralValue) SEPARATOR HANDLE_OP1(Convert, Type *, ResultType) SEPARATOR +HANDLE_OP1(ZExt, Type *, ResultType) +SEPARATOR +HANDLE_OP1(SExt, Type *, ResultType) +SEPARATOR HANDLE_OP1(Reinterpret, Type *, ResultType) SEPARATOR HANDLE_OP1(BitOffset, Type *, ResultType) @@ -112,11 +116,15 @@ HANDLE_OP0(Mul) SEPARATOR HANDLE_OP0(Div) SEPARATOR -HANDLE_OP0(Shr) +HANDLE_OP0(LShr) +SEPARATOR +HANDLE_OP0(AShr) SEPARATOR HANDLE_OP0(Shl) SEPARATOR HANDLE_OP1(PushLane, Type *, ResultType) +SEPARATOR +HANDLE_OP2(Fragment, uint32_t, BitOffset, uint32_t, BitSize) #undef SEPARATOR #undef HANDLE_OP2 diff --git a/llvm/include/llvm/IR/DebugInfoMetadata.h b/llvm/include/llvm/IR/DebugInfoMetadata.h index 23bd19cedb925b..988f37ca795c21 100644 --- a/llvm/include/llvm/IR/DebugInfoMetadata.h +++ b/llvm/include/llvm/IR/DebugInfoMetadata.h @@ -2735,6 +2735,401 @@ class DIVariable : public DIObject { } }; +namespace DIOp { + +// These are the concrete alternatives that a DIOp::Variant encapsulates. +#define HANDLE_OP0(NAME) \ + class NAME { \ + public: \ + explicit constexpr NAME() {} \ + bool operator==(const NAME &O) const { return true; } \ + friend hash_code hash_value(const NAME &O); \ + static constexpr StringRef getAsmName(); \ + static constexpr unsigned getBitcodeID(); \ + }; +#define HANDLE_OP1(NAME, TYPE1, NAME1) \ + class NAME { \ + TYPE1 NAME1; \ + \ + public: \ + explicit constexpr NAME(TYPE1 NAME1) : NAME1(NAME1) {} \ + bool operator==(const NAME &O) const { return NAME1 == O.NAME1; } \ + friend hash_code hash_value(const NAME &O); \ + static constexpr StringRef getAsmName(); \ + static constexpr unsigned getBitcodeID(); \ + TYPE1 get##NAME1() const { return NAME1; } \ + void set##NAME1(TYPE1 NAME1) { this->NAME1 = NAME1; } \ + }; +#define HANDLE_OP2(NAME, TYPE1, NAME1, TYPE2, NAME2) \ + class NAME { \ + TYPE1 NAME1; \ + TYPE2 NAME2; \ + \ + public: \ + explicit constexpr NAME(TYPE1 NAME1, TYPE2 NAME2) \ + : NAME1(NAME1), NAME2(NAME2) {} \ + bool operator==(const NAME &O) const { \ + return NAME1 == O.NAME1 && NAME2 == O.NAME2; \ + } \ + friend hash_code hash_value(const NAME &O); \ + static constexpr StringRef getAsmName(); \ + static constexpr unsigned getBitcodeID(); \ + TYPE1 get##NAME1() const { return NAME1; } \ + void set##NAME1(TYPE1 NAME1) { this->NAME1 = NAME1; } \ + TYPE2 get##NAME2() const { return NAME2; } \ + void set##NAME2(TYPE2 NAME2) { this->NAME2 = NAME2; } \ + }; +LLVM_PACKED_START +#include "llvm/IR/DIExprOps.def" +LLVM_PACKED_END + +/// Container for a runtime-variant DIOp +using Variant = std::variant< +#define HANDLE_OP_NAME(NAME) NAME +#define SEPARATOR , +#include "llvm/IR/DIExprOps.def" + >; + +#define HANDLE_OP_NAME(NAME) \ + constexpr StringRef DIOp::NAME::getAsmName() { return "DIOp" #NAME; } +#include "llvm/IR/DIExprOps.def" + +StringRef getAsmName(const Variant &V); + +#define DEFINE_BC_ID(NAME, ID) \ + constexpr unsigned DIOp::NAME::getBitcodeID() { return ID; } +DEFINE_BC_ID(Referrer, 1u) +DEFINE_BC_ID(Arg, 2u) +DEFINE_BC_ID(TypeObject, 3u) +DEFINE_BC_ID(Constant, 4u) +DEFINE_BC_ID(Convert, 5u) +DEFINE_BC_ID(Reinterpret, 6u) +DEFINE_BC_ID(BitOffset, 7u) +DEFINE_BC_ID(ByteOffset, 8u) +DEFINE_BC_ID(Composite, 9u) +DEFINE_BC_ID(Extend, 10u) +DEFINE_BC_ID(Select, 11u) +DEFINE_BC_ID(AddrOf, 12u) +DEFINE_BC_ID(Deref, 13u) +DEFINE_BC_ID(Read, 14u) +DEFINE_BC_ID(Add, 15u) +DEFINE_BC_ID(Sub, 16u) +DEFINE_BC_ID(Mul, 17u) +DEFINE_BC_ID(Div, 18u) +DEFINE_BC_ID(LShr, 19u) +DEFINE_BC_ID(Shl, 20u) +DEFINE_BC_ID(PushLane, 21u) +DEFINE_BC_ID(Fragment, 22u) +DEFINE_BC_ID(ZExt, 23u) +DEFINE_BC_ID(SExt, 24u) +DEFINE_BC_ID(AShr, 25u) +#undef DEFINE_BC_ID + +unsigned getBitcodeID(const Variant &V); + +/// Get the number of stack elements this operation consumes. +unsigned getNumInputs(Variant V); + +// The sizeof of `Op` is the size of the largest union variant, which +// should essentially be defined as a packed struct equivalent to: +// +// uint8_t Index; // Internal to std::variant, but we expect this to be +// // the smallest available integral type which +// // can represent our set of alternatives. +// uint32_t I; +// void* P; +// +// Note that there is no public interface which lets a pointer to the members +// of the alternative types escape, and so we can safely pack them. This +// means huge performance benefits (smaller memory footprint and more +// cache-friendly traversal). +// +// This static_assert tries to catch issues where the struct is not packed into +// at most two 64-bit words, as we would expect it to be. +// +// FIXME: If we can constrain `I` further to <= 16 bits we should also +// fit in two 32-bit words on 32-bit targets. +static_assert(sizeof(DIOp::Variant) <= 16); + +} // namespace DIOp + +/// Context in which a DIExpression is to be evaluated, used to permit more +/// complete validation. +struct DIExpressionEnv { + /// The source variable whose location is being described by the expression. + DIVariable *Variable; + /// Argument(s) to the debug intrinsic or DIGlobalVariableExpression node + /// referencing the expression. + ArrayRef Arguments; + /// DataLayout of the Target associated with the expression. + const DataLayout &DL; +}; + +/// CRTP visitor class for visiting DIExpr operations in order. +/// +/// The derived class must provide an overload set for the method +/// `bool visit(OpT Op, Type *ResultType, ArrayRef Inputs)` handling +/// every "DIOp*" `OpT` (i.e. for every alternative type of `DIOp::Variant`). +/// The `ResultType` is the type of the entry the operation pushes onto the +/// stack (or `nullptr` if the operation pushes nothing). The `Inputs` are the +/// stack entries the operation consumes, where the highest index is the top of +/// the stack (i.e. the most recently pushed entry). The return value is +/// `true` when the visit succeeds, and `false` when it fails; a returned +/// `false` will short-circuit to the caller, so the rest of the expression will +/// not be visited. +/// +/// For convenience a no-op overload set is defined in this class, where each +/// method simply returns `true`. If the derived class does not intend to +/// exhaustively cover every "DIOp*" operation it can declare `using +/// DIExprConstVisitor::visit;` to bring the no-op overload set into +/// the derived class, and then it can selectively shadow the overloads it is +/// interested in. This scheme is employed to avoid the need for dynamic virtual +/// function dispatch. +/// +/// This class validates that the expression yields one stack entry. To visit +/// that final `StackEntry` the derived class can implement `bool +/// visitResult(StackEntry Result)`. +/// +/// To handle error messages generated by this class, the derived class can +/// define a method `bool error(const Twine &)` which will be called with +/// any error messages before `false` is returned. +/// +/// This class implements type propagation, and maintains a stack so operation +/// visitor functions can inspect their input stack entries. It validates +/// properties of the expression which can be checked purely by looking at the +/// expression itself, including: +/// +/// * Input and result type equality (e.g. for arithmetic operations) +/// * Type category requirements (e.g. for shift operations requiring integer +/// types) +/// * Input counts, including the dynamic input requirement of DIOpComposite +/// +/// Anything further, including debug intrinsic argument type compatibility +/// with DIOpArg uses, must be handled by the derived class if required. +template class DIExprConstVisitor { +protected: + LLVMContext &Context; + ArrayRef Expr; + + /// Represents the result of evaluating an operation. + /// ResultType cannot be null. + struct StackEntry { + DIOp::Variant Operation; + Type *ResultType; + + StackEntry(DIOp::Variant Operation, Type *ResultType) + : Operation(Operation), ResultType(ResultType) { + assert(ResultType && + "null ResultType indicates no StackEntry should be created"); + } + }; + + SmallVector Stack; + + bool error(const Twine &) { return false; } + + Derived &getDerived() { return static_cast(*this); } + + std::optional getTypeError(const Twine &Msg) { + getDerived().error(Msg); + return std::nullopt; + } + + // The getType overloads return: + // + // * std::nullopt when an error has occured. + // * nullptr when the operation does not push anything. + // * the type of the pushed entry, otherwise. + // + // Note: This assumes operations push either 0 or 1 entries, which is + // currently true. + + std::optional getType(DIOp::Referrer Op, ArrayRef) { + return Op.getResultType(); + } + + std::optional getType(DIOp::Arg Op, ArrayRef) { + return Op.getResultType(); + } + + std::optional getType(DIOp::TypeObject Op, ArrayRef) { + return Op.getResultType(); + } + + std::optional getType(DIOp::Constant Op, ArrayRef) { + return Op.getLiteralValue()->getType(); + } + + std::optional getType(DIOp::Convert Op, ArrayRef) { + return Op.getResultType(); + } + + std::optional getType(DIOp::ZExt Op, ArrayRef Ins) { + if (!Ins[0].ResultType->isIntegerTy()) + return getTypeError("DIOpZExt requires integer typed input"); + return Op.getResultType(); + } + + std::optional getType(DIOp::SExt Op, ArrayRef Ins) { + if (!Ins[0].ResultType->isIntegerTy()) + return getTypeError("DIOpSExt requires integer typed input"); + return Op.getResultType(); + } + + std::optional getType(DIOp::Reinterpret Op, ArrayRef) { + return Op.getResultType(); + } + + std::optional getType(DIOp::BitOffset Op, ArrayRef Ins) { + if (!Ins[0].ResultType->isIntegerTy()) + return getTypeError( + "DIOpBitOffset requires first input be integer typed"); + return Op.getResultType(); + } + + std::optional getType(DIOp::ByteOffset Op, ArrayRef Ins) { + if (!Ins[0].ResultType->isIntegerTy()) + return getTypeError( + "DIOpByteOffset requires first input be integer typed"); + return Op.getResultType(); + } + + std::optional getType(DIOp::Composite Op, ArrayRef Ins) { + assert(Op.getCount() == Ins.size() && + "DIOpComposite has wrong number of inputs"); + return Op.getResultType(); + } + + std::optional getType(DIOp::Extend Op, ArrayRef Ins) { + if (!Ins[0].ResultType->isPointerTy() && + !Ins[0].ResultType->isFloatingPointTy() && + !Ins[0].ResultType->isIntegerTy()) + return getTypeError( + "DIOpExtend child must have integer, floating point, or ptr type"); + return VectorType::get(Ins[0].ResultType, + ElementCount::getFixed(Op.getCount())); + } + + std::optional getType(DIOp::Select Op, ArrayRef Ins) { + if (Ins[0].ResultType != Ins[1].ResultType) + return getTypeError( + "DIOpSelect requires first two inputs have same type"); + if (!Ins[0].ResultType->isVectorTy()) + return getTypeError( + "DIOpSelect requires first two inputs to be vector typed"); + return Ins[0].ResultType; + } + + std::optional getType(DIOp::AddrOf Op, ArrayRef) { + // FIXME: Track this to ensure invariants on uses + return PointerType::get(Context, Op.getAddressSpace()); + } + + std::optional getType(DIOp::Deref Op, ArrayRef Ins) { + if (!Ins[0].ResultType->isPointerTy()) + return getTypeError("DIOpDeref requires input to be pointer typed"); + return Op.getResultType(); + } + + std::optional getType(DIOp::Read Op, ArrayRef Ins) { + return Ins[0].ResultType; + } + + template + std::optional getTypeBinOp(OpT Op, ArrayRef Ins) { + if (Ins[0].ResultType != Ins[1].ResultType) + return getTypeError(Twine(Op.getAsmName()) + + " requires identical type inputs"); + return Ins[0].ResultType; + } + + std::optional getType(DIOp::Add Op, ArrayRef Ins) { + return getTypeBinOp(Op, Ins); + } + + std::optional getType(DIOp::Sub Op, ArrayRef Ins) { + return getTypeBinOp(Op, Ins); + } + + std::optional getType(DIOp::Mul Op, ArrayRef Ins) { + return getTypeBinOp(Op, Ins); + } + + std::optional getType(DIOp::Div Op, ArrayRef Ins) { + return getTypeBinOp(Op, Ins); + } + + std::optional getType(DIOp::LShr, ArrayRef Ins) { + if (!Ins[0].ResultType->isIntegerTy() || !Ins[1].ResultType->isIntegerTy()) + return getTypeError("DIOpLShr requires all integer inputs"); + return Ins[0].ResultType; + } + + std::optional getType(DIOp::AShr, ArrayRef Ins) { + if (!Ins[0].ResultType->isIntegerTy() || !Ins[1].ResultType->isIntegerTy()) + return getTypeError("DIOpAShr requires all integer inputs"); + return Ins[0].ResultType; + } + + std::optional getType(DIOp::Shl, ArrayRef Ins) { + if (!Ins[0].ResultType->isIntegerTy() || !Ins[1].ResultType->isIntegerTy()) + return getTypeError("DIOpShl requires all integer inputs"); + return Ins[0].ResultType; + } + + std::optional getType(DIOp::PushLane Op, ArrayRef) { + if (!Op.getResultType()->isIntegerTy()) + return getTypeError("DIOpPushLane requires integer result type"); + return Op.getResultType(); + } + + std::optional getType(DIOp::Fragment, ArrayRef) { + return nullptr; + } + + template bool visitOperator(OpT Op) { + if (Stack.size() < getNumInputs(Op)) + return getDerived().error(Op.getAsmName() + " requires more inputs"); + auto InBegin = Stack.end() - getNumInputs(Op); + std::optional Ty = getType(Op, ArrayRef(InBegin, Stack.end())); + if (!Ty) + return false; + if (!getDerived().visit(Op, *Ty, ArrayRef(InBegin, Stack.end()))) + return false; + Stack.erase(InBegin, Stack.end()); + if (*Ty) + Stack.emplace_back(Op, *Ty); + return true; + } + +#define HANDLE_OP_NAME(NAME) \ + bool visit(DIOp::NAME Op, Type *ResultType, ArrayRef Inputs) { \ + return true; \ + } +#include "DIExprOps.def" + + bool visitResult(StackEntry Result) { return true; } + +public: + DIExprConstVisitor(LLVMContext &Context, ArrayRef Expr) + : Context(Context), Expr(Expr) {} + + bool visitInOrder() { + for (const auto &Op : Expr) { + if (!std::visit([this](auto Op) { return this->visitOperator(Op); }, Op)) + return false; + } + if (Stack.size() != 1) { + getDerived().error( + "DIOp expression requires one element on stack after evaluating"); + return false; + } + if (!getDerived().visitResult(Stack.back())) + return false; + return true; + } +}; + /// DWARF expression. /// /// This is (almost) a DWARF expression that modifies the location of a @@ -2748,15 +3143,56 @@ class DIExpression : public MDNode { friend class LLVMContextImpl; friend class MDNode; - std::vector Elements; +public: + using OldElements = std::vector; + using NewElements = SmallVector; + using OldElementsRef = ArrayRef; + using NewElementsRef = ArrayRef; + using ElementsRef = std::variant; + +private: + std::variant Elements; + + // When existing code operates on a DIOp-based (i.e. "NewElements") + // DIExpression they will transparently see this expression in place of + // the actual expression. So long as they unconditionally replace the + // expression with a new "OldElements" version derived from this poison we + // will see this DW_OP_LLVM_poisoned operation during DWARF generation and can + // e.g. lower it to an undefined location to reflect the fact that the + // expression was not understood by some pass. + // + // There is some risk that a particular set of circumstances in code from + // upstream could align to foil this scheme, e.g. if a pass were to + // inspect an expression to see if it contains some particular pattern + // and decides only to update the expression in the absense of that pattern + // then the poisoned expression would lead to it not making the change. In + // practice no such call-site could be identified in the codebase, and in + // general the decision to modify the expression is made irrespective of + // the expression contents (although the contents in many cases then + // influences exactly *how* the expression is modified). + static constexpr std::array PoisonedExpr = { + dwarf::DW_OP_LLVM_poisoned}; DIExpression(LLVMContext &C, StorageType Storage, ArrayRef Elements) : MDNode(C, DIExpressionKind, Storage, std::nullopt), - Elements(Elements.begin(), Elements.end()) {} + Elements(std::in_place_type, Elements.begin(), + Elements.end()) {} + DIExpression(LLVMContext &C, StorageType Storage, + ArrayRef Elements) + : MDNode(C, DIExpressionKind, Storage, std::nullopt), + Elements(std::in_place_type, Elements.begin(), + Elements.end()) {} ~DIExpression() = default; - static DIExpression *getImpl(LLVMContext &Context, - ArrayRef Elements, StorageType Storage, + // FIXME: workaround to avoid updating callsites for now + static DIExpression *getImpl(LLVMContext &Context, std::nullopt_t Elements, + StorageType Storage, bool ShouldCreate = true); + + static DIExpression *getImpl(LLVMContext &Context, OldElementsRef Elements, + StorageType Storage, bool ShouldCreate = true); + + static DIExpression *getImpl(LLVMContext &Context, bool /*ignored*/, + NewElementsRef Elements, StorageType Storage, bool ShouldCreate = true); TempDIExpression cloneImpl() const { @@ -2764,18 +3200,56 @@ class DIExpression : public MDNode { } public: + DEFINE_MDNODE_GET(DIExpression, (std::nullopt_t Elements), (Elements)) DEFINE_MDNODE_GET(DIExpression, (ArrayRef Elements), (Elements)) + // The bool parameter is ignored, and only present to disambiguate the + // overload for the new elements from the old for the empty initializer list + // case (i.e. DIExpression::new({})) + DEFINE_MDNODE_GET(DIExpression, + (bool /*ignored*/, ArrayRef Elements), + (false, Elements)) + + static DIExpression *getPoisoned(LLVMContext &Ctx) { + return get(Ctx, PoisonedExpr); + } + DIExpression *getPoisoned() const { return getPoisoned(getContext()); } TempDIExpression clone() const { return cloneImpl(); } - ArrayRef getElements() const { return Elements; } + OldElementsRef getElements() const { + if (auto *E = std::get_if(&Elements)) + return *E; + return PoisonedExpr; + } - unsigned getNumElements() const { return Elements.size(); } + unsigned getNumElements() const { return getElements().size(); } uint64_t getElement(unsigned I) const { - assert(I < Elements.size() && "Index out of range"); - return Elements[I]; + assert(I < getNumElements() && "Index out of range"); + return getElements()[I]; + } + + ElementsRef getElementsRef() const { + return std::visit([](auto &&V) -> ElementsRef { return {V}; }, Elements); + } + std::optional getOldElementsRef() const { + if (auto *E = std::get_if(&Elements)) + return *E; + return std::nullopt; + } + std::optional getNewElementsRef() const { + if (auto *E = std::get_if(&Elements)) + return *E; + return std::nullopt; + } + + template bool holds() const { + return std::holds_alternative(Elements); } + bool holdsOldElements() const { return holds(); } + bool holdsNewElements() const { return holds(); } + + bool isPoisoned() const; enum SignedOrUnsignedConstant { SignedConstant, UnsignedConstant }; /// Determine whether this represents a constant value, if so @@ -2792,6 +3266,10 @@ class DIExpression : public MDNode { /// (0 and 1). uint64_t getNumLocationOperands() const; + /// Return the number of unique location operands referred to (via DIOpArg) in + /// this expression. Like getNumLocationOperands, but for DIOp-DIExpressions. + uint64_t getNewNumLocationOperands() const; + using element_iterator = ArrayRef::iterator; element_iterator elements_begin() const { return getElements().begin(); } @@ -2896,7 +3374,9 @@ class DIExpression : public MDNode { } /// @} - bool isValid() const; + bool isValid(std::optional Env = std::nullopt, + std::optional> ErrS = + std::nullopt) const; static bool classof(const Metadata *MD) { return MD->getMetadataID() == DIExpressionKind; @@ -2936,8 +3416,12 @@ class DIExpression : public MDNode { static std::optional getFragmentInfo(expr_op_iterator Start, expr_op_iterator End); + static std::optional getFragmentInfo(NewElementsRef E); + /// Retrieve the details of this fragment expression. std::optional getFragmentInfo() const { + if (auto NewElements = getNewElementsRef()) + return getFragmentInfo(*NewElements); return getFragmentInfo(expr_op_begin(), expr_op_end()); } @@ -3071,6 +3555,15 @@ class DIExpression : public MDNode { ArrayRef Ops, unsigned ArgNo, bool StackValue = false); + /// Create a copy of \p Expr by appending the given list of \p Ops to each + /// instance of the operand `DIOpArg(ArgNo, OldArgType)`, updating OldArgType + /// to \p NewArgType if non-null. This is used to modify a specific location + /// used by \p Expr, such as when salvaging that location. + static DIExpression *appendNewOpsToArg(const DIExpression *Expr, + ArrayRef Ops, + unsigned ArgNo, + Type *NewArgType = nullptr); + /// Create a copy of \p Expr with each instance of /// `DW_OP_LLVM_arg, \p OldArg` replaced with `DW_OP_LLVM_arg, \p NewArg`, /// and each instance of `DW_OP_LLVM_arg, Arg` with `DW_OP_LLVM_arg, Arg - 1` @@ -3179,135 +3672,27 @@ template <> struct DenseMapInfo { static bool isEqual(const FragInfo &A, const FragInfo &B) { return A == B; } }; -namespace DIOp { - -// These are the concrete alternatives that a DIOp::Variant encapsulates. -#define HANDLE_OP0(NAME) \ - class NAME { \ - public: \ - explicit constexpr NAME() {} \ - bool operator==(const NAME &O) const { return true; } \ - friend hash_code hash_value(const NAME &O); \ - static constexpr StringRef getAsmName(); \ - static constexpr unsigned getBitcodeID(); \ - }; -#define HANDLE_OP1(NAME, TYPE1, NAME1) \ - class NAME { \ - TYPE1 NAME1; \ - \ - public: \ - explicit constexpr NAME(TYPE1 NAME1) : NAME1(NAME1) {} \ - bool operator==(const NAME &O) const { return NAME1 == O.NAME1; } \ - friend hash_code hash_value(const NAME &O); \ - static constexpr StringRef getAsmName(); \ - static constexpr unsigned getBitcodeID(); \ - TYPE1 get##NAME1() const { return NAME1; } \ - void set##NAME1(TYPE1 NAME1) { this->NAME1 = NAME1; } \ - }; -#define HANDLE_OP2(NAME, TYPE1, NAME1, TYPE2, NAME2) \ - class NAME { \ - TYPE1 NAME1; \ - TYPE2 NAME2; \ - \ - public: \ - explicit constexpr NAME(TYPE1 NAME1, TYPE2 NAME2) \ - : NAME1(NAME1), NAME2(NAME2) {} \ - bool operator==(const NAME &O) const { \ - return NAME1 == O.NAME1 && NAME2 == O.NAME2; \ - } \ - friend hash_code hash_value(const NAME &O); \ - static constexpr StringRef getAsmName(); \ - static constexpr unsigned getBitcodeID(); \ - TYPE1 get##NAME1() const { return NAME1; } \ - void set##NAME1(TYPE1 NAME1) { this->NAME1 = NAME1; } \ - TYPE2 get##NAME2() const { return NAME2; } \ - void set##NAME2(TYPE2 NAME2) { this->NAME2 = NAME2; } \ - }; -LLVM_PACKED_START -#include "llvm/IR/DIExprOps.def" -LLVM_PACKED_END - -/// Container for a runtime-variant DIOp -using Variant = std::variant< -#define HANDLE_OP_NAME(NAME) NAME -#define SEPARATOR , -#include "llvm/IR/DIExprOps.def" - >; - -#define HANDLE_OP_NAME(NAME) \ - constexpr StringRef DIOp::NAME::getAsmName() { return "DIOp" #NAME; } -#include "llvm/IR/DIExprOps.def" - -StringRef getAsmName(const Variant &V); - -#define DEFINE_BC_ID(NAME, ID) \ - constexpr unsigned DIOp::NAME::getBitcodeID() { return ID; } -DEFINE_BC_ID(Referrer, 1u) -DEFINE_BC_ID(Arg, 2u) -DEFINE_BC_ID(TypeObject, 3u) -DEFINE_BC_ID(Constant, 4u) -DEFINE_BC_ID(Convert, 5u) -DEFINE_BC_ID(Reinterpret, 6u) -DEFINE_BC_ID(BitOffset, 7u) -DEFINE_BC_ID(ByteOffset, 8u) -DEFINE_BC_ID(Composite, 9u) -DEFINE_BC_ID(Extend, 10u) -DEFINE_BC_ID(Select, 11u) -DEFINE_BC_ID(AddrOf, 12u) -DEFINE_BC_ID(Deref, 13u) -DEFINE_BC_ID(Read, 14u) -DEFINE_BC_ID(Add, 15u) -DEFINE_BC_ID(Sub, 16u) -DEFINE_BC_ID(Mul, 17u) -DEFINE_BC_ID(Div, 18u) -DEFINE_BC_ID(Shr, 19u) -DEFINE_BC_ID(Shl, 20u) -DEFINE_BC_ID(PushLane, 21u) -#undef DEFINE_BC_ID - -unsigned getBitcodeID(const Variant &V); - -// The sizeof of `Op` is the size of the largest union variant, which -// should essentially be defined as a packed struct equivalent to: -// -// uint8_t Index; // Internal to std::variant, but we expect this to be -// // the smallest available integral type which -// // can represent our set of alternatives. -// uint32_t I; -// void* P; -// -// Note that there is no public interface which lets a pointer to the members -// of the alternative types escape, and so we can safely pack them. This -// means huge performance benefits (smaller memory footprint and more -// cache-friendly traversal). -// -// This static_assert tries to catch issues where the struct is not packed into -// at most two 64-bit words, as we would expect it to be. -// -// FIXME: If we can constrain `I` further to <= 16 bits we should also -// fit in two 32-bit words on 32-bit targets. -static_assert(sizeof(DIOp::Variant) <= 16); - -} // namespace DIOp - template struct MDNodeKeyImpl; - /// Mutable buffer to manipulate debug info expressions. - /// - /// Example of creating a new expression from scratch: - /// - /// LLVMContext Ctx; - /// - /// DIExpr::Builder Builder(Ctx); - /// Builder.append(DIOp::InPlaceAdd).intoExpr(); - /// - /// Example of creating a new expression: - /// - /// DIExpr *Expr = ...; - /// ... - /// DIExpr *NewExpr = Expr.builder() - /// .append(DIOp::InPlaceDeref) - /// .intoExpr(); +/// Mutable buffer to manipulate debug info expressions. +/// +/// Example of creating a new expression from scratch: +/// +/// LLVMContext Ctx; +/// +/// DIExprBuilder Builder(Ctx); +/// Builder.append().intoExpr(); +/// +/// Example of modifying an expression: +/// +/// DIExpr *Expr = ...; +/// ... +/// DIExpr *NewExpr = Expr.builder() +/// .append(DIOp::InPlaceDeref) +/// .intoExpr(); +/// +/// Despite the name, it supports creating both DIExpr and DIOp-based +/// ("NewElements") DIExpression nodes. class DIExprBuilder { LLVMContext &C; SmallVector Elements; @@ -3320,8 +3705,12 @@ class DIExprBuilder { /// Create a builder for a new expression for the sequence of ops in \p IL. explicit DIExprBuilder(LLVMContext &C, std::initializer_list IL); + /// Create a builder for a new expression for the sequence of ops in \p V. + explicit DIExprBuilder(LLVMContext &C, ArrayRef V); /// Create a builder for a new expression, initially a copy of \p E. explicit DIExprBuilder(const DIExpr &E); + /// Create a builder for a new expression, initially a copy of \p E. + explicit DIExprBuilder(const DIExpression &E); class Iterator : public iterator_facade_base Elements; - if (Lex.getKind() != lltok::rparen) - do { - if (Lex.getKind() == lltok::DwarfOp) { - if (unsigned Op = dwarf::getOperationEncoding(Lex.getStrVal())) { - Lex.Lex(); - Elements.push_back(Op); - continue; - } - return tokError(Twine("invalid DWARF op '") + Lex.getStrVal() + "'"); - } - - if (Lex.getKind() == lltok::DwarfAttEncoding) { - if (unsigned Op = dwarf::getAttributeEncoding(Lex.getStrVal())) { - Lex.Lex(); - Elements.push_back(Op); - continue; - } - return tokError(Twine("invalid DWARF attribute encoding '") + - Lex.getStrVal() + "'"); - } - - if (Lex.getKind() != lltok::APSInt || Lex.getAPSIntVal().isSigned()) - return tokError("expected unsigned integer"); - - auto &U = Lex.getAPSIntVal(); - if (U.ugt(UINT64_MAX)) - return tokError("element too large, limit is " + Twine(UINT64_MAX)); - Elements.push_back(U.getZExtValue()); - Lex.Lex(); - } while (EatIfPresent(lltok::comma)); - - if (parseToken(lltok::rparen, "expected ')' here")) - return true; - - Result = GET_OR_DISTINCT(DIExpression, (Context, Elements)); - return false; -} - -/// ParseDIArgList: -/// ::= !DIArgList(i32 7, i64 %0) -bool LLParser::parseDIArgList(Metadata *&MD, PerFunctionState *PFS) { - assert(PFS && "Expected valid function state"); - assert(Lex.getKind() == lltok::MetadataVar && "Expected metadata type name"); - Lex.Lex(); - - if (parseToken(lltok::lparen, "expected '(' here")) - return true; - - SmallVector Args; - if (Lex.getKind() != lltok::rparen) - do { - Metadata *MD; - if (parseValueAsMetadata(MD, "expected value-as-metadata operand", PFS)) - return true; - Args.push_back(dyn_cast(MD)); - } while (EatIfPresent(lltok::comma)); - - if (parseToken(lltok::rparen, "expected ')' here")) - return true; - - MD = DIArgList::get(Context, Args); - return false; -} - -bool LLParser::parseDIExpr(MDNode *&Result, bool IsDistinct) { - if (IsDistinct) - return Lex.Error("'distinct' not allowed for !DIExpr"); - - assert(Lex.getKind() == lltok::MetadataVar && "Expected metadata type name"); - Lex.Lex(); - - if (parseToken(lltok::lparen, "expected '(' here")) - return true; - +// Common parser for both DIExpr and DIOp-based ("NewElements") DIExpression. +// Begins parsing assuming the name and open parenthesis has been parsed +// already, and populates Result with the appropriate metadata based on +// IsDIExpr. +// +// An empty DIExpr is permitted (although currently has no use), but an empty +// DIOp-based DIExpression is not as at least one DIOp token is required to +// disambiguate with an empty "OldElements" DIExpression. +bool LLParser::parseDIOpExpression(MDNode *&Result, bool IsDIExpr) { DIExprBuilder Builder(Context); - if (Lex.getKind() != lltok::rparen) + if (!IsDIExpr || Lex.getKind() != lltok::rparen) do { if (Lex.getKind() != lltok::DIOp) return tokError("expected DIOp"); @@ -5696,6 +5636,16 @@ bool LLParser::parseDIExpr(MDNode *&Result, bool IsDistinct) { if (parseFirstClassType(Ty)) return true; Builder.append(Ty); + } else if (Name == DIOp::ZExt::getAsmName()) { + Type *Ty = nullptr; + if (parseFirstClassType(Ty)) + return true; + Builder.append(Ty); + } else if (Name == DIOp::SExt::getAsmName()) { + Type *Ty = nullptr; + if (parseFirstClassType(Ty)) + return true; + Builder.append(Ty); } else if (Name == DIOp::Reinterpret::getAsmName()) { Type *Ty = nullptr; if (parseFirstClassType(Ty)) @@ -5741,6 +5691,15 @@ bool LLParser::parseDIExpr(MDNode *&Result, bool IsDistinct) { if (parseFirstClassType(Ty)) return true; Builder.append(Ty); + } else if (Name == DIOp::Fragment::getAsmName()) { + uint32_t BitOffset, BitSize; + if (parseUInt32(BitOffset)) + return true; + if (parseToken(lltok::comma, "expected ',' here")) + return true; + if (parseUInt32(BitSize)) + return true; + Builder.append(BitOffset, BitSize); } #define HANDLE_OP0(NAME) \ else if (Name == DIOp::NAME::getAsmName()) { \ @@ -5758,10 +5717,110 @@ bool LLParser::parseDIExpr(MDNode *&Result, bool IsDistinct) { if (parseToken(lltok::rparen, "expected ')' here")) return true; - Result = Builder.intoExpr(); + if (IsDIExpr) + Result = Builder.intoExpr(); + else + Result = Builder.intoExpression(); + return false; +} + +/// parseDIExpressionBody: +/// ::= (0, 7, -1) +bool LLParser::parseDIExpressionBody(MDNode *&Result, bool IsDistinct) { + if (parseToken(lltok::lparen, "expected '(' here")) + return true; + + if (Lex.getKind() == lltok::DIOp) + return parseDIOpExpression(Result, /*IsDIExpr=*/false); + + SmallVector Elements; + if (Lex.getKind() != lltok::rparen) + do { + if (Lex.getKind() == lltok::DwarfOp) { + if (unsigned Op = dwarf::getOperationEncoding(Lex.getStrVal())) { + Lex.Lex(); + Elements.push_back(Op); + continue; + } + return tokError(Twine("invalid DWARF op '") + Lex.getStrVal() + "'"); + } + + if (Lex.getKind() == lltok::DwarfAttEncoding) { + if (unsigned Op = dwarf::getAttributeEncoding(Lex.getStrVal())) { + Lex.Lex(); + Elements.push_back(Op); + continue; + } + return tokError(Twine("invalid DWARF attribute encoding '") + + Lex.getStrVal() + "'"); + } + + if (Lex.getKind() != lltok::APSInt || Lex.getAPSIntVal().isSigned()) + return tokError("expected unsigned integer"); + + auto &U = Lex.getAPSIntVal(); + if (U.ugt(UINT64_MAX)) + return tokError("element too large, limit is " + Twine(UINT64_MAX)); + Elements.push_back(U.getZExtValue()); + Lex.Lex(); + } while (EatIfPresent(lltok::comma)); + + if (parseToken(lltok::rparen, "expected ')' here")) + return true; + + Result = GET_OR_DISTINCT(DIExpression, (Context, Elements)); + return false; +} + +/// parseDIExpression: +/// ::= !DIExpression(0, 7, -1) +bool LLParser::parseDIExpression(MDNode *&Result, bool IsDistinct) { + assert(Lex.getKind() == lltok::MetadataVar && "Expected metadata type name"); + assert(Lex.getStrVal() == "DIExpression" && "Expected '!DIExpression'"); + Lex.Lex(); + + return parseDIExpressionBody(Result, IsDistinct); +} + +/// ParseDIArgList: +/// ::= !DIArgList(i32 7, i64 %0) +bool LLParser::parseDIArgList(Metadata *&MD, PerFunctionState *PFS) { + assert(PFS && "Expected valid function state"); + assert(Lex.getKind() == lltok::MetadataVar && "Expected metadata type name"); + Lex.Lex(); + + if (parseToken(lltok::lparen, "expected '(' here")) + return true; + + SmallVector Args; + if (Lex.getKind() != lltok::rparen) + do { + Metadata *MD; + if (parseValueAsMetadata(MD, "expected value-as-metadata operand", PFS)) + return true; + Args.push_back(dyn_cast(MD)); + } while (EatIfPresent(lltok::comma)); + + if (parseToken(lltok::rparen, "expected ')' here")) + return true; + + MD = DIArgList::get(Context, Args); return false; } +bool LLParser::parseDIExpr(MDNode *&Result, bool IsDistinct) { + if (IsDistinct) + return Lex.Error("'distinct' not allowed for !DIExpr"); + + assert(Lex.getKind() == lltok::MetadataVar && "Expected metadata type name"); + Lex.Lex(); + + if (parseToken(lltok::lparen, "expected '(' here")) + return true; + + return parseDIOpExpression(Result, /*IsDIExpr=*/true); +} + bool LLParser::parseDIFragment(MDNode *&Result, bool IsDistinct) { if (!IsDistinct) return Lex.Error("missing 'distinct', required for !DIFragment"); diff --git a/llvm/lib/AsmParser/Parser.cpp b/llvm/lib/AsmParser/Parser.cpp index eded892f358a89..07fdce981b084e 100644 --- a/llvm/lib/AsmParser/Parser.cpp +++ b/llvm/lib/AsmParser/Parser.cpp @@ -12,6 +12,7 @@ #include "llvm/AsmParser/Parser.h" #include "llvm/AsmParser/LLParser.h" +#include "llvm/IR/DebugInfoMetadata.h" #include "llvm/IR/Module.h" #include "llvm/IR/ModuleSummaryIndex.h" #include "llvm/Support/MemoryBuffer.h" @@ -224,3 +225,18 @@ Type *llvm::parseTypeAtBeginning(StringRef Asm, unsigned &Read, return nullptr; return Ty; } + +DIExpression *llvm::parseDIExpressionBodyAtBeginning(StringRef Asm, + unsigned &Read, + SMDiagnostic &Err, + const Module &M, + const SlotMapping *Slots) { + SourceMgr SM; + std::unique_ptr Buf = MemoryBuffer::getMemBuffer(Asm); + SM.AddNewSourceBuffer(std::move(Buf), SMLoc()); + MDNode *MD; + if (LLParser(Asm, SM, Err, const_cast(&M), nullptr, M.getContext()) + .parseDIExpressionBodyAtBeginning(MD, Read, Slots)) + return nullptr; + return dyn_cast(MD); +} diff --git a/llvm/lib/BinaryFormat/Dwarf.cpp b/llvm/lib/BinaryFormat/Dwarf.cpp index a1d7775d20e97b..d5e7be7183ce02 100644 --- a/llvm/lib/BinaryFormat/Dwarf.cpp +++ b/llvm/lib/BinaryFormat/Dwarf.cpp @@ -155,6 +155,8 @@ StringRef llvm::dwarf::OperationEncodingString(unsigned Encoding) { return "DW_OP_LLVM_implicit_pointer"; case DW_OP_LLVM_arg: return "DW_OP_LLVM_arg"; + case DW_OP_LLVM_poisoned: + return "DW_OP_LLVM_poisoned"; } } @@ -169,6 +171,7 @@ unsigned llvm::dwarf::getOperationEncoding(StringRef OperationEncodingString) { .Case("DW_OP_LLVM_entry_value", DW_OP_LLVM_entry_value) .Case("DW_OP_LLVM_implicit_pointer", DW_OP_LLVM_implicit_pointer) .Case("DW_OP_LLVM_arg", DW_OP_LLVM_arg) + .Case("DW_OP_LLVM_poisoned", DW_OP_LLVM_poisoned) .Default(0); } diff --git a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp index 437779a372a56b..4cbeeb0857aa4f 100644 --- a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp +++ b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp @@ -482,6 +482,9 @@ class MetadataLoader::MetadataLoaderImpl { /// True if metadata is being parsed for a module being ThinLTO imported. bool IsImporting = false; + template + Error appendDIOpsToBuilder(BuilderType &Builder, ArrayRef Elems); + Error parseOneMetadata(SmallVectorImpl &Record, unsigned Code, PlaceholderQueue &Placeholders, StringRef Blob, unsigned &NextMetadataNo); @@ -1248,6 +1251,184 @@ static Value *getValueFwdRef(BitcodeReaderValueList &ValueList, unsigned Idx, return nullptr; } +/// Walk through the elements of a DIOp-based DIExpr/DIExpression record and add +/// the operations to the builder type one by one. +template +Error MetadataLoader::MetadataLoaderImpl::appendDIOpsToBuilder( + BuilderType &Builder, ArrayRef Elems) { + while (Elems.size() > 0) { + auto DIOpID = Elems[0]; + Elems = Elems.slice(1); + switch (DIOpID) { + default: + return error("Invalid record"); +#define HANDLE_OP0(NAME) \ + case DIOp::NAME::getBitcodeID(): \ + Builder.template append(); \ + break; +#include "llvm/IR/DIExprOps.def" + case DIOp::Referrer::getBitcodeID(): { + if (Elems.size() < 1) + return error("Invalid record"); + Type *Ty = Callbacks.GetTypeByID(Elems[0]); + if (!Ty || !Ty->isFirstClassType()) + return error("Invalid record"); + Builder.template append(Ty); + Elems = Elems.slice(1); + break; + } + case DIOp::Arg::getBitcodeID(): { + if (Elems.size() < 2) + return error("Invalid record"); + Type *Ty = Callbacks.GetTypeByID(Elems[0]); + if (!Ty || !Ty->isFirstClassType()) + return error("Invalid record"); + Builder.template append(Elems[1], Ty); + Elems = Elems.slice(2); + break; + } + case DIOp::TypeObject::getBitcodeID(): { + if (Elems.size() < 1) + return error("Invalid record"); + Type *Ty = Callbacks.GetTypeByID(Elems[0]); + if (!Ty || !Ty->isFirstClassType()) + return error("Invalid record"); + Builder.template append(Ty); + Elems = Elems.slice(1); + break; + } + case DIOp::Constant::getBitcodeID(): { + if (Elems.size() < 2) + return error("Invalid record"); + Type *Ty = Callbacks.GetTypeByID(Elems[0]); + if (!Ty || !Ty->isFirstClassType()) + return error("Invalid record"); + Value *V = ValueList[Elems[1]]; + if (!V || !isa(V)) + return error("Invalid record"); + if (Ty != V->getType()) + report_fatal_error("Invalid record"); + Builder.template append(cast(V)); + Elems = Elems.slice(2); + break; + } + case DIOp::Convert::getBitcodeID(): { + if (Elems.size() < 1) + return error("Invalid record"); + Type *Ty = Callbacks.GetTypeByID(Elems[0]); + if (!Ty || !Ty->isFirstClassType()) + return error("Invalid record"); + Builder.template append(Ty); + Elems = Elems.slice(1); + break; + } + case DIOp::ZExt::getBitcodeID(): { + if (Elems.size() < 1) + return error("Invalid record"); + Type *Ty = Callbacks.GetTypeByID(Elems[0]); + if (!Ty || !Ty->isFirstClassType()) + return error("Invalid record"); + Builder.template append(Ty); + Elems = Elems.slice(1); + break; + } + case DIOp::SExt::getBitcodeID(): { + if (Elems.size() < 1) + return error("Invalid record"); + Type *Ty = Callbacks.GetTypeByID(Elems[0]); + if (!Ty || !Ty->isFirstClassType()) + return error("Invalid record"); + Builder.template append(Ty); + Elems = Elems.slice(1); + break; + } + case DIOp::Reinterpret::getBitcodeID(): { + if (Elems.size() < 1) + return error("Invalid record"); + Type *Ty = Callbacks.GetTypeByID(Elems[0]); + if (!Ty || !Ty->isFirstClassType()) + return error("Invalid record"); + Builder.template append(Ty); + Elems = Elems.slice(1); + break; + } + case DIOp::BitOffset::getBitcodeID(): { + if (Elems.size() < 1) + return error("Invalid record"); + Type *Ty = Callbacks.GetTypeByID(Elems[0]); + if (!Ty || !Ty->isFirstClassType()) + return error("Invalid record"); + Builder.template append(Ty); + Elems = Elems.slice(1); + break; + } + case DIOp::ByteOffset::getBitcodeID(): { + if (Elems.size() < 1) + return error("Invalid record"); + Type *Ty = Callbacks.GetTypeByID(Elems[0]); + if (!Ty || !Ty->isFirstClassType()) + return error("Invalid record"); + Builder.template append(Ty); + Elems = Elems.slice(1); + break; + } + case DIOp::Composite::getBitcodeID(): { + if (Elems.size() < 2) + return error("Invalid record"); + Type *Ty = Callbacks.GetTypeByID(Elems[0]); + if (!Ty || !Ty->isFirstClassType()) + return error("Invalid record"); + Builder.template append(Elems[1], Ty); + Elems = Elems.slice(2); + break; + } + case DIOp::Extend::getBitcodeID(): { + if (Elems.size() < 1) + return error("Invalid record"); + Builder.template append(Elems[0]); + Elems = Elems.slice(1); + break; + } + case DIOp::AddrOf::getBitcodeID(): { + if (Elems.size() < 1) + return error("Invalid record"); + Builder.template append(Elems[0]); + Elems = Elems.slice(1); + break; + } + case DIOp::Deref::getBitcodeID(): { + if (Elems.size() < 1) + return error("Invalid record"); + Type *Ty = Callbacks.GetTypeByID(Elems[0]); + if (!Ty || !Ty->isFirstClassType()) + return error("Invalid record"); + Builder.template append(Ty); + Elems = Elems.slice(1); + break; + } + case DIOp::PushLane::getBitcodeID(): { + if (Elems.size() < 1) + return error("Invalid record"); + Type *Ty = Callbacks.GetTypeByID(Elems[0]); + if (!Ty || !Ty->isFirstClassType()) + return error("Invalid record"); + Builder.template append(Ty); + Elems = Elems.slice(1); + break; + } + case DIOp::Fragment::getBitcodeID(): { + if (Elems.size() < 2) + return error("Invalid record"); + Builder.template append(Elems[0], Elems[1]); + Elems = Elems.slice(2); + break; + } + } + } + + return Error::success(); +} + Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata( SmallVectorImpl &Record, unsigned Code, PlaceholderQueue &Placeholders, StringRef Blob, unsigned &NextMetadataNo) { @@ -2182,6 +2363,16 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata( uint64_t Version = Record[0] >> 1; auto Elts = MutableArrayRef(Record).slice(1); + // Version 16 signifies a DIOp-based DIExpression. + if (Version == 16) { + DIExprBuilder Builder(Context); + if (Error Err = appendDIOpsToBuilder(Builder, Elts)) + return Err; + MetadataList.assignValue(Builder.intoExpression(), NextMetadataNo); + NextMetadataNo++; + break; + } + SmallVector Buffer; if (Error Err = upgradeDIExpression(Version, Elts, Buffer)) return Err; @@ -2199,147 +2390,9 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata( return error("Invalid record: unknown DIExpr version " + Twine(Version)); DIExprBuilder Builder(Context); - - for (auto Elems = ArrayRef(Record).slice(1); Elems.size() > 0;) { - auto DIOpID = Elems[0]; - Elems = Elems.slice(1); - switch (DIOpID) { -#define HANDLE_OP0(NAME) \ - case DIOp::NAME::getBitcodeID(): \ - Builder.append(); \ - break; -#include "llvm/IR/DIExprOps.def" - case DIOp::Referrer::getBitcodeID(): { - if (Elems.size() < 1) - return error("Invalid record"); - Type *Ty = Callbacks.GetTypeByID(Elems[0]); - if (!Ty || !Ty->isFirstClassType()) - return error("Invalid record"); - Builder.append(Ty); - Elems = Elems.slice(1); - break; - } - case DIOp::Arg::getBitcodeID(): { - if (Elems.size() < 2) - return error("Invalid record"); - Type *Ty = Callbacks.GetTypeByID(Elems[0]); - if (!Ty || !Ty->isFirstClassType()) - return error("Invalid record"); - Builder.append(Elems[1], Ty); - Elems = Elems.slice(2); - break; - } - case DIOp::TypeObject::getBitcodeID(): { - if (Elems.size() < 1) - return error("Invalid record"); - Type *Ty = Callbacks.GetTypeByID(Elems[0]); - if (!Ty || !Ty->isFirstClassType()) - return error("Invalid record"); - Builder.append(Ty); - Elems = Elems.slice(1); - break; - } - case DIOp::Constant::getBitcodeID(): { - if (Elems.size() < 2) - return error("Invalid record"); - Type *Ty = Callbacks.GetTypeByID(Elems[0]); - if (!Ty || !Ty->isFirstClassType()) - return error("Invalid record"); - Value *V = ValueList[Elems[1]]; - if (!V || !isa(V)) - return error("Invalid record"); - if (Ty != V->getType()) - report_fatal_error("Invalid record"); - Builder.append(cast(V)); - Elems = Elems.slice(2); - break; - } - case DIOp::Convert::getBitcodeID(): { - if (Elems.size() < 1) - return error("Invalid record"); - Type *Ty = Callbacks.GetTypeByID(Elems[0]); - if (!Ty || !Ty->isFirstClassType()) - return error("Invalid record"); - Builder.append(Ty); - Elems = Elems.slice(1); - break; - } - case DIOp::Reinterpret::getBitcodeID(): { - if (Elems.size() < 1) - return error("Invalid record"); - Type *Ty = Callbacks.GetTypeByID(Elems[0]); - if (!Ty || !Ty->isFirstClassType()) - return error("Invalid record"); - Builder.append(Ty); - Elems = Elems.slice(1); - break; - } - case DIOp::BitOffset::getBitcodeID(): { - if (Elems.size() < 1) - return error("Invalid record"); - Type *Ty = Callbacks.GetTypeByID(Elems[0]); - if (!Ty || !Ty->isFirstClassType()) - return error("Invalid record"); - Builder.append(Ty); - Elems = Elems.slice(1); - break; - } - case DIOp::ByteOffset::getBitcodeID(): { - if (Elems.size() < 1) - return error("Invalid record"); - Type *Ty = Callbacks.GetTypeByID(Elems[0]); - if (!Ty || !Ty->isFirstClassType()) - return error("Invalid record"); - Builder.append(Ty); - Elems = Elems.slice(1); - break; - } - case DIOp::Composite::getBitcodeID(): { - if (Elems.size() < 2) - return error("Invalid record"); - Type *Ty = Callbacks.GetTypeByID(Elems[0]); - if (!Ty || !Ty->isFirstClassType()) - return error("Invalid record"); - Builder.append(Elems[1], Ty); - Elems = Elems.slice(2); - break; - } - case DIOp::Extend::getBitcodeID(): { - if (Elems.size() < 1) - return error("Invalid record"); - Builder.append(Elems[0]); - Elems = Elems.slice(1); - break; - } - case DIOp::AddrOf::getBitcodeID(): { - if (Elems.size() < 1) - return error("Invalid record"); - Builder.append(Elems[0]); - Elems = Elems.slice(1); - break; - } - case DIOp::Deref::getBitcodeID(): { - if (Elems.size() < 1) - return error("Invalid record"); - Type *Ty = Callbacks.GetTypeByID(Elems[0]); - if (!Ty || !Ty->isFirstClassType()) - return error("Invalid record"); - Builder.append(Ty); - Elems = Elems.slice(1); - break; - } - case DIOp::PushLane::getBitcodeID(): { - if (Elems.size() < 1) - return error("Invalid record"); - Type *Ty = Callbacks.GetTypeByID(Elems[0]); - if (!Ty || !Ty->isFirstClassType()) - return error("Invalid record"); - Builder.append(Ty); - Elems = Elems.slice(1); - break; - } - } - } + if (Error Err = + appendDIOpsToBuilder(Builder, ArrayRef(Record).slice(1))) + return Err; MetadataList.assignValue(Builder.intoExpr(), NextMetadataNo); NextMetadataNo++; diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp index 2e04da93eccc21..2355b4936eaae9 100644 --- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -356,6 +356,11 @@ class ModuleBitcodeWriter : public ModuleBitcodeWriterBase { unsigned Abbrev); void writeDILabel(const DILabel *N, SmallVectorImpl &Record, unsigned Abbrev); + + void writeOneDIOpToRecord(SmallVectorImpl &Record, + DIOp::Variant Op); + void writeNewDIExpression(const DIExpression *N, + SmallVectorImpl &Record, unsigned Abbrev); void writeDIExpression(const DIExpression *N, SmallVectorImpl &Record, unsigned Abbrev); void writeDIExpr(const DIExpr *N, SmallVectorImpl &Record, @@ -2156,9 +2161,90 @@ void ModuleBitcodeWriter::writeDILabel( Record.clear(); } +void ModuleBitcodeWriter::writeOneDIOpToRecord( + SmallVectorImpl &Record, DIOp::Variant Op) { + Record.push_back(DIOp::getBitcodeID(Op)); + std::visit( + makeVisitor( +#define HANDLE_OP0(NAME) [](DIOp::NAME) {}, +#include "llvm/IR/DIExprOps.def" +#undef HANDLE_OP0 + [&](DIOp::Referrer Referrer) { + Record.push_back(VE.getTypeID(Referrer.getResultType())); + }, + [&](DIOp::Arg Arg) { + Record.push_back(VE.getTypeID(Arg.getResultType())); + Record.push_back(Arg.getIndex()); + }, + [&](DIOp::TypeObject TypeObject) { + Record.push_back(VE.getTypeID(TypeObject.getResultType())); + }, + [&](DIOp::Constant Constant) { + Record.push_back( + VE.getTypeID(Constant.getLiteralValue()->getType())); + Record.push_back(VE.getValueID(Constant.getLiteralValue())); + }, + [&](DIOp::Convert Convert) { + Record.push_back(VE.getTypeID(Convert.getResultType())); + }, + [&](DIOp::ZExt ZExt) { + Record.push_back(VE.getTypeID(ZExt.getResultType())); + }, + [&](DIOp::SExt SExt) { + Record.push_back(VE.getTypeID(SExt.getResultType())); + }, + [&](DIOp::Reinterpret Reinterpret) { + Record.push_back(VE.getTypeID(Reinterpret.getResultType())); + }, + [&](DIOp::BitOffset BitOffset) { + Record.push_back(VE.getTypeID(BitOffset.getResultType())); + }, + [&](DIOp::ByteOffset ByteOffset) { + Record.push_back(VE.getTypeID(ByteOffset.getResultType())); + }, + [&](DIOp::Composite Composite) { + Record.push_back(VE.getTypeID(Composite.getResultType())); + Record.push_back(Composite.getCount()); + }, + [&](DIOp::Extend Extend) { Record.push_back(Extend.getCount()); }, + [&](DIOp::AddrOf AddrOf) { + Record.push_back(AddrOf.getAddressSpace()); + }, + [&](DIOp::Deref Deref) { + Record.push_back(VE.getTypeID(Deref.getResultType())); + }, + [&](DIOp::PushLane PushLane) { + Record.push_back(VE.getTypeID(PushLane.getResultType())); + }, + [&](DIOp::Fragment Fragment) { + Record.push_back(Fragment.getBitOffset()); + Record.push_back(Fragment.getBitSize()); + }), + Op); +} + +void ModuleBitcodeWriter::writeNewDIExpression( + const DIExpression *N, SmallVectorImpl &Record, unsigned Abbrev) { + assert(N->holdsNewElements()); + + // Use version 16 for DIOp DIExpressions. This is just an arbitrary large + // number to avoid any merge issues if the upstream version increases from 3. + const uint64_t Version = 16 << 1; + Record.push_back((uint64_t)N->isDistinct() | Version); + auto Elements = N->getNewElementsRef(); + for (auto &Elem : *Elements) + writeOneDIOpToRecord(Record, Elem); + + Stream.EmitRecord(bitc::METADATA_EXPRESSION, Record, Abbrev); + Record.clear(); +} + void ModuleBitcodeWriter::writeDIExpression(const DIExpression *N, SmallVectorImpl &Record, unsigned Abbrev) { + if (N->holdsNewElements()) + return writeNewDIExpression(N, Record, Abbrev); + Record.reserve(N->getElements().size() + 1); const uint64_t Version = 3 << 1; Record.push_back((uint64_t)N->isDistinct() | Version); @@ -2174,55 +2260,8 @@ void ModuleBitcodeWriter::writeDIExpr(const DIExpr *N, assert(!N->isDistinct() && "Expected non-distinct expr"); const unsigned Version = 0; Record.push_back(Version); - for (auto &Op : N->builder()) { - Record.push_back(DIOp::getBitcodeID(Op)); - std::visit(makeVisitor( -#define HANDLE_OP0(NAME) [](DIOp::NAME) {}, -#include "llvm/IR/DIExprOps.def" -#undef HANDLE_OP0 - [&](DIOp::Referrer Referrer) { - Record.push_back(VE.getTypeID(Referrer.getResultType())); - }, - [&](DIOp::Arg Arg) { - Record.push_back(VE.getTypeID(Arg.getResultType())); - Record.push_back(Arg.getIndex()); - }, - [&](DIOp::TypeObject TypeObject) { - Record.push_back(VE.getTypeID(TypeObject.getResultType())); - }, - [&](DIOp::Constant Constant) { - Record.push_back( - VE.getTypeID(Constant.getLiteralValue()->getType())); - Record.push_back(VE.getValueID(Constant.getLiteralValue())); - }, - [&](DIOp::Convert Convert) { - Record.push_back(VE.getTypeID(Convert.getResultType())); - }, - [&](DIOp::Reinterpret Reinterpret) { - Record.push_back(VE.getTypeID(Reinterpret.getResultType())); - }, - [&](DIOp::BitOffset BitOffset) { - Record.push_back(VE.getTypeID(BitOffset.getResultType())); - }, - [&](DIOp::ByteOffset ByteOffset) { - Record.push_back(VE.getTypeID(ByteOffset.getResultType())); - }, - [&](DIOp::Composite Composite) { - Record.push_back(VE.getTypeID(Composite.getResultType())); - Record.push_back(Composite.getCount()); - }, - [&](DIOp::Extend Extend) { Record.push_back(Extend.getCount()); }, - [&](DIOp::AddrOf AddrOf) { - Record.push_back(AddrOf.getAddressSpace()); - }, - [&](DIOp::Deref Deref) { - Record.push_back(VE.getTypeID(Deref.getResultType())); - }, - [&](DIOp::PushLane PushLane) { - Record.push_back(VE.getTypeID(PushLane.getResultType())); - }), - Op); - } + for (auto &Op : N->builder()) + writeOneDIOpToRecord(Record, Op); Stream.EmitRecord(bitc::METADATA_EXPR, Record, Abbrev); Record.clear(); } diff --git a/llvm/lib/Bitcode/Writer/ValueEnumerator.cpp b/llvm/lib/Bitcode/Writer/ValueEnumerator.cpp index 132df5f6dfaa20..e81b7d18e5c99b 100644 --- a/llvm/lib/Bitcode/Writer/ValueEnumerator.cpp +++ b/llvm/lib/Bitcode/Writer/ValueEnumerator.cpp @@ -700,24 +700,40 @@ const MDNode *ValueEnumerator::enumerateMetadataImpl(unsigned F, const Metadata return nullptr; } - if (auto *E = dyn_cast(MD)) - for (auto &&Op : E->builder()) - std::visit(makeVisitor( + auto enumerateDIOp = [this](DIOp::Variant Op) { + std::visit( + makeVisitor( #define HANDLE_OP0(NAME) [](DIOp::NAME) {}, #include "llvm/IR/DIExprOps.def" - [&](DIOp::Referrer R) { EnumerateType(R.getResultType()); }, - [&](DIOp::Arg A) { EnumerateType(A.getResultType()); }, - [&](DIOp::TypeObject T) { EnumerateType(T.getResultType()); }, - [&](DIOp::Constant C) { EnumerateValue(C.getLiteralValue()); }, - [&](DIOp::Convert C) { EnumerateType(C.getResultType()); }, - [&](DIOp::Reinterpret R) { EnumerateType(R.getResultType()); }, - [&](DIOp::BitOffset B) { EnumerateType(B.getResultType()); }, - [&](DIOp::ByteOffset B) { EnumerateType(B.getResultType()); }, - [&](DIOp::Composite C) { EnumerateType(C.getResultType()); }, - [&](DIOp::Extend) {}, [&](DIOp::AddrOf) {}, - [&](DIOp::Deref D) { EnumerateType(D.getResultType()); }, - [&](DIOp::PushLane P) { EnumerateType(P.getResultType()); }), - Op); + [&](DIOp::Referrer R) { EnumerateType(R.getResultType()); }, + [&](DIOp::Arg A) { EnumerateType(A.getResultType()); }, + [&](DIOp::TypeObject T) { EnumerateType(T.getResultType()); }, + [&](DIOp::Constant C) { EnumerateValue(C.getLiteralValue()); }, + [&](DIOp::Convert C) { EnumerateType(C.getResultType()); }, + [&](DIOp::ZExt C) { EnumerateType(C.getResultType()); }, + [&](DIOp::SExt C) { EnumerateType(C.getResultType()); }, + [&](DIOp::Reinterpret R) { EnumerateType(R.getResultType()); }, + [&](DIOp::BitOffset B) { EnumerateType(B.getResultType()); }, + [&](DIOp::ByteOffset B) { EnumerateType(B.getResultType()); }, + [&](DIOp::Composite C) { EnumerateType(C.getResultType()); }, + [&](DIOp::Extend) {}, [&](DIOp::AddrOf) {}, + [&](DIOp::Deref D) { EnumerateType(D.getResultType()); }, + [&](DIOp::PushLane P) { EnumerateType(P.getResultType()); }, + [&](DIOp::Fragment) {}), + Op); + }; + + if (auto *E = dyn_cast(MD)) { + for (const auto &Op : E->builder()) + enumerateDIOp(Op); + } + + if (auto *E = dyn_cast(MD)) { + if (auto Elems = E->getNewElementsRef()) { + for (const auto &Op : *Elems) + enumerateDIOp(Op); + } + } // Don't assign IDs to metadata nodes. if (auto *N = dyn_cast(MD)) diff --git a/llvm/lib/CodeGen/AsmPrinter/DebugLocEntry.h b/llvm/lib/CodeGen/AsmPrinter/DebugLocEntry.h index 726aba18bb804c..b1c06bb3c2fd6b 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DebugLocEntry.h +++ b/llvm/lib/CodeGen/AsmPrinter/DebugLocEntry.h @@ -41,6 +41,7 @@ class DbgValueLocEntry { /// Type of entry that this represents. enum EntryType { + E_Global, E_Location, E_Integer, E_ConstantFP, @@ -63,6 +64,9 @@ class DbgValueLocEntry { TargetIndexLocation TIL; }; + /// Or a global variable location. + const GlobalVariable *GV; + public: DbgValueLocEntry(int64_t i) : EntryKind(E_Integer) { Constant.Int = i; } DbgValueLocEntry(const ConstantFP *CFP) : EntryKind(E_ConstantFP) { @@ -91,8 +95,21 @@ class DbgValueLocEntry { MachineLocation getLoc() const { return Loc; } TargetIndexLocation getTargetIndexLocation() const { return TIL; } friend bool operator==(const DbgValueLocEntry &, const DbgValueLocEntry &); + + DbgValueLocEntry(const GlobalVariable *GV) : EntryKind(E_Global), GV(GV) {} + bool isGlobal() const { return EntryKind == E_Global; } + const GlobalVariable *getGlobal() const { return GV; } + #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) LLVM_DUMP_METHOD void dump() const { + + if (isGlobal()) { + llvm::dbgs() << "GV = { "; + GV->printAsOperand(llvm::dbgs(), false); + llvm::dbgs() << "} "; + return; + } + if (isLocation()) { llvm::dbgs() << "Loc = { reg=" << Loc.getReg() << " "; if (Loc.isIndirect()) @@ -258,6 +275,8 @@ inline bool operator==(const DbgValueLocEntry &A, const DbgValueLocEntry &B) { return false; switch (A.EntryKind) { + case DbgValueLocEntry::E_Global: + return A.GV == B.GV; case DbgValueLocEntry::E_Location: return A.Loc == B.Loc; case DbgValueLocEntry::E_TargetIndexLocation: diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp index c8384ecf4df1fa..435318060d7f51 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp @@ -332,6 +332,14 @@ void DwarfCompileUnit::addLocationAttribute( } } DwarfExpr->addFragmentOffset(Expr); + + if (auto NewElementsRef = Expr->getNewElementsRef()) { + SmallVector ArgLocEntries; + if (Global) + ArgLocEntries.emplace_back(Global); + DwarfExpr->addExpression(*NewElementsRef, ArgLocEntries); + continue; + } } // FIXME: This is a workaround to avoid generating symbols for non-global @@ -890,6 +898,8 @@ DIE *DwarfCompileUnit::constructVariableDIE(DbgVariable &DV, bool Abstract) { void DwarfCompileUnit::applyConcreteDbgVariableAttributes( const Loc::Single &Single, const DbgVariable &DV, DIE &VariableDie) { const DbgValueLoc *DVal = &Single.getValueLoc(); + const DIExpression *Expr = Single.getExpr(); + if (!DVal->isVariadic()) { const DbgValueLocEntry *Entry = DVal->getLocEntries().begin(); if (Entry->isLocation()) { @@ -929,14 +939,23 @@ void DwarfCompileUnit::applyConcreteDbgVariableAttributes( return Entry.isLocation() && !Entry.getLoc().getReg(); })) return; - const DIExpression *Expr = Single.getExpr(); assert(Expr && "Variadic Debug Value must have an Expression."); DIELoc *Loc = new (DIEValueAllocator) DIELoc; + DIEDwarfExpression DwarfExpr(*Asm, *this, *Loc); DwarfExpr.addFragmentOffset(Expr); - DIExpressionCursor Cursor(Expr); const TargetRegisterInfo &TRI = *Asm->MF->getSubtarget().getRegisterInfo(); + if (Expr) { + if (auto NewElementsRef = Expr->getNewElementsRef()) { + DwarfExpr.addExpression(*NewElementsRef, DVal->getLocEntries(), &TRI); + addBlock(VariableDie, dwarf::DW_AT_location, DwarfExpr.finalize()); + return; + } + } + + DIExpressionCursor Cursor(Expr); + auto AddEntry = [&](const DbgValueLocEntry &Entry, DIExpressionCursor &Cursor) { if (Entry.isLocation()) { @@ -1002,6 +1021,15 @@ void DwarfCompileUnit::applyConcreteDbgVariableAttributes(const Loc::MMI &MMI, std::optional NVPTXAddressSpace; DIELoc *Loc = new (DIEValueAllocator) DIELoc; DIEDwarfExpression DwarfExpr(*Asm, *this, *Loc); + auto PoisonedExpr = + find_if(MMI.getFrameIndexExprs(), [](const auto &Fragment) { + return Fragment.Expr->holdsOldElements() && Fragment.Expr->isPoisoned(); + }); + if (PoisonedExpr != MMI.getFrameIndexExprs().end()) { + DwarfExpr.addExpression(PoisonedExpr->Expr); + addBlock(VariableDie, dwarf::DW_AT_location, DwarfExpr.finalize()); + return; + } for (const auto &Fragment : MMI.getFrameIndexExprs()) { Register FrameReg; const DIExpression *Expr = Fragment.Expr; @@ -1011,6 +1039,22 @@ void DwarfCompileUnit::applyConcreteDbgVariableAttributes(const Loc::MMI &MMI, DwarfExpr.addFragmentOffset(Expr); auto *TRI = Asm->MF->getSubtarget().getRegisterInfo(); + + if (Expr->holdsNewElements()) { + // TODO: support frame symbol + assert(!Asm->getFunctionFrameSymbol()); + SmallVector ArgLocEntries; + if (FrameReg) + ArgLocEntries.push_back({MachineLocation{FrameReg}}); + else + ArgLocEntries.push_back({int64_t{0}}); + DIExpression *UpdatedExpr = + TFI->lowerFIArgToFPArg(*Asm->MF, Expr, /*ArgIndex=*/0u, Offset); + DwarfExpr.addExpression(*UpdatedExpr->getNewElementsRef(), ArgLocEntries, + TRI); + continue; + } + SmallVector Ops; TRI->getOffsetOpcodes(Offset, Ops); diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp index 16be44e17ac784..d0afe52a191666 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -195,6 +195,10 @@ void DebugLocDwarfExpression::emitBaseTypeRef(uint64_t Idx) { getActiveStreamer().emitULEB128(Idx, Twine(Idx), ULEB128PadSize); } +void DebugLocDwarfExpression::emitOpAddress(const GlobalVariable *GV) { + llvm_unreachable("cannot have loc_list for global"); +} + bool DebugLocDwarfExpression::isFrameRegister(const TargetRegisterInfo &TRI, llvm::Register MachineReg) { // This information is not available while emitting .debug_loc entries. @@ -282,7 +286,7 @@ bool llvm::operator<(const EntryValueInfo &LHS, const EntryValueInfo &RHS) { Loc::Single::Single(DbgValueLoc ValueLoc) : ValueLoc(std::make_unique(ValueLoc)), Expr(ValueLoc.getExpression()) { - if (!Expr->getNumElements()) + if (Expr->holdsOldElements() && !Expr->getNumElements()) Expr = nullptr; } @@ -298,7 +302,8 @@ void Loc::MMI::addFrameIndexExpr(const DIExpression *Expr, int FI) { assert((FrameIndexExprs.size() == 1 || llvm::all_of(FrameIndexExprs, [](const FrameIndexExpr &FIE) { - return FIE.Expr && FIE.Expr->isFragment(); + return FIE.Expr && (FIE.Expr->isFragment() || + FIE.Expr->isPoisoned()); })) && "conflicting locations for variable"); } @@ -2787,9 +2792,18 @@ void DwarfDebug::emitDebugLocValue(const AsmPrinter &AP, const DIBasicType *BT, const DbgValueLoc &Value, DwarfExpression &DwarfExpr) { auto *DIExpr = Value.getExpression(); - DIExpressionCursor ExprCursor(DIExpr); DwarfExpr.addFragmentOffset(DIExpr); + if (DIExpr) { + if (auto NewElementsRef = DIExpr->getNewElementsRef()) { + DwarfExpr.addExpression(*NewElementsRef, Value.getLocEntries(), + AP.MF->getSubtarget().getRegisterInfo()); + return; + } + } + + DIExpressionCursor ExprCursor(DIExpr); + // If the DIExpr is an Entry Value, we want to follow the same code path // regardless of whether the DBG_VALUE is variadic or not. if (DIExpr && DIExpr->isEntryValue()) { @@ -2887,7 +2901,7 @@ void DebugLocEntry::finalize(const AsmPrinter &AP, assert(Begin != End && "unexpected location list entry with empty range"); DebugLocStream::EntryBuilder Entry(List, Begin, End); BufferByteStreamer Streamer = Entry.getStreamer(); - DebugLocDwarfExpression DwarfExpr(AP.getDwarfVersion(), Streamer, TheCU); + DebugLocDwarfExpression DwarfExpr(AP, Streamer, TheCU); const DbgValueLoc &Value = Values[0]; if (Value.isFragment()) { // Emit all fragments that belong to the same variable and range. diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp index b0dca224cca870..ec0bdbd887886a 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp @@ -43,9 +43,10 @@ void DwarfExpression::emitConstu(uint64_t Value) { void DwarfExpression::addReg(int DwarfReg, const char *Comment) { assert(DwarfReg >= 0 && "invalid negative dwarf register number"); - assert((isUnknownLocation() || isRegisterLocation()) && - "location description already locked down"); - LocationKind = Register; + assert(ASTRoot || (isUnknownLocation() || isRegisterLocation()) && + "location description already locked down"); + if (!ASTRoot) + LocationKind = Register; if (DwarfReg < 32) { emitOp(dwarf::DW_OP_reg0 + DwarfReg, Comment); } else { @@ -523,6 +524,11 @@ bool DwarfExpression::addExpression( } switch (OpNum) { + case dwarf::DW_OP_LLVM_poisoned: + emitOp(dwarf::DW_OP_LLVM_user); + emitOp(dwarf::DW_OP_LLVM_USER_undefined); + LocationKind = Unknown; + return true; case dwarf::DW_OP_LLVM_arg: if (!InsertArg(Op->getArg(0), ExprCursor)) { LocationKind = Unknown; @@ -670,6 +676,18 @@ bool DwarfExpression::addExpression( return true; } +void DwarfExpression::addExpression(DIExpression::NewElementsRef Expr, + ArrayRef ArgLocEntries, + const TargetRegisterInfo *TRI) { + this->ArgLocEntries = ArgLocEntries; + this->TRI = TRI; + buildAST(Expr); + traverse(ASTRoot.get(), ValueKind::LocationDesc); + ASTRoot.reset(); + this->TRI = nullptr; + this->ArgLocEntries = std::nullopt; +} + /// add masking operations to stencil out a subregister. void DwarfExpression::maskSubRegister() { assert(SubRegisterSizeInBits && "no subregister was registered"); @@ -679,6 +697,17 @@ void DwarfExpression::maskSubRegister() { addAnd(Mask); } +void DwarfExpression::emitUserOp(uint8_t UserOp, const char *Comment) { + if (!EmitHeterogeneousDwarfAsUserOps) { + auto OptNonUserOp = dwarf::getNonUserOp(UserOp); + assert(OptNonUserOp && "non-user op passed to DwarfExpression::emitUserOp"); + emitOp(*OptNonUserOp, Comment); + return; + } + emitOp(dwarf::DW_OP_LLVM_user); + emitOp(UserOp); +} + void DwarfExpression::finalize() { assert(DwarfRegs.size() == 0 && "dwarf registers not emitted"); // Emit any outstanding DW_OP_piece operations to mask out subregisters. @@ -757,42 +786,361 @@ static bool isUnsigned(const ConstantInt *CI) { return (CI->getIntegerType()->getSignBit() & CI->getSExtValue()) == 0; } -size_t DwarfExprAST::Node::getChildrenCount() const { - using R = size_t; - return std::visit( - makeVisitor( - [](DIOp::Arg) -> R { return 0; }, - [](DIOp::Constant) -> R { return 0; }, - [](DIOp::PushLane) -> R { return 0; }, - [](DIOp::Referrer) -> R { return 0; }, - [](DIOp::TypeObject) -> R { return 0; }, - [](DIOp::AddrOf) -> R { return 1; }, - [](DIOp::Convert) -> R { return 1; }, - [](DIOp::Deref) -> R { return 1; }, - [](DIOp::Extend) -> R { return 1; }, - [](DIOp::Read) -> R { return 1; }, - [](DIOp::Reinterpret) -> R { return 1; }, - [](DIOp::Add) -> R { return 2; }, - [](DIOp::BitOffset) -> R { return 2; }, - [](DIOp::ByteOffset) -> R { return 2; }, - [](DIOp::Div) -> R { return 2; }, [](DIOp::Mul) -> R { return 2; }, - [](DIOp::Shl) -> R { return 2; }, [](DIOp::Shr) -> R { return 2; }, - [](DIOp::Sub) -> R { return 2; }, [](DIOp::Select) -> R { return 3; }, - [](DIOp::Composite) -> R { - // FIXME(KZHURAVL): Handle DIOp::Composite. - llvm_unreachable("DIOp::Composite is not handled in " - "DwarfExprAST::Node::getChildrenCount"); - }), - Element); +void DwarfExpression::buildAST(DIExpression::NewElementsRef Elements) { + std::stack> Operands; + + for (const auto &Op : Elements) { + if (std::holds_alternative(Op)) + continue; + std::unique_ptr OpNode = + std::make_unique(Op); + size_t OpChildrenCount = DIOp::getNumInputs(OpNode->getElement()); + if (OpChildrenCount == 0) { + Operands.push(std::move(OpNode)); + } else { + for (size_t I = 0; I < OpChildrenCount; ++I) { + OpNode->getChildren().insert(OpNode->getChildren().begin(), + std::move(Operands.top())); + Operands.pop(); + } + Operands.push(std::move(OpNode)); + } + } + + assert(Operands.size() == 1); + ASTRoot = std::move(Operands.top()); +} + +using NewOpResult = DwarfExpression::OpResult; + +std::optional +DwarfExpression::traverse(Node *OpNode, std::optional ReqVK) { + std::optional Result = + std::visit([&](auto &&E) { return traverse(E, OpNode->getChildren()); }, + OpNode->getElement()); + if (!Result) { + IsImplemented = false; + return Result; + } + OpNode->setIsLowered(); + OpNode->setResultType(Result->Ty); + return ReqVK ? convertValueKind(*Result, *ReqVK) : Result; +} + +NewOpResult DwarfExpression::convertValueKind(const NewOpResult &Res, + ValueKind ReqVK) { + if (Res.VK == ValueKind::Value && ReqVK == ValueKind::LocationDesc) { + emitOp(dwarf::DW_OP_stack_value); + return {Res.Ty, ValueKind::LocationDesc}; + } + + if (Res.VK == ValueKind::LocationDesc && ReqVK == ValueKind::Value) { + readToValue(Res.Ty); + return {Res.Ty, ValueKind::Value}; + } + + return Res; +} + +std::optional DwarfExpression::traverse(DIOp::Arg Arg, + ChildrenT Children) { + uint32_t Index = Arg.getIndex(); + assert(Index < ArgLocEntries.size()); + auto Entry = ArgLocEntries[Index]; + + if (Entry.isGlobal()) { + const GlobalVariable *GV = Entry.getGlobal(); + + // FIXME: This is a workaround to avoid generating symbols for non-global + // address spaces, e.g. LDS. Generate a 'DW_OP_constu' with a dummy + // constant value (0) for now. + unsigned AMDGPUGlobalAddrSpace = 1; + if ((AP.TM.getTargetTriple().getArch() == Triple::amdgcn) && + (GV->getAddressSpace() != AMDGPUGlobalAddrSpace)) { + emitConstu(0); + emitOp(dwarf::DW_OP_stack_value); + return NewOpResult{Arg.getResultType(), ValueKind::LocationDesc}; + } + + // TODO: We only support PIC reloc-model and non-TLS globals so far, see + // DwarfCompileUnit::addLocationAttribute(..., DIGlobalVariable *, ...) for + // what (more) general support might entail. + if (GV->isThreadLocal() || AP.TM.getRelocationModel() != Reloc::PIC_ || + AP.TM.getTargetTriple().isWasm()) + return std::nullopt; + + CU.getDwarfDebug().addArangeLabel(SymbolCU(&CU, AP.getSymbol(GV))); + emitOpAddress(GV); + emitOp(dwarf::DW_OP_stack_value); + return NewOpResult{Arg.getResultType(), ValueKind::LocationDesc}; + } + + if (Entry.isLocation()) { + auto DWARFRegister = TRI->getDwarfRegNum(Entry.getLoc().getReg(), false); + if (DWARFRegister < 0) { + return std::nullopt; + } + addReg(DWARFRegister); + return NewOpResult{Arg.getResultType(), ValueKind::LocationDesc}; + } + + if (Entry.isInt()) { + addUnsignedConstant(Entry.getInt()); + } else if (Entry.isConstantFP()) { + // DwarfExpression does not support arguments wider than 64 bits + // (see PR52584). + // TODO: Consider chunking expressions containing overly wide + // arguments into separate pointer-sized fragment expressions. + APInt RawBytes = Entry.getConstantFP()->getValueAPF().bitcastToAPInt(); + if (RawBytes.getBitWidth() > 64) + return std::nullopt; + addUnsignedConstant(RawBytes.getZExtValue()); + } else if (Entry.isConstantInt()) { + APInt RawBytes = Entry.getConstantInt()->getValue(); + if (RawBytes.getBitWidth() > 64) + return std::nullopt; + addUnsignedConstant(RawBytes.getZExtValue()); + } else if (Entry.isTargetIndexLocation()) { + return std::nullopt; + } else { + llvm_unreachable("Unsupported Entry type."); + } + + return NewOpResult{Arg.getResultType(), ValueKind::Value}; +} + +std::optional DwarfExpression::traverse(DIOp::Constant Constant, + ChildrenT Children) { + ConstantData *LiteralValue = Constant.getLiteralValue(); + + // FIXME: Support ConstantFP? + ConstantInt *IntLiteralValue = dyn_cast(LiteralValue); + if (!IntLiteralValue) + return std::nullopt; + + if (isUnsigned(IntLiteralValue)) { + addUnsignedConstant(IntLiteralValue->getZExtValue()); + } else { + addSignedConstant(IntLiteralValue->getSExtValue()); + } + + return NewOpResult{IntLiteralValue->getType(), ValueKind::Value}; +} + +std::optional DwarfExpression::traverse(DIOp::PushLane PushLane, + ChildrenT Children) { + return std::nullopt; +} + +std::optional DwarfExpression::traverse(DIOp::Referrer ReferrerOp, + ChildrenT Children) { + return std::nullopt; +} + +std::optional +DwarfExpression::traverse(DIOp::TypeObject TypeObject, ChildrenT Children) { + return std::nullopt; +} + +std::optional DwarfExpression::traverse(DIOp::AddrOf AddrOf, + ChildrenT Children) { + return std::nullopt; +} + +std::optional DwarfExpression::traverse(DIOp::Convert Convert, + ChildrenT Children) { + auto Child = traverse(Children[0].get(), ValueKind::Value); + if (!Child) + return std::nullopt; + + Type *DestTy = Convert.getResultType(); + if (!Child->Ty->isIntegerTy() || !DestTy->isIntegerTy()) + return std::nullopt; + + uint64_t ToBits = DestTy->getPrimitiveSizeInBits().getFixedValue(); + uint64_t FromBits = Child->Ty->getPrimitiveSizeInBits().getFixedValue(); + + if (ToBits < FromBits) { + // This function is called "ZExt", but it's actually doing a truncation on + // generic types (operation is "Child & ((1u << ToBits) - 1)"). + emitLegacyZExt(ToBits); + } + return NewOpResult{DestTy, ValueKind::Value}; +} + +std::optional DwarfExpression::traverse(DIOp::ZExt ZExt, + ChildrenT Children) { + auto Child = traverse(Children[0].get(), ValueKind::Value); + if (!Child || !Child->Ty->isIntegerTy()) + return std::nullopt; + + uint64_t FromBits = Child->Ty->getPrimitiveSizeInBits().getFixedValue(); + emitLegacyZExt(FromBits); + return NewOpResult{ZExt.getResultType(), ValueKind::Value}; +} + +std::optional DwarfExpression::traverse(DIOp::SExt SExt, + ChildrenT Children) { + auto Child = traverse(Children[0].get(), ValueKind::Value); + if (!Child || !Child->Ty->isIntegerTy()) + return std::nullopt; + + uint64_t FromBits = Child->Ty->getPrimitiveSizeInBits().getFixedValue(); + emitLegacySExt(FromBits); + return NewOpResult{SExt.getResultType(), ValueKind::Value}; +} + +std::optional DwarfExpression::traverse(DIOp::Deref Deref, + ChildrenT Children) { + auto Child = traverse(Children[0].get(), ValueKind::LocationDesc); + if (!Child) + return std::nullopt; + + // FIXME(KZHURAVL): Support non pointer types? + if (!Child->Ty->isPointerTy()) + return std::nullopt; + + PointerType *PointerResultType = dyn_cast(Child->Ty); + assert(PointerResultType && "Expected PointerType, but got something else"); + + uint64_t PointerSizeInBits = AP.getDataLayout().getPointerSizeInBits( + PointerResultType->getAddressSpace()); + assert(PointerSizeInBits % 8 == 0 && "Expected multiple of 8"); + + uint64_t PointerSizeInBytes = PointerSizeInBits / 8; + + unsigned PointerLLVMAddrSpace = PointerResultType->getAddressSpace(); + auto PointerDWARFAddrSpace = AP.TM.mapToDWARFAddrSpace(PointerLLVMAddrSpace); + if (!PointerDWARFAddrSpace) { + LLVM_DEBUG(dbgs() << "Failed to lower DIOpDeref of pointer to addrspace(" + << PointerLLVMAddrSpace + << "): no corresponding DWARF addrspace.\n"); + return std::nullopt; + } + + emitOp(dwarf::DW_OP_deref_size); + emitData1(PointerSizeInBytes); + addUnsignedConstant(*PointerDWARFAddrSpace); + emitUserOp(dwarf::DW_OP_LLVM_USER_form_aspace_address); + + // FIXME(KZHURAVL): Is the following result type correct? + return NewOpResult{Deref.getResultType(), ValueKind::LocationDesc}; +} + +std::optional DwarfExpression::traverse(DIOp::Extend Extend, + ChildrenT Children) { + return std::nullopt; +} + +std::optional DwarfExpression::traverse(DIOp::Read Read, + ChildrenT Children) { + auto Child = traverse(Children[0].get(), ValueKind::LocationDesc); + if (!Child) + return std::nullopt; + readToValue(Children[0].get()); + return NewOpResult{Child->Ty, ValueKind::Value}; +} + +std::optional +DwarfExpression::traverse(DIOp::Reinterpret Reinterpret, ChildrenT Children) { + auto Child = traverse(Children[0].get(), ValueKind::LocationDesc); + if (!Child) + return Child; + return NewOpResult{Reinterpret.getResultType(), Child->VK}; +} + +std::optional DwarfExpression::traverse(DIOp::Select Select, + ChildrenT Children) { + return std::nullopt; +} + +std::optional DwarfExpression::traverse(DIOp::Composite Composite, + ChildrenT Children) { + return std::nullopt; +} + +std::optional DwarfExpression::traverseMathOp(uint8_t DwarfOp, + ChildrenT Children) { + auto LHS = traverse(Children[0].get(), ValueKind::Value); + if (!LHS) + return std::nullopt; + auto RHS = traverse(Children[1].get(), ValueKind::Value); + if (!RHS) + return std::nullopt; + + emitOp(DwarfOp); + return NewOpResult{LHS->Ty, ValueKind::Value}; +} + +std::optional +DwarfExpression::traverse(DIOp::ByteOffset ByteOffset, ChildrenT Children) { + auto LHS = traverse(Children[0].get(), ValueKind::LocationDesc); + if (!LHS) + return std::nullopt; + auto RHS = traverse(Children[1].get(), ValueKind::Value); + if (!RHS) + return std::nullopt; + + emitUserOp(dwarf::DW_OP_LLVM_USER_offset); + return NewOpResult{ByteOffset.getResultType(), ValueKind::LocationDesc}; +} + +std::optional DwarfExpression::traverse(DIOp::BitOffset BitOffset, + ChildrenT Children) { + auto LHS = traverse(Children[0].get(), ValueKind::LocationDesc); + if (!LHS) + return std::nullopt; + auto RHS = traverse(Children[1].get(), ValueKind::Value); + if (!RHS) + return std::nullopt; + + emitUserOp(dwarf::DW_OP_LLVM_USER_bit_offset); + return NewOpResult{BitOffset.getResultType(), ValueKind::LocationDesc}; +} + +std::optional DwarfExpression::traverse(DIOp::Fragment Fragment, + ChildrenT Children) { + llvm_unreachable("should have dropped fragments by now"); + return std::nullopt; +} + +void DwarfExpression::readToValue(Type *Ty) { + uint64_t PrimitiveSizeInBits = Ty->getPrimitiveSizeInBits(); + assert(PrimitiveSizeInBits != 0 && "Expected primitive type"); + + uint64_t ByteAlignedPrimitiveSizeInBits = alignTo<8>(PrimitiveSizeInBits); + uint64_t PrimitiveSizeInBytes = ByteAlignedPrimitiveSizeInBits / 8; + bool NeedsMask = ByteAlignedPrimitiveSizeInBits != PrimitiveSizeInBits; + + emitOp(dwarf::DW_OP_deref_size); + emitData1(PrimitiveSizeInBytes); + + if (NeedsMask) { + uint64_t Mask = (1ULL << PrimitiveSizeInBits) - 1ULL; + addUnsignedConstant(Mask); + emitOp(dwarf::DW_OP_and); + } +} + +void DwarfExpression::readToValue(DwarfExpression::Node *OpNode) { + assert(OpNode->isLowered() && "Expected lowered node"); + assert(OpNode->getResultType() && "Expected non-null result type"); + readToValue(OpNode->getResultType()); } void DwarfExprAST::buildDIExprAST() { std::stack> Operands; for (const auto &Op : Lifetime.getLocation()->builder()) { + // DIOp::Fragment is not a true operation, and like DW_OP_LLVM_fragment + // it can be ignored when interpreting the expression semantically. Just + // drop it here during the first walk of the expression and assert it + // is not present later. + if (std::holds_alternative(Op)) + continue; std::unique_ptr OpNode = std::make_unique(Op); - size_t OpChildrenCount = OpNode->getChildrenCount(); + size_t OpChildrenCount = DIOp::getNumInputs(OpNode->getElement()); if (OpChildrenCount == 0) { Operands.push(std::move(OpNode)); } else { @@ -809,44 +1157,51 @@ void DwarfExprAST::buildDIExprAST() { Root = std::move(Operands.top()); } -void DwarfExprAST::traverseAndLower(DwarfExprAST::Node *OpNode) { - if (!OpNode || !IsImplemented) { - return; - } - - for (auto &ChildOpNode : OpNode->getChildren()) { - // FIXME(KZHURAVL): Do this iteratively, otherwise we may hit stack size - // problems. - traverseAndLower(ChildOpNode.get()); - if (!IsImplemented) { - return; - } - } - - lower(OpNode); -} +using OpResult = DwarfExprAST::OpResult; -void DwarfExprAST::lower(DwarfExprAST::Node *OpNode) { - Type *ResultType = - std::visit([=](auto &&E) { return lower(E, OpNode->getChildren()); }, +std::optional DwarfExprAST::traverse(Node *OpNode, + std::optional ReqVK) { + std::optional Result = + std::visit([&](auto &&E) { return traverse(E, OpNode->getChildren()); }, OpNode->getElement()); - if (!ResultType) { + if (!Result) { IsImplemented = false; - return; + return Result; } OpNode->setIsLowered(); - OpNode->setResultType(ResultType); + OpNode->setResultType(Result->Ty); + return ReqVK ? convertValueKind(*Result, *ReqVK) : Result; +} + +OpResult DwarfExprAST::convertValueKind(const OpResult &Res, ValueKind ReqVK) { + if (Res.VK == ValueKind::Value && ReqVK == ValueKind::LocationDesc) { + emitDwarfOp(dwarf::DW_OP_stack_value); + return {Res.Ty, ValueKind::LocationDesc}; + } + + if (Res.VK == ValueKind::LocationDesc && ReqVK == ValueKind::Value) { + readToValue(Res.Ty); + return {Res.Ty, ValueKind::Value}; + } + + return Res; } -bool DwarfExprAST::tryInlineArgObject(DIObject *ArgObject) { +std::optional DwarfExprAST::traverse(DIOp::Arg Arg, + ChildrenT Children) { + uint32_t Index = Arg.getIndex(); + assert(Index < std::distance(Lifetime.argObjects().begin(), + Lifetime.argObjects().end())); + DIObject *ArgObject = *(Lifetime.argObjects().begin() + Index); + if (!GVFragmentMap) - return false; + return std::nullopt; auto *Fragment = dyn_cast(ArgObject); if (!Fragment) - return false; + return std::nullopt; const auto GVRef = GVFragmentMap->find(Fragment); if (GVRef == GVFragmentMap->end() || !GVRef->getSecond()) - return false; + return std::nullopt; const GlobalVariable *Global = cast(GVRef->getSecond()); // FIXME(KZHURAVL): This depends on the target and address space // semantics. For AMDGPU, address space 3 is lds/local/shared. @@ -878,29 +1233,18 @@ bool DwarfExprAST::tryInlineArgObject(DIObject *ArgObject) { emitDwarfAddr(Sym); } } - emitDwarfOp(dwarf::DW_OP_stack_value); - return true; -} - -Type *DwarfExprAST::lower(DIOp::Arg Arg, ChildrenT Children) { - uint32_t Index = Arg.getIndex(); - assert(Index < std::distance(Lifetime.argObjects().begin(), - Lifetime.argObjects().end())); - DIObject *ArgObject = *(Lifetime.argObjects().begin() + Index); - if (!tryInlineArgObject(ArgObject)) - return nullptr; - - return Arg.getResultType(); + return OpResult{Arg.getResultType(), ValueKind::Value}; } -Type *DwarfExprAST::lower(DIOp::Constant Constant, ChildrenT Children) { +std::optional DwarfExprAST::traverse(DIOp::Constant Constant, + ChildrenT Children) { ConstantData *LiteralValue = Constant.getLiteralValue(); // FIXME(KZHURAVL): Support ConstantFP? ConstantInt *IntLiteralValue = dyn_cast(LiteralValue); if (!IntLiteralValue) - return nullptr; + return std::nullopt; if (isUnsigned(IntLiteralValue)) { emitUnsigned(IntLiteralValue->getZExtValue()); @@ -908,60 +1252,77 @@ Type *DwarfExprAST::lower(DIOp::Constant Constant, ChildrenT Children) { emitSigned(IntLiteralValue->getSExtValue()); } - emitDwarfOp(dwarf::DW_OP_stack_value); - - return IntLiteralValue->getType(); + return OpResult{IntLiteralValue->getType(), ValueKind::Value}; } -Type *DwarfExprAST::lower(DIOp::PushLane PushLane, ChildrenT Children) { - return nullptr; +std::optional DwarfExprAST::traverse(DIOp::PushLane PushLane, + ChildrenT Children) { + return std::nullopt; } -Type *DwarfExprAST::lower(DIOp::Referrer ReferrerOp, ChildrenT Children) { +std::optional DwarfExprAST::traverse(DIOp::Referrer ReferrerOp, + ChildrenT Children) { if (Referrer->isReg() && Referrer->getReg()) { auto DWARFRegister = TRI->getDwarfRegNum(Referrer->getReg(), false); if (DWARFRegister == -1) { - return nullptr; + return std::nullopt; } emitReg(DWARFRegister); - } else if (Referrer->isImm()) { + return OpResult{ReferrerOp.getResultType(), ValueKind::LocationDesc}; + } + + if (Referrer->isImm()) { auto I = Referrer->getImm(); if (I >= 0) emitUnsigned(static_cast(I)); else emitSigned(I); - emitDwarfOp(dwarf::DW_OP_stack_value); - } else { - return nullptr; + return OpResult{ReferrerOp.getResultType(), ValueKind::Value}; } - // FIXME(KZHURAVL): Is the following result type correct? - return ReferrerOp.getResultType(); + return std::nullopt; +} + +std::optional DwarfExprAST::traverse(DIOp::TypeObject TypeObject, + ChildrenT Children) { + return std::nullopt; } -Type *DwarfExprAST::lower(DIOp::TypeObject TypeObject, ChildrenT Children) { - return nullptr; +std::optional DwarfExprAST::traverse(DIOp::AddrOf AddrOf, + ChildrenT Children) { + return std::nullopt; } -Type *DwarfExprAST::lower(DIOp::AddrOf AddrOf, ChildrenT Children) { - return nullptr; +std::optional DwarfExprAST::traverse(DIOp::Convert Convert, + ChildrenT Children) { + return std::nullopt; } -Type *DwarfExprAST::lower(DIOp::Convert Convert, ChildrenT Children) { - return nullptr; +std::optional DwarfExprAST::traverse(DIOp::ZExt ZExt, + ChildrenT Children) { + return std::nullopt; } -Type *DwarfExprAST::lower(DIOp::Deref Deref, ChildrenT Children) { - Type *ResultType = Children[0]->getResultType(); +std::optional DwarfExprAST::traverse(DIOp::SExt SExt, + ChildrenT Children) { + return std::nullopt; +} + +std::optional DwarfExprAST::traverse(DIOp::Deref Deref, + ChildrenT Children) { + auto Child = traverse(Children[0].get(), ValueKind::LocationDesc); + if (!Child) + return std::nullopt; // FIXME(KZHURAVL): Support non pointer types? - if (!ResultType->isPointerTy()) - return nullptr; + if (!Child->Ty->isPointerTy()) + return std::nullopt; - PointerType *PointerResultType = dyn_cast(ResultType); + PointerType *PointerResultType = dyn_cast(Child->Ty); assert(PointerResultType && "Expected PointerType, but got something else"); - uint64_t PointerSizeInBits = AP.getDataLayout().getPointerSizeInBits(PointerResultType->getAddressSpace()); + uint64_t PointerSizeInBits = AP.getDataLayout().getPointerSizeInBits( + PointerResultType->getAddressSpace()); assert(PointerSizeInBits % 8 == 0 && "Expected multiple of 8"); uint64_t PointerSizeInBytes = PointerSizeInBits / 8; @@ -972,7 +1333,7 @@ Type *DwarfExprAST::lower(DIOp::Deref Deref, ChildrenT Children) { LLVM_DEBUG(dbgs() << "Failed to lower DIOpDeref of pointer to addrspace(" << PointerLLVMAddrSpace << "): no corresponding DWARF addrspace.\n"); - return nullptr; + return std::nullopt; } emitDwarfOp(dwarf::DW_OP_deref_size); @@ -982,46 +1343,111 @@ Type *DwarfExprAST::lower(DIOp::Deref Deref, ChildrenT Children) { emitDwarfOp(dwarf::DW_OP_LLVM_form_aspace_address); // FIXME(KZHURAVL): Is the following result type correct? - return Deref.getResultType(); + return OpResult{Deref.getResultType(), ValueKind::LocationDesc}; } -Type *DwarfExprAST::lower(DIOp::Extend Extend, ChildrenT Children) { - return nullptr; +std::optional DwarfExprAST::traverse(DIOp::Extend Extend, + ChildrenT Children) { + return std::nullopt; } -Type *DwarfExprAST::lower(DIOp::Read Read, ChildrenT Children) { - return nullptr; +std::optional DwarfExprAST::traverse(DIOp::Read Read, + ChildrenT Children) { + auto Child = traverse(Children[0].get(), ValueKind::LocationDesc); + if (!Child) + return std::nullopt; + readToValue(Children[0].get()); + return OpResult{Child->Ty, ValueKind::Value}; } -Type *DwarfExprAST::lower(DIOp::Reinterpret Reinterpret, ChildrenT Children) { - return Reinterpret.getResultType(); +std::optional DwarfExprAST::traverse(DIOp::Reinterpret Reinterpret, + ChildrenT Children) { + auto Child = traverse(Children[0].get(), ValueKind::LocationDesc); + if (!Child) + return Child; + return OpResult{Reinterpret.getResultType(), Child->VK}; } -Type *DwarfExprAST::lower(DIOp::Select Select, ChildrenT Children) { - return nullptr; +std::optional DwarfExprAST::traverse(DIOp::Select Select, + ChildrenT Children) { + return std::nullopt; } -Type *DwarfExprAST::lower(DIOp::Composite Composite, ChildrenT Children) { - return nullptr; +std::optional DwarfExprAST::traverse(DIOp::Composite Composite, + ChildrenT Children) { + return std::nullopt; } -void DwarfExprAST::readToValue(DwarfExprAST::Node *OpNode, bool NeedsSwap) { - assert(OpNode->isLowered() && "Expected lowered node"); - assert(OpNode->getResultType() && "Expected non-null result type"); - uint64_t PrimitiveSizeInBits = - OpNode->getResultType()->getPrimitiveSizeInBits(); +std::optional DwarfExprAST::traverseMathOp(uint8_t DwarfOp, + ChildrenT Children) { + auto LHS = traverse(Children[0].get(), ValueKind::Value); + if (!LHS) + return std::nullopt; + auto RHS = traverse(Children[1].get(), ValueKind::Value); + if (!RHS) + return std::nullopt; + + emitDwarfOp(DwarfOp); + return OpResult{LHS->Ty, ValueKind::Value}; +} + +std::optional DwarfExprAST::traverse(DIOp::ByteOffset ByteOffset, + ChildrenT Children) { + auto LHS = traverse(Children[0].get(), ValueKind::LocationDesc); + if (!LHS) + return std::nullopt; + auto RHS = traverse(Children[1].get(), ValueKind::Value); + if (!RHS) + return std::nullopt; + + emitDwarfOp(dwarf::DW_OP_LLVM_offset); + return OpResult{ByteOffset.getResultType(), ValueKind::LocationDesc}; +} + +std::optional DwarfExprAST::traverse(DIOp::BitOffset BitOffset, + ChildrenT Children) { + auto LHS = traverse(Children[0].get(), ValueKind::LocationDesc); + if (!LHS) + return std::nullopt; + auto RHS = traverse(Children[1].get(), ValueKind::Value); + if (!RHS) + return std::nullopt; + + emitDwarfOp(dwarf::DW_OP_LLVM_bit_offset); + return OpResult{BitOffset.getResultType(), ValueKind::LocationDesc}; +} + +std::optional DwarfExprAST::traverse(DIOp::Fragment Fragment, + ChildrenT Children) { + llvm_unreachable("should have dropped fragments by now"); + return std::nullopt; +} + +void DwarfExprAST::readToValue(Type *Ty) { + uint64_t PrimitiveSizeInBits = Ty->getPrimitiveSizeInBits(); assert(PrimitiveSizeInBits != 0 && "Expected primitive type"); - assert(PrimitiveSizeInBits % 8 == 0 && "Expected multiple of 8"); - uint64_t PrimitiveSizeInBytes = PrimitiveSizeInBits / 8; + uint64_t ByteAlignedPrimitiveSizeInBits = alignTo<8>(PrimitiveSizeInBits); + uint64_t PrimitiveSizeInBytes = ByteAlignedPrimitiveSizeInBits / 8; + bool NeedsMask = ByteAlignedPrimitiveSizeInBits != PrimitiveSizeInBits; emitDwarfOp(dwarf::DW_OP_deref_size); emitDwarfData1(PrimitiveSizeInBytes); - if (NeedsSwap) { - emitDwarfOp(dwarf::DW_OP_swap); + + if (NeedsMask) { + uint64_t Mask = (1ULL << PrimitiveSizeInBits) - 1ULL; + emitDwarfOp(dwarf::DW_OP_constu); + emitDwarfUnsigned(Mask); + emitDwarfOp(dwarf::DW_OP_and); } } +void DwarfExprAST::readToValue(DwarfExprAST::Node *OpNode) { + assert(OpNode->isLowered() && "Expected lowered node"); + assert(OpNode->getResultType() && "Expected non-null result type"); + readToValue(OpNode->getResultType()); +} + void DwarfExprAST::emitReg(int32_t DwarfReg, const char *Comment) { assert(DwarfReg >= 0 && "Invalid dwarf register number"); diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h b/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h index adf736dc3b9fb7..6f564061e6e5ae 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h @@ -128,6 +128,7 @@ class DwarfExpression { /// Whether we are currently emitting an entry value operation. bool IsEmittingEntryValue = false; + const AsmPrinter &AP; DwarfCompileUnit &CU; /// The register location, if any. @@ -184,6 +185,9 @@ class DwarfExpression { /// Add masking operations to stencil out a subregister. void maskSubRegister(); + /// Emit DW_OP_LLVM_user followed by the SubOp \p UserOp. + void emitUserOp(uint8_t UserOp, const char *Comment = nullptr); + /// Output a dwarf operand and an optional assembler comment. virtual void emitOp(uint8_t Op, const char *Comment = nullptr) = 0; @@ -197,6 +201,9 @@ class DwarfExpression { virtual void emitBaseTypeRef(uint64_t Idx) = 0; + /// Emit a dwarf op address for the given GlobalValue \p GV. + virtual void emitOpAddress(const GlobalVariable *GV) = 0; + /// Start emitting data to the temporary buffer. The data stored in the /// temporary buffer can be committed to the main output using /// commitTemporaryBuffer(). @@ -283,10 +290,10 @@ class DwarfExpression { ~DwarfExpression() = default; public: - DwarfExpression(unsigned DwarfVersion, DwarfCompileUnit &CU) - : CU(CU), SubRegisterSizeInBits(0), SubRegisterOffsetInBits(0), + DwarfExpression(const AsmPrinter &AP, DwarfCompileUnit &CU) + : AP(AP), CU(CU), SubRegisterSizeInBits(0), SubRegisterOffsetInBits(0), LocationKind(Unknown), SavedLocationKind(Unknown), - LocationFlags(Unknown), DwarfVersion(DwarfVersion) {} + LocationFlags(Unknown), DwarfVersion(AP.getDwarfVersion()) {} /// This needs to be called last to commit any pending changes. void finalize(); @@ -352,6 +359,13 @@ class DwarfExpression { DIExpressionCursor &&Expr, llvm::function_ref InsertArg); + /// Emit all operations in \p Expr, indexing into \p ArgLocEntries to + /// implement any DIOpArg operations. Function local locations require \p + /// TRI present to translate register identifiers. + void addExpression(DIExpression::NewElementsRef Expr, + ArrayRef ArgLocEntries, + const TargetRegisterInfo *TRI = nullptr); + /// If applicable, emit an empty DW_OP_piece / DW_OP_bit_piece to advance to /// the fragment described by \c Expr. void addFragmentOffset(const DIExpression *Expr); @@ -362,6 +376,132 @@ class DwarfExpression { /// Emit location information expressed via WebAssembly location + offset /// The Index is an identifier for locals, globals or operand stack. void addWasmLocation(unsigned Index, uint64_t Offset); + + // Note: All following members are to support expressions containg + // DIExpression::NewElements (i.e. DIOp* expressions). +public: + class Node { + private: + DIOp::Variant Element; + SmallVector> Children; + + bool IsLowered = false; + Type *ResultType = nullptr; + + public: + Node(DIOp::Variant Element) : Element(Element) {} + + const DIOp::Variant &getElement() const { return Element; } + const SmallVector> &getChildren() const { + return Children; + } + + DIOp::Variant &getElement() { return Element; } + SmallVector> &getChildren() { return Children; } + + const bool &isLowered() const { return IsLowered; } + const Type *getResultType() const { return ResultType; } + + bool &isLowered() { return IsLowered; } + Type *getResultType() { return ResultType; } + + void setIsLowered(bool IL = true) { + IsLowered = IL; + } + void setResultType(Type *RT) { ResultType = RT; } + }; + + // An `std::optional` where `nullptr` represents + // `None`. Only present when in a function context. + const TargetRegisterInfo *TRI; + + std::unique_ptr ASTRoot; + ArrayRef ArgLocEntries; + // This is a temporary boolean variable that indicates whether the lowering of + // this expression is supported or not. If the lowering is supported, then + // the expression lowers as expected. If the lowering is not supported, it + // is terminated by a DW_OP_LLVM_undefined operation. + bool IsImplemented = true; + + void buildAST(DIExpression::NewElementsRef Elements); + + /// Describes a kind of value on the DWARF expression stack. ValueKind::Value + /// is a DWARF5-style value, and ValueKind::LocationDesc is a location + /// description. + enum class ValueKind { + Value, + LocationDesc, + }; + + /// The result of evaluating a DIExpr operation. Describes the value that the + /// operation will push onto the DWARF expression stack. + struct OpResult { + Type *Ty; + ValueKind VK; + }; + + /// Optionally emit DWARF operations to convert the value at the top of the + /// stack to RequiredVK. Nop if Res.VK is RequiredVK. + OpResult convertValueKind(const OpResult &Res, ValueKind RequiredVK); + + void readToValue(Type *Ty); + void readToValue(Node *OpNode); + + using ChildrenT = ArrayRef>; + + /// Dispatch to a specific traverse() function, and convert the result to + /// ReqVK if non-nullopt. + std::optional traverse(Node *OpNode, + std::optional ReqVK); + + std::optional traverse(DIOp::Arg Arg, ChildrenT Children); + std::optional traverse(DIOp::Constant Constant, ChildrenT Children); + std::optional traverse(DIOp::PushLane PushLane, ChildrenT Children); + std::optional traverse(DIOp::Referrer Referrer, ChildrenT Children); + std::optional traverse(DIOp::TypeObject TypeObject, + ChildrenT Children); + std::optional traverse(DIOp::AddrOf AddrOf, ChildrenT Children); + std::optional traverse(DIOp::Convert Convert, ChildrenT Children); + std::optional traverse(DIOp::ZExt ZExt, ChildrenT Children); + std::optional traverse(DIOp::SExt SExt, ChildrenT Children); + std::optional traverse(DIOp::Deref Deref, ChildrenT Children); + std::optional traverse(DIOp::Extend Extend, ChildrenT Children); + std::optional traverse(DIOp::Read Read, ChildrenT Children); + std::optional traverse(DIOp::Reinterpret Reinterpret, + ChildrenT Children); + std::optional traverse(DIOp::Select Select, ChildrenT Children); + std::optional traverse(DIOp::Composite Composite, + ChildrenT Children); + + std::optional traverseMathOp(uint8_t DwarfOp, ChildrenT Children); + std::optional traverse(DIOp::Add Op, ChildrenT Children) { + return traverseMathOp(dwarf::DW_OP_plus, Children); + } + std::optional traverse(DIOp::Div Op, ChildrenT Children) { + return traverseMathOp(dwarf::DW_OP_div, Children); + } + std::optional traverse(DIOp::Mul Op, ChildrenT Children) { + return traverseMathOp(dwarf::DW_OP_mul, Children); + } + std::optional traverse(DIOp::Shl Op, ChildrenT Children) { + return traverseMathOp(dwarf::DW_OP_shl, Children); + } + std::optional traverse(DIOp::LShr Op, ChildrenT Children) { + return traverseMathOp(dwarf::DW_OP_shr, Children); + } + std::optional traverse(DIOp::AShr Op, ChildrenT Children) { + return traverseMathOp(dwarf::DW_OP_shra, Children); + } + std::optional traverse(DIOp::Sub Op, ChildrenT Children) { + return traverseMathOp(dwarf::DW_OP_minus, Children); + } + + std::optional traverse(DIOp::BitOffset BitOffset, + ChildrenT Children); + std::optional traverse(DIOp::ByteOffset ByteOffset, + ChildrenT Children); + + std::optional traverse(DIOp::Fragment Fragment, ChildrenT Children); }; /// DwarfExpression implementation for .debug_loc entries. @@ -388,6 +528,8 @@ class DebugLocDwarfExpression final : public DwarfExpression { void emitData1(uint8_t Value) override; void emitBaseTypeRef(uint64_t Idx) override; + void emitOpAddress(const GlobalVariable *GV) override; + void enableTemporaryBuffer() override; void disableTemporaryBuffer() override; unsigned getTemporaryBufferSize() override; @@ -397,14 +539,13 @@ class DebugLocDwarfExpression final : public DwarfExpression { llvm::Register MachineReg) override; public: - DebugLocDwarfExpression(unsigned DwarfVersion, BufferByteStreamer &BS, + DebugLocDwarfExpression(const AsmPrinter &AP, BufferByteStreamer &BS, DwarfCompileUnit &CU) - : DwarfExpression(DwarfVersion, CU), OutBS(BS) {} + : DwarfExpression(AP, CU), OutBS(BS) {} }; /// DwarfExpression implementation for singular DW_AT_location. class DIEDwarfExpression final : public DwarfExpression { - const AsmPrinter &AP; DIELoc &OutDIE; DIELoc TmpDIE; bool IsBuffering = false; @@ -418,6 +559,8 @@ class DIEDwarfExpression final : public DwarfExpression { void emitData1(uint8_t Value) override; void emitBaseTypeRef(uint64_t Idx) override; + void emitOpAddress(const GlobalVariable *GV) override; + void enableTemporaryBuffer() override; void disableTemporaryBuffer() override; unsigned getTemporaryBufferSize() override; @@ -430,26 +573,16 @@ class DIEDwarfExpression final : public DwarfExpression { DIEDwarfExpression(const AsmPrinter &AP, DwarfCompileUnit &CU, DIELoc &DIE); DIELoc *finalize() { + if (!IsImplemented) { + emitUserOp(dwarf::DW_OP_LLVM_USER_undefined); + } DwarfExpression::finalize(); return &OutDIE; } }; -constexpr uint8_t getEquivalentDwarfOp(DIOp::Add) { return dwarf::DW_OP_plus; } -constexpr uint8_t getEquivalentDwarfOp(DIOp::Div) { return dwarf::DW_OP_div; } -constexpr uint8_t getEquivalentDwarfOp(DIOp::Mul) { return dwarf::DW_OP_mul; } -constexpr uint8_t getEquivalentDwarfOp(DIOp::Shl) { return dwarf::DW_OP_shl; } -constexpr uint8_t getEquivalentDwarfOp(DIOp::Shr) { return dwarf::DW_OP_shr; } -constexpr uint8_t getEquivalentDwarfOp(DIOp::Sub) { return dwarf::DW_OP_minus; } -constexpr uint8_t getEquivalentDwarfOp(DIOp::BitOffset) { - return dwarf::DW_OP_LLVM_bit_offset; -} -constexpr uint8_t getEquivalentDwarfOp(DIOp::ByteOffset) { - return dwarf::DW_OP_LLVM_offset; -} - class DwarfExprAST { -protected: +public: class Node { private: DIOp::Variant Element; @@ -495,11 +628,7 @@ class DwarfExprAST { void setIsLowered(bool IL = true) { IsLowered = IL; } - void setResultType(Type *RT) { - ResultType = RT; - } - - size_t getChildrenCount() const; + void setResultType(Type *RT) { ResultType = RT; } }; const AsmPrinter &AP; @@ -524,55 +653,84 @@ class DwarfExprAST { bool IsImplemented = true; void buildDIExprAST(); - void traverseAndLower(DwarfExprAST::Node *OpNode); - void lower(DwarfExprAST::Node *OpNode); - /// Attempt to perform the optimization of inlining the expression of a global - /// value DIFragment, referenced through a DIOpArg. - /// - /// \returns true if the optimization was performed successfully, false if it - /// is not applicable. - bool tryInlineArgObject(DIObject *ArgObject); + + /// Describes a kind of value on the DWARF expression stack. ValueKind::Value + /// is a DWARF5-style value, and ValueKind::LocationDesc is a location + /// description. + enum class ValueKind { + Value, + LocationDesc, + }; + + /// The result of evaluating a DIExpr operation. Describes the value that the + /// operation will push onto the DWARF expression stack. + struct OpResult { + Type *Ty; + ValueKind VK; + }; + + /// Optionally emit DWARF operations to convert the value at the top of the + /// stack to RequiredVK. Nop if Res.VK is RequiredVK. + OpResult convertValueKind(const OpResult &Res, ValueKind RequiredVK); + + void readToValue(Type *Ty); + void readToValue(Node *OpNode); + using ChildrenT = ArrayRef>; - // Each `lower` overload below will handle one or more concrete DIOp - // operations, and will be dispatched to by `lower(DwarfExprAST::Node*)`. - // These overloads return `nullptr` when they are not yet implemented, or - // return their result Type otherwise. - Type *lower(DIOp::Arg Arg, ChildrenT Children); - Type *lower(DIOp::Constant Constant, ChildrenT Children); - Type *lower(DIOp::PushLane PushLane, ChildrenT Children); - Type *lower(DIOp::Referrer Referrer, ChildrenT Children); - Type *lower(DIOp::TypeObject TypeObject, ChildrenT Children); - Type *lower(DIOp::AddrOf AddrOf, ChildrenT Children); - Type *lower(DIOp::Convert Convert, ChildrenT Children); - Type *lower(DIOp::Deref Deref, ChildrenT Children); - Type *lower(DIOp::Extend Extend, ChildrenT Children); - Type *lower(DIOp::Read Read, ChildrenT Children); - Type *lower(DIOp::Reinterpret Reinterpret, ChildrenT Children); - Type *lower(DIOp::Select Select, ChildrenT Children); - Type *lower(DIOp::Composite Composite, ChildrenT Children); - template - std::enable_if_t::value, - Type *> - lower(T MathOp, ChildrenT Children) { - assert(Children.size() == 2 && "Expected 2 children"); - for (auto &ChildOpNode : Children) - readToValue(ChildOpNode.get(), /*NeedsSwap=*/true); - emitDwarfOp(getEquivalentDwarfOp(MathOp)); - emitDwarfOp(dwarf::DW_OP_stack_value); - return Children[0]->getResultType(); + + /// Dispatch to a specific traverse() function, and convert the result to + /// ReqVK if non-nullopt. + std::optional traverse(Node *OpNode, + std::optional ReqVK); + + std::optional traverse(DIOp::Arg Arg, ChildrenT Children); + std::optional traverse(DIOp::Constant Constant, ChildrenT Children); + std::optional traverse(DIOp::PushLane PushLane, ChildrenT Children); + std::optional traverse(DIOp::Referrer Referrer, ChildrenT Children); + std::optional traverse(DIOp::TypeObject TypeObject, + ChildrenT Children); + std::optional traverse(DIOp::AddrOf AddrOf, ChildrenT Children); + std::optional traverse(DIOp::Convert Convert, ChildrenT Children); + std::optional traverse(DIOp::ZExt ZExt, ChildrenT Children); + std::optional traverse(DIOp::SExt SExt, ChildrenT Children); + std::optional traverse(DIOp::Deref Deref, ChildrenT Children); + std::optional traverse(DIOp::Extend Extend, ChildrenT Children); + std::optional traverse(DIOp::Read Read, ChildrenT Children); + std::optional traverse(DIOp::Reinterpret Reinterpret, + ChildrenT Children); + std::optional traverse(DIOp::Select Select, ChildrenT Children); + std::optional traverse(DIOp::Composite Composite, + ChildrenT Children); + + std::optional traverseMathOp(uint8_t DwarfOp, ChildrenT Children); + std::optional traverse(DIOp::Add Op, ChildrenT Children) { + return traverseMathOp(dwarf::DW_OP_plus, Children); + } + std::optional traverse(DIOp::Div Op, ChildrenT Children) { + return traverseMathOp(dwarf::DW_OP_div, Children); + } + std::optional traverse(DIOp::Mul Op, ChildrenT Children) { + return traverseMathOp(dwarf::DW_OP_mul, Children); } - template - std::enable_if_t::value, - Type *> - lower(T OffsetOp, ChildrenT Children) { - assert(Children.size() == 2 && "Expected 2 children"); - readToValue(Children[1].get(), /*NeedsSwap=*/false); - emitDwarfOp(getEquivalentDwarfOp(OffsetOp)); - return OffsetOp.getResultType(); + std::optional traverse(DIOp::Shl Op, ChildrenT Children) { + return traverseMathOp(dwarf::DW_OP_shl, Children); } + std::optional traverse(DIOp::LShr Op, ChildrenT Children) { + return traverseMathOp(dwarf::DW_OP_shr, Children); + } + std::optional traverse(DIOp::AShr Op, ChildrenT Children) { + return traverseMathOp(dwarf::DW_OP_shra, Children); + } + std::optional traverse(DIOp::Sub Op, ChildrenT Children) { + return traverseMathOp(dwarf::DW_OP_minus, Children); + } + + std::optional traverse(DIOp::BitOffset BitOffset, + ChildrenT Children); + std::optional traverse(DIOp::ByteOffset ByteOffset, + ChildrenT Children); - void readToValue(DwarfExprAST::Node *OpNode, bool NeedsSwap); + std::optional traverse(DIOp::Fragment Fragment, ChildrenT Children); void emitReg(int32_t DwarfReg, const char *Comment = nullptr); void emitSigned(int64_t SignedValue); @@ -634,7 +792,7 @@ class DebugLocDwarfExprAST final : DwarfExprAST { ~DebugLocDwarfExprAST() {} bool finalize() { - traverseAndLower(Root.get()); + traverse(Root.get(), ValueKind::LocationDesc); return IsImplemented; } }; @@ -674,7 +832,7 @@ class DIEDwarfExprAST final : DwarfExprAST { ~DIEDwarfExprAST() {} DIELoc *finalize() { - traverseAndLower(Root.get()); + traverse(Root.get(), ValueKind::LocationDesc); return IsImplemented ? &OutDIE : nullptr; } }; diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp index 04aa2237d30ab8..b730c2162b3f59 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp @@ -46,7 +46,7 @@ static cl::opt DisableDwarfLocationsOpt( DIEDwarfExpression::DIEDwarfExpression(const AsmPrinter &AP, DwarfCompileUnit &CU, DIELoc &DIE) - : DwarfExpression(AP.getDwarfVersion(), CU), AP(AP), OutDIE(DIE) {} + : DwarfExpression(AP, CU), OutDIE(DIE) {} void DIEDwarfExpression::emitOp(uint8_t Op, const char* Comment) { CU.addUInt(getActiveDIE(), dwarf::DW_FORM_data1, Op); @@ -68,6 +68,10 @@ void DIEDwarfExpression::emitBaseTypeRef(uint64_t Idx) { CU.addBaseTypeRef(getActiveDIE(), Idx); } +void DIEDwarfExpression::emitOpAddress(const GlobalVariable *GV) { + CU.addOpAddress(getActiveDIE(), AP.getSymbol(GV)); +} + void DIEDwarfExpression::enableTemporaryBuffer() { assert(!IsBuffering && "Already buffering?"); IsBuffering = true; diff --git a/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.h b/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.h index 6d77a6972f09b3..f6ab9e40bc6326 100644 --- a/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.h +++ b/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.h @@ -280,7 +280,8 @@ class DbgValueProperties { /// Extract properties from an existing DBG_VALUE instruction. DbgValueProperties(const MachineInstr &MI) { assert(MI.isDebugValue()); - assert(MI.getDebugExpression()->getNumLocationOperands() == 0 || + assert(MI.getDebugExpression()->isPoisoned() || + MI.getDebugExpression()->getNumLocationOperands() == 0 || MI.isDebugValueList() || MI.isUndefDebugValue()); IsVariadic = MI.isDebugValueList(); DIExpr = MI.getDebugExpression(); diff --git a/llvm/lib/CodeGen/MIRParser/MIParser.cpp b/llvm/lib/CodeGen/MIRParser/MIParser.cpp index 397bac7cd979cb..c52a25cc9391b5 100644 --- a/llvm/lib/CodeGen/MIRParser/MIParser.cpp +++ b/llvm/lib/CodeGen/MIRParser/MIParser.cpp @@ -2294,48 +2294,14 @@ bool MIParser::parseMDNode(MDNode *&Node) { } bool MIParser::parseDIExpression(MDNode *&Expr) { - assert(Token.is(MIToken::md_diexpr)); - lex(); - - // FIXME: Share this parsing with the IL parser. - SmallVector Elements; - - if (expectAndConsume(MIToken::lparen)) - return true; - - if (Token.isNot(MIToken::rparen)) { - do { - if (Token.is(MIToken::Identifier)) { - if (unsigned Op = dwarf::getOperationEncoding(Token.stringValue())) { - lex(); - Elements.push_back(Op); - continue; - } - if (unsigned Enc = dwarf::getAttributeEncoding(Token.stringValue())) { - lex(); - Elements.push_back(Enc); - continue; - } - return error(Twine("invalid DWARF op '") + Token.stringValue() + "'"); - } - - if (Token.isNot(MIToken::IntegerLiteral) || - Token.integerValue().isSigned()) - return error("expected unsigned integer"); - - auto &U = Token.integerValue(); - if (U.ugt(UINT64_MAX)) - return error("element too large, limit is " + Twine(UINT64_MAX)); - Elements.push_back(U.getZExtValue()); - lex(); - - } while (consumeIfPresent(MIToken::comma)); - } - - if (expectAndConsume(MIToken::rparen)) - return true; - - Expr = DIExpression::get(MF.getFunction().getContext(), Elements); + unsigned Read; + Expr = llvm::parseDIExpressionBodyAtBeginning( + CurrentSource, Read, Error, *PFS.MF.getFunction().getParent(), + &PFS.IRSlots); + CurrentSource = CurrentSource.slice(Read, StringRef::npos); + lex(); + if (!Expr) + return error(Error.getMessage()); return false; } diff --git a/llvm/lib/CodeGen/MachineInstr.cpp b/llvm/lib/CodeGen/MachineInstr.cpp index b2288de3ee968d..5fa106f2f8db76 100644 --- a/llvm/lib/CodeGen/MachineInstr.cpp +++ b/llvm/lib/CodeGen/MachineInstr.cpp @@ -685,6 +685,10 @@ bool MachineInstr::isIdenticalTo(const MachineInstr &Other, } bool MachineInstr::isEquivalentDbgInstr(const MachineInstr &Other) const { + // FIXME: Actually consider expression equality + if (getDebugExpression()->holdsNewElements() || + Other.getDebugExpression()->holdsNewElements()) + return false; if (!isDebugValueLike() || !Other.isDebugValueLike()) return false; if (getDebugLoc() != Other.getDebugLoc()) diff --git a/llvm/lib/CodeGen/PrologEpilogInserter.cpp b/llvm/lib/CodeGen/PrologEpilogInserter.cpp index 09ec6f17a6b549..af55b6faeafee8 100644 --- a/llvm/lib/CodeGen/PrologEpilogInserter.cpp +++ b/llvm/lib/CodeGen/PrologEpilogInserter.cpp @@ -1439,6 +1439,24 @@ bool PEI::replaceFrameIndexDebugInstr(MachineFunction &MF, MachineInstr &MI, return true; } + if (MI.isDebugValue() && MI.getDebugExpression()->holdsNewElements()) { + MachineOperand &Op = MI.getOperand(OpIdx); + Register Reg; + unsigned FrameIdx = Op.getIndex(); + StackOffset Offset = TFI->getFrameIndexReference(MF, FrameIdx, Reg); + + if (Reg) { + Op.ChangeToRegister(Reg, false /*isDef*/); + Op.setIsDebug(); + } else { + Op.ChangeToImmediate(0); + } + + MI.getDebugExpressionOp().setMetadata(TFI->lowerFIArgToFPArg( + MF, MI.getDebugExpression(), MI.getDebugOperandIndex(&Op), Offset)); + return true; + } + if (MI.isDebugValue()) { MachineOperand &Op = MI.getOperand(OpIdx); diff --git a/llvm/lib/CodeGen/TargetFrameLoweringImpl.cpp b/llvm/lib/CodeGen/TargetFrameLoweringImpl.cpp index c83af4300ce1d5..07563b40919d38 100644 --- a/llvm/lib/CodeGen/TargetFrameLoweringImpl.cpp +++ b/llvm/lib/CodeGen/TargetFrameLoweringImpl.cpp @@ -22,6 +22,7 @@ #include "llvm/IR/DebugInfoMetadata.h" #include "llvm/IR/Function.h" #include "llvm/IR/InstrTypes.h" +#include "llvm/IR/Module.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCRegisterInfo.h" #include "llvm/Support/Compiler.h" @@ -74,6 +75,31 @@ DIExprBuilder::Iterator TargetFrameLowering::insertFrameLocation( return Builder.insert(BI, IL) + IL.size(); } +DIExpression *TargetFrameLowering::lowerFIArgToFPArg(const MachineFunction &MF, + const DIExpression *Expr, + uint64_t ArgIndex, + StackOffset Offset) const { + const DataLayout &DL = MF.getDataLayout(); + LLVMContext &Context = MF.getFunction().getParent()->getContext(); + DIExprBuilder Builder(*Expr); + for (auto &&I = Builder.begin(); I != Builder.end(); ++I) { + if (auto *Arg = std::get_if(&*I)) { + if (Arg->getIndex() != ArgIndex) + continue; + Type *ResultType = Arg->getResultType(); + unsigned PointerSizeInBits = + DL.getPointerSizeInBits(ResultType->getPointerAddressSpace()); + auto *IntTy = IntegerType::get(Context, PointerSizeInBits); + ConstantData *C = ConstantInt::get(IntTy, Offset.getFixed(), true); + std::initializer_list IL = {DIOp::Reinterpret(IntTy), + DIOp::Constant(C), DIOp::Add(), + DIOp::Reinterpret(ResultType)}; + I = Builder.insert(++I, IL); + } + } + return Builder.intoExpression(); +} + bool TargetFrameLowering::needsFrameIndexResolution( const MachineFunction &MF) const { return MF.getFrameInfo().hasStackObjects(); diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp index c19f125e7a86a3..1294c5e8141157 100644 --- a/llvm/lib/IR/AsmWriter.cpp +++ b/llvm/lib/IR/AsmWriter.cpp @@ -2398,9 +2398,9 @@ static void writeDILabel(raw_ostream &Out, const DILabel *N, Out << ")"; } -static void writeDIExpression(raw_ostream &Out, const DIExpression *N, - AsmWriterContext &WriterCtx) { - Out << "!DIExpression("; +static void writeDIExpressionImpl(raw_ostream &Out, const DIExpression *N, + AsmWriterContext &WriterCtx, + DIExpression::OldElementsRef) { FieldSeparator FS; if (N->isValid()) { for (const DIExpression::ExprOperand &Op : N->expr_ops()) { @@ -2420,6 +2420,80 @@ static void writeDIExpression(raw_ostream &Out, const DIExpression *N, for (const auto &I : N->getElements()) Out << FS << I; } +} + +static void writeDIExpressionImpl(raw_ostream &Out, const DIExpression *N, + AsmWriterContext &WriterCtx, + DIExpression::NewElementsRef Elements) { + assert(WriterCtx.TypePrinter && "DIExpr require TypePrinting!"); + assert(!Elements.empty() && "DIOp-based DIExpression cannot be empty"); + FieldSeparator FS; + for (auto Op : Elements) { + Out << FS << DIOp::getAsmName(Op) << '('; + std::visit( + makeVisitor( +#define HANDLE_OP0(NAME) [](DIOp::NAME) {}, +#include "llvm/IR/DIExprOps.def" +#undef HANDLE_OP0 + [&](DIOp::Referrer Referrer) { + WriterCtx.TypePrinter->print(Referrer.getResultType(), Out); + }, + [&](DIOp::Arg Arg) { + Out << Arg.getIndex() << ", "; + WriterCtx.TypePrinter->print(Arg.getResultType(), Out); + }, + [&](DIOp::TypeObject TypeObject) { + WriterCtx.TypePrinter->print(TypeObject.getResultType(), Out); + }, + [&](DIOp::Constant Constant) { + WriterCtx.TypePrinter->print( + Constant.getLiteralValue()->getType(), Out); + Out << ' '; + WriteConstantInternal(Out, Constant.getLiteralValue(), WriterCtx); + }, + [&](DIOp::Convert Convert) { + WriterCtx.TypePrinter->print(Convert.getResultType(), Out); + }, + [&](DIOp::ZExt ZExt) { + WriterCtx.TypePrinter->print(ZExt.getResultType(), Out); + }, + [&](DIOp::SExt SExt) { + WriterCtx.TypePrinter->print(SExt.getResultType(), Out); + }, + [&](DIOp::Reinterpret Reinterpret) { + WriterCtx.TypePrinter->print(Reinterpret.getResultType(), Out); + }, + [&](DIOp::BitOffset BitOffset) { + WriterCtx.TypePrinter->print(BitOffset.getResultType(), Out); + }, + [&](DIOp::ByteOffset ByteOffset) { + WriterCtx.TypePrinter->print(ByteOffset.getResultType(), Out); + }, + [&](DIOp::Composite Composite) { + Out << Composite.getCount() << ", "; + WriterCtx.TypePrinter->print(Composite.getResultType(), Out); + }, + [&](DIOp::Extend Extend) { Out << Extend.getCount(); }, + [&](DIOp::AddrOf AddrOf) { Out << AddrOf.getAddressSpace(); }, + [&](DIOp::Deref Deref) { + WriterCtx.TypePrinter->print(Deref.getResultType(), Out); + }, + [&](DIOp::PushLane PushLane) { + WriterCtx.TypePrinter->print(PushLane.getResultType(), Out); + }, + [&](DIOp::Fragment Fragment) { + Out << Fragment.getBitOffset() << ", " << Fragment.getBitSize(); + }), + Op); + Out << ')'; + } +} + +static void writeDIExpression(raw_ostream &Out, const DIExpression *N, + AsmWriterContext &WriterCtx) { + Out << "!DIExpression("; + std::visit([&](auto E) { writeDIExpressionImpl(Out, N, WriterCtx, E); }, + N->getElementsRef()); Out << ")"; } @@ -2445,52 +2519,61 @@ static void writeDIExpr(raw_ostream &Out, const DIExpr *N, Out << "!DIExpr("; for (auto &&Op : N->builder()) { Out << FS << DIOp::getAsmName(Op) << '('; - std::visit(makeVisitor( + std::visit( + makeVisitor( #define HANDLE_OP0(NAME) [](DIOp::NAME) {}, #include "llvm/IR/DIExprOps.def" #undef HANDLE_OP0 - [&](DIOp::Referrer Referrer) { - WriterCtx.TypePrinter->print(Referrer.getResultType(), Out); - }, - [&](DIOp::Arg Arg) { - Out << Arg.getIndex() << ", "; - WriterCtx.TypePrinter->print(Arg.getResultType(), Out); - }, - [&](DIOp::TypeObject TypeObject) { - WriterCtx.TypePrinter->print(TypeObject.getResultType(), Out); - }, - [&](DIOp::Constant Constant) { - WriterCtx.TypePrinter->print( - Constant.getLiteralValue()->getType(), Out); - Out << ' '; - WriteConstantInternal(Out, Constant.getLiteralValue(), - WriterCtx); - }, - [&](DIOp::Convert Convert) { - WriterCtx.TypePrinter->print(Convert.getResultType(), Out); - }, - [&](DIOp::Reinterpret Reinterpret) { - WriterCtx.TypePrinter->print(Reinterpret.getResultType(), Out); - }, - [&](DIOp::BitOffset BitOffset) { - WriterCtx.TypePrinter->print(BitOffset.getResultType(), Out); - }, - [&](DIOp::ByteOffset ByteOffset) { - WriterCtx.TypePrinter->print(ByteOffset.getResultType(), Out); - }, - [&](DIOp::Composite Composite) { - Out << Composite.getCount() << ", "; - WriterCtx.TypePrinter->print(Composite.getResultType(), Out); - }, - [&](DIOp::Extend Extend) { Out << Extend.getCount(); }, - [&](DIOp::AddrOf AddrOf) { Out << AddrOf.getAddressSpace(); }, - [&](DIOp::Deref Deref) { - WriterCtx.TypePrinter->print(Deref.getResultType(), Out); - }, - [&](DIOp::PushLane PushLane) { - WriterCtx.TypePrinter->print(PushLane.getResultType(), Out); - }), - Op); + [&](DIOp::Referrer Referrer) { + WriterCtx.TypePrinter->print(Referrer.getResultType(), Out); + }, + [&](DIOp::Arg Arg) { + Out << Arg.getIndex() << ", "; + WriterCtx.TypePrinter->print(Arg.getResultType(), Out); + }, + [&](DIOp::TypeObject TypeObject) { + WriterCtx.TypePrinter->print(TypeObject.getResultType(), Out); + }, + [&](DIOp::Constant Constant) { + WriterCtx.TypePrinter->print( + Constant.getLiteralValue()->getType(), Out); + Out << ' '; + WriteConstantInternal(Out, Constant.getLiteralValue(), WriterCtx); + }, + [&](DIOp::Convert Convert) { + WriterCtx.TypePrinter->print(Convert.getResultType(), Out); + }, + [&](DIOp::ZExt ZExt) { + WriterCtx.TypePrinter->print(ZExt.getResultType(), Out); + }, + [&](DIOp::SExt SExt) { + WriterCtx.TypePrinter->print(SExt.getResultType(), Out); + }, + [&](DIOp::Reinterpret Reinterpret) { + WriterCtx.TypePrinter->print(Reinterpret.getResultType(), Out); + }, + [&](DIOp::BitOffset BitOffset) { + WriterCtx.TypePrinter->print(BitOffset.getResultType(), Out); + }, + [&](DIOp::ByteOffset ByteOffset) { + WriterCtx.TypePrinter->print(ByteOffset.getResultType(), Out); + }, + [&](DIOp::Composite Composite) { + Out << Composite.getCount() << ", "; + WriterCtx.TypePrinter->print(Composite.getResultType(), Out); + }, + [&](DIOp::Extend Extend) { Out << Extend.getCount(); }, + [&](DIOp::AddrOf AddrOf) { Out << AddrOf.getAddressSpace(); }, + [&](DIOp::Deref Deref) { + WriterCtx.TypePrinter->print(Deref.getResultType(), Out); + }, + [&](DIOp::PushLane PushLane) { + WriterCtx.TypePrinter->print(PushLane.getResultType(), Out); + }, + [&](DIOp::Fragment Fragment) { + Out << Fragment.getBitOffset() << ", " << Fragment.getBitSize(); + }), + Op); Out << ')'; } Out << ')'; @@ -3664,7 +3747,7 @@ void AssemblyWriter::printNamedMDNode(const NamedMDNode *NMD) { // FIXME: Ban DIExpressions in NamedMDNodes, they will serve no purpose. MDNode *Op = NMD->getOperand(i); if (auto *Expr = dyn_cast(Op)) { - writeDIExpression(Out, Expr, AsmWriterContext::getEmpty()); + writeDIExpression(Out, Expr, WriterCtx); continue; } if (auto *Expr = dyn_cast(Op)) { diff --git a/llvm/lib/IR/DebugInfoMetadata.cpp b/llvm/lib/IR/DebugInfoMetadata.cpp index 178e0b68c03c52..5ca5e13d118f28 100644 --- a/llvm/lib/IR/DebugInfoMetadata.cpp +++ b/llvm/lib/IR/DebugInfoMetadata.cpp @@ -1367,7 +1367,19 @@ DILabel *DILabel::getImpl(LLVMContext &Context, Metadata *Scope, MDString *Name, } DIExpression *DIExpression::getImpl(LLVMContext &Context, - ArrayRef Elements, + std::nullopt_t Elements, + StorageType Storage, bool ShouldCreate) { + DEFINE_GETIMPL_LOOKUP(DIExpression, (OldElementsRef{})); + DEFINE_GETIMPL_STORE_NO_OPS(DIExpression, (OldElementsRef{})); +} +DIExpression *DIExpression::getImpl(LLVMContext &Context, + OldElementsRef Elements, + StorageType Storage, bool ShouldCreate) { + DEFINE_GETIMPL_LOOKUP(DIExpression, (Elements)); + DEFINE_GETIMPL_STORE_NO_OPS(DIExpression, (Elements)); +} +DIExpression *DIExpression::getImpl(LLVMContext &Context, bool /*ignored*/, + NewElementsRef Elements, StorageType Storage, bool ShouldCreate) { DEFINE_GETIMPL_LOOKUP(DIExpression, (Elements)); DEFINE_GETIMPL_STORE_NO_OPS(DIExpression, (Elements)); @@ -1424,12 +1436,209 @@ unsigned DIExpression::ExprOperand::getSize() const { } } -bool DIExpression::isValid() const { +namespace { +/// Extends validation to include Arguments and DataLayout when available, +/// falling back to assuming the expression is valid when these are not +/// supplied. +class DIExprVerifier : public DIExprConstVisitor { + std::optional Env; + std::string ErrorMsg; + + std::optional Fragment; + +public: + DIExprVerifier(LLVMContext &Context, ArrayRef Expr, + std::optional Env) + : DIExprConstVisitor(Context, Expr), Env(Env) {} + + bool error(const Twine &Msg) { + ErrorMsg = Msg.str(); + return false; + } + + StringRef getErrorMsg() const { + assert(!ErrorMsg.empty() && "Expected error string to be present here"); + return ErrorMsg; + } + + std::optional getSizeInBits(Type *T) { + TypeSize TS = TypeSize::getFixed(0); + if (Env) + TS = Env->DL.getTypeSizeInBits(T); + else + TS = T->getPrimitiveSizeInBits(); + if (TS.isScalable() || !TS.getFixedValue()) + return std::nullopt; + return TS.getFixedValue(); + } + + bool expectSameSize(Type *T, Type *U, const Twine &ErrorMsg) { + if (T == U) + return true; + std::optional TS = getSizeInBits(T); + std::optional US = getSizeInBits(U); + // If we cannot be certain the expression is invalid, just assume it is + // valid. For example, we may not have a DataLayout to determine pointer + // sizes, depending on the caller. + if (!TS || !US) + return true; + if (*TS != *US) + return error(ErrorMsg); + return true; + } + + using DIExprConstVisitor::visit; + + bool visit(DIOp::Referrer Op, Type *ResultType, ArrayRef) { + if (!Env) + return true; + if (Env->Arguments.empty()) + return error("DIOpReferrer requires an argument"); + return expectSameSize( + ResultType, Env->Arguments[0]->getType(), + "DIOpReferrer type must be same size in bits as argument"); + } + + bool visit(DIOp::Arg Op, Type *ResultType, ArrayRef) { + if (!Env) + return true; + if (Op.getIndex() >= Env->Arguments.size()) + // FIXME(diexpression-poison): A debug-intrinsic can end up with a "null" + // value op (represented as an empty MDNode `!{}`) which we will + // eventually lower to an undef location. We could either always use a + // DIArgList or make a location_ops-like adapter that papers over this, + // but for now it should be safe to just ignore it. + // return error("DIOpArg index out of range"); + return true; + return expectSameSize(ResultType, Env->Arguments[Op.getIndex()]->getType(), + "DIOpArg type must be same size in bits as argument"); + } + + bool visit(DIOp::Reinterpret Op, Type *ResultType, + ArrayRef Ins) { + return expectSameSize(ResultType, Ins[0].ResultType, + "DIOpReinterpret must not alter bitsize of child"); + } + + bool visit(DIOp::Composite Op, Type *ResultType, + ArrayRef Ins) { + assert(Op.getCount() == Ins.size()); + + std::optional ResultSizeInBits = getSizeInBits(Op.getResultType()); + if (!ResultSizeInBits) + return true; + + uint64_t TotalSizeInBits = 0u; + for (auto &In : Ins) { + std::optional InSizeInBits = getSizeInBits(In.ResultType); + if (!InSizeInBits) + return true; + TotalSizeInBits += *InSizeInBits; + } + + if (TotalSizeInBits != *ResultSizeInBits) + return error( + "DIOpComposite bitsize does not match sum of child bitsizes"); + + return true; + } + + bool visit(DIOp::Convert Op, Type *ResultType, ArrayRef Ins) { + // We only currently diagnose when DIOpConvert extends one integral + // type to a larger one, so only check when both types are integral. + if (!ResultType->isIntegerTy() || !Ins[0].ResultType->isIntegerTy()) + return true; + std::optional InSizeInBits = getSizeInBits(Ins[0].ResultType); + std::optional ResultSizeInBits = getSizeInBits(ResultType); + if (!InSizeInBits || !ResultSizeInBits) + return true; + if (*ResultSizeInBits > *InSizeInBits) + return error( + Op.getAsmName() + + " on integers requires result type to be no wider than input type"); + return true; + } + + template + bool visitExt(ExtOpT Op, Type *ResultType, ArrayRef Ins) { + std::optional InSizeInBits = getSizeInBits(Ins[0].ResultType); + std::optional ResultSizeInBits = getSizeInBits(ResultType); + if (!InSizeInBits || !ResultSizeInBits) + return true; + if (*ResultSizeInBits <= *InSizeInBits) + return error(Op.getAsmName() + + " requires result type to be wider than input type"); + return true; + } + + bool visit(DIOp::ZExt Op, Type *ResultType, ArrayRef Ins) { + return visitExt(Op, ResultType, Ins); + } + + bool visit(DIOp::SExt Op, Type *ResultType, ArrayRef Ins) { + return visitExt(Op, ResultType, Ins); + } + + bool visit(DIOp::Fragment Op, Type *ResultType, ArrayRef Ins) { + if (Env) { + std::optional VariableSizeInBits = + Env->Variable->getSizeInBits(); + if (VariableSizeInBits && + Op.getBitOffset() + Op.getBitSize() > *VariableSizeInBits) + return error("DIOpFragment must be contained within variable"); + } + Fragment = Op; + return true; + } + + bool visitResult(StackEntry Result) { + // FIXME(diexpression-poison): The IR type size in bits may not correspond + // to the DIType size as calculated by Clang, for example the debug type + // for "uchar3" calls it 32-bits whereas the IR type chosen for it <3 x i8> + // will naively be only 24-bits. Until we can reconcile this issue just + // avoid failing it in the verifier. + return true; + if (!Env) + return true; + std::optional ResultSizeInBits = getSizeInBits(Result.ResultType); + std::optional VariableSizeInBits; + if (Fragment) + VariableSizeInBits = Fragment->getBitSize(); + else + VariableSizeInBits = Env->Variable->getSizeInBits(); + if (!ResultSizeInBits || !VariableSizeInBits) + return true; + if (*ResultSizeInBits < *VariableSizeInBits) + return error("DIExpression must yield a location at least as wide as the " + "variable or fragment it describes"); + return true; + } +}; +} // namespace + +bool DIExpression::isValid( + std::optional Env, + std::optional> ErrS) const { + if (auto NewElementsRef = getNewElementsRef()) { + if (NewElementsRef->empty()) { + if (ErrS) + *ErrS << "DIOp-based DIExpression cannot be empty\n"; + return false; + } + DIExprVerifier Verifier{getContext(), *NewElementsRef, Env}; + bool Result = Verifier.visitInOrder(); + if (!Result && ErrS) + *ErrS << Verifier.getErrorMsg() << '\n'; + return Result; + } for (auto I = expr_op_begin(), E = expr_op_end(); I != E; ++I) { // Check that there's space for the operand. if (I->get() + I->getSize() > E->get()) return false; + if (I->getOp() == dwarf::DW_OP_LLVM_poisoned) + return true; + uint64_t Op = I->getOp(); if ((Op >= dwarf::DW_OP_reg0 && Op <= dwarf::DW_OP_reg31) || (Op >= dwarf::DW_OP_breg0 && Op <= dwarf::DW_OP_breg31)) @@ -1478,6 +1687,7 @@ bool DIExpression::isValid() const { case dwarf::DW_OP_LLVM_convert: case dwarf::DW_OP_LLVM_arg: case dwarf::DW_OP_LLVM_tag_offset: + case dwarf::DW_OP_LLVM_poisoned: case dwarf::DW_OP_constu: case dwarf::DW_OP_plus_uconst: case dwarf::DW_OP_plus: @@ -1561,6 +1771,11 @@ bool DIExpression::isSingleLocationExpression() const { if (!isValid()) return false; + // It is simpler for these cases to always be considered variadic, as + // there are fewer paths to handle. + if (holdsNewElements() || isPoisoned()) + return false; + if (getNumElements() == 0) return true; @@ -1619,6 +1834,9 @@ DIExpression::convertToVariadicExpression(const DIExpression *Expr) { std::optional DIExpression::convertToNonVariadicExpression(const DIExpression *Expr) { + if (Expr->holdsNewElements()) + return std::nullopt; + if (!Expr) return std::nullopt; @@ -1680,6 +1898,14 @@ DIExpression::getFragmentInfo(expr_op_iterator Start, expr_op_iterator End) { return std::nullopt; } +std::optional +DIExpression::getFragmentInfo(NewElementsRef E) { + for (auto Op : E) + if (auto *Fragment = std::get_if(&Op)) + return {{Fragment->getBitSize(), Fragment->getBitOffset()}}; + return std::nullopt; +} + void DIExpression::appendOffset(SmallVectorImpl &Ops, int64_t Offset) { if (Offset > 0) { @@ -1783,6 +2009,10 @@ DIExpression *DIExpression::appendOpsToArg(const DIExpression *Expr, unsigned ArgNo, bool StackValue) { assert(Expr && "Can't add ops to this expression"); + // FIXME: Handle newops here? + if (Expr->isPoisoned()) + return Expr->getPoisoned(); + // Handle non-variadic intrinsics by prepending the opcodes. if (!any_of(Expr->expr_ops(), [](auto Op) { return Op.getOp() == dwarf::DW_OP_LLVM_arg; })) { @@ -1813,6 +2043,28 @@ DIExpression *DIExpression::appendOpsToArg(const DIExpression *Expr, return DIExpression::get(Expr->getContext(), NewOps); } +DIExpression *DIExpression::appendNewOpsToArg(const DIExpression *Expr, + ArrayRef Ops, + unsigned ArgNo, + Type *NewArgType) { + assert(Expr && "Can't add ops to this expression"); + + DIExprBuilder Builder(Expr->getContext()); + auto ExprOps = Expr->getNewElementsRef(); + for (auto Op : *ExprOps) { + DIOp::Arg *AsArg = std::get_if(&Op); + if (AsArg && AsArg->getIndex() == ArgNo) { + Builder.append( + AsArg->getIndex(), NewArgType ? NewArgType : AsArg->getResultType()); + Builder.insert(Builder.end(), Ops.begin(), Ops.end()); + } else { + Builder.append(Op); + } + } + + return Builder.intoExpression(); +} + DIExpression *DIExpression::replaceArg(const DIExpression *Expr, uint64_t OldArg, uint64_t NewArg) { assert(Expr && "Can't replace args in this expression"); @@ -1872,6 +2124,9 @@ DIExpression *DIExpression::append(const DIExpression *Expr, ArrayRef Ops) { assert(Expr && !Ops.empty() && "Can't append ops to this expression"); + if (Expr->isPoisoned()) + return Expr->getPoisoned(); + // Copy Expr's current op list. SmallVector NewOps; for (auto Op : Expr->expr_ops()) { @@ -1925,8 +2180,98 @@ DIExpression *DIExpression::appendToStack(const DIExpression *Expr, return DIExpression::append(Expr, NewOps); } +template static bool isDIOpVariantOneOf(DIOp::Variant Op) { + return (std::holds_alternative(Op) || ...); +} + +/// Skip past *It and any inputs that it consumes. +template +static void skipNewDIExpressionInputs(RIter &It, RIter Last) { + if (It == Last) + return; + + unsigned NumInputs = DIOp::getNumInputs(*It++); + for (unsigned I = 0; I < NumInputs; ++I) + skipNewDIExpressionInputs(It, Last); +} + +/// Check whether the expression described by [It, Last) can be safely +/// fragmented. For example, we have to reject an expression that produces an +/// implicit location description using DIOpAdd since we can't handle carry over +/// between fragments. This is analogous to what createFragmentExpression() is +/// doing below. +/// +/// RIter is a reverse iterator over a DIOp-based DIExpression, so the +/// operations that produce the stack inputs follow the operations that consume +/// them. +template +static bool canFragmentNewDIExpression(RIter &It, RIter Last) { + if (It == Last) + return false; + + DIOp::Variant Op = *It++; + + // FIXME: The Deref could technically be a problem if it's input is an AddrOf. + if (isDIOpVariantOneOf(Op)) + return true; + + if (isDIOpVariantOneOf(Op)) + return false; + + if (isDIOpVariantOneOf(Op)) { + // Skip the offset expression and drill into the base. + skipNewDIExpressionInputs(It, Last); + return canFragmentNewDIExpression(It, Last); + } + + if (isDIOpVariantOneOf(Op)) + return canFragmentNewDIExpression(It, Last); + + // FIXME: Missing DIOpComposite, DIOpExtend, DIOpSelect. + return false; +} + +static std::optional +createNewFragmentExpression(const DIExpression *Expr, unsigned OffsetInBits, + unsigned SizeInBits) { + auto NewElems = Expr->getNewElementsRef(); + assert(NewElems && "expected DIOp expression"); + + auto Iter = NewElems->rbegin(), End = NewElems->rend(); + if (!canFragmentNewDIExpression(Iter, End)) + return std::nullopt; + + DIExprBuilder ExprBuilder(Expr->getContext()); + for (DIOp::Variant Op : *NewElems) { + if (auto *Frag = std::get_if(&Op)) { + assert((OffsetInBits + SizeInBits <= Frag->getBitSize()) && + "new fragment outside of original fragment"); + OffsetInBits += Frag->getBitOffset(); + } else { + ExprBuilder.append(Op); + } + } + + ExprBuilder.append(OffsetInBits, SizeInBits); + return ExprBuilder.intoExpression(); +} + std::optional DIExpression::createFragmentExpression( const DIExpression *Expr, unsigned OffsetInBits, unsigned SizeInBits) { + + if (Expr->holdsNewElements()) + return createNewFragmentExpression(Expr, OffsetInBits, SizeInBits); + + // FIXME(diexpression-poison): Is it safe to handle each fragment + // independently? If a fragment gets poisoned we lose the fragment info, so + // can't locate it correctly. Conservatively we can just have it cover the + // whole variable. + if (Expr->isPoisoned()) + return Expr->getPoisoned(); + SmallVector Ops; // Track whether it's safe to split the value at the top of the DWARF stack, // assuming that it'll be used as an implicit location value. @@ -2036,6 +2381,28 @@ uint64_t DIExpression::getNumLocationOperands() const { return Result; } +uint64_t DIExpression::getNewNumLocationOperands() const { + uint64_t Result = 0; + auto Ops = getNewElementsRef(); + for (DIOp::Variant Op : *Ops) + if (auto *Arg = std::get_if(&Op)) + Result = std::max(Result, static_cast(Arg->getIndex() + 1)); + return Result; +} + +/// Returns true if the expression holds NewElements or contains the +/// DW_OP_LLVM_poisoned operation. +/// +/// \warning This is intended for use in "old paths" where a new expression is +/// equivalent to a poisoned expression. These paths still need to create a +/// poison expression if this returns true, however; the underlying expression +/// may hold NewElements otherwise. +bool DIExpression::isPoisoned() const { + return any_of(expr_ops(), [](auto Op) { + return Op.getOp() == dwarf::DW_OP_LLVM_poisoned; + }); +} + std::optional DIExpression::isConstant() const { @@ -2085,6 +2452,38 @@ unsigned DIOp::getBitcodeID(const Variant &V) { return std::visit(makeVisitor([](auto &&Op) { return Op.getBitcodeID(); }), V); } +unsigned DIOp::getNumInputs(Variant V) { + // clang-format off + using R = unsigned; + return std::visit(makeVisitor( + [](DIOp::Arg) -> R { return 0; }, + [](DIOp::Constant) -> R { return 0; }, + [](DIOp::PushLane) -> R { return 0; }, + [](DIOp::Referrer) -> R { return 0; }, + [](DIOp::TypeObject) -> R { return 0; }, + [](DIOp::AddrOf) -> R { return 1; }, + [](DIOp::Convert) -> R { return 1; }, + [](DIOp::ZExt) -> R { return 1; }, + [](DIOp::SExt) -> R { return 1; }, + [](DIOp::Deref) -> R { return 1; }, + [](DIOp::Extend) -> R { return 1; }, + [](DIOp::Read) -> R { return 1; }, + [](DIOp::Reinterpret) -> R { return 1; }, + [](DIOp::Add) -> R { return 2; }, + [](DIOp::BitOffset) -> R { return 2; }, + [](DIOp::ByteOffset) -> R { return 2; }, + [](DIOp::Div) -> R { return 2; }, + [](DIOp::Mul) -> R { return 2; }, + [](DIOp::Shl) -> R { return 2; }, + [](DIOp::LShr) -> R { return 2; }, + [](DIOp::AShr) -> R { return 2; }, + [](DIOp::Sub) -> R { return 2; }, + [](DIOp::Select) -> R { return 3; }, + [](DIOp::Composite C) -> R { return C.getCount(); }, + [](DIOp::Fragment) -> R { return 0; }), V); + // clang-format on +} + namespace llvm { namespace DIOp { #define HANDLE_OP0(NAME) \ @@ -2099,10 +2498,14 @@ namespace DIOp { DIExprBuilder::DIExprBuilder(LLVMContext &C) : C(C) {} DIExprBuilder::DIExprBuilder(LLVMContext &C, - std::initializer_list IL) + std::initializer_list IL) : C(C), Elements(IL) {} +DIExprBuilder::DIExprBuilder(LLVMContext &C, ArrayRef V) + : C(C), Elements(V) {} DIExprBuilder::DIExprBuilder(const DIExpr &E) : C(E.getContext()), Elements(E.Elements) {} +DIExprBuilder::DIExprBuilder(const DIExpression &E) + : C(E.getContext()), Elements(*E.getNewElementsRef()) {} DIExprBuilder &DIExprBuilder::append(DIOp::Variant O) { Elements.push_back(O); @@ -2129,6 +2532,14 @@ DIExpr *DIExprBuilder::intoExpr() { return DIExpr::get(C, std::move(Elements)); } +DIExpression *DIExprBuilder::intoExpression() { +#ifndef NDEBUG + assert(!StateIsUnspecified); + StateIsUnspecified = true; +#endif + return DIExpression::get(C, false, std::move(Elements)); +} + DIExprBuilder &DIExprBuilder::removeReferrerIndirection(Type *PointeeType) { for (auto &&I = begin(); I != end(); ++I) { if (auto *ReferrerOp = std::get_if(&*I)) { diff --git a/llvm/lib/IR/DebugProgramInstruction.cpp b/llvm/lib/IR/DebugProgramInstruction.cpp index fd234685d5fd4b..29e5d16a06cd56 100644 --- a/llvm/lib/IR/DebugProgramInstruction.cpp +++ b/llvm/lib/IR/DebugProgramInstruction.cpp @@ -216,11 +216,12 @@ void DPValue::replaceVariableLocationOp(unsigned OpIdx, Value *NewValue) { } void DPValue::addVariableLocationOps(ArrayRef NewValues, - DIExpression *NewExpr) { - assert(NewExpr->hasAllLocationOps(getNumVariableLocationOps() + + DIExpression *NewExpr) { + assert(NewExpr->holdsNewElements() || + NewExpr->hasAllLocationOps(getNumVariableLocationOps() + NewValues.size()) && - "NewExpr for debug variable intrinsic does not reference every " - "location operand."); + "NewExpr for debug variable intrinsic does not reference every " + "location operand."); assert(!is_contained(NewValues, nullptr) && "New values must be non-null"); setExpression(NewExpr); SmallVector MDs; diff --git a/llvm/lib/IR/IntrinsicInst.cpp b/llvm/lib/IR/IntrinsicInst.cpp index 7a3b708e740067..ec33c1c227fe63 100644 --- a/llvm/lib/IR/IntrinsicInst.cpp +++ b/llvm/lib/IR/IntrinsicInst.cpp @@ -177,10 +177,11 @@ void DbgVariableIntrinsic::replaceVariableLocationOp(unsigned OpIdx, void DbgVariableIntrinsic::addVariableLocationOps(ArrayRef NewValues, DIExpression *NewExpr) { - assert(NewExpr->hasAllLocationOps(getNumVariableLocationOps() + + assert(NewExpr->holdsNewElements() || + NewExpr->hasAllLocationOps(getNumVariableLocationOps() + NewValues.size()) && - "NewExpr for debug variable intrinsic does not reference every " - "location operand."); + "NewExpr for debug variable intrinsic does not reference every " + "location operand."); assert(!is_contained(NewValues, nullptr) && "New values must be non-null"); setArgOperand(2, MetadataAsValue::get(getContext(), NewExpr)); SmallVector MDs; diff --git a/llvm/lib/IR/LLVMContextImpl.h b/llvm/lib/IR/LLVMContextImpl.h index 246856ea203ab5..0a20fec8c47adf 100644 --- a/llvm/lib/IR/LLVMContextImpl.h +++ b/llvm/lib/IR/LLVMContextImpl.h @@ -1183,18 +1183,17 @@ template <> struct MDNodeKeyImpl { }; template <> struct MDNodeKeyImpl { - ArrayRef Elements; + DIExpression::ElementsRef Elements; + MDNodeKeyImpl(DIExpression::NewElementsRef Elements) : Elements(Elements) {} MDNodeKeyImpl(ArrayRef Elements) : Elements(Elements) {} - MDNodeKeyImpl(const DIExpression *N) : Elements(N->getElements()) {} + MDNodeKeyImpl(const DIExpression *N) : Elements(N->getElementsRef()) {} bool isKeyOf(const DIExpression *RHS) const { - return Elements == RHS->getElements(); + return Elements == RHS->getElementsRef(); } - unsigned getHashValue() const { - return hash_combine_range(Elements.begin(), Elements.end()); - } + unsigned getHashValue() const { return hash_value(Elements); } }; template <> struct MDNodeKeyImpl { diff --git a/llvm/lib/IR/TypeFinder.cpp b/llvm/lib/IR/TypeFinder.cpp index 2b97d0a8fd2781..61de93a5122251 100644 --- a/llvm/lib/IR/TypeFinder.cpp +++ b/llvm/lib/IR/TypeFinder.cpp @@ -173,27 +173,42 @@ void TypeFinder::incorporateMDNode(const MDNode *V) { if (!VisitedMetadata.insert(V).second) return; + auto incorporateDIOp = [this](DIOp::Variant Op) { + std::visit( + makeVisitor( +#define HANDLE_OP0(NAME) [](DIOp::NAME) {}, +#include "llvm/IR/DIExprOps.def" + [&](DIOp::Referrer R) { incorporateType(R.getResultType()); }, + [&](DIOp::Arg A) { incorporateType(A.getResultType()); }, + [&](DIOp::TypeObject T) { incorporateType(T.getResultType()); }, + [&](DIOp::Constant C) { incorporateValue(C.getLiteralValue()); }, + [&](DIOp::Convert C) { incorporateType(C.getResultType()); }, + [&](DIOp::ZExt C) { incorporateType(C.getResultType()); }, + [&](DIOp::SExt C) { incorporateType(C.getResultType()); }, + [&](DIOp::Reinterpret R) { incorporateType(R.getResultType()); }, + [&](DIOp::BitOffset B) { incorporateType(B.getResultType()); }, + [&](DIOp::ByteOffset B) { incorporateType(B.getResultType()); }, + [&](DIOp::Composite C) { incorporateType(C.getResultType()); }, + [&](DIOp::Extend) {}, [&](DIOp::AddrOf) {}, + [&](DIOp::Deref D) { incorporateType(D.getResultType()); }, + [&](DIOp::PushLane P) { incorporateType(P.getResultType()); }, + [&](DIOp::Fragment F) {}), + Op); + }; + // The operations in a DIExpr are not exposed as operands, so handle such // nodes specifically here. if (const auto *E = dyn_cast(V)) { - for (auto &&Op : E->builder()) - std::visit( - makeVisitor( -#define HANDLE_OP0(NAME) [](DIOp::NAME) {}, -#include "llvm/IR/DIExprOps.def" - [&](DIOp::Referrer R) { incorporateType(R.getResultType()); }, - [&](DIOp::Arg A) { incorporateType(A.getResultType()); }, - [&](DIOp::TypeObject T) { incorporateType(T.getResultType()); }, - [&](DIOp::Constant C) { incorporateValue(C.getLiteralValue()); }, - [&](DIOp::Convert C) { incorporateType(C.getResultType()); }, - [&](DIOp::Reinterpret R) { incorporateType(R.getResultType()); }, - [&](DIOp::BitOffset B) { incorporateType(B.getResultType()); }, - [&](DIOp::ByteOffset B) { incorporateType(B.getResultType()); }, - [&](DIOp::Composite C) { incorporateType(C.getResultType()); }, - [&](DIOp::Extend) {}, [&](DIOp::AddrOf) {}, - [&](DIOp::Deref D) { incorporateType(D.getResultType()); }, - [&](DIOp::PushLane P) { incorporateType(P.getResultType()); }), - Op); + for (const auto &Op : E->builder()) + incorporateDIOp(Op); + return; + } + + if (const auto *E = dyn_cast(V)) { + if (auto Elems = E->getNewElementsRef()) { + for (const auto &Op : *Elems) + incorporateDIOp(Op); + } return; } diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp index 4ed2f261df66ad..a4d8e1802a06dd 100644 --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -854,6 +854,14 @@ void Verifier::visitGlobalVariable(const GlobalVariable &GV) { SmallVector MDs; GV.getMetadata(LLVMContext::MD_dbg, MDs); for (auto *MD : MDs) { + if (auto *GVE = dyn_cast(MD)) { + if (auto *E = dyn_cast_or_null(GVE->getRawExpression())) { + SmallVector Arguments{&GV}; + DIExpressionEnv Env{GVE->getVariable(), Arguments, DL}; + CheckDI(E->isValid(Env, dbgs()), + "invalid DIExpression in DIGlobalVariableExpression", &GV); + } + } if (auto *GVE = dyn_cast(MD)) visitDIGlobalVariableExpression(*GVE); else @@ -6494,6 +6502,14 @@ void Verifier::visitDbgIntrinsic(StringRef Kind, DbgVariableIntrinsic &DII) { "invalid llvm.dbg." + Kind + " intrinsic expression", &DII, DII.getRawExpression()); + // This is redundant with the preprocessor-generated check, but here we + // can include arguments for DIOp-based expression checking. + SmallVector Arguments{DII.location_ops()}; + DIExpressionEnv Env{DII.getVariable(), Arguments, DL}; + CheckDI(DII.getExpression()->isValid(Env, dbgs()), + "invalid DIExpression in llvm.dbg." + Kind + " intrinsic", &DII, + DII.getRawExpression()); + if (auto *DAI = dyn_cast(&DII)) { CheckDI(isa(DAI->getRawAssignID()), "invalid llvm.dbg.assign intrinsic DIAssignID", &DII, diff --git a/llvm/lib/Target/AMDGPU/AMDGPUFrameLowering.cpp b/llvm/lib/Target/AMDGPU/AMDGPUFrameLowering.cpp index 0383ffdd064b5e..10430274dcb7fc 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPUFrameLowering.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPUFrameLowering.cpp @@ -82,9 +82,39 @@ DIExprBuilder::Iterator AMDGPUFrameLowering::insertFrameLocation( SmallVector FL = { DIOp::Referrer(IntPtrTy) }; if (!ST.enableFlatScratch()) - FL.append({ DIOp::Constant(WavefrontSizeLog2), DIOp::Shr() }); + FL.append({DIOp::Constant(WavefrontSizeLog2), DIOp::LShr()}); FL.append( { DIOp::Reinterpret(PointerType::get(ResultType, AllocaAddrSpace)), DIOp::Deref(ResultType) }); return Builder.insert(BI, FL) + FL.size(); } + +DIExpression *AMDGPUFrameLowering::lowerFIArgToFPArg(const MachineFunction &MF, + const DIExpression *Expr, + uint64_t ArgIndex, + StackOffset Offset) const { + const DataLayout &DL = MF.getDataLayout(); + LLVMContext &Context = MF.getFunction().getParent()->getContext(); + const auto &ST = MF.getSubtarget(); + DIExprBuilder Builder(*Expr); + for (auto &&I = Builder.begin(); I != Builder.end(); ++I) { + if (auto *Arg = std::get_if(&*I)) { + if (Arg->getIndex() != ArgIndex) + continue; + Type *ResultType = Arg->getResultType(); + unsigned PointerSizeInBits = + DL.getPointerSizeInBits(ResultType->getPointerAddressSpace()); + auto *IntTy = IntegerType::get(Context, PointerSizeInBits); + ConstantData *WavefrontSizeLog2 = static_cast( + ConstantInt::get(IntTy, ST.getWavefrontSizeLog2(), false)); + ConstantData *C = ConstantInt::get(IntTy, Offset.getFixed(), true); + SmallVector FL = {DIOp::Reinterpret(IntTy)}; + if (!ST.enableFlatScratch()) + FL.append({DIOp::Constant(WavefrontSizeLog2), DIOp::LShr()}); + FL.append( + {DIOp::Constant(C), DIOp::Add(), DIOp::Reinterpret(ResultType)}); + I = Builder.insert(++I, FL); + } + } + return Builder.intoExpression(); +} diff --git a/llvm/lib/Target/AMDGPU/AMDGPUFrameLowering.h b/llvm/lib/Target/AMDGPU/AMDGPUFrameLowering.h index 2fdc05663dd7c1..aa73e128ade9de 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPUFrameLowering.h +++ b/llvm/lib/Target/AMDGPU/AMDGPUFrameLowering.h @@ -37,6 +37,10 @@ class AMDGPUFrameLowering : public TargetFrameLowering { DIExprBuilder &Builder, DIExprBuilder::Iterator BI, Type *ResultType) const override; + + DIExpression *lowerFIArgToFPArg(const MachineFunction &MF, + const DIExpression *Expr, uint64_t ArgIndex, + StackOffset Offset) const override; }; } // end namespace llvm diff --git a/llvm/lib/Target/AMDGPU/AMDGPULowerModuleLDSPass.cpp b/llvm/lib/Target/AMDGPU/AMDGPULowerModuleLDSPass.cpp index 77f0bbf2d80fe4..470d296d396fba 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPULowerModuleLDSPass.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPULowerModuleLDSPass.cpp @@ -1191,11 +1191,19 @@ class AMDGPULowerModuleLDS { performOptimizedStructLayout(LayoutFields); - struct VarInfo { + struct DIExprVarInfo { GlobalVariable *Var; uint64_t Offset; }; - DenseMap Fragment2VarInfo; + DenseMap Fragment2VarInfo; + + struct DIExpressionVarInfo { + GlobalVariable *Var; + Metadata *DIVar; + DIExpression::NewElementsRef Expr; + uint64_t Offset; + }; + SmallVector DIExpressionVarInfos; std::vector LocalVars; BitVector IsPaddingField; @@ -1225,8 +1233,21 @@ class AMDGPULowerModuleLDS { CurrentOffset += Padding; } - if (isHeterogeneousDebug(M)) - Fragment2VarInfo[FGV->getDbgDef()] = VarInfo{ FGV, CurrentOffset }; + if (isHeterogeneousDebug(M)) { + Fragment2VarInfo[FGV->getDbgDef()] = + DIExprVarInfo{FGV, CurrentOffset}; + } else { + SmallVector OriginalGVEs; + FGV->getDebugInfo(OriginalGVEs); + for (const auto *OriginalGVE : OriginalGVEs) { + if (auto NewElementsRef = + OriginalGVE->getExpression()->getNewElementsRef()) { + DIExpressionVarInfos.push_back({FGV, + OriginalGVE->getRawVariable(), + *NewElementsRef, CurrentOffset}); + } + } + } LocalVars.push_back(FGV); IsPaddingField.push_back(false); @@ -1287,6 +1308,36 @@ class AMDGPULowerModuleLDS { L->replaceOperandWith(2, DbgVarFragment); } } + } else { + for (auto VarInfo : DIExpressionVarInfos) { + DIExprBuilder ExprBuilder(Ctx); + for (auto Op : VarInfo.Expr) { + if (auto *ArgOp = std::get_if(&Op)) { + assert(ArgOp->getIndex() == 0u && + "DIOp-based DIExpression in DIGlobalVariableExpression must " + "have only one argument"); + Type *ArgTy = SGV->getType(); + assert(isa(ArgTy)); + Type *ResultTy = VarInfo.Var->getType(); + assert(isa(ResultTy)); + assert(ArgTy->getPointerAddressSpace() == + ResultTy->getPointerAddressSpace()); + unsigned PointerSizeInBits = + DL.getPointerSizeInBits(ArgTy->getPointerAddressSpace()); + auto *IntTy = IntegerType::get(Ctx, PointerSizeInBits); + ConstantData *C = ConstantInt::get(IntTy, VarInfo.Offset, true); + ExprBuilder.append(0u, ArgTy); + ExprBuilder.append(IntTy); + ExprBuilder.append(C); + ExprBuilder.append(); + ExprBuilder.append(ResultTy); + } else { + ExprBuilder.append(Op); + } + } + SGV->addDebugInfo(DIGlobalVariableExpression::get( + Ctx, VarInfo.DIVar, ExprBuilder.intoExpression())); + } } DenseMap Map; diff --git a/llvm/lib/Transforms/Utils/Debugify.cpp b/llvm/lib/Transforms/Utils/Debugify.cpp index d0cc603426d2a7..e92831a8e4f588 100644 --- a/llvm/lib/Transforms/Utils/Debugify.cpp +++ b/llvm/lib/Transforms/Utils/Debugify.cpp @@ -55,6 +55,10 @@ cl::opt DebugifyLevel( "Locations and Variables")), cl::init(Level::LocationsAndVariables)); +cl::opt DebugifyDIOpDIExprs( + "debugify-diop-diexprs", + cl::desc("Generate DIOp-based DIExpressions in debugify"), cl::init(false)); + raw_ostream &dbg() { return Quiet ? nulls() : errs(); } uint64_t getAllocSizeInBits(Module &M, Type *Ty) { @@ -137,6 +141,24 @@ bool llvm::applyDebugifyMetadata( auto LocalVar = DIB.createAutoVariable(SP, Name, File, Loc->getLine(), getCachedDIType(V->getType()), /*AlwaysPreserve=*/true); + if (DebugifyDIOpDIExprs) { + DIExprBuilder ExprBuilder(Ctx); + ExprBuilder.append(0, V->getType()); + std::optional IRSize; + if (TypeSize IRTypeSize = + M.getDataLayout().getTypeSizeInBits(V->getType())) + if (!IRTypeSize.isScalable()) + IRSize = IRTypeSize.getFixedValue(); + std::optional DISize = LocalVar->getSizeInBits(); + if (IRSize && DISize) { + assert(DISize >= IRSize); + if (DISize > IRSize) + ExprBuilder.append(IntegerType::get(Ctx, *DISize)); + } + DIB.insertDbgValueIntrinsic(V, LocalVar, ExprBuilder.intoExpression(), + Loc, InsertBefore); + return; + } DIB.insertDbgValueIntrinsic(V, LocalVar, DIB.createExpression(), Loc, InsertBefore); }; diff --git a/llvm/lib/Transforms/Utils/Local.cpp b/llvm/lib/Transforms/Utils/Local.cpp index d1b42f28923f5e..84faae3712f9cf 100644 --- a/llvm/lib/Transforms/Utils/Local.cpp +++ b/llvm/lib/Transforms/Utils/Local.cpp @@ -1679,6 +1679,41 @@ static void insertDbgValueOrDPValueAfter(DIBuilder &Builder, Value *DV, } } +// \p In is an expression that takes a pointer argument. Attempt to create an +// equivalent expression that takes a value by replacing the type field to the +// DIOpArg and adding a DIOpAddrOf after it. +static DIExpression *tryRemoveNewDIExpressionIndirection(DIExpression *In, + Type *ArgType) { + if (!In->holdsNewElements()) + return In; + + auto Elements = In->getNewElementsRef(); + DIExprBuilder ExprBuilder(In->getContext()); + unsigned NumReplacedArgs = 0; + for (auto Iter = Elements->begin(), End = Elements->end(); Iter != End; + ++Iter) { + auto *Arg = std::get_if(&*Iter); + if (!Arg) { + ExprBuilder.append(*Iter); + continue; + } + + ++NumReplacedArgs; + ExprBuilder.append(Arg->getIndex(), ArgType); + auto *PointerTy = dyn_cast(Arg->getResultType()); + if (!PointerTy) + return nullptr; + + auto Next = std::next(Iter); + if (Next == Elements->end() || !std::holds_alternative(*Next)) + ExprBuilder.append(PointerTy->getAddressSpace()); + else + Iter = Next; + } + + return NumReplacedArgs == 1 ? ExprBuilder.intoExpression() : nullptr; +} + /// Inserts a llvm.dbg.value intrinsic before a store to an alloca'd value /// that has an associated llvm.dbg.declare intrinsic. void llvm::ConvertDebugDeclareToDebugValue(DbgVariableIntrinsic *DII, @@ -1689,6 +1724,10 @@ void llvm::ConvertDebugDeclareToDebugValue(DbgVariableIntrinsic *DII, auto *DIExpr = DII->getExpression(); Value *DV = SI->getValueOperand(); + DIExpr = tryRemoveNewDIExpressionIndirection(DIExpr, DV->getType()); + if (!DIExpr) + return; + DebugLoc NewLoc = getDebugValueLoc(DII); // If the alloca describes the variable itself, i.e. the expression in the @@ -1706,6 +1745,11 @@ void llvm::ConvertDebugDeclareToDebugValue(DbgVariableIntrinsic *DII, bool CanConvert = DIExpr->isDeref() || (!DIExpr->startsWithDeref() && valueCoversEntireFragment(DV->getType(), DII)); + + // There are no such limitations on new DIExpressions. + if (DIExpr->holdsNewElements()) + CanConvert = true; + if (CanConvert) { insertDbgValueOrDPValue(Builder, DV, DIVar, DIExpr, NewLoc, SI->getIterator()); @@ -1746,7 +1790,12 @@ void llvm::ConvertDebugDeclareToDebugValue(DbgVariableIntrinsic *DII, auto *DIExpr = DII->getExpression(); assert(DIVar && "Missing variable"); - if (!valueCoversEntireFragment(LI->getType(), DII)) { + DIExpr = tryRemoveNewDIExpressionIndirection(DIExpr, LI->getType()); + if (!DIExpr) + return; + + if (!DIExpr->holdsNewElements() && + !valueCoversEntireFragment(LI->getType(), DII)) { // FIXME: If only referring to a part of the variable described by the // dbg.declare, then we want to insert a dbg.value for the corresponding // fragment. @@ -1775,6 +1824,10 @@ void llvm::ConvertDebugDeclareToDebugValue(DPValue *DPV, StoreInst *SI, DebugLoc NewLoc = getDebugValueLoc(DPV); + DIExpr = tryRemoveNewDIExpressionIndirection(DIExpr, DV->getType()); + if (!DIExpr) + return; + // If the alloca describes the variable itself, i.e. the expression in the // dbg.declare doesn't start with a dereference, we can perform the // conversion if the value covers the entire fragment of DII. @@ -1790,6 +1843,11 @@ void llvm::ConvertDebugDeclareToDebugValue(DPValue *DPV, StoreInst *SI, bool CanConvert = DIExpr->isDeref() || (!DIExpr->startsWithDeref() && valueCoversEntireFragment(DV->getType(), DPV)); + + // There are no such limitations on new DIExpressions. + if (DIExpr->holdsNewElements()) + CanConvert = true; + if (CanConvert) { insertDbgValueOrDPValue(Builder, DV, DIVar, DIExpr, NewLoc, SI->getIterator()); @@ -1819,10 +1877,15 @@ void llvm::ConvertDebugDeclareToDebugValue(DbgVariableIntrinsic *DII, auto *DIExpr = DII->getExpression(); assert(DIVar && "Missing variable"); + DIExpr = tryRemoveNewDIExpressionIndirection(DIExpr, APN->getType()); + if (!DIExpr) + return; + if (PhiHasDebugValue(DIVar, DIExpr, APN)) return; - if (!valueCoversEntireFragment(APN->getType(), DII)) { + if (!DIExpr->holdsNewElements() && + !valueCoversEntireFragment(APN->getType(), DII)) { // FIXME: If only referring to a part of the variable described by the // dbg.declare, then we want to insert a dbg.value for the corresponding // fragment. @@ -1850,7 +1913,8 @@ void llvm::ConvertDebugDeclareToDebugValue(DPValue *DPV, LoadInst *LI, auto *DIExpr = DPV->getExpression(); assert(DIVar && "Missing variable"); - if (!valueCoversEntireFragment(LI->getType(), DPV)) { + if (!DIExpr->holdsNewElements() && + !valueCoversEntireFragment(LI->getType(), DPV)) { // FIXME: If only referring to a part of the variable described by the // dbg.declare, then we want to insert a DPValue for the corresponding // fragment. @@ -1859,6 +1923,10 @@ void llvm::ConvertDebugDeclareToDebugValue(DPValue *DPV, LoadInst *LI, return; } + DIExpr = tryRemoveNewDIExpressionIndirection(DIExpr, LI->getType()); + if (!DIExpr) + return; + DebugLoc NewLoc = getDebugValueLoc(DPV); // We are now tracking the loaded value instead of the address. In the @@ -1889,10 +1957,15 @@ void llvm::ConvertDebugDeclareToDebugValue(DPValue *DPV, PHINode *APN, auto *DIExpr = DPV->getExpression(); assert(DIVar && "Missing variable"); + DIExpr = tryRemoveNewDIExpressionIndirection(DIExpr, APN->getType()); + if (!DIExpr) + return; + if (PhiHasDebugValue(DIVar, DIExpr, APN)) return; - if (!valueCoversEntireFragment(APN->getType(), DPV)) { + if (!DIExpr->holdsNewElements() && + !valueCoversEntireFragment(APN->getType(), DPV)) { // FIXME: If only referring to a part of the variable described by the // dbg.declare, then we want to insert a DPValue for the corresponding // fragment. @@ -1974,10 +2047,19 @@ bool llvm::LowerDbgDeclare(Function &F) { // the variable by dereferencing the alloca. if (!CI->isLifetimeStartOrEnd()) { DebugLoc NewLoc = getDebugValueLoc(DDI); - auto *DerefExpr = - DIExpression::append(DDI->getExpression(), dwarf::DW_OP_deref); - insertDbgValueOrDPValue(DIB, AI, DDI->getVariable(), DerefExpr, - NewLoc, CI->getIterator()); + if (DDI->getExpression()->holdsNewElements()) { + // In DIOp-based DIExpressions it's okay for a dbg.value to + // produce a memory location descriptor, so there isn't any need + // to change the expression. + insertDbgValueOrDPValue(DIB, AI, DDI->getVariable(), + DDI->getExpression(), NewLoc, + CI->getIterator()); + } else { + auto *DerefExpr = DIExpression::append(DDI->getExpression(), + dwarf::DW_OP_deref); + insertDbgValueOrDPValue(DIB, AI, DDI->getVariable(), DerefExpr, + NewLoc, CI->getIterator()); + } } } else if (BitCastInst *BI = dyn_cast(U)) { if (BI->getType()->isPointerTy()) @@ -2237,6 +2319,139 @@ static void salvageDbgAssignAddress(DbgAssignIntrinsic *DAI) { } } +/// This is a port of getSalvageOpsForBinOp() to DIOp-based DIExpressions. +static Value * +getNewSalvageOpsForBinOp(BinaryOperator *BI, uint64_t CurrentLocOps, + SmallVectorImpl &Ops, + SmallVectorImpl &AdditionalValues) { + // Handle binary operations with constant integer operands as a special case. + auto *ConstInt = dyn_cast(BI->getOperand(1)); + + if (ConstInt) { + // Values wider than 64 bits cannot be represented within a DIExpression. + if (ConstInt->getBitWidth() > 64) + return nullptr; + Ops.emplace_back(DIOp::Constant(ConstInt)); + } else { + Ops.emplace_back(DIOp::Arg(CurrentLocOps, BI->getOperand(1)->getType())); + AdditionalValues.push_back(BI->getOperand(1)); + } + + switch (BI->getOpcode()) { + default: + // FIXME: Some binary operators aren't representable in DIOp-based + // DIExpressions. + return nullptr; + case Instruction::Add: + Ops.emplace_back(DIOp::Add()); + break; + case Instruction::Sub: + Ops.emplace_back(DIOp::Sub()); + break; + case Instruction::Mul: + Ops.emplace_back(DIOp::Mul()); + break; + case Instruction::SDiv: + Ops.emplace_back(DIOp::Div()); + break; + case Instruction::Shl: + Ops.emplace_back(DIOp::Shl()); + break; + case Instruction::LShr: + Ops.emplace_back(DIOp::LShr()); + break; + case Instruction::AShr: + Ops.emplace_back(DIOp::AShr()); + break; + } + + return BI->getOperand(0); +} + +/// This is a port of getSalvageOpsForGEP() to DIOp-based DIExpressions. +static Value * +getNewSalvageOpsForGEP(GetElementPtrInst *GEP, const DataLayout &DL, + uint64_t CurrentLocOps, + SmallVectorImpl &Ops, + SmallVectorImpl &AdditionalValues) { + LLVMContext &Ctx = GEP->getContext(); + Type *PointerTy = GEP->getPointerOperand()->getType(); + auto *IntPtrTy = IntegerType::get(Ctx, DL.getPointerTypeSizeInBits(PointerTy)); + unsigned BitWidth = DL.getIndexSizeInBits(GEP->getPointerAddressSpace()); + + // Rewrite a GEP into a DIExpression. + MapVector VariableOffsets; + APInt ConstantOffset(BitWidth, 0); + if (!GEP->collectOffset(DL, BitWidth, VariableOffsets, ConstantOffset)) + return nullptr; + + Ops.emplace_back(DIOp::Reinterpret(IntPtrTy)); + + for (const auto &Offset : VariableOffsets) { + AdditionalValues.push_back(Offset.first); + assert(Offset.second.isStrictlyPositive() && + "Expected strictly positive multiplier for offset."); + ConstantInt *ConstOffset = + ConstantInt::get(IntPtrTy, Offset.second.getZExtValue()); + DIOp::Variant NewOps[] = { + DIOp::Arg(CurrentLocOps++, ConstOffset->getType()), + DIOp::Constant(ConstOffset), DIOp::Mul(), DIOp::Add()}; + Ops.append(std::begin(NewOps), std::end(NewOps)); + } + + Ops.emplace_back(DIOp::Constant( + ConstantInt::get(IntPtrTy, ConstantOffset.getZExtValue()))); + Ops.emplace_back(DIOp::Add()); + Ops.emplace_back(DIOp::Reinterpret(PointerTy)); + return GEP->getOperand(0); +} + +/// This is a port of salvageDebugInfoImpl() to DIOp-based DIExpressions. +/// +/// \param I is an instruction that's about to be deleted, used as a location op +/// to a debug intrinsic. \p Ops will be populated with DIOps that have the same +/// semantics as I. +/// \param CurrentLocOps is the number of location ops the debug intrinsic +/// currently uses. +/// \param AdditionalValues is populated with any additional location ops we +/// need to add to the intrinsic to salvage this instruction. +/// \returns a Value to replace I with in the debug intrinsic's location ops. +static Value *salvageNewDebugInfo(Instruction &I, uint64_t CurrentLocOps, + SmallVectorImpl &AdditionalValues, + SmallVectorImpl &Ops) { + auto &M = *I.getModule(); + auto &DL = M.getDataLayout(); + + if (auto *CI = dyn_cast(&I)) { + Value *FromValue = CI->getOperand(0); + Type *Type = CI->getType(); + + if (CI->isNoopCast(DL)) + Ops.emplace_back(DIOp::Reinterpret(Type)); + // FIXME(diexpression-poison): relax restriction to integer type to match IR + // instruction + else if (isa(&I) && Type->isIntegerTy()) + Ops.emplace_back(DIOp::SExt(Type)); + // FIXME(diexpression-poison): relax restriction to integer type to match IR + // instruction + else if (isa(&I) && Type->isIntegerTy()) + Ops.emplace_back(DIOp::ZExt(Type)); + else if (isa(&I)) + Ops.emplace_back(DIOp::Convert(Type)); + else + return nullptr; + + return FromValue; + } + + if (auto *BI = dyn_cast(&I)) + return getNewSalvageOpsForBinOp(BI, CurrentLocOps, Ops, AdditionalValues); + if (auto *GEP = dyn_cast(&I)) + return getNewSalvageOpsForGEP(GEP, DL, CurrentLocOps, Ops, AdditionalValues); + + return nullptr; +} + void llvm::salvageDebugInfoForDbgValues( Instruction &I, ArrayRef DbgUsers, ArrayRef DPUsers) { @@ -2272,6 +2487,25 @@ void llvm::salvageDebugInfoForDbgValues( Value *Op0 = nullptr; DIExpression *SalvagedExpr = DII->getExpression(); auto LocItr = find(DIILocation, &I); + + if (SalvagedExpr->holdsNewElements()) { + while (SalvagedExpr && LocItr != DIILocation.end()) { + SmallVector Ops; + unsigned LocNo = std::distance(DIILocation.begin(), LocItr); + uint64_t CurrentLocOps = SalvagedExpr->getNewNumLocationOperands(); + Op0 = salvageNewDebugInfo(I, CurrentLocOps, AdditionalValues, Ops); + if (!Op0) + break; + SalvagedExpr = DIExpression::appendNewOpsToArg(SalvagedExpr, Ops, LocNo, + Op0->getType()); + LocItr = std::find(++LocItr, DIILocation.end(), &I); + } + // salvageDebugInfoImpl should fail on examining the first element of + // DbgUsers, or none of them. + if (!Op0) + break; + } + while (SalvagedExpr && LocItr != DIILocation.end()) { SmallVector Ops; unsigned LocNo = std::distance(DIILocation.begin(), LocItr); @@ -2323,6 +2557,25 @@ void llvm::salvageDebugInfoForDbgValues( Value *Op0 = nullptr; DIExpression *SalvagedExpr = DPV->getExpression(); auto LocItr = find(DPVLocation, &I); + + if (SalvagedExpr->holdsNewElements()) { + while (SalvagedExpr && LocItr != DPVLocation.end()) { + SmallVector Ops; + unsigned LocNo = std::distance(DPVLocation.begin(), LocItr); + uint64_t CurrentLocOps = SalvagedExpr->getNewNumLocationOperands(); + Op0 = salvageNewDebugInfo(I, CurrentLocOps, AdditionalValues, Ops); + if (!Op0) + break; + SalvagedExpr = DIExpression::appendNewOpsToArg(SalvagedExpr, Ops, LocNo, + Op0->getType()); + LocItr = std::find(++LocItr, DPVLocation.end(), &I); + } + // salvageDebugInfoImpl should fail on examining the first element of + // DbgUsers, or none of them. + if (!Op0) + break; + } + while (SalvagedExpr && LocItr != DPVLocation.end()) { SmallVector Ops; unsigned LocNo = std::distance(DPVLocation.begin(), LocItr); @@ -2697,6 +2950,93 @@ static bool isBitCastSemanticsPreserving(const DataLayout &DL, Type *FromTy, return false; } +/// Generate new DIOps for a conversion from \param SourceTy to \param DestTy. +/// Returns true if the conversion was successful. +static bool getNewDIConversionOps(const DataLayout &DL, Type *SourceTy, + Type *DestTy, + std::optional Sign, + SmallVectorImpl &Ops) { + if (SourceTy == DestTy) + return true; // No conversion necessary. + + TypeSize SourceBits = DL.getTypeSizeInBits(SourceTy); + TypeSize DestBits = DL.getTypeSizeInBits(DestTy); + + if (SourceBits == DestBits && !DL.isNonIntegralPointerType(SourceTy) && + !DL.isNonIntegralPointerType(DestTy) && + ((SourceTy->isPointerTy() && DestTy->isIntegerTy()) || + (SourceTy->isIntegerTy() && DestTy->isPointerTy()))) { + Ops.emplace_back(DIOp::Reinterpret(DestTy)); + return true; + } + + if (!SourceTy->isIntegerTy() || !DestTy->isIntegerTy()) + return false; + + if (SourceBits < DestBits) { + if (!Sign) + return false; + + if (*Sign == DIBasicType::Signedness::Signed) + Ops.emplace_back(DIOp::SExt(DestTy)); + else + Ops.emplace_back(DIOp::ZExt(DestTy)); + return true; + } + + Ops.emplace_back(DIOp::Convert(DestTy)); + return true; +} + +/// Convert the type of all DIOpArgs that refer to \param LocOp to \param NewTy. +/// This is done by replacing the DIOpArg type and adding an appropriate +/// conversion operator back to the original type. e.g, the following +/// expression: +/// +/// DIExpression(DIOpArg(ptr), DIOpDeref(i32)) +/// +/// Becomes: +/// +/// DIExpression(DIOpArg(i64), DIOpReinterpret(ptr), DIOpDeref(i32)) +/// +/// If NewTy is i64. After this function returns, DII must be updated with a new +/// value of the correct type. +template +static std::optional +updateNewDIExpressionArgType(IntrinsicOrRecord &DII, Value *LocOp, + Type *NewTy) { + DIExpression *Expr = DII.getExpression(); + assert(Expr->holdsNewElements() && "expected a new DIExpression!"); + + // If the types are the same, then the expression is already correct. + if (LocOp->getType() == NewTy) + return Expr; + + const DataLayout &DL = DII.getModule()->getDataLayout(); + auto LocOps = DII.location_ops(); + for (auto Iter = LocOps.begin(); Iter != LocOps.end(); ++Iter) { + Value *V = *Iter; + if (V != LocOp) + continue; + + // Use the signedness of the variable to determine whether we should use + // ZExt/SExt for integer promotions. This isn't necessarily correct, but + // it's probably the best we can do given replaceAllDbgUsesWith()'s API. + SmallVector ConversionOps; + if (!getNewDIConversionOps(DL, NewTy, LocOp->getType(), + DII.getVariable()->getSignedness(), + ConversionOps)) + return std::nullopt; + + unsigned LocNo = std::distance(LocOps.begin(), Iter); + Expr = DIExpression::appendNewOpsToArg(Expr, ConversionOps, LocNo, NewTy); + if (!Expr) + return std::nullopt; + } + + return Expr; +} + bool llvm::replaceAllDbgUsesWith(Instruction &From, Value &To, Instruction &DomPoint, DominatorTree &DT) { // Exit early if From has no debug users. @@ -2709,9 +3049,13 @@ bool llvm::replaceAllDbgUsesWith(Instruction &From, Value &To, Type *ToTy = To.getType(); auto Identity = [&](DbgVariableIntrinsic &DII) -> DbgValReplacement { + if (DII.getExpression()->holdsNewElements()) + return updateNewDIExpressionArgType(DII, &From, ToTy); return DII.getExpression(); }; auto IdentityDPV = [&](DPValue &DPV) -> DbgValReplacement { + if (DPV.getExpression()->holdsNewElements()) + return updateNewDIExpressionArgType(DPV, &From, ToTy); return DPV.getExpression(); }; @@ -2736,6 +3080,9 @@ bool llvm::replaceAllDbgUsesWith(Instruction &From, Value &To, // The width of the result has shrunk. Use sign/zero extension to describe // the source variable's high bits. auto SignOrZeroExt = [&](DbgVariableIntrinsic &DII) -> DbgValReplacement { + if (DII.getExpression()->holdsNewElements()) + return updateNewDIExpressionArgType(DII, &From, ToTy); + DILocalVariable *Var = DII.getVariable(); // Without knowing signedness, sign/zero extension isn't possible. @@ -2747,9 +3094,12 @@ bool llvm::replaceAllDbgUsesWith(Instruction &From, Value &To, return DIExpression::appendExt(DII.getExpression(), ToBits, FromBits, Signed); }; - // RemoveDIs: duplicate implementation working on DPValues rather than on - // dbg.value intrinsics. + // RemoveDIs: duplicate implementation working on DbgVariableRecords rather + // than on dbg.value intrinsics. auto SignOrZeroExtDPV = [&](DPValue &DPV) -> DbgValReplacement { + if (DPV.getExpression()->holdsNewElements()) + return updateNewDIExpressionArgType(DPV, &From, ToTy); + DILocalVariable *Var = DPV.getVariable(); // Without knowing signedness, sign/zero extension isn't possible. diff --git a/llvm/test/Assembler/DIExpr.ll b/llvm/test/Assembler/DIExpr.ll index fe955b414fbb5f..b1acc7ccbcc87b 100644 --- a/llvm/test/Assembler/DIExpr.ll +++ b/llvm/test/Assembler/DIExpr.ll @@ -34,6 +34,10 @@ !DIExpr(DIOpConvert(i16)), ; CHECK-SAME: !DIExpr(DIOpConvert(%t)), !DIExpr(DIOpConvert(%t)), +; CHECK-SAME: !DIExpr(DIOpZExt(i32)), +!DIExpr(DIOpZExt(i32)), +; CHECK-SAME: !DIExpr(DIOpSExt(i32)), +!DIExpr(DIOpSExt(i32)), ; CHECK-SAME: !DIExpr(DIOpReinterpret(i64)), !DIExpr(DIOpReinterpret(i64)), ; CHECK-SAME: !DIExpr(DIOpReinterpret(%t)), @@ -70,8 +74,10 @@ !DIExpr(DIOpMul()), ; CHECK-SAME: !DIExpr(DIOpDiv()), !DIExpr(DIOpDiv()), -; CHECK-SAME: !DIExpr(DIOpShr()), -!DIExpr(DIOpShr()), +; CHECK-SAME: !DIExpr(DIOpLShr()), +!DIExpr(DIOpLShr()), +; CHECK-SAME: !DIExpr(DIOpAShr()), +!DIExpr(DIOpAShr()), ; CHECK-SAME: !DIExpr(DIOpShl()), !DIExpr(DIOpShl()), ; CHECK-SAME: !DIExpr(DIOpPushLane(i32)), diff --git a/llvm/test/Assembler/DIExpressionNew.ll b/llvm/test/Assembler/DIExpressionNew.ll new file mode 100644 index 00000000000000..aea7d814a17d71 --- /dev/null +++ b/llvm/test/Assembler/DIExpressionNew.ll @@ -0,0 +1,89 @@ +; RUN: llvm-as -disable-verify < %s | llvm-dis | llvm-as -disable-verify | llvm-dis | FileCheck %s + +; CHECK: %t = type { i32, i32 } +%t = type { i32, i32 } +; CHECK: %u = type { %t, i32 } +%u = type { %t, i32 } + +; CHECK: !named = !{ +!named = !{ +; CHECK-SAME: !DIExpression(), +!DIExpression(), +; CHECK-SAME: !DIExpression(DIOpReferrer(i32)), +!DIExpression(DIOpReferrer(i32)), +; CHECK-SAME: !DIExpression(DIOpReferrer(%t)), +!DIExpression(DIOpReferrer(%t)), +; CHECK-SAME: !DIExpression(DIOpReferrer(%u)), +!DIExpression(DIOpReferrer(%u)), +; CHECK-SAME: !DIExpression(DIOpReferrer({ i16, float })), +!DIExpression(DIOpReferrer({ i16, float })), +; CHECK-SAME: !DIExpression(DIOpArg(0, i32), DIOpConvert(float)), +!DIExpression(DIOpArg(0, i32), DIOpConvert(float)), +; CHECK-SAME: !DIExpression(DIOpArg(0, %t), DIOpConvert(%u)), +!DIExpression(DIOpArg(0, %t), DIOpConvert(%u)), +; CHECK-SAME: !DIExpression(DIOpTypeObject(double)), +!DIExpression(DIOpTypeObject(double)), +; CHECK-SAME: !DIExpression(DIOpTypeObject(%t)), +!DIExpression(DIOpTypeObject(%t)), +; CHECK-SAME: !DIExpression(DIOpConstant(i8 1)), +!DIExpression(DIOpConstant(i8 1)), +; CHECK-SAME: !DIExpression(DIOpConstant(%u undef)), +!DIExpression(DIOpConstant(%u undef)), +; CHECK-SAME: !DIExpression(DIOpConvert(i16)), +!DIExpression(DIOpConvert(i16)), +; CHECK-SAME: !DIExpression(DIOpConvert(%t)), +!DIExpression(DIOpConvert(%t)), +; CHECK-SAME: !DIExpression(DIOpZExt(i32)), +!DIExpression(DIOpZExt(i32)), +; CHECK-SAME: !DIExpression(DIOpSExt(i32)), +!DIExpression(DIOpSExt(i32)), +; CHECK-SAME: !DIExpression(DIOpReinterpret(i64)), +!DIExpression(DIOpReinterpret(i64)), +; CHECK-SAME: !DIExpression(DIOpReinterpret(%t)), +!DIExpression(DIOpReinterpret(%t)), +; CHECK-SAME: !DIExpression(DIOpBitOffset(i1)), +!DIExpression(DIOpBitOffset(i1)), +; CHECK-SAME: !DIExpression(DIOpBitOffset(%u)), +!DIExpression(DIOpBitOffset(%u)), +; CHECK-SAME: !DIExpression(DIOpByteOffset(i16)), +!DIExpression(DIOpByteOffset(i16)), +; CHECK-SAME: !DIExpression(DIOpByteOffset(%t)), +!DIExpression(DIOpByteOffset(%t)), +; CHECK-SAME: !DIExpression(DIOpComposite(4, i8)), +!DIExpression(DIOpComposite(4, i8)), +; CHECK-SAME: !DIExpression(DIOpComposite(2, %u)), +!DIExpression(DIOpComposite(2, %u)), +; CHECK-SAME: !DIExpression(DIOpExtend(6)), +!DIExpression(DIOpExtend(6)), +; CHECK-SAME: !DIExpression(DIOpSelect()), +!DIExpression(DIOpSelect()), +; CHECK-SAME: !DIExpression(DIOpAddrOf(1)), +!DIExpression(DIOpAddrOf(1)), +; CHECK-SAME: !DIExpression(DIOpDeref(i32)), +!DIExpression(DIOpDeref(i32)), +; CHECK-SAME: !DIExpression(DIOpDeref(%t)), +!DIExpression(DIOpDeref(%t)), +; CHECK-SAME: !DIExpression(DIOpRead()), +!DIExpression(DIOpRead()), +; CHECK-SAME: !DIExpression(DIOpAdd()), +!DIExpression(DIOpAdd()), +; CHECK-SAME: !DIExpression(DIOpSub()), +!DIExpression(DIOpSub()), +; CHECK-SAME: !DIExpression(DIOpMul()), +!DIExpression(DIOpMul()), +; CHECK-SAME: !DIExpression(DIOpDiv()), +!DIExpression(DIOpDiv()), +; CHECK-SAME: !DIExpression(DIOpLShr()), +!DIExpression(DIOpLShr()), +; CHECK-SAME: !DIExpression(DIOpAShr()), +!DIExpression(DIOpAShr()), +; CHECK-SAME: !DIExpression(DIOpShl()), +!DIExpression(DIOpShl()), +; CHECK-SAME: !DIExpression(DIOpPushLane(i32)), +!DIExpression(DIOpPushLane(i32)), +; CHECK-SAME: !DIExpression(DIOpPushLane(%u)), +!DIExpression(DIOpPushLane(%u)), +; CHECK-SAME: !DIExpression() +!DIExpression(), +; CHECK-SAME: !DIExpression(DIOpFragment(1, 2))} +!DIExpression(DIOpFragment(1, 2))} diff --git a/llvm/test/Bitcode/bcanalyzer-metadata-diexpression.ll b/llvm/test/Bitcode/bcanalyzer-metadata-diexpression.ll new file mode 100644 index 00000000000000..541ba3e751f25b --- /dev/null +++ b/llvm/test/Bitcode/bcanalyzer-metadata-diexpression.ll @@ -0,0 +1,10 @@ +; RUN: llvm-as < %s | llvm-bcanalyzer -dump | FileCheck %s + +!named = !{!0, !1} + +%t = type { i32, i32 } + +; CHECK: +!0 = !DIExpression(DIOpReferrer(%t)) +; CHECK: +!1 = !DIExpression() diff --git a/llvm/test/CodeGen/AMDGPU/heterogeneous-debug-info-live-through.mir b/llvm/test/CodeGen/AMDGPU/heterogeneous-debug-info-live-through.mir index a9ba5215bbcf53..3a7bf11ad44c91 100644 --- a/llvm/test/CodeGen/AMDGPU/heterogeneous-debug-info-live-through.mir +++ b/llvm/test/CodeGen/AMDGPU/heterogeneous-debug-info-live-through.mir @@ -97,18 +97,18 @@ !9 = !DILocalVariable(name: "x", scope: !5, file: !1, line: 1, type: !10) !10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) !11 = !DILocalVariable(name: "y", scope: !5, file: !1, line: 1, type: !10) - !12 = distinct !DILifetime(object: !9, location: !DIExpr(DIOpReferrer(i32), DIOpConstant(i32 6), DIOpShr(), DIOpReinterpret(ptr addrspace(5)), DIOpDeref(i32), DIOpConstant(i32 0), DIOpByteOffset(i32))) + !12 = distinct !DILifetime(object: !9, location: !DIExpr(DIOpReferrer(i32), DIOpConstant(i32 6), DIOpLShr(), DIOpReinterpret(ptr addrspace(5)), DIOpDeref(i32), DIOpConstant(i32 0), DIOpByteOffset(i32))) !13 = !DILocation(line: 1, column: 51, scope: !5) - !14 = distinct !DILifetime(object: !11, location: !DIExpr(DIOpReferrer(i32), DIOpConstant(i32 6), DIOpShr(), DIOpReinterpret(ptr addrspace(5)), DIOpDeref(i32), DIOpConstant(i32 4), DIOpByteOffset(i32))) + !14 = distinct !DILifetime(object: !11, location: !DIExpr(DIOpReferrer(i32), DIOpConstant(i32 6), DIOpLShr(), DIOpReinterpret(ptr addrspace(5)), DIOpDeref(i32), DIOpConstant(i32 4), DIOpByteOffset(i32))) !15 = !DILocation(line: 1, column: 54, scope: !5) !16 = !DILocation(line: 1, column: 57, scope: !5) !17 = distinct !DISubprogram(name: "not_live_through", linkageName: "_Z16not_live_throughv", scope: !1, file: !1, line: 1, type: !6, scopeLine: 1, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !18) !18 = !{!19, !20} !19 = !DILocalVariable(name: "x", scope: !17, file: !1, line: 1, type: !10) !20 = !DILocalVariable(name: "y", scope: !17, file: !1, line: 1, type: !10) - !21 = distinct !DILifetime(object: !19, location: !DIExpr(DIOpReferrer(i32), DIOpConstant(i32 6), DIOpShr(), DIOpReinterpret(ptr addrspace(5)), DIOpDeref(i32), DIOpConstant(i32 0), DIOpByteOffset(i32))) + !21 = distinct !DILifetime(object: !19, location: !DIExpr(DIOpReferrer(i32), DIOpConstant(i32 6), DIOpLShr(), DIOpReinterpret(ptr addrspace(5)), DIOpDeref(i32), DIOpConstant(i32 0), DIOpByteOffset(i32))) !22 = !DILocation(line: 1, column: 113, scope: !17) - !23 = distinct !DILifetime(object: !20, location: !DIExpr(DIOpReferrer(i32), DIOpConstant(i32 6), DIOpShr(), DIOpReinterpret(ptr addrspace(5)), DIOpDeref(i32), DIOpConstant(i32 4), DIOpByteOffset(i32))) + !23 = distinct !DILifetime(object: !20, location: !DIExpr(DIOpReferrer(i32), DIOpConstant(i32 6), DIOpLShr(), DIOpReinterpret(ptr addrspace(5)), DIOpDeref(i32), DIOpConstant(i32 4), DIOpByteOffset(i32))) !24 = !DILocation(line: 1, column: 116, scope: !17) !25 = !DILocation(line: 1, column: 119, scope: !17) diff --git a/llvm/test/CodeGen/AMDGPU/heterogeneous-debug-info.ll b/llvm/test/CodeGen/AMDGPU/heterogeneous-debug-info.ll index 5af203c64ae104..485c5b4f60f004 100644 --- a/llvm/test/CodeGen/AMDGPU/heterogeneous-debug-info.ll +++ b/llvm/test/CodeGen/AMDGPU/heterogeneous-debug-info.ll @@ -12,11 +12,11 @@ ; AFTER-RA-DAG: ![[STACK_LIFETIME_VAR_I:[0-9]+]] = distinct !DILifetime(object: ![[VAR_I]], location: !DIExpr(DIOpReferrer(i32))) ; AFTER-RA-DAG: ![[STACK_LIFETIME_VAR_R:[0-9]+]] = distinct !DILifetime(object: ![[VAR_R]], location: !DIExpr(DIOpReferrer(i32))) ; AFTER-PEI-DAG: ![[ENTRY_LIFETIME_VAR_I:[0-9]+]] = distinct !DILifetime(object: ![[VAR_I]], location: !DIExpr(DIOpReferrer(i32))) -; AFTER-PEI-DAG: ![[STACK_LIFETIME_VAR_I:[0-9]+]] = distinct !DILifetime(object: ![[VAR_I]], location: !DIExpr(DIOpReferrer(i32), DIOpConstant(i32 6), DIOpShr(), DIOpReinterpret(ptr addrspace(5)), DIOpDeref(i32), DIOpConstant(i32 4), DIOpByteOffset(i32))) -; AFTER-PEI-DAG: ![[STACK_LIFETIME_VAR_R:[0-9]+]] = distinct !DILifetime(object: ![[VAR_R]], location: !DIExpr(DIOpReferrer(i32), DIOpConstant(i32 6), DIOpShr(), DIOpReinterpret(ptr addrspace(5)), DIOpDeref(i32), DIOpConstant(i32 8), DIOpByteOffset(i32))) +; AFTER-PEI-DAG: ![[STACK_LIFETIME_VAR_I:[0-9]+]] = distinct !DILifetime(object: ![[VAR_I]], location: !DIExpr(DIOpReferrer(i32), DIOpConstant(i32 6), DIOpLShr(), DIOpReinterpret(ptr addrspace(5)), DIOpDeref(i32), DIOpConstant(i32 4), DIOpByteOffset(i32))) +; AFTER-PEI-DAG: ![[STACK_LIFETIME_VAR_R:[0-9]+]] = distinct !DILifetime(object: ![[VAR_R]], location: !DIExpr(DIOpReferrer(i32), DIOpConstant(i32 6), DIOpLShr(), DIOpReinterpret(ptr addrspace(5)), DIOpDeref(i32), DIOpConstant(i32 8), DIOpByteOffset(i32))) ; AFTER-LDV-DAG: ![[ENTRY_LIFETIME_VAR_I:[0-9]+]] = distinct !DILifetime(object: ![[VAR_I]], location: !DIExpr(DIOpReferrer(i32))) -; AFTER-LDV-DAG: ![[STACK_LIFETIME_VAR_I:[0-9]+]] = distinct !DILifetime(object: ![[VAR_I]], location: !DIExpr(DIOpReferrer(i32), DIOpConstant(i32 6), DIOpShr(), DIOpReinterpret(ptr addrspace(5)), DIOpDeref(i32), DIOpConstant(i32 4), DIOpByteOffset(i32))) -; AFTER-LDV-DAG: ![[STACK_LIFETIME_VAR_R:[0-9]+]] = distinct !DILifetime(object: ![[VAR_R]], location: !DIExpr(DIOpReferrer(i32), DIOpConstant(i32 6), DIOpShr(), DIOpReinterpret(ptr addrspace(5)), DIOpDeref(i32), DIOpConstant(i32 8), DIOpByteOffset(i32))) +; AFTER-LDV-DAG: ![[STACK_LIFETIME_VAR_I:[0-9]+]] = distinct !DILifetime(object: ![[VAR_I]], location: !DIExpr(DIOpReferrer(i32), DIOpConstant(i32 6), DIOpLShr(), DIOpReinterpret(ptr addrspace(5)), DIOpDeref(i32), DIOpConstant(i32 4), DIOpByteOffset(i32))) +; AFTER-LDV-DAG: ![[STACK_LIFETIME_VAR_R:[0-9]+]] = distinct !DILifetime(object: ![[VAR_R]], location: !DIExpr(DIOpReferrer(i32), DIOpConstant(i32 6), DIOpLShr(), DIOpReinterpret(ptr addrspace(5)), DIOpDeref(i32), DIOpConstant(i32 8), DIOpByteOffset(i32))) ; COMMON-LABEL: bb.{{[0-9]}}.entry: ; COMMON: {{^$}} ; AFTER-ISEL-NOT: DBG_ diff --git a/llvm/test/CodeGen/BPF/CORE/field-reloc-bitfield-1-bpfeb.ll b/llvm/test/CodeGen/BPF/CORE/field-reloc-bitfield-1-bpfeb.ll index 63a0945edf152a..394cc734455b29 100644 --- a/llvm/test/CodeGen/BPF/CORE/field-reloc-bitfield-1-bpfeb.ll +++ b/llvm/test/CodeGen/BPF/CORE/field-reloc-bitfield-1-bpfeb.ll @@ -26,68 +26,6 @@ target triple = "bpfeb" ; Function Attrs: nounwind readnone define dso_local i32 @test(ptr %arg) local_unnamed_addr #0 !dbg !13 { -; CHECK-ALU64-LABEL: test: -; CHECK-ALU64: .Ltest$local: -; CHECK-ALU64-NEXT: .type .Ltest$local,@function -; CHECK-ALU64-NEXT: .Lfunc_begin0: -; CHECK-ALU64-NEXT: .loc 1 11 0 # test.c:11:0 -; CHECK-ALU64-NEXT: .cfi_sections .debug_frame -; CHECK-ALU64-NEXT: .cfi_startproc -; CHECK-ALU64-NEXT: # %bb.0: # %entry -; CHECK-ALU64-NEXT: #DEBUG_VALUE: test:arg <- $r1 -; CHECK-ALU64-NEXT: .Ltmp0: -; CHECK-ALU64-NEXT: r1 = 16 -; CHECK-ALU64-NEXT: .Ltmp1: -; CHECK-ALU64-NEXT: .Ltmp2: -; CHECK-ALU64-NEXT: .Ltmp3: -; CHECK-ALU64-NEXT: r0 = 8 -; CHECK-ALU64-NEXT: .Ltmp4: -; CHECK-ALU64-NEXT: .loc 1 12 69 prologue_end # test.c:12:69 -; CHECK-ALU64-NEXT: .Ltmp5: -; CHECK-ALU64-NEXT: .Ltmp6: -; CHECK-ALU64-NEXT: r0 += r1 -; CHECK-ALU64-NEXT: .Ltmp7: -; CHECK-ALU64-NEXT: r1 = 45 -; CHECK-ALU64-NEXT: .loc 1 13 67 # test.c:13:67 -; CHECK-ALU64-NEXT: .Ltmp8: -; CHECK-ALU64-NEXT: r0 += r1 -; CHECK-ALU64-NEXT: .loc 1 12 3 # test.c:12:3 -; CHECK-ALU64-NEXT: .Ltmp9: -; CHECK-ALU64-NEXT: exit -; CHECK-ALU64-NEXT: .Ltmp10: -; CHECK-ALU64-NEXT: .Ltmp11: -; -; CHECK-ALU32-LABEL: test: -; CHECK-ALU32: .Ltest$local: -; CHECK-ALU32-NEXT: .type .Ltest$local,@function -; CHECK-ALU32-NEXT: .Lfunc_begin0: -; CHECK-ALU32-NEXT: .loc 1 11 0 # test.c:11:0 -; CHECK-ALU32-NEXT: .cfi_sections .debug_frame -; CHECK-ALU32-NEXT: .cfi_startproc -; CHECK-ALU32-NEXT: # %bb.0: # %entry -; CHECK-ALU32-NEXT: #DEBUG_VALUE: test:arg <- $r1 -; CHECK-ALU32-NEXT: .Ltmp0: -; CHECK-ALU32-NEXT: r1 = 16 -; CHECK-ALU32-NEXT: .Ltmp1: -; CHECK-ALU32-NEXT: .Ltmp2: -; CHECK-ALU32-NEXT: .Ltmp3: -; CHECK-ALU32-NEXT: r0 = 8 -; CHECK-ALU32-NEXT: .Ltmp4: -; CHECK-ALU32-NEXT: .loc 1 12 69 prologue_end # test.c:12:69 -; CHECK-ALU32-NEXT: .Ltmp5: -; CHECK-ALU32-NEXT: .Ltmp6: -; CHECK-ALU32-NEXT: w0 += w1 -; CHECK-ALU32-NEXT: .Ltmp7: -; CHECK-ALU32-NEXT: r1 = 45 -; CHECK-ALU32-NEXT: .loc 1 13 67 # test.c:13:67 -; CHECK-ALU32-NEXT: .Ltmp8: -; CHECK-ALU32-NEXT: w0 += w1 -; CHECK-ALU32-NEXT: # kill: def $w0 killed $w0 killed $r0 -; CHECK-ALU32-NEXT: .loc 1 12 3 # test.c:12:3 -; CHECK-ALU32-NEXT: .Ltmp9: -; CHECK-ALU32-NEXT: exit -; CHECK-ALU32-NEXT: .Ltmp10: -; CHECK-ALU32-NEXT: .Ltmp11: entry: call void @llvm.dbg.value(metadata ptr %arg, metadata !30, metadata !DIExpression()), !dbg !31 %0 = tail call ptr @llvm.preserve.struct.access.index.p0.p0.ss(ptr elementtype(%struct.s) %arg, i32 5, i32 6), !dbg !32, !llvm.preserve.access.index !18 @@ -178,3 +116,7 @@ attributes #2 = { nounwind readnone speculatable } !37 = !DILocation(line: 13, column: 67, scope: !13) !38 = !DILocation(line: 12, column: 3, scope: !13) +;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line: +; CHECK: {{.*}} +; CHECK-ALU32: {{.*}} +; CHECK-ALU64: {{.*}} diff --git a/llvm/test/CodeGen/BPF/CORE/field-reloc-bitfield-1.ll b/llvm/test/CodeGen/BPF/CORE/field-reloc-bitfield-1.ll index 33462198eab15a..7323736245727c 100644 --- a/llvm/test/CodeGen/BPF/CORE/field-reloc-bitfield-1.ll +++ b/llvm/test/CodeGen/BPF/CORE/field-reloc-bitfield-1.ll @@ -26,68 +26,6 @@ target triple = "bpfel" ; Function Attrs: nounwind readnone define dso_local i32 @test(ptr %arg) local_unnamed_addr #0 !dbg !13 { -; CHECK-ALU64-LABEL: test: -; CHECK-ALU64: .Ltest$local: -; CHECK-ALU64-NEXT: .type .Ltest$local,@function -; CHECK-ALU64-NEXT: .Lfunc_begin0: -; CHECK-ALU64-NEXT: .loc 1 11 0 # test.c:11:0 -; CHECK-ALU64-NEXT: .cfi_sections .debug_frame -; CHECK-ALU64-NEXT: .cfi_startproc -; CHECK-ALU64-NEXT: # %bb.0: # %entry -; CHECK-ALU64-NEXT: #DEBUG_VALUE: test:arg <- $r1 -; CHECK-ALU64-NEXT: .Ltmp0: -; CHECK-ALU64-NEXT: r1 = 16 -; CHECK-ALU64-NEXT: .Ltmp1: -; CHECK-ALU64-NEXT: .Ltmp2: -; CHECK-ALU64-NEXT: .Ltmp3: -; CHECK-ALU64-NEXT: r0 = 8 -; CHECK-ALU64-NEXT: .Ltmp4: -; CHECK-ALU64-NEXT: .loc 1 12 69 prologue_end # test.c:12:69 -; CHECK-ALU64-NEXT: .Ltmp5: -; CHECK-ALU64-NEXT: .Ltmp6: -; CHECK-ALU64-NEXT: r0 += r1 -; CHECK-ALU64-NEXT: .Ltmp7: -; CHECK-ALU64-NEXT: r1 = 18 -; CHECK-ALU64-NEXT: .loc 1 13 67 # test.c:13:67 -; CHECK-ALU64-NEXT: .Ltmp8: -; CHECK-ALU64-NEXT: r0 += r1 -; CHECK-ALU64-NEXT: .loc 1 12 3 # test.c:12:3 -; CHECK-ALU64-NEXT: .Ltmp9: -; CHECK-ALU64-NEXT: exit -; CHECK-ALU64-NEXT: .Ltmp10: -; CHECK-ALU64-NEXT: .Ltmp11: -; -; CHECK-ALU32-LABEL: test: -; CHECK-ALU32: .Ltest$local: -; CHECK-ALU32-NEXT: .type .Ltest$local,@function -; CHECK-ALU32-NEXT: .Lfunc_begin0: -; CHECK-ALU32-NEXT: .loc 1 11 0 # test.c:11:0 -; CHECK-ALU32-NEXT: .cfi_sections .debug_frame -; CHECK-ALU32-NEXT: .cfi_startproc -; CHECK-ALU32-NEXT: # %bb.0: # %entry -; CHECK-ALU32-NEXT: #DEBUG_VALUE: test:arg <- $r1 -; CHECK-ALU32-NEXT: .Ltmp0: -; CHECK-ALU32-NEXT: r1 = 16 -; CHECK-ALU32-NEXT: .Ltmp1: -; CHECK-ALU32-NEXT: .Ltmp2: -; CHECK-ALU32-NEXT: .Ltmp3: -; CHECK-ALU32-NEXT: r0 = 8 -; CHECK-ALU32-NEXT: .Ltmp4: -; CHECK-ALU32-NEXT: .loc 1 12 69 prologue_end # test.c:12:69 -; CHECK-ALU32-NEXT: .Ltmp5: -; CHECK-ALU32-NEXT: .Ltmp6: -; CHECK-ALU32-NEXT: w0 += w1 -; CHECK-ALU32-NEXT: .Ltmp7: -; CHECK-ALU32-NEXT: r1 = 18 -; CHECK-ALU32-NEXT: .loc 1 13 67 # test.c:13:67 -; CHECK-ALU32-NEXT: .Ltmp8: -; CHECK-ALU32-NEXT: w0 += w1 -; CHECK-ALU32-NEXT: # kill: def $w0 killed $w0 killed $r0 -; CHECK-ALU32-NEXT: .loc 1 12 3 # test.c:12:3 -; CHECK-ALU32-NEXT: .Ltmp9: -; CHECK-ALU32-NEXT: exit -; CHECK-ALU32-NEXT: .Ltmp10: -; CHECK-ALU32-NEXT: .Ltmp11: entry: call void @llvm.dbg.value(metadata ptr %arg, metadata !30, metadata !DIExpression()), !dbg !31 %0 = tail call ptr @llvm.preserve.struct.access.index.p0.p0.ss(ptr elementtype(%struct.s) %arg, i32 5, i32 6), !dbg !32, !llvm.preserve.access.index !18 @@ -177,3 +115,7 @@ attributes #2 = { nounwind readnone speculatable } !36 = !DILocation(line: 14, column: 10, scope: !13) !37 = !DILocation(line: 13, column: 67, scope: !13) !38 = !DILocation(line: 12, column: 3, scope: !13) +;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line: +; CHECK: {{.*}} +; CHECK-ALU32: {{.*}} +; CHECK-ALU64: {{.*}} diff --git a/llvm/test/CodeGen/MIR/Generic/diexpression.mir b/llvm/test/CodeGen/MIR/Generic/diexpression.mir new file mode 100644 index 00000000000000..92532bb0a86394 --- /dev/null +++ b/llvm/test/CodeGen/MIR/Generic/diexpression.mir @@ -0,0 +1,67 @@ +# RUN: sed -e 's/STACK_EXPR//g' -e 's/BODY_EXPR//g' %s | llc -x mir -run-pass none -o - 2>&1 | FileCheck --check-prefix=EXPR-NONE %s +# RUN: sed -e 's/STACK_EXPR/DW_OP_LLVM_arg, 0, DW_OP_dup, DW_OP_plus/g' -e 's/BODY_EXPR/DW_OP_LLVM_arg, 0, DW_OP_dup, DW_OP_plus/g' %s \ +# RUN: | llc -x mir -run-pass none -o - 2>&1 | FileCheck --check-prefix=EXPR-SOME %s +# RUN: sed -e 's/STACK_EXPR/DW_OP_foobar/g' -e 's/BODY_EXPR//g' %s | not llc -x mir -run-pass none -o - 2>&1 | FileCheck --check-prefix=EXPR-ERR-STACK-INVALID-OP %s +# RUN: sed -e 's/STACK_EXPR//g' -e 's/BODY_EXPR/DW_OP_foobar/g' %s | not llc -x mir -run-pass none -o - 2>&1 | FileCheck --check-prefix=EXPR-ERR-BODY-INVALID-OP %s +# RUN: sed -e 's/STACK_EXPR/DW_ATE_foobar/g' -e 's/BODY_EXPR//g' %s | not llc -x mir -run-pass none -o - 2>&1 | FileCheck --check-prefix=EXPR-ERR-STACK-INVALID-ATTR %s +# RUN: sed -e 's/STACK_EXPR//g' -e 's/BODY_EXPR/DW_ATE_foobar/g' %s | not llc -x mir -run-pass none -o - 2>&1 | FileCheck --check-prefix=EXPR-ERR-BODY-INVALID-ATTR %s +# RUN: sed -e 's/STACK_EXPR/foobar/g' -e 's/BODY_EXPR//g' %s | not llc -x mir -run-pass none -o - 2>&1 | FileCheck --check-prefix=EXPR-ERR-STACK-INVALID-INT %s +# RUN: sed -e 's/STACK_EXPR//g' -e 's/BODY_EXPR/foobar/g' %s | not llc -x mir -run-pass none -o - 2>&1 | FileCheck --check-prefix=EXPR-ERR-BODY-INVALID-INT %s + +# Test that we successfully parse valid DIExpression metadata in MIR, and that +# we reject invalid DIExpression metadata in MIR. + +--- | + define void @func() #0 !dbg !6 { + entry: + call void @llvm.dbg.value(metadata i32 0, metadata !10, metadata !DIExpression()), !dbg !12 + ret void + } + + declare void @llvm.dbg.value(metadata, metadata, metadata) #1 + + attributes #0 = { noinline nounwind optnone } + attributes #1 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) } + + !llvm.module.flags = !{!0, !1} + !llvm.ident = !{!2} + !llvm.dbg.cu = !{!3} + !llvm.debugify = !{!5, !5} + + !0 = !{i32 1, !"wchar_size", i32 4} + !1 = !{i32 2, !"Debug Info Version", i32 3} + !2 = !{!"clang"} + !3 = distinct !DICompileUnit(language: DW_LANG_C, file: !4, producer: "debugify", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug) + !4 = !DIFile(filename: "", directory: "/") + !5 = !{i32 1} + !6 = distinct !DISubprogram(name: "func", linkageName: "func", scope: null, file: !4, line: 1, type: !7, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !3, retainedNodes: !9) + !7 = !DISubroutineType(types: !8) + !8 = !{} + !9 = !{!10} + !10 = !DILocalVariable(name: "1", scope: !6, file: !4, line: 1, type: !11) + !11 = !DIBasicType(name: "ty32", size: 32, encoding: DW_ATE_unsigned) + !12 = !DILocation(line: 1, column: 1, scope: !6) + +... +--- + +# EXPR-NONE: debug-info-expression: '!DIExpression()' +# EXPR-NONE: DBG_VALUE 0, 0, ![[#]], !DIExpression(), debug-location ![[#]] + +# EXPR-SOME: debug-info-expression: '!DIExpression(DW_OP_LLVM_arg, 0, DW_OP_dup, DW_OP_plus)' +# EXPR-SOME: DBG_VALUE 0, 0, ![[#]], !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_dup, DW_OP_plus), debug-location ![[#]] + +name: func +stack: + # EXPR-ERR-STACK-INVALID-OP: :[[#@LINE+4]]:45: invalid DWARF op 'DW_OP_foobar' + # EXPR-ERR-STACK-INVALID-ATTR: :[[#@LINE+3]]:45: invalid DWARF attribute encoding 'DW_ATE_foobar' + # EXPR-ERR-STACK-INVALID-INT: :[[#@LINE+2]]:45: expected unsigned integer + - { id: 0, size: 4, debug-info-variable: '!10', debug-info-location: '!12', + debug-info-expression: '!DIExpression(STACK_EXPR)' } +body: | + bb.0.entry: + ; EXPR-ERR-BODY-INVALID-OP: :[[#@LINE+3]]:40: invalid DWARF op 'DW_OP_foobar' + ; EXPR-ERR-BODY-INVALID-ATTR: :[[#@LINE+2]]:40: invalid DWARF attribute encoding 'DW_ATE_foobar' + ; EXPR-ERR-BODY-INVALID-INT: :[[#@LINE+1]]:40: expected unsigned integer + DBG_VALUE 0, 0, !10, !DIExpression(BODY_EXPR), debug-location !12 +... diff --git a/llvm/test/DebugInfo/AMDGPU/heterogeneous-dwarf-amdgcn-abi.ll b/llvm/test/DebugInfo/AMDGPU/heterogeneous-dwarf-amdgcn-abi.ll index 0e3a6cc5936dfa..c0560b4ba177cf 100644 --- a/llvm/test/DebugInfo/AMDGPU/heterogeneous-dwarf-amdgcn-abi.ll +++ b/llvm/test/DebugInfo/AMDGPU/heterogeneous-dwarf-amdgcn-abi.ll @@ -26,8 +26,8 @@ target triple = "amdgcn-amd-amdhsa" ; CHECK: DW_TAG_subprogram ; CHECK-LABEL: DW_AT_name ("Test_Func_StructEmpty") ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_LLVM_user DW_OP_LLVM_offset) ; Function Attrs: convergent mustprogress noinline nounwind optnone define dso_local void @_Z21Test_Func_StructEmpty11StructEmpty() #0 !dbg !24 { @@ -44,8 +44,8 @@ declare void @llvm.dbg.def(metadata, metadata) #1 ; CHECK: DW_TAG_subprogram ; CHECK-LABEL: DW_AT_name ("Test_Kern_StructEmpty") ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_LLVM_user DW_OP_LLVM_offset) ; Function Attrs: convergent mustprogress noinline norecurse nounwind optnone define dso_local amdgpu_kernel void @_Z21Test_Kern_StructEmpty11StructEmpty(ptr addrspace(4) byref(%struct.StructEmpty) align 1 %0) #2 !dbg !33 { @@ -63,8 +63,8 @@ declare void @llvm.memcpy.p0.p4.i64(i8* noalias nocapture writeonly, ptr addrspa ; CHECK: DW_TAG_subprogram ; CHECK-LABEL: DW_AT_name ("Test_Func_StructSingleElement") ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_LLVM_user DW_OP_LLVM_offset) ; Function Attrs: convergent mustprogress noinline nounwind optnone define dso_local void @_Z29Test_Func_StructSingleElement19StructSingleElement(i8 %.coerce) #0 !dbg !39 { @@ -80,8 +80,8 @@ entry: ; CHECK: DW_TAG_subprogram ; CHECK-LABEL: DW_AT_name ("Test_Kern_StructSingleElement") ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_LLVM_user DW_OP_LLVM_offset) ; Function Attrs: convergent mustprogress noinline norecurse nounwind optnone define dso_local amdgpu_kernel void @_Z29Test_Kern_StructSingleElement19StructSingleElement(i8 %.coerce) #2 !dbg !50 { @@ -97,8 +97,8 @@ entry: ; CHECK: DW_TAG_subprogram ; CHECK-LABEL: DW_AT_name ("Test_Func_StructSingleElementRecursive") ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_LLVM_user DW_OP_LLVM_offset) ; Function Attrs: convergent mustprogress noinline nounwind optnone define dso_local void @_Z38Test_Func_StructSingleElementRecursive28StructSingleElementRecursive(i8 %.coerce) #0 !dbg !56 { @@ -115,8 +115,8 @@ entry: ; CHECK: DW_TAG_subprogram ; CHECK-LABEL: DW_AT_name ("Test_Kern_StructSingleElementRecursive") ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_LLVM_user DW_OP_LLVM_offset) ; Function Attrs: convergent mustprogress noinline norecurse nounwind optnone define dso_local amdgpu_kernel void @_Z38Test_Kern_StructSingleElementRecursive28StructSingleElementRecursive(i8 %.coerce) #2 !dbg !67 { @@ -133,8 +133,8 @@ entry: ; CHECK: DW_TAG_subprogram ; CHECK-LABEL: DW_AT_name ("Test_Func_StructTrivialCopyTrivialMove") ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_LLVM_user DW_OP_LLVM_offset) ; Function Attrs: convergent mustprogress noinline nounwind optnone define dso_local void @_Z38Test_Func_StructTrivialCopyTrivialMove28StructTrivialCopyTrivialMove(i8 %.coerce) #0 !dbg !73 { @@ -150,8 +150,8 @@ entry: ; CHECK: DW_TAG_subprogram ; CHECK-LABEL: DW_AT_name ("Test_Kern_StructTrivialCopyTrivialMove") ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_LLVM_user DW_OP_LLVM_offset) ; Function Attrs: convergent mustprogress noinline norecurse nounwind optnone define dso_local amdgpu_kernel void @_Z38Test_Kern_StructTrivialCopyTrivialMove28StructTrivialCopyTrivialMove(i8 %.coerce) #2 !dbg !94 { @@ -167,8 +167,8 @@ entry: ; CHECK: DW_TAG_subprogram ; CHECK-LABEL: DW_AT_name ("Test_Func_StructNoCopyTrivialMove") ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_LLVM_user DW_OP_LLVM_offset) ; Function Attrs: convergent mustprogress noinline nounwind optnone define dso_local void @_Z33Test_Func_StructNoCopyTrivialMove23StructNoCopyTrivialMove(i8 %.coerce) #0 !dbg !100 { @@ -184,8 +184,8 @@ entry: ; CHECK: DW_TAG_subprogram ; CHECK-LABEL: DW_AT_name ("Test_Kern_StructNoCopyTrivialMove") ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_LLVM_user DW_OP_LLVM_offset) ; Function Attrs: convergent mustprogress noinline norecurse nounwind optnone define dso_local amdgpu_kernel void @_Z33Test_Kern_StructNoCopyTrivialMove23StructNoCopyTrivialMove(i8 %.coerce) #2 !dbg !121 { @@ -201,8 +201,8 @@ entry: ; CHECK: DW_TAG_subprogram ; CHECK: DW_AT_name ("Test_Func_StructTrivialCopyNoMove") ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_LLVM_user DW_OP_LLVM_offset) ; Function Attrs: convergent mustprogress noinline nounwind optnone define dso_local void @_Z33Test_Func_StructTrivialCopyNoMove23StructTrivialCopyNoMove(i8 %.coerce) #0 !dbg !127 { @@ -218,8 +218,8 @@ entry: ; CHECK: DW_TAG_subprogram ; CHECK-LABEL: DW_AT_name ("Test_Kern_StructTrivialCopyNoMove") ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_LLVM_user DW_OP_LLVM_offset) ; Function Attrs: convergent mustprogress noinline norecurse nounwind optnone define dso_local amdgpu_kernel void @_Z33Test_Kern_StructTrivialCopyNoMove23StructTrivialCopyNoMove(i8 %.coerce) #2 !dbg !148 { @@ -249,8 +249,8 @@ entry: ; CHECK: DW_TAG_subprogram ; CHECK-LABEL: DW_AT_name ("Test_Kern_StructNoCopyNoMove") ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_LLVM_user DW_OP_LLVM_offset) ; Function Attrs: convergent mustprogress noinline norecurse nounwind optnone define dso_local amdgpu_kernel void @_Z28Test_Kern_StructNoCopyNoMove18StructNoCopyNoMove(i8 %.coerce) #2 !dbg !175 { @@ -266,8 +266,8 @@ entry: ; CHECK: DW_TAG_subprogram ; CHECK-LABEL: DW_AT_name ("Test_Func_Struct2Bytes") ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_LLVM_user DW_OP_LLVM_offset) ; Function Attrs: convergent mustprogress noinline nounwind optnone define dso_local void @_Z22Test_Func_Struct2Bytes12StructNBytesILj2EE(i16 %.coerce) #0 !dbg !181 { @@ -282,8 +282,8 @@ entry: ; CHECK: DW_TAG_subprogram ; CHECK-LABEL: DW_AT_name ("Test_Kern_Struct2Bytes") ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_LLVM_user DW_OP_LLVM_offset) ; Function Attrs: convergent mustprogress noinline norecurse nounwind optnone define dso_local amdgpu_kernel void @_Z22Test_Kern_Struct2Bytes12StructNBytesILj2EE(ptr addrspace(4) byref(%struct.StructNBytes) align 1 %0) #2 !dbg !198 { @@ -298,8 +298,8 @@ entry: ; CHECK: DW_TAG_subprogram ; CHECK-LABEL: DW_AT_name ("Test_Func_Struct3Bytes") ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_LLVM_user DW_OP_LLVM_offset) ; Function Attrs: convergent mustprogress noinline nounwind optnone define dso_local void @_Z22Test_Func_Struct3Bytes12StructNBytesILj3EE(i32 %.coerce) #0 !dbg !204 { @@ -320,8 +320,8 @@ declare void @llvm.memcpy.p0.p0.i64(i8* noalias nocapture writeonly, i8* noalias ; CHECK: DW_TAG_subprogram ; CHECK-LABEL: DW_AT_name ("Test_Kern_Struct3Bytes") ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_LLVM_user DW_OP_LLVM_offset) ; Function Attrs: convergent mustprogress noinline norecurse nounwind optnone define dso_local amdgpu_kernel void @_Z22Test_Kern_Struct3Bytes12StructNBytesILj3EE(ptr addrspace(4) byref(%struct.StructNBytes.0) align 1 %0) #2 !dbg !221 { @@ -336,8 +336,8 @@ entry: ; CHECK: DW_TAG_subprogram ; CHECK-LABEL: DW_AT_name ("Test_Func_Struct4Bytes") ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_LLVM_user DW_OP_LLVM_offset) ; Function Attrs: convergent mustprogress noinline nounwind optnone define dso_local void @_Z22Test_Func_Struct4Bytes12StructNBytesILj4EE(i32 %.coerce) #0 !dbg !227 { @@ -352,8 +352,8 @@ entry: ; CHECK: DW_TAG_subprogram ; CHECK-LABEL: DW_AT_name ("Test_Kern_Struct4Bytes") ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_LLVM_user DW_OP_LLVM_offset) ; Function Attrs: convergent mustprogress noinline norecurse nounwind optnone define dso_local amdgpu_kernel void @_Z22Test_Kern_Struct4Bytes12StructNBytesILj4EE(ptr addrspace(4) byref(%struct.StructNBytes.1) align 1 %0) #2 !dbg !244 { @@ -368,8 +368,8 @@ entry: ; CHECK: DW_TAG_subprogram ; CHECK-LABEL: DW_AT_name ("Test_Func_Struct5Bytes") ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_LLVM_user DW_OP_LLVM_offset) ; Function Attrs: convergent mustprogress noinline nounwind optnone define dso_local void @_Z22Test_Func_Struct5Bytes12StructNBytesILj5EE([2 x i32] %.coerce) #0 !dbg !250 { @@ -387,8 +387,8 @@ entry: ; CHECK: DW_TAG_subprogram ; CHECK-LABEL: DW_AT_name ("Test_Kern_Struct5Bytes") ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_LLVM_user DW_OP_LLVM_offset) ; Function Attrs: convergent mustprogress noinline norecurse nounwind optnone define dso_local amdgpu_kernel void @_Z22Test_Kern_Struct5Bytes12StructNBytesILj5EE(ptr addrspace(4) byref(%struct.StructNBytes.2) align 1 %0) #2 !dbg !267 { @@ -403,8 +403,8 @@ entry: ; CHECK: DW_TAG_subprogram ; CHECK-LABEL: DW_AT_name ("Test_Func_Struct6Bytes") ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_LLVM_user DW_OP_LLVM_offset) ; Function Attrs: convergent mustprogress noinline nounwind optnone define dso_local void @_Z22Test_Func_Struct6Bytes12StructNBytesILj6EE([2 x i32] %.coerce) #0 !dbg !273 { @@ -422,8 +422,8 @@ entry: ; CHECK: DW_TAG_subprogram ; CHECK-LABEL: DW_AT_name ("Test_Kern_Struct6Bytes") ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_LLVM_user DW_OP_LLVM_offset) ; Function Attrs: convergent mustprogress noinline norecurse nounwind optnone define dso_local amdgpu_kernel void @_Z22Test_Kern_Struct6Bytes12StructNBytesILj6EE(ptr addrspace(4) byref(%struct.StructNBytes.3) align 1 %0) #2 !dbg !290 { @@ -438,8 +438,8 @@ entry: ; CHECK: DW_TAG_subprogram ; CHECK-LABEL: DW_AT_name ("Test_Func_Struct7Bytes") ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_LLVM_user DW_OP_LLVM_offset) ; Function Attrs: convergent mustprogress noinline nounwind optnone define dso_local void @_Z22Test_Func_Struct7Bytes12StructNBytesILj7EE([2 x i32] %.coerce) #0 !dbg !296 { @@ -457,8 +457,8 @@ entry: ; CHECK: DW_TAG_subprogram ; CHECK-LABEL: DW_AT_name ("Test_Kern_Struct7Bytes") ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_LLVM_user DW_OP_LLVM_offset) ; Function Attrs: convergent mustprogress noinline norecurse nounwind optnone define dso_local amdgpu_kernel void @_Z22Test_Kern_Struct7Bytes12StructNBytesILj7EE(ptr addrspace(4) byref(%struct.StructNBytes.4) align 1 %0) #2 !dbg !313 { @@ -473,8 +473,8 @@ entry: ; CHECK: DW_TAG_subprogram ; CHECK-LABEL: DW_AT_name ("Test_Func_Struct8Bytes") ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_LLVM_user DW_OP_LLVM_offset) ; Function Attrs: convergent mustprogress noinline nounwind optnone define dso_local void @_Z22Test_Func_Struct8Bytes12StructNBytesILj8EE([2 x i32] %.coerce) #0 !dbg !319 { @@ -489,8 +489,8 @@ entry: ; CHECK: DW_TAG_subprogram ; CHECK-LABEL: DW_AT_name ("Test_Kern_Struct8Bytes") ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_LLVM_user DW_OP_LLVM_offset) ; Function Attrs: convergent mustprogress noinline norecurse nounwind optnone define dso_local amdgpu_kernel void @_Z22Test_Kern_Struct8Bytes12StructNBytesILj8EE(ptr addrspace(4) byref(%struct.StructNBytes.5) align 1 %0) #2 !dbg !336 { @@ -505,8 +505,8 @@ entry: ; CHECK: DW_TAG_subprogram ; CHECK-LABEL: DW_AT_name ("Test_Func_Struct9Bytes") ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_LLVM_user DW_OP_LLVM_offset) ; Function Attrs: convergent mustprogress noinline nounwind optnone define dso_local void @_Z22Test_Func_Struct9Bytes12StructNBytesILj9EE(i8 %.coerce0, [8 x i8] %.coerce1) #0 !dbg !342 { @@ -524,8 +524,8 @@ entry: ; CHECK: DW_TAG_subprogram ; CHECK-LABEL: DW_AT_name ("Test_Kern_Struct9Bytes") ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_LLVM_user DW_OP_LLVM_offset) ; Function Attrs: convergent mustprogress noinline norecurse nounwind optnone define dso_local amdgpu_kernel void @_Z22Test_Kern_Struct9Bytes12StructNBytesILj9EE(ptr addrspace(4) byref(%struct.StructNBytes.6) align 1 %0) #2 !dbg !359 { @@ -554,8 +554,8 @@ entry: ; CHECK: DW_TAG_subprogram ; CHECK-LABEL: DW_AT_name ("Test_Kern_Struct64Bytes") ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_LLVM_user DW_OP_LLVM_offset) ; Function Attrs: convergent mustprogress noinline norecurse nounwind optnone define dso_local amdgpu_kernel void @_Z23Test_Kern_Struct64Bytes12StructNBytesILj64EE(ptr addrspace(4) byref(%struct.StructNBytes.7) align 1 %0) #2 !dbg !382 { @@ -570,8 +570,8 @@ entry: ; CHECK: DW_TAG_subprogram ; CHECK-LABEL: DW_AT_name ("Test_Func_Int8T") ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_LLVM_user DW_OP_LLVM_offset) ; Function Attrs: convergent mustprogress noinline nounwind optnone define dso_local void @_Z15Test_Func_Int8Tc(i8 noundef signext %0) #0 !dbg !388 { @@ -586,8 +586,8 @@ entry: ; CHECK: DW_TAG_subprogram ; CHECK-LABEL: DW_AT_name ("Test_Kern_Int8T") ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_LLVM_user DW_OP_LLVM_offset) ; Function Attrs: convergent mustprogress noinline norecurse nounwind optnone define dso_local amdgpu_kernel void @_Z15Test_Kern_Int8Tc(i8 noundef %0) #2 !dbg !396 { @@ -602,8 +602,8 @@ entry: ; CHECK: DW_TAG_subprogram ; CHECK-LABEL: DW_AT_name ("Test_Func_UInt8T") ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_LLVM_user DW_OP_LLVM_offset) ; Function Attrs: convergent mustprogress noinline nounwind optnone define dso_local void @_Z16Test_Func_UInt8Th(i8 noundef zeroext %0) #0 !dbg !402 { @@ -618,8 +618,8 @@ entry: ; CHECK: DW_TAG_subprogram ; CHECK-LABEL: DW_AT_name ("Test_Kern_UInt8T") ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_LLVM_user DW_OP_LLVM_offset) ; Function Attrs: convergent mustprogress noinline norecurse nounwind optnone define dso_local amdgpu_kernel void @_Z16Test_Kern_UInt8Th(i8 noundef %0) #2 !dbg !410 { @@ -634,8 +634,8 @@ entry: ; CHECK: DW_TAG_subprogram ; CHECK-LABEL: DW_AT_name ("Test_Func_Int16T") ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_LLVM_user DW_OP_LLVM_offset) ; Function Attrs: convergent mustprogress noinline nounwind optnone define dso_local void @_Z16Test_Func_Int16Ts(i16 noundef signext %0) #0 !dbg !416 { @@ -650,8 +650,8 @@ entry: ; CHECK: DW_TAG_subprogram ; CHECK-LABEL: DW_AT_name ("Test_Kern_Int16T") ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_LLVM_user DW_OP_LLVM_offset) ; Function Attrs: convergent mustprogress noinline norecurse nounwind optnone define dso_local amdgpu_kernel void @_Z16Test_Kern_Int16Ts(i16 noundef %0) #2 !dbg !424 { @@ -666,8 +666,8 @@ entry: ; CHECK: DW_TAG_subprogram ; CHECK-LABEL: DW_AT_name ("Test_Func_UInt16T") ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_LLVM_user DW_OP_LLVM_offset) ; Function Attrs: convergent mustprogress noinline nounwind optnone define dso_local void @_Z17Test_Func_UInt16Tt(i16 noundef zeroext %0) #0 !dbg !430 { @@ -682,8 +682,8 @@ entry: ; CHECK: DW_TAG_subprogram ; CHECK-LABEL: DW_AT_name ("Test_Kern_UInt16T") ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_LLVM_user DW_OP_LLVM_offset) ; Function Attrs: convergent mustprogress noinline norecurse nounwind optnone define dso_local amdgpu_kernel void @_Z17Test_Kern_UInt16Tt(i16 noundef %0) #2 !dbg !438 { @@ -698,8 +698,8 @@ entry: ; CHECK: DW_TAG_subprogram ; CHECK-LABEL: DW_AT_name ("Test_Func_Int32T") ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_LLVM_user DW_OP_LLVM_offset) ; Function Attrs: convergent mustprogress noinline nounwind optnone define dso_local void @_Z16Test_Func_Int32Ti(i32 noundef %0) #0 !dbg !444 { @@ -714,8 +714,8 @@ entry: ; CHECK: DW_TAG_subprogram ; CHECK-LABEL: DW_AT_name ("Test_Kern_Int32T") ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_LLVM_user DW_OP_LLVM_offset) ; Function Attrs: convergent mustprogress noinline norecurse nounwind optnone define dso_local amdgpu_kernel void @_Z16Test_Kern_Int32Ti(i32 noundef %0) #2 !dbg !452 { @@ -730,8 +730,8 @@ entry: ; CHECK: DW_TAG_subprogram ; CHECK-LABEL: DW_AT_name ("Test_Func_UInt32T") ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_LLVM_user DW_OP_LLVM_offset) ; Function Attrs: convergent mustprogress noinline nounwind optnone define dso_local void @_Z17Test_Func_UInt32Tj(i32 noundef %0) #0 !dbg !458 { @@ -746,8 +746,8 @@ entry: ; CHECK: DW_TAG_subprogram ; CHECK-LABEL: DW_AT_name ("Test_Kern_UInt32T") ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_LLVM_user DW_OP_LLVM_offset) ; Function Attrs: convergent mustprogress noinline norecurse nounwind optnone define dso_local amdgpu_kernel void @_Z17Test_Kern_UInt32Tj(i32 noundef %0) #2 !dbg !466 { @@ -762,8 +762,8 @@ entry: ; CHECK: DW_TAG_subprogram ; CHECK-LABEL: DW_AT_name ("Test_Func_Int64T") ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_LLVM_user DW_OP_LLVM_offset) ; Function Attrs: convergent mustprogress noinline nounwind optnone define dso_local void @_Z16Test_Func_Int64Tl(i64 noundef %0) #0 !dbg !472 { @@ -778,8 +778,8 @@ entry: ; CHECK: DW_TAG_subprogram ; CHECK-LABEL: DW_AT_name ("Test_Kern_Int64T") ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit8, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit8, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit8, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit8, DW_OP_LLVM_user DW_OP_LLVM_offset) ; Function Attrs: convergent mustprogress noinline norecurse nounwind optnone define dso_local amdgpu_kernel void @_Z16Test_Kern_Int64Tl(i64 noundef %0) #2 !dbg !480 { @@ -794,8 +794,8 @@ entry: ; CHECK: DW_TAG_subprogram ; CHECK-LABEL: DW_AT_name ("Test_Func_UInt64T") ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_LLVM_user DW_OP_LLVM_offset) ; Function Attrs: convergent mustprogress noinline nounwind optnone define dso_local void @_Z17Test_Func_UInt64Tm(i64 noundef %0) #0 !dbg !486 { @@ -810,8 +810,8 @@ entry: ; CHECK: DW_TAG_subprogram ; CHECK-LABEL: DW_AT_name ("Test_Kern_UInt64T") ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit8, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit8, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit8, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit8, DW_OP_LLVM_user DW_OP_LLVM_offset) ; Function Attrs: convergent mustprogress noinline norecurse nounwind optnone define dso_local amdgpu_kernel void @_Z17Test_Kern_UInt64Tm(i64 noundef %0) #2 !dbg !494 { @@ -826,8 +826,8 @@ entry: ; CHECK: DW_TAG_subprogram ; CHECK-LABEL: DW_AT_name ("Test_Func_EnumInt8T") ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_LLVM_user DW_OP_LLVM_offset) ; Function Attrs: convergent mustprogress noinline nounwind optnone define dso_local void @_Z19Test_Func_EnumInt8T9EnumInt8T(i8 noundef signext %0) #0 !dbg !500 { @@ -842,8 +842,8 @@ entry: ; CHECK: DW_TAG_subprogram ; CHECK-LABEL: DW_AT_name ("Test_Kern_EnumInt8T") ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_LLVM_user DW_OP_LLVM_offset) ; Function Attrs: convergent mustprogress noinline norecurse nounwind optnone define dso_local amdgpu_kernel void @_Z19Test_Kern_EnumInt8T9EnumInt8T(i8 noundef %0) #2 !dbg !508 { @@ -858,8 +858,8 @@ entry: ; CHECK: DW_TAG_subprogram ; CHECK-LABEL: DW_AT_name ("Test_Func_EnumUInt8T") ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_LLVM_user DW_OP_LLVM_offset) ; Function Attrs: convergent mustprogress noinline nounwind optnone define dso_local void @_Z20Test_Func_EnumUInt8T10EnumUInt8T(i8 noundef zeroext %0) #0 !dbg !514 { @@ -874,8 +874,8 @@ entry: ; CHECK: DW_TAG_subprogram ; CHECK-LABEL: DW_AT_name ("Test_Kern_EnumUInt8T") ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_LLVM_user DW_OP_LLVM_offset) ; Function Attrs: convergent mustprogress noinline norecurse nounwind optnone define dso_local amdgpu_kernel void @_Z20Test_Kern_EnumUInt8T10EnumUInt8T(i8 noundef %0) #2 !dbg !522 { @@ -890,8 +890,8 @@ entry: ; CHECK: DW_TAG_subprogram ; CHECK-LABEL: DW_AT_name ("Test_Func_EnumInt16T") ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_LLVM_user DW_OP_LLVM_offset) ; Function Attrs: convergent mustprogress noinline nounwind optnone define dso_local void @_Z20Test_Func_EnumInt16T10EnumInt16T(i16 noundef signext %0) #0 !dbg !528 { @@ -906,8 +906,8 @@ entry: ; CHECK: DW_TAG_subprogram ; CHECK-LABEL: DW_AT_name ("Test_Kern_EnumInt16T") ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_LLVM_user DW_OP_LLVM_offset) ; Function Attrs: convergent mustprogress noinline norecurse nounwind optnone define dso_local amdgpu_kernel void @_Z20Test_Kern_EnumInt16T10EnumInt16T(i16 noundef %0) #2 !dbg !536 { @@ -922,8 +922,8 @@ entry: ; CHECK: DW_TAG_subprogram ; CHECK-LABEL: DW_AT_name ("Test_Func_EnumUInt16T") ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_LLVM_user DW_OP_LLVM_offset) ; Function Attrs: convergent mustprogress noinline nounwind optnone define dso_local void @_Z21Test_Func_EnumUInt16T11EnumUInt16T(i16 noundef zeroext %0) #0 !dbg !542 { @@ -938,8 +938,8 @@ entry: ; CHECK: DW_TAG_subprogram ; CHECK-LABEL: DW_AT_name ("Test_Kern_EnumUInt16T") ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_LLVM_user DW_OP_LLVM_offset) ; Function Attrs: convergent mustprogress noinline norecurse nounwind optnone define dso_local amdgpu_kernel void @_Z21Test_Kern_EnumUInt16T11EnumUInt16T(i16 noundef %0) #2 !dbg !550 { @@ -954,8 +954,8 @@ entry: ; CHECK: DW_TAG_subprogram ; CHECK-LABEL: DW_AT_name ("Test_Func_EnumInt32T") ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_LLVM_user DW_OP_LLVM_offset) ; Function Attrs: convergent mustprogress noinline nounwind optnone define dso_local void @_Z20Test_Func_EnumInt32T10EnumInt32T(i32 noundef %0) #0 !dbg !556 { @@ -970,8 +970,8 @@ entry: ; CHECK: DW_TAG_subprogram ; CHECK-LABEL: DW_AT_name ("Test_Kern_EnumInt32T") ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_LLVM_user DW_OP_LLVM_offset) ; Function Attrs: convergent mustprogress noinline norecurse nounwind optnone define dso_local amdgpu_kernel void @_Z20Test_Kern_EnumInt32T10EnumInt32T(i32 noundef %0) #2 !dbg !564 { @@ -986,8 +986,8 @@ entry: ; CHECK: DW_TAG_subprogram ; CHECK-LABEL: DW_AT_name ("Test_Func_EnumUInt32T") ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_LLVM_user DW_OP_LLVM_offset) ; Function Attrs: convergent mustprogress noinline nounwind optnone define dso_local void @_Z21Test_Func_EnumUInt32T11EnumUInt32T(i32 noundef %0) #0 !dbg !570 { @@ -1002,8 +1002,8 @@ entry: ; CHECK: DW_TAG_subprogram ; CHECK-LABEL: DW_AT_name ("Test_Kern_EnumUInt32T") ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_LLVM_user DW_OP_LLVM_offset) ; Function Attrs: convergent mustprogress noinline norecurse nounwind optnone define dso_local amdgpu_kernel void @_Z21Test_Kern_EnumUInt32T11EnumUInt32T(i32 noundef %0) #2 !dbg !578 { @@ -1018,8 +1018,8 @@ entry: ; CHECK: DW_TAG_subprogram ; CHECK-LABEL: DW_AT_name ("Test_Func_EnumInt64T") ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_LLVM_user DW_OP_LLVM_offset) ; Function Attrs: convergent mustprogress noinline nounwind optnone define dso_local void @_Z20Test_Func_EnumInt64T10EnumInt64T(i64 noundef %0) #0 !dbg !584 { @@ -1034,8 +1034,8 @@ entry: ; CHECK: DW_TAG_subprogram ; CHECK-LABEL: DW_AT_name ("Test_Kern_EnumInt64T") ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit8, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit8, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit8, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit8, DW_OP_LLVM_user DW_OP_LLVM_offset) ; Function Attrs: convergent mustprogress noinline norecurse nounwind optnone define dso_local amdgpu_kernel void @_Z20Test_Kern_EnumInt64T10EnumInt64T(i64 noundef %0) #2 !dbg !592 { @@ -1050,8 +1050,8 @@ entry: ; CHECK: DW_TAG_subprogram ; CHECK-LABEL: DW_AT_name ("Test_Func_EnumUInt64T") ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_LLVM_user DW_OP_LLVM_offset) ; Function Attrs: convergent mustprogress noinline nounwind optnone define dso_local void @_Z21Test_Func_EnumUInt64T11EnumUInt64T(i64 noundef %0) #0 !dbg !598 { @@ -1066,8 +1066,8 @@ entry: ; CHECK: DW_TAG_subprogram ; CHECK-LABEL: DW_AT_name ("Test_Kern_EnumUInt64T") ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit8, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit8, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit8, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit8, DW_OP_LLVM_user DW_OP_LLVM_offset) ; Function Attrs: convergent mustprogress noinline norecurse nounwind optnone define dso_local amdgpu_kernel void @_Z21Test_Kern_EnumUInt64T11EnumUInt64T(i64 noundef %0) #2 !dbg !606 { @@ -1082,8 +1082,8 @@ entry: ; CHECK: DW_TAG_subprogram ; CHECK-LABEL: DW_AT_name ("Test_Func_PromotableInteger") ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_LLVM_user DW_OP_LLVM_offset) ; Function Attrs: convergent mustprogress noinline nounwind optnone define dso_local void @_Z27Test_Func_PromotableIntegerb(i1 noundef zeroext %0) #0 !dbg !612 { @@ -1099,8 +1099,8 @@ entry: ; CHECK: DW_TAG_subprogram ; CHECK-LABEL: DW_AT_name ("Test_Kern_PromotableInteger") ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit4, DW_OP_LLVM_user DW_OP_LLVM_offset) ; Function Attrs: convergent mustprogress noinline norecurse nounwind optnone define dso_local amdgpu_kernel void @_Z27Test_Kern_PromotableIntegerb(i1 noundef %0) #2 !dbg !621 { @@ -1116,8 +1116,8 @@ entry: ; CHECK: DW_TAG_subprogram ; CHECK-LABEL: DW_AT_name ("Test_Func_Pointer") ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_LLVM_user DW_OP_LLVM_offset) ; Function Attrs: convergent mustprogress noinline nounwind optnone define dso_local void @_Z17Test_Func_PointerPi(ptr noundef %0) #0 !dbg !627 { @@ -1132,8 +1132,8 @@ entry: ; CHECK: DW_TAG_subprogram ; CHECK-LABEL: DW_AT_name ("Test_Kern_Pointer") ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit16, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit16, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit16, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit16, DW_OP_LLVM_user DW_OP_LLVM_offset) ; Function Attrs: convergent mustprogress noinline norecurse nounwind optnone define dso_local amdgpu_kernel void @_Z17Test_Kern_PointerPi(ptr addrspace(1) noundef %.coerce) #2 !dbg !636 { @@ -1153,8 +1153,8 @@ entry: ; CHECK: DW_TAG_subprogram ; CHECK-LABEL: DW_AT_name ("Test_Func_Reference") ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_LLVM_user DW_OP_LLVM_offset) ; Function Attrs: convergent mustprogress noinline nounwind optnone define dso_local void @_Z19Test_Func_ReferenceRi(ptr noundef nonnull align 4 dereferenceable(4) %0) #0 !dbg !642 { @@ -1169,8 +1169,8 @@ entry: ; CHECK: DW_TAG_subprogram ; CHECK-LABEL: DW_AT_name ("Test_Kern_Reference") ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit16, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit16, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit16, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit16, DW_OP_LLVM_user DW_OP_LLVM_offset) ; Function Attrs: convergent mustprogress noinline norecurse nounwind optnone define dso_local amdgpu_kernel void @_Z19Test_Kern_ReferenceRi(ptr addrspace(1) noundef nonnull align 4 dereferenceable(4) %.coerce) #2 !dbg !651 { @@ -1190,8 +1190,8 @@ entry: ; CHECK: DW_TAG_subprogram ; CHECK-LABEL: DW_AT_name ("Test_Func_StructSinglePointerElement") ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_LLVM_user DW_OP_LLVM_offset) ; Function Attrs: convergent mustprogress noinline nounwind optnone define dso_local void @_Z36Test_Func_StructSinglePointerElement26StructSinglePointerElement(ptr %.coerce) #0 !dbg !657 { @@ -1207,8 +1207,8 @@ entry: ; CHECK: DW_TAG_subprogram ; CHECK-LABEL: DW_AT_name ("Test_Kern_StructSinglePointerElement") ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit8, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit8, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit8, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit8, DW_OP_LLVM_user DW_OP_LLVM_offset) ; Function Attrs: convergent mustprogress noinline norecurse nounwind optnone define dso_local amdgpu_kernel void @_Z36Test_Kern_StructSinglePointerElement26StructSinglePointerElement(ptr addrspace(1) %.coerce) #2 !dbg !668 { @@ -1225,8 +1225,8 @@ entry: ; CHECK: DW_TAG_subprogram ; CHECK-LABEL: DW_AT_name ("Test_Func_StructPointerElements") ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_LLVM_user DW_OP_LLVM_offset) ; Function Attrs: convergent mustprogress noinline nounwind optnone define dso_local void @_Z31Test_Func_StructPointerElements21StructPointerElements(ptr %.coerce0, ptr %.coerce1) #0 !dbg !674 { @@ -1244,8 +1244,8 @@ entry: ; CHECK: DW_TAG_subprogram ; CHECK-LABEL: DW_AT_name ("Test_Kern_StructPointerElements") ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit8, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit8, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit8, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit8, DW_OP_LLVM_user DW_OP_LLVM_offset) ; Function Attrs: convergent mustprogress noinline norecurse nounwind optnone define dso_local amdgpu_kernel void @_Z31Test_Kern_StructPointerElements21StructPointerElements(ptr addrspace(4) byref(%struct.StructPointerElements) align 8 %0) #2 !dbg !688 { @@ -1260,29 +1260,29 @@ entry: ; CHECK: DW_TAG_subprogram ; CHECK-LABEL: DW_AT_name ("Test_Func_ParamRegLimitExpandedStruct") ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit16, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit16, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit16, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit16, DW_OP_LLVM_user DW_OP_LLVM_offset) ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit24, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit24, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit24, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit24, DW_OP_LLVM_user DW_OP_LLVM_offset) ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_constu 0x20, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_constu 0x20, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_constu 0x20, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_constu 0x20, DW_OP_LLVM_user DW_OP_LLVM_offset) ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_constu 0x28, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_constu 0x28, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_constu 0x28, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_constu 0x28, DW_OP_LLVM_user DW_OP_LLVM_offset) ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_constu 0x30, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_constu 0x30, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_constu 0x30, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_constu 0x30, DW_OP_LLVM_user DW_OP_LLVM_offset) ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_constu 0x38, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_constu 0x38, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_constu 0x38, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_constu 0x38, DW_OP_LLVM_user DW_OP_LLVM_offset) ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_constu 0x40, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_constu 0x40, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_constu 0x40, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_constu 0x40, DW_OP_LLVM_user DW_OP_LLVM_offset) ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit0, DW_OP_LLVM_user DW_OP_LLVM_offset) ; Function Attrs: convergent mustprogress noinline nounwind optnone define dso_local void @_Z37Test_Func_ParamRegLimitExpandedStructlllllli22StructMultipleElements(i64 noundef %0, i64 noundef %1, i64 noundef %2, i64 noundef %3, i64 noundef %4, i64 noundef %5, i32 noundef %6, i32 %.coerce0, i64 %.coerce1) #0 !dbg !694 { @@ -1328,29 +1328,29 @@ entry: ; CHECK: DW_TAG_subprogram ; CHECK-LABEL: DW_AT_name ("Test_Kern_ParamRegLimitExpandedStruct") ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit24, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit24, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit24, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit24, DW_OP_LLVM_user DW_OP_LLVM_offset) ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_constu 0x20, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_constu 0x20, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_constu 0x20, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_constu 0x20, DW_OP_LLVM_user DW_OP_LLVM_offset) ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_constu 0x28, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_constu 0x28, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_constu 0x28, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_constu 0x28, DW_OP_LLVM_user DW_OP_LLVM_offset) ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_constu 0x30, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_constu 0x30, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_constu 0x30, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_constu 0x30, DW_OP_LLVM_user DW_OP_LLVM_offset) ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_constu 0x38, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_constu 0x38, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_constu 0x38, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_constu 0x38, DW_OP_LLVM_user DW_OP_LLVM_offset) ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_constu 0x40, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_constu 0x40, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_constu 0x40, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_constu 0x40, DW_OP_LLVM_user DW_OP_LLVM_offset) ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_constu 0x48, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_constu 0x48, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_constu 0x48, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_constu 0x48, DW_OP_LLVM_user DW_OP_LLVM_offset) ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit8, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit8, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit8, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit8, DW_OP_LLVM_user DW_OP_LLVM_offset) ; Function Attrs: convergent mustprogress noinline norecurse nounwind optnone define dso_local amdgpu_kernel void @_Z37Test_Kern_ParamRegLimitExpandedStructlllllli22StructMultipleElements(i64 noundef %0, i64 noundef %1, i64 noundef %2, i64 noundef %3, i64 noundef %4, i64 noundef %5, i32 noundef %6, ptr addrspace(4) byref(%struct.StructMultipleElements) align 8 %7) #2 !dbg !727 { @@ -1393,26 +1393,26 @@ entry: ; CHECK: DW_TAG_subprogram ; CHECK-LABEL: DW_AT_name ("Test_Func_ParamRegLimitUnexpandedStruct") ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit16, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit16, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit16, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit16, DW_OP_LLVM_user DW_OP_LLVM_offset) ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit24, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit24, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit24, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit24, DW_OP_LLVM_user DW_OP_LLVM_offset) ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_constu 0x20, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_constu 0x20, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_constu 0x20, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_constu 0x20, DW_OP_LLVM_user DW_OP_LLVM_offset) ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_constu 0x28, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_constu 0x28, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_constu 0x28, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_constu 0x28, DW_OP_LLVM_user DW_OP_LLVM_offset) ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_constu 0x30, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_constu 0x30, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_constu 0x30, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_constu 0x30, DW_OP_LLVM_user DW_OP_LLVM_offset) ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_constu 0x38, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_constu 0x38, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_constu 0x38, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_constu 0x38, DW_OP_LLVM_user DW_OP_LLVM_offset) ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_constu 0x40, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_constu 0x40, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_constu 0x40, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_regx SGPR32_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_constu 0x40, DW_OP_LLVM_user DW_OP_LLVM_offset) ; CHECK: DW_TAG_formal_parameter ; FIXME: fix byval ; CHECK: DW_AT_location () @@ -1456,29 +1456,29 @@ entry: ; CHECK: DW_TAG_subprogram ; CHECK-LABEL: DW_AT_name ("Test_Kern_ParamRegLimitUnexpandedStruct") ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit24, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit24, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit24, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit24, DW_OP_LLVM_user DW_OP_LLVM_offset) ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_constu 0x20, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_constu 0x20, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_constu 0x20, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_constu 0x20, DW_OP_LLVM_user DW_OP_LLVM_offset) ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_constu 0x28, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_constu 0x28, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_constu 0x28, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_constu 0x28, DW_OP_LLVM_user DW_OP_LLVM_offset) ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_constu 0x30, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_constu 0x30, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_constu 0x30, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_constu 0x30, DW_OP_LLVM_user DW_OP_LLVM_offset) ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_constu 0x38, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_constu 0x38, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_constu 0x38, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_constu 0x38, DW_OP_LLVM_user DW_OP_LLVM_offset) ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_constu 0x40, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_constu 0x40, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_constu 0x40, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_constu 0x40, DW_OP_LLVM_user DW_OP_LLVM_offset) ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_constu 0x48, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_constu 0x48, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_constu 0x48, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_constu 0x48, DW_OP_LLVM_user DW_OP_LLVM_offset) ; CHECK: DW_TAG_formal_parameter -; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit8, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_offset) -; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_stack_value, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit8, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; CHECK-ORIG-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_form_aspace_address, DW_OP_lit8, DW_OP_LLVM_offset) +; CHECK-USER-OPS: DW_AT_location (DW_OP_lit0, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit8, DW_OP_LLVM_user DW_OP_LLVM_offset) ; Function Attrs: convergent mustprogress noinline norecurse nounwind optnone define dso_local amdgpu_kernel void @_Z39Test_Kern_ParamRegLimitUnexpandedStructlllllll22StructMultipleElements(i64 noundef %0, i64 noundef %1, i64 noundef %2, i64 noundef %3, i64 noundef %4, i64 noundef %5, i64 noundef %6, ptr addrspace(4) byref(%struct.StructMultipleElements) align 8 %7) #2 !dbg !783 { diff --git a/llvm/test/DebugInfo/AMDGPU/heterogeneous-dwarf.ll b/llvm/test/DebugInfo/AMDGPU/heterogeneous-dwarf.ll index 34f1b9b326f76a..4b3e3eb647b418 100644 --- a/llvm/test/DebugInfo/AMDGPU/heterogeneous-dwarf.ll +++ b/llvm/test/DebugInfo/AMDGPU/heterogeneous-dwarf.ll @@ -14,8 +14,8 @@ target triple = "amdgcn-amd-amdhsa" ; CHECK-NEXT: DW_AT_name {{.*}}"B" ; COMMON: {{.*}}DW_TAG_variable -; FLAT-SCR-DIS: DW_AT_location [DW_FORM_exprloc] (DW_OP_regx SGPR33_LO16, DW_OP_lit6, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_deref_size 0x4, DW_OP_swap, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit20, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) -; FLAT-SCR-ENA: DW_AT_location [DW_FORM_exprloc] (DW_OP_regx SGPR33_LO16, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit16, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_LLVM_user DW_OP_LLVM_offset) +; FLAT-SCR-DIS: DW_AT_location [DW_FORM_exprloc] (DW_OP_regx SGPR33_LO16, DW_OP_deref_size 0x4, DW_OP_lit6, DW_OP_shr, DW_OP_stack_value, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit16, DW_OP_LLVM_user DW_OP_LLVM_offset) +; FLAT-SCR-ENA: DW_AT_location [DW_FORM_exprloc] (DW_OP_regx SGPR33_LO16, DW_OP_deref_size 0x4, DW_OP_constu 0x5, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_lit16, DW_OP_LLVM_user DW_OP_LLVM_offset) ; COMMON: DW_AT_name {{.*}}"C" define protected amdgpu_kernel void @testKernel(i32 addrspace(1)* %A) #0 !dbg !11 !kernel_arg_addr_space !17 !kernel_arg_access_qual !18 !kernel_arg_type !19 !kernel_arg_base_type !19 !kernel_arg_type_qual !20 { diff --git a/llvm/test/DebugInfo/heterogeneous-diop-in-diexpression-conversion.ll b/llvm/test/DebugInfo/heterogeneous-diop-in-diexpression-conversion.ll new file mode 100644 index 00000000000000..28ed78acc045cc --- /dev/null +++ b/llvm/test/DebugInfo/heterogeneous-diop-in-diexpression-conversion.ll @@ -0,0 +1,72 @@ +; RUN: llc --filetype=obj --fast-isel=true < %s | llvm-dwarfdump -debug-info - | FileCheck %s + +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +define void @main() !dbg !5 { + + ; CHECK: 0x{{[0-9a-z]+}}: DW_TAG_variable + ; CHECK-NEXT: DW_AT_location (DW_OP_constu 0xff, DW_OP_dup, DW_OP_constu 0x7, DW_OP_shr, DW_OP_lit0, DW_OP_not, DW_OP_mul, DW_OP_constu 0x8, DW_OP_shl, DW_OP_or, DW_OP_stack_value) + ; CHECK-NEXT: DW_AT_name ("sext_i8") + ; CHECK-NEXT: DW_AT_decl_file + ; CHECK-NEXT: DW_AT_decl_line + ; CHECK-NEXT: DW_AT_type (0x{{[0-9a-z]+}} "i32") + tail call void @llvm.dbg.value(metadata i8 -1, metadata !10, metadata !DIExpression(DIOpArg(0, i8), DIOpSExt(i32))), !dbg !15 + + ; CHECK: 0x{{[0-9a-z]+}}: DW_TAG_variable + ; CHECK-NEXT: DW_AT_location (DW_OP_constu 0xff, DW_OP_constu 0xff, DW_OP_and, DW_OP_stack_value) + ; CHECK-NEXT: DW_AT_name ("zext_i8") + ; CHECK-NEXT: DW_AT_decl_file + ; CHECK-NEXT: DW_AT_decl_line + ; CHECK-NEXT: DW_AT_type (0x{{[0-9a-z]+}} "i32") + tail call void @llvm.dbg.value(metadata i8 -1, metadata !11, metadata !DIExpression(DIOpArg(0, i8), DIOpZExt(i32))), !dbg !15 + + ; CHECK: 0x{{[0-9a-z]+}}: DW_TAG_variable + ; CHECK-NEXT: DW_AT_location (DW_OP_constu 0xfffffffffffffff6, DW_OP_constu 0xffffffff, DW_OP_and, DW_OP_stack_value) + ; CHECK-NEXT: DW_AT_name ("trunc_i64") + ; CHECK-NEXT: DW_AT_decl_file + ; CHECK-NEXT: DW_AT_decl_line + ; CHECK-NEXT: DW_AT_type (0x{{[0-9a-z]+}} "i32") + tail call void @llvm.dbg.value(metadata i64 -10, metadata !12, metadata !DIExpression(DIOpArg(0, i64), DIOpConvert(i32))), !dbg !15 + + ; CHECK: 0x{{[0-9a-z]+}}: DW_TAG_variable + ; CHECK-NEXT: DW_AT_location (DW_OP_constu 0xff, DW_OP_dup, DW_OP_constu 0x7, DW_OP_shr, DW_OP_lit0, DW_OP_not, DW_OP_mul, DW_OP_constu 0x8, DW_OP_shl, DW_OP_or, DW_OP_lit1, DW_OP_plus, DW_OP_stack_value) + ; CHECK-NEXT: DW_AT_name ("add_const") + ; CHECK-NEXT: DW_AT_decl_file + ; CHECK-NEXT: DW_AT_decl_line + ; CHECK-NEXT: DW_AT_type (0x{{[0-9a-z]+}} "i32") + tail call void @llvm.dbg.value(metadata i8 -1, metadata !13, metadata !DIExpression(DIOpArg(0, i8), DIOpSExt(i32), DIOpConstant(i32 1), DIOpAdd())), !dbg !15 + + ; CHECK: 0x{{[0-9a-z]+}}: DW_TAG_variable + ; CHECK-NEXT: DW_AT_location (DW_OP_constu 0x2a, DW_OP_stack_value) + ; CHECK-NEXT: DW_AT_name ("noop_convert") + ; CHECK-NEXT: DW_AT_decl_file + ; CHECK-NEXT: DW_AT_decl_line + ; CHECK-NEXT: DW_AT_type (0x{{[0-9a-z]+}} "i32") + tail call void @llvm.dbg.value(metadata i32 42, metadata !14, metadata !DIExpression(DIOpArg(0, i32), DIOpConvert(i32))), !dbg !15 + + ret void, !dbg !15 +} + +declare void @llvm.dbg.value(metadata, metadata, metadata) + +!llvm.dbg.cu = !{!0} +!llvm.debugify = !{!2, !3} +!llvm.module.flags = !{!4} + +!0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, producer: "debugify", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug) +!1 = !DIFile(filename: "t.c", directory: "/") +!2 = !{i32 8} +!3 = !{i32 7} +!4 = !{i32 2, !"Debug Info Version", i32 3} +!5 = distinct !DISubprogram(name: "test", linkageName: "test", scope: null, file: !1, line: 1, type: !6, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !8) +!6 = !DISubroutineType(types: !7) +!7 = !{} +!8 = !{!10, !11, !12, !13} +!9 = !DIBasicType(name: "i32", size: 32, encoding: DW_ATE_signed) +!10 = !DILocalVariable(name: "sext_i8", scope: !5, file: !1, line: 1, type: !9) +!11 = !DILocalVariable(name: "zext_i8", scope: !5, file: !1, line: 2, type: !9) +!12 = !DILocalVariable(name: "trunc_i64", scope: !5, file: !1, line: 3, type: !9) +!13 = !DILocalVariable(name: "add_const", scope: !5, file: !1, line: 4, type: !9) +!14 = !DILocalVariable(name: "noop_convert", scope: !5, file: !1, line: 4, type: !9) +!15 = !DILocation(line: 1, column: 1, scope: !5) diff --git a/llvm/test/DebugInfo/heterogeneous-diop-in-diexpression.ll b/llvm/test/DebugInfo/heterogeneous-diop-in-diexpression.ll new file mode 100644 index 00000000000000..ecb3785582c061 --- /dev/null +++ b/llvm/test/DebugInfo/heterogeneous-diop-in-diexpression.ll @@ -0,0 +1,101 @@ +; RUN: opt -S -passes=verify < %s | FileCheck %s +; RUN: llc --filetype=obj --relocation-model=pic -fast-isel=false < %s | llvm-dwarfdump -v -debug-info - | FileCheck --check-prefix=DWARF %s +; RUN: llc --filetype=obj --relocation-model=pic -fast-isel=true < %s | llvm-dwarfdump -v -debug-info - | FileCheck --check-prefix=DWARF %s + +; TODO: Test for global isel + +; DWARF: DW_TAG_variable +; DWARF: DW_AT_name [DW_FORM_strx1] (indexed ([[#%x,]]) string = "glob") +; DWARF: DW_AT_location [DW_FORM_exprloc] (DW_OP_addrx 0x0, DW_OP_stack_value, DW_OP_deref_size 0x8, DW_OP_lit0, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address) + +; DWARF: DW_TAG_variable +; DWARF: DW_AT_name [DW_FORM_strx1] (indexed ([[#%x,]]) string = "glob_fragmented") +; DWARF: DW_AT_location [DW_FORM_exprloc] (DW_OP_addrx 0x1, DW_OP_stack_value, DW_OP_deref_size 0x8, DW_OP_lit0, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_piece 0x2, DW_OP_addrx 0x2, DW_OP_stack_value, DW_OP_deref_size 0x8, DW_OP_lit0, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address) + +; DWARF: DW_TAG_variable +; DWARF: DW_AT_location [DW_FORM_loclistx] (indexed (0x[[#%x,]]) loclist = 0x[[#%x,]]: +; DWARF: [0x[[#%x,]], 0x[[#%x,]]) ".text": DW_OP_reg6 RBP, DW_OP_deref_size 0x8, DW_OP_consts -4, DW_OP_plus, DW_OP_stack_value, DW_OP_deref_size 0x8, DW_OP_lit0, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address +; DWARF: DW_AT_name [DW_FORM_strx1] (indexed ([[#%x,]]) string = "var") + +; DWARF: DW_TAG_variable +; DWARF: DW_AT_location [DW_FORM_loclistx] (indexed (0x[[#%x,]]) loclist = 0x[[#%x,]]: +; DWARF: [0x[[#%x,]], 0x[[#%x,]]) ".text": DW_OP_reg6 RBP, DW_OP_deref_size 0x8, DW_OP_consts -8, DW_OP_plus, DW_OP_stack_value, DW_OP_deref_size 0x8, DW_OP_lit0, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address +; DWARF: [0x[[#%x,]], 0x[[#%x,]]) ".text": DW_OP_reg6 RBP, DW_OP_deref_size 0x8, DW_OP_consts -8, DW_OP_plus, DW_OP_stack_value, DW_OP_deref_size 0x8, DW_OP_lit0, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address, DW_OP_piece 0x2, DW_OP_reg6 RBP, DW_OP_deref_size 0x8, DW_OP_consts -6, DW_OP_plus, DW_OP_stack_value, DW_OP_deref_size 0x8, DW_OP_lit0, DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address) +; DWARF: DW_AT_name [DW_FORM_strx1] (indexed ([[#%x,]]) string = "var_fragmented") + +; ModuleID = '' +source_filename = "" +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +declare void @ex() + +; CHECK: @glob = {{.*}}, !dbg ![[#GLOB_GVE:]] +@glob = global i32 42, align 4, !dbg !0 + +; CHECK: @glob_fragmented.lo = {{.*}}, !dbg ![[#GLOB_FRAGMENTED_LO_GVE:]] +@glob_fragmented.lo = global i16 42, align 2, !dbg !23 +; CHECK: @glob_fragmented.hi = {{.*}}, !dbg ![[#GLOB_FRAGMENTED_HI_GVE:]] +@glob_fragmented.hi = global i16 42, align 2, !dbg !24 + +; Function Attrs: noinline nounwind optnone uwtable +define dso_local void @func() #0 !dbg !13 { +entry: + %var = alloca i32, align 4 + ; CHECK: tail call void @llvm.dbg.value(metadata !DIArgList(ptr %var), metadata ![[#]], metadata !DIExpression(DIOpArg(0, ptr), DIOpFragment(1, 2), DIOpDeref(i32))) + tail call void @llvm.dbg.value(metadata !DIArgList(ptr %var), metadata !18, metadata !DIExpression(DIOpArg(0, ptr), DIOpFragment(1, 2), DIOpDeref(i32))), !dbg !19 + ; CHECK: tail call void @llvm.dbg.value(metadata ptr %var, metadata ![[#VAR:]], metadata !DIExpression(DIOpArg(0, ptr), DIOpDeref(i32))) + tail call void @llvm.dbg.value(metadata ptr %var, metadata !18, metadata !DIExpression(DIOpArg(0, ptr), DIOpDeref(i32))), !dbg !19 + %var_fragmented.lo = alloca i16, align 2 + %var_fragmented.hi = alloca i16, align 2 + ; CHECK: tail call void @llvm.dbg.value(metadata ptr %var_fragmented.lo, metadata ![[#VAR_FRAGMENTED:]], metadata !DIExpression(DIOpArg(0, ptr), DIOpDeref(i16), DIOpFragment(0, 16))) + tail call void @llvm.dbg.value(metadata ptr %var_fragmented.lo, metadata !22, metadata !DIExpression(DIOpArg(0, ptr), DIOpDeref(i16), DIOpFragment(0, 16))), !dbg !19 + call void @ex() + ; CHECK: tail call void @llvm.dbg.value(metadata ptr %var_fragmented.hi, metadata ![[#VAR_FRAGMENTED]], metadata !DIExpression(DIOpArg(0, ptr), DIOpDeref(i16), DIOpFragment(16, 16))) + tail call void @llvm.dbg.value(metadata ptr %var_fragmented.hi, metadata !22, metadata !DIExpression(DIOpArg(0, ptr), DIOpDeref(i16), DIOpFragment(16, 16))), !dbg !19 + ret void, !dbg !20 +} + +; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none) +declare void @llvm.dbg.value(metadata, metadata, metadata) #1 + +attributes #0 = { noinline nounwind optnone uwtable "frame-pointer"="all" "target-cpu"="x86-64" } +attributes #1 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) } + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!5, !6, !7, !8, !9, !10, !11} +!llvm.ident = !{!12} + +; CHECK-DAG: ![[#GLOB_GVE]] = !DIGlobalVariableExpression(var: ![[#GLOB:]], expr: !DIExpression(DIOpArg(0, ptr), DIOpDeref(i32))) +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression(DIOpArg(0, ptr), DIOpDeref(i32))) +; CHECK-DAG: ![[#GLOB]] = distinct !DIGlobalVariable(name: "glob", +!1 = distinct !DIGlobalVariable(name: "glob", scope: !2, file: !3, line: 1, type: !4, isLocal: false, isDefinition: true) +!2 = distinct !DICompileUnit(language: DW_LANG_C11, file: !3, producer: "clang version 19.0.0git (git@github.com:slinder1/llvm-project.git e4263955383c3e364bd752d02fc44cf5f22143ef)", isOptimized: false, runtimeVersion: 0, globals: !21, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None) +!3 = !DIFile(filename: "-", directory: "/home/slinder1/llvm-project/main", checksumkind: CSK_MD5, checksum: "9e51994790e4105fa7153a61c95a824f") +!4 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!5 = !{i32 7, !"Dwarf Version", i32 5} +!6 = !{i32 2, !"Debug Info Version", i32 3} +!7 = !{i32 1, !"wchar_size", i32 4} +!8 = !{i32 8, !"PIC Level", i32 2} +!9 = !{i32 7, !"PIE Level", i32 2} +!10 = !{i32 7, !"uwtable", i32 2} +!11 = !{i32 7, !"frame-pointer", i32 2} +!12 = !{!"clang version 19.0.0git (git@github.com:slinder1/llvm-project.git e4263955383c3e364bd752d02fc44cf5f22143ef)"} +!13 = distinct !DISubprogram(name: "func", scope: !14, file: !14, line: 15, type: !15, scopeLine: 15, spFlags: DISPFlagDefinition, unit: !2, retainedNodes: !17) +!14 = !DIFile(filename: "", directory: "/home/slinder1/llvm-project/main", checksumkind: CSK_MD5, checksum: "9e51994790e4105fa7153a61c95a824f") +!15 = !DISubroutineType(types: !16) +!16 = !{null} +!17 = !{} +; CHECK-DAG: ![[#VAR]] = !DILocalVariable(name: "var", +!18 = !DILocalVariable(name: "var", scope: !13, file: !14, line: 16, type: !4) +!19 = !DILocation(line: 16, column: 9, scope: !13) +!20 = !DILocation(line: 17, column: 1, scope: !13) +!21 = !{!0, !23, !24} +; CHECK-DAG: ![[#VAR_FRAGMENTED]] = !DILocalVariable(name: "var_fragmented", +!22 = !DILocalVariable(name: "var_fragmented", scope: !13, file: !14, line: 16, type: !4) +; CHECK-DAG: ![[#GLOB_FRAGMENTED_LO_GVE]] = !DIGlobalVariableExpression(var: ![[#GLOB_FRAGMENTED:]], expr: !DIExpression(DIOpArg(0, ptr), DIOpDeref(i16), DIOpFragment(0, 16))) +!23 = !DIGlobalVariableExpression(var: !25, expr: !DIExpression(DIOpArg(0, ptr), DIOpDeref(i16), DIOpFragment(0, 16))) +; CHECK-DAG: ![[#GLOB_FRAGMENTED_HI_GVE]] = !DIGlobalVariableExpression(var: ![[#GLOB_FRAGMENTED]], expr: !DIExpression(DIOpArg(0, ptr), DIOpDeref(i16), DIOpFragment(16, 16))) +!24 = !DIGlobalVariableExpression(var: !25, expr: !DIExpression(DIOpArg(0, ptr), DIOpDeref(i16), DIOpFragment(16, 16))) +; CHECK-DAG: ![[#GLOB_FRAGMENTED]] = distinct !DIGlobalVariable(name: "glob_fragmented", +!25 = distinct !DIGlobalVariable(name: "glob_fragmented", scope: !2, file: !3, line: 1, type: !4, isLocal: false, isDefinition: true) diff --git a/llvm/test/DebugInfo/verify-diop-based-diexpression.ll b/llvm/test/DebugInfo/verify-diop-based-diexpression.ll new file mode 100644 index 00000000000000..c56db6bec4301f --- /dev/null +++ b/llvm/test/DebugInfo/verify-diop-based-diexpression.ll @@ -0,0 +1,178 @@ +; RUN: rm -rf %t && split-file %s %t && cd %t + +;--- valid.ll +; RUN: opt valid.ll -S -passes=verify 2>&1 | FileCheck --implicit-check-not 'invalid expression' valid.ll + +source_filename = "t.c" +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +declare void @llvm.dbg.declare(metadata, metadata, metadata) +declare void @llvm.dbg.value(metadata, metadata, metadata) + +%struct.type = type { ptr, ptr } + +define dso_local void @test_diexpr_eval() !dbg !17 { +entry: + %x = alloca ptr, align 8 + %i = alloca i32, align 4 + + ; CHECK: call void @llvm.dbg.declare(metadata ptr %i, metadata ![[#]], metadata !DIExpression(DIOpArg(0, ptr), DIOpArg(0, ptr), DIOpComposite(2, %struct.type))) + call void @llvm.dbg.declare(metadata ptr %i, metadata !21, metadata !DIExpression(DIOpArg(0, ptr), DIOpArg(0, ptr), DIOpComposite(2, %struct.type))), !dbg !22 + + ; CHECK: call void @llvm.dbg.declare(metadata i16 42, metadata ![[#]], metadata !DIExpression(DIOpArg(0, i16), DIOpFragment(16, 16))) + call void @llvm.dbg.declare(metadata i16 42, metadata !21, metadata !DIExpression(DIOpArg(0, i16), DIOpFragment(16, 16))), !dbg !22 + + ret void +} + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!2, !3, !4} + +!0 = distinct !DICompileUnit(language: DW_LANG_C11, file: !1, producer: "clang version 18", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None) +!1 = !DIFile(filename: "t.c", directory: "/") +!2 = !{i32 7, !"Dwarf Version", i32 5} +!3 = !{i32 2, !"Debug Info Version", i32 3} +!4 = !{i32 1, !"wchar_size", i32 4} +!5 = distinct !DISubprogram(name: "test_broken_declare", scope: !1, file: !1, line: 2, type: !6, scopeLine: 2, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !8) +!6 = !DISubroutineType(types: !7) +!7 = !{null} +!8 = !{} +!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!11 = !DILocation(line: 3, column: 7, scope: !5) +!12 = !DILocation(line: 4, column: 1, scope: !5) +!13 = distinct !DISubprogram(name: "test_broken_value", scope: !1, file: !1, line: 6, type: !6, scopeLine: 6, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !8) +!15 = !DILocation(line: 7, column: 7, scope: !13) +!16 = !DILocation(line: 8, column: 1, scope: !13) +!17 = distinct !DISubprogram(name: "test_diexpr_eval", scope: !1, file: !1, line: 10, type: !6, scopeLine: 10, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !8) +!18 = !DILocalVariable(name: "x", scope: !17, file: !1, line: 11, type: !19) +!19 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: null, size: 64) +!20 = !DILocation(line: 11, column: 9, scope: !17) +!21 = !DILocalVariable(name: "i", scope: !17, file: !1, line: 12, type: !10) +!22 = !DILocation(line: 12, column: 7, scope: !17) +!23 = !DILocation(line: 13, column: 1, scope: !17) + +;--- invalid.ll +; RUN: opt invalid.ll -S -passes=verify 2>&1 | FileCheck invalid.ll + +source_filename = "t.c" +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +declare void @llvm.dbg.declare(metadata, metadata, metadata) +declare void @llvm.dbg.value(metadata, metadata, metadata) + +define dso_local void @test_diexpr_eval() !dbg !17 { +entry: + %x = alloca ptr, align 8 + %i = alloca i32, align 4 + + ; CHECK: DIOpReferrer type must be same size in bits as argument + call void @llvm.dbg.declare(metadata ptr %x, metadata !18, metadata !DIExpression(DIOpReferrer(i32), DIOpDeref(ptr))), !dbg !20 + + ; FIXME(diexpression-poison): DIOpArg index out of range + call void @llvm.dbg.declare(metadata ptr %x, metadata !18, metadata !DIExpression(DIOpArg(1, ptr))), !dbg !20 + + ; CHECK: DIOpArg type must be same size in bits as argument + call void @llvm.dbg.declare(metadata ptr %x, metadata !18, metadata !DIExpression(DIOpArg(0, i32))), !dbg !20 + + ; CHECK: DIOpReinterpret must not alter bitsize of child + call void @llvm.dbg.declare(metadata ptr %x, metadata !18, metadata !DIExpression(DIOpArg(0, ptr), DIOpReinterpret(i32))), !dbg !20 + + ; CHECK: DIOpBitOffset requires first input be integer typed + call void @llvm.dbg.declare(metadata ptr %x, metadata !18, metadata !DIExpression(DIOpConstant(float 0.0), DIOpArg(0, ptr), DIOpBitOffset(ptr))), !dbg !20 + + ; CHECK: DIOpByteOffset requires first input be integer typed + call void @llvm.dbg.declare(metadata ptr %x, metadata !18, metadata !DIExpression(DIOpConstant(ptr undef), DIOpArg(0, ptr), DIOpByteOffset(ptr))), !dbg !20 + + ; CHECK: DIOpComposite bitsize does not match sum of child bitsizes + call void @llvm.dbg.declare(metadata ptr %i, metadata !21, metadata !DIExpression(DIOpArg(0, ptr), DIOpDeref(i16), DIOpConstant(i8 0), DIOpComposite(2, i32))), !dbg !22 + + ; CHECK: DIOpExtend child must have integer, floating point, or ptr type + call void @llvm.dbg.declare(metadata ptr %i, metadata !21, metadata !DIExpression(DIOpConstant(<2 x i32> ), DIOpExtend(2))), !dbg !22 + + ; CHECK: DIOpDeref requires input to be pointer typed + call void @llvm.dbg.declare(metadata ptr %i, metadata !21, metadata !DIExpression(DIOpArg(0, ptr), DIOpDeref(i32), DIOpDeref(i32))), !dbg !22 + + ; CHECK: DIOpAdd requires identical type inputs + call void @llvm.dbg.declare(metadata ptr %i, metadata !21, metadata !DIExpression(DIOpConstant(i32 0), DIOpConstant(i8 0), DIOpAdd())), !dbg !22 + + ; CHECK: DIOpPushLane requires integer result type + call void @llvm.dbg.declare(metadata ptr %i, metadata !21, metadata !DIExpression(DIOpPushLane(ptr))), !dbg !22 + + ; CHECK: DIOpAdd requires more inputs + call void @llvm.dbg.declare(metadata ptr %i, metadata !21, metadata !DIExpression(DIOpConstant(i32 0), DIOpAdd())), !dbg !22 + + ; CHECK: DIOpArg type must be same size in bits as argument + call void @llvm.dbg.declare(metadata !DIArgList(ptr %x, ptr %i), metadata !21, metadata !DIExpression(DIOpArg(0, i32), DIOpArg(1, i32), DIOpAdd())), !dbg !22 + + ; CHECK: DIOpArg type must be same size in bits as argument + call void @llvm.dbg.declare(metadata !DIArgList(ptr %x, ptr %i), metadata !21, metadata !DIExpression(DIOpArg(0, i8), DIOpArg(1, i8), DIOpAdd())), !dbg !22 + + ; CHECK: DIOp expression requires one element on stack after evaluating + call void @llvm.dbg.declare(metadata !DIArgList(ptr %x, ptr %i), metadata !21, metadata !DIExpression(DIOpArg(0, i64), DIOpArg(1, i64))), !dbg !22 + + ; CHECK: DIOpZExt requires integer typed input + call void @llvm.dbg.declare(metadata ptr %i, metadata !21, metadata !DIExpression(DIOpArg(0, ptr), DIOpZExt(i64))), !dbg !22 + + ; CHECK: DIOpZExt requires result type to be wider than input type + call void @llvm.dbg.declare(metadata ptr %i, metadata !21, metadata !DIExpression(DIOpArg(0, i64), DIOpZExt(i64))), !dbg !22 + + ; CHECK: DIOpSExt requires integer typed input + call void @llvm.dbg.declare(metadata ptr %i, metadata !21, metadata !DIExpression(DIOpArg(0, ptr), DIOpSExt(i64))), !dbg !22 + + ; CHECK: DIOpSExt requires result type to be wider than input type + call void @llvm.dbg.declare(metadata ptr %i, metadata !21, metadata !DIExpression(DIOpArg(0, i64), DIOpSExt(i64))), !dbg !22 + + ; CHECK: DIOpLShr requires all integer inputs + call void @llvm.dbg.declare(metadata ptr %i, metadata !21, metadata !DIExpression(DIOpArg(0, ptr), DIOpArg(0, ptr), DIOpLShr())), !dbg !22 + + ; CHECK: DIOpAShr requires all integer inputs + call void @llvm.dbg.declare(metadata ptr %i, metadata !21, metadata !DIExpression(DIOpArg(0, ptr), DIOpArg(0, ptr), DIOpAShr())), !dbg !22 + + ; CHECK: DIOpShl requires all integer inputs + call void @llvm.dbg.declare(metadata ptr %i, metadata !21, metadata !DIExpression(DIOpArg(0, ptr), DIOpArg(0, ptr), DIOpShl())), !dbg !22 + + ; CHECK: DIOpConvert on integers requires result type to be no wider than input type + call void @llvm.dbg.declare(metadata i8 42, metadata !21, metadata !DIExpression(DIOpArg(0, i8), DIOpConvert(i16))), !dbg !22 + + ; FIXME(diexpression-poison): DIExpression must yield a location at least as wide as the variable or fragment it describes + ;call void @llvm.dbg.declare(metadata i8 42, metadata !21, metadata !DIExpression(DIOpArg(0, i8))), !dbg !22 + + ; FIXME(diexpression-poison): DIExpression must yield a location at least as wide as the variable or fragment it describes + ;call void @llvm.dbg.declare(metadata ptr %i, metadata !21, metadata !DIExpression(DIOpArg(0, ptr), DIOpDeref(i16), DIOpConstant(i16 1), DIOpAdd())), !dbg !22 + + ; FIXME(diexpression-poison): DIExpression must yield a location at least as wide as the variable or fragment it describes + ;call void @llvm.dbg.declare(metadata i8 42, metadata !21, metadata !DIExpression(DIOpArg(0, i8), DIOpFragment(0, 16))), !dbg !22 + + ; CHECK: DIOpFragment must be contained within variable + call void @llvm.dbg.declare(metadata i16 42, metadata !21, metadata !DIExpression(DIOpArg(0, i16), DIOpFragment(24, 16))), !dbg !22 + + ret void +} + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!2, !3, !4} + +!0 = distinct !DICompileUnit(language: DW_LANG_C11, file: !1, producer: "clang version 18", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None) +!1 = !DIFile(filename: "t.c", directory: "/") +!2 = !{i32 7, !"Dwarf Version", i32 5} +!3 = !{i32 2, !"Debug Info Version", i32 3} +!4 = !{i32 1, !"wchar_size", i32 4} +!5 = distinct !DISubprogram(name: "test_broken_declare", scope: !1, file: !1, line: 2, type: !6, scopeLine: 2, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !8) +!6 = !DISubroutineType(types: !7) +!7 = !{null} +!8 = !{} +!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!11 = !DILocation(line: 3, column: 7, scope: !5) +!12 = !DILocation(line: 4, column: 1, scope: !5) +!13 = distinct !DISubprogram(name: "test_broken_value", scope: !1, file: !1, line: 6, type: !6, scopeLine: 6, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !8) +!15 = !DILocation(line: 7, column: 7, scope: !13) +!16 = !DILocation(line: 8, column: 1, scope: !13) +!17 = distinct !DISubprogram(name: "test_diexpr_eval", scope: !1, file: !1, line: 10, type: !6, scopeLine: 10, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !8) +!18 = !DILocalVariable(name: "x", scope: !17, file: !1, line: 11, type: !19) +!19 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: null, size: 64) +!20 = !DILocation(line: 11, column: 9, scope: !17) +!21 = !DILocalVariable(name: "i", scope: !17, file: !1, line: 12, type: !10) +!22 = !DILocation(line: 12, column: 7, scope: !17) +!23 = !DILocation(line: 13, column: 1, scope: !17) diff --git a/llvm/test/Transforms/InstCombine/cast-mul-select.ll b/llvm/test/Transforms/InstCombine/cast-mul-select.ll index 581c10de35e4f4..4b2145bd26b7ae 100644 --- a/llvm/test/Transforms/InstCombine/cast-mul-select.ll +++ b/llvm/test/Transforms/InstCombine/cast-mul-select.ll @@ -6,6 +6,9 @@ ; corresponding debug-info updates that are required, are not yet implemented. ; run: opt -passes=debugify,instcombine -S < %s --try-experimental-debuginfo-iterators | FileCheck %s -check-prefix DBGINFO +; RUN: opt -passes=debugify,instcombine --debugify-diop-diexprs --experimental-debuginfo-iterators=true -S < %s | FileCheck %s -check-prefix DIOP-DBGINFO +; RUN: opt -passes=debugify,instcombine --debugify-diop-diexprs --experimental-debuginfo-iterators=false -S < %s | FileCheck %s -check-prefix DIOP-DBGINFO + target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32" define i32 @mul(i32 %x, i32 %y) { @@ -15,14 +18,23 @@ define i32 @mul(i32 %x, i32 %y) { ; CHECK-NEXT: ret i32 [[D]] ; ; DBGINFO-LABEL: @mul( -; DBGINFO-NEXT: call void @llvm.dbg.value(metadata i32 [[X:%.*]], metadata [[META9:![0-9]+]], metadata !DIExpression(DW_OP_LLVM_convert, 32, DW_ATE_unsigned, DW_OP_LLVM_convert, 8, DW_ATE_unsigned, DW_OP_stack_value)), !dbg [[DBG15:![0-9]+]] -; DBGINFO-NEXT: call void @llvm.dbg.value(metadata i32 [[Y:%.*]], metadata [[META11:![0-9]+]], metadata !DIExpression(DW_OP_LLVM_convert, 32, DW_ATE_unsigned, DW_OP_LLVM_convert, 8, DW_ATE_unsigned, DW_OP_stack_value)), !dbg [[DBG16:![0-9]+]] +; DBGINFO-NEXT: tail call void @llvm.dbg.value(metadata i32 [[X:%.*]], metadata [[META9:![0-9]+]], metadata !DIExpression(DW_OP_LLVM_convert, 32, DW_ATE_unsigned, DW_OP_LLVM_convert, 8, DW_ATE_unsigned, DW_OP_stack_value)), !dbg [[DBG15:![0-9]+]] +; DBGINFO-NEXT: tail call void @llvm.dbg.value(metadata i32 [[Y:%.*]], metadata [[META11:![0-9]+]], metadata !DIExpression(DW_OP_LLVM_convert, 32, DW_ATE_unsigned, DW_OP_LLVM_convert, 8, DW_ATE_unsigned, DW_OP_stack_value)), !dbg [[DBG16:![0-9]+]] ; DBGINFO-NEXT: [[C:%.*]] = mul i32 [[X]], [[Y]], !dbg [[DBG17:![0-9]+]] ; DBGINFO-NEXT: [[D:%.*]] = and i32 [[C]], 255, !dbg [[DBG18:![0-9]+]] -; DBGINFO-NEXT: call void @llvm.dbg.value(metadata i32 [[C]], metadata [[META12:![0-9]+]], metadata !DIExpression()), !dbg [[DBG17]] -; DBGINFO-NEXT: call void @llvm.dbg.value(metadata i32 [[D]], metadata [[META13:![0-9]+]], metadata !DIExpression()), !dbg [[DBG18]] +; DBGINFO-NEXT: tail call void @llvm.dbg.value(metadata i32 [[C]], metadata [[META12:![0-9]+]], metadata !DIExpression()), !dbg [[DBG17]] +; DBGINFO-NEXT: tail call void @llvm.dbg.value(metadata i32 [[D]], metadata [[META13:![0-9]+]], metadata !DIExpression()), !dbg [[DBG18]] ; DBGINFO-NEXT: ret i32 [[D]], !dbg [[DBG19:![0-9]+]] ; +; DIOP-DBGINFO-LABEL: @mul( +; DIOP-DBGINFO-NEXT: tail call void @llvm.dbg.value(metadata i32 [[X:%.*]], metadata [[META9:![0-9]+]], metadata !DIExpression(DIOpArg(0, i32), DIOpConvert(i8))), !dbg [[DBG15:![0-9]+]] +; DIOP-DBGINFO-NEXT: tail call void @llvm.dbg.value(metadata i32 [[Y:%.*]], metadata [[META11:![0-9]+]], metadata !DIExpression(DIOpArg(0, i32), DIOpConvert(i8))), !dbg [[DBG16:![0-9]+]] +; DIOP-DBGINFO-NEXT: [[C:%.*]] = mul i32 [[X]], [[Y]], !dbg [[DBG17:![0-9]+]] +; DIOP-DBGINFO-NEXT: [[D:%.*]] = and i32 [[C]], 255, !dbg [[DBG18:![0-9]+]] +; DIOP-DBGINFO-NEXT: tail call void @llvm.dbg.value(metadata i32 [[C]], metadata [[META12:![0-9]+]], metadata !DIExpression(DIOpArg(0, i32), DIOpConvert(i8))), !dbg [[DBG17]] +; DIOP-DBGINFO-NEXT: tail call void @llvm.dbg.value(metadata i32 [[D]], metadata [[META13:![0-9]+]], metadata !DIExpression(DIOpArg(0, i32))), !dbg [[DBG18]] +; DIOP-DBGINFO-NEXT: ret i32 [[D]], !dbg [[DBG19:![0-9]+]] +; ; Test that when zext is evaluated in different type ; we preserve the debug information in the resulting @@ -43,16 +55,28 @@ define i32 @select1(i1 %cond, i32 %x, i32 %y, i32 %z) { ; CHECK-NEXT: ret i32 [[F]] ; ; DBGINFO-LABEL: @select1( -; DBGINFO-NEXT: call void @llvm.dbg.value(metadata i32 [[X:%.*]], metadata [[META22:![0-9]+]], metadata !DIExpression(DW_OP_LLVM_convert, 32, DW_ATE_unsigned, DW_OP_LLVM_convert, 8, DW_ATE_unsigned, DW_OP_stack_value)), !dbg [[DBG28:![0-9]+]] -; DBGINFO-NEXT: call void @llvm.dbg.value(metadata i32 [[Y:%.*]], metadata [[META23:![0-9]+]], metadata !DIExpression(DW_OP_LLVM_convert, 32, DW_ATE_unsigned, DW_OP_LLVM_convert, 8, DW_ATE_unsigned, DW_OP_stack_value)), !dbg [[DBG29:![0-9]+]] -; DBGINFO-NEXT: call void @llvm.dbg.value(metadata i32 [[Z:%.*]], metadata [[META24:![0-9]+]], metadata !DIExpression(DW_OP_LLVM_convert, 32, DW_ATE_unsigned, DW_OP_LLVM_convert, 8, DW_ATE_unsigned, DW_OP_stack_value)), !dbg [[DBG30:![0-9]+]] +; DBGINFO-NEXT: tail call void @llvm.dbg.value(metadata i32 [[X:%.*]], metadata [[META22:![0-9]+]], metadata !DIExpression(DW_OP_LLVM_convert, 32, DW_ATE_unsigned, DW_OP_LLVM_convert, 8, DW_ATE_unsigned, DW_OP_stack_value)), !dbg [[DBG28:![0-9]+]] +; DBGINFO-NEXT: tail call void @llvm.dbg.value(metadata i32 [[Y:%.*]], metadata [[META23:![0-9]+]], metadata !DIExpression(DW_OP_LLVM_convert, 32, DW_ATE_unsigned, DW_OP_LLVM_convert, 8, DW_ATE_unsigned, DW_OP_stack_value)), !dbg [[DBG29:![0-9]+]] +; DBGINFO-NEXT: tail call void @llvm.dbg.value(metadata i32 [[Z:%.*]], metadata [[META24:![0-9]+]], metadata !DIExpression(DW_OP_LLVM_convert, 32, DW_ATE_unsigned, DW_OP_LLVM_convert, 8, DW_ATE_unsigned, DW_OP_stack_value)), !dbg [[DBG30:![0-9]+]] ; DBGINFO-NEXT: [[D:%.*]] = add i32 [[X]], [[Y]], !dbg [[DBG31:![0-9]+]] -; DBGINFO-NEXT: call void @llvm.dbg.value(metadata !DIArgList(i32 [[X]], i32 [[Y]]), metadata [[META25:![0-9]+]], metadata !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_LLVM_convert, 32, DW_ATE_unsigned, DW_OP_LLVM_convert, 8, DW_ATE_unsigned, DW_OP_LLVM_arg, 1, DW_OP_LLVM_convert, 32, DW_ATE_unsigned, DW_OP_LLVM_convert, 8, DW_ATE_unsigned, DW_OP_plus, DW_OP_stack_value)), !dbg [[DBG31]] +; DBGINFO-NEXT: tail call void @llvm.dbg.value(metadata !DIArgList(i32 [[X]], i32 [[Y]]), metadata [[META25:![0-9]+]], metadata !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_LLVM_convert, 32, DW_ATE_unsigned, DW_OP_LLVM_convert, 8, DW_ATE_unsigned, DW_OP_LLVM_arg, 1, DW_OP_LLVM_convert, 32, DW_ATE_unsigned, DW_OP_LLVM_convert, 8, DW_ATE_unsigned, DW_OP_plus, DW_OP_stack_value)), !dbg [[DBG31]] ; DBGINFO-NEXT: [[E:%.*]] = select i1 [[COND:%.*]], i32 [[Z]], i32 [[D]], !dbg [[DBG32:![0-9]+]] ; DBGINFO-NEXT: [[F:%.*]] = and i32 [[E]], 255, !dbg [[DBG33:![0-9]+]] -; DBGINFO-NEXT: call void @llvm.dbg.value(metadata i32 [[E]], metadata [[META26:![0-9]+]], metadata !DIExpression()), !dbg [[DBG32]] -; DBGINFO-NEXT: call void @llvm.dbg.value(metadata i32 [[F]], metadata [[META27:![0-9]+]], metadata !DIExpression()), !dbg [[DBG33]] +; DBGINFO-NEXT: tail call void @llvm.dbg.value(metadata i32 [[E]], metadata [[META26:![0-9]+]], metadata !DIExpression()), !dbg [[DBG32]] +; DBGINFO-NEXT: tail call void @llvm.dbg.value(metadata i32 [[F]], metadata [[META27:![0-9]+]], metadata !DIExpression()), !dbg [[DBG33]] ; DBGINFO-NEXT: ret i32 [[F]], !dbg [[DBG34:![0-9]+]] +; +; DIOP-DBGINFO-LABEL: @select1( +; DIOP-DBGINFO-NEXT: tail call void @llvm.dbg.value(metadata i32 [[X:%.*]], metadata [[META22:![0-9]+]], metadata !DIExpression(DIOpArg(0, i32), DIOpConvert(i8))), !dbg [[DBG28:![0-9]+]] +; DIOP-DBGINFO-NEXT: tail call void @llvm.dbg.value(metadata i32 [[Y:%.*]], metadata [[META23:![0-9]+]], metadata !DIExpression(DIOpArg(0, i32), DIOpConvert(i8))), !dbg [[DBG29:![0-9]+]] +; DIOP-DBGINFO-NEXT: tail call void @llvm.dbg.value(metadata i32 [[Z:%.*]], metadata [[META24:![0-9]+]], metadata !DIExpression(DIOpArg(0, i32), DIOpConvert(i8))), !dbg [[DBG30:![0-9]+]] +; DIOP-DBGINFO-NEXT: [[D:%.*]] = add i32 [[X]], [[Y]], !dbg [[DBG31:![0-9]+]] +; DIOP-DBGINFO-NEXT: tail call void @llvm.dbg.value(metadata !DIArgList(i32 [[X]], i32 [[Y]]), metadata [[META25:![0-9]+]], metadata !DIExpression(DIOpArg(0, i32), DIOpConvert(i8), DIOpArg(1, i32), DIOpConvert(i8), DIOpAdd())), !dbg [[DBG31]] +; DIOP-DBGINFO-NEXT: [[E:%.*]] = select i1 [[COND:%.*]], i32 [[Z]], i32 [[D]], !dbg [[DBG32:![0-9]+]] +; DIOP-DBGINFO-NEXT: [[F:%.*]] = and i32 [[E]], 255, !dbg [[DBG33:![0-9]+]] +; DIOP-DBGINFO-NEXT: tail call void @llvm.dbg.value(metadata i32 [[E]], metadata [[META26:![0-9]+]], metadata !DIExpression(DIOpArg(0, i32), DIOpConvert(i8))), !dbg [[DBG32]] +; DIOP-DBGINFO-NEXT: tail call void @llvm.dbg.value(metadata i32 [[F]], metadata [[META27:![0-9]+]], metadata !DIExpression(DIOpArg(0, i32))), !dbg [[DBG33]] +; DIOP-DBGINFO-NEXT: ret i32 [[F]], !dbg [[DBG34:![0-9]+]] ; %A = trunc i32 %x to i8 %B = trunc i32 %y to i8 @@ -70,15 +94,26 @@ define i8 @select2(i1 %cond, i8 %x, i8 %y, i8 %z) { ; CHECK-NEXT: ret i8 [[E]] ; ; DBGINFO-LABEL: @select2( -; DBGINFO-NEXT: call void @llvm.dbg.value(metadata i8 [[X:%.*]], metadata [[META37:![0-9]+]], metadata !DIExpression(DW_OP_LLVM_convert, 8, DW_ATE_unsigned, DW_OP_LLVM_convert, 32, DW_ATE_unsigned, DW_OP_stack_value)), !dbg [[DBG43:![0-9]+]] -; DBGINFO-NEXT: call void @llvm.dbg.value(metadata i8 [[Y:%.*]], metadata [[META38:![0-9]+]], metadata !DIExpression(DW_OP_LLVM_convert, 8, DW_ATE_unsigned, DW_OP_LLVM_convert, 32, DW_ATE_unsigned, DW_OP_stack_value)), !dbg [[DBG44:![0-9]+]] -; DBGINFO-NEXT: call void @llvm.dbg.value(metadata i8 [[Z:%.*]], metadata [[META39:![0-9]+]], metadata !DIExpression(DW_OP_LLVM_convert, 8, DW_ATE_unsigned, DW_OP_LLVM_convert, 32, DW_ATE_unsigned, DW_OP_stack_value)), !dbg [[DBG45:![0-9]+]] +; DBGINFO-NEXT: tail call void @llvm.dbg.value(metadata i8 [[X:%.*]], metadata [[META37:![0-9]+]], metadata !DIExpression(DW_OP_LLVM_convert, 8, DW_ATE_unsigned, DW_OP_LLVM_convert, 32, DW_ATE_unsigned, DW_OP_stack_value)), !dbg [[DBG43:![0-9]+]] +; DBGINFO-NEXT: tail call void @llvm.dbg.value(metadata i8 [[Y:%.*]], metadata [[META38:![0-9]+]], metadata !DIExpression(DW_OP_LLVM_convert, 8, DW_ATE_unsigned, DW_OP_LLVM_convert, 32, DW_ATE_unsigned, DW_OP_stack_value)), !dbg [[DBG44:![0-9]+]] +; DBGINFO-NEXT: tail call void @llvm.dbg.value(metadata i8 [[Z:%.*]], metadata [[META39:![0-9]+]], metadata !DIExpression(DW_OP_LLVM_convert, 8, DW_ATE_unsigned, DW_OP_LLVM_convert, 32, DW_ATE_unsigned, DW_OP_stack_value)), !dbg [[DBG45:![0-9]+]] ; DBGINFO-NEXT: [[D:%.*]] = add i8 [[X]], [[Y]], !dbg [[DBG46:![0-9]+]] -; DBGINFO-NEXT: call void @llvm.dbg.value(metadata !DIArgList(i8 [[X]], i8 [[Y]]), metadata [[META40:![0-9]+]], metadata !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_LLVM_convert, 8, DW_ATE_unsigned, DW_OP_LLVM_convert, 32, DW_ATE_unsigned, DW_OP_LLVM_arg, 1, DW_OP_LLVM_convert, 8, DW_ATE_unsigned, DW_OP_LLVM_convert, 32, DW_ATE_unsigned, DW_OP_plus, DW_OP_stack_value)), !dbg [[DBG46]] +; DBGINFO-NEXT: tail call void @llvm.dbg.value(metadata !DIArgList(i8 [[X]], i8 [[Y]]), metadata [[META40:![0-9]+]], metadata !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_LLVM_convert, 8, DW_ATE_unsigned, DW_OP_LLVM_convert, 32, DW_ATE_unsigned, DW_OP_LLVM_arg, 1, DW_OP_LLVM_convert, 8, DW_ATE_unsigned, DW_OP_LLVM_convert, 32, DW_ATE_unsigned, DW_OP_plus, DW_OP_stack_value)), !dbg [[DBG46]] ; DBGINFO-NEXT: [[E:%.*]] = select i1 [[COND:%.*]], i8 [[Z]], i8 [[D]], !dbg [[DBG47:![0-9]+]] -; DBGINFO-NEXT: call void @llvm.dbg.value(metadata i32 poison, metadata [[META41:![0-9]+]], metadata !DIExpression()), !dbg [[DBG47]] -; DBGINFO-NEXT: call void @llvm.dbg.value(metadata i8 [[E]], metadata [[META42:![0-9]+]], metadata !DIExpression()), !dbg [[DBG48:![0-9]+]] +; DBGINFO-NEXT: tail call void @llvm.dbg.value(metadata i32 poison, metadata [[META41:![0-9]+]], metadata !DIExpression()), !dbg [[DBG47]] +; DBGINFO-NEXT: tail call void @llvm.dbg.value(metadata i8 [[E]], metadata [[META42:![0-9]+]], metadata !DIExpression()), !dbg [[DBG48:![0-9]+]] ; DBGINFO-NEXT: ret i8 [[E]], !dbg [[DBG49:![0-9]+]] +; +; DIOP-DBGINFO-LABEL: @select2( +; DIOP-DBGINFO-NEXT: tail call void @llvm.dbg.value(metadata i8 [[X:%.*]], metadata [[META37:![0-9]+]], metadata !DIExpression(DIOpArg(0, i8), DIOpZExt(i32))), !dbg [[DBG43:![0-9]+]] +; DIOP-DBGINFO-NEXT: tail call void @llvm.dbg.value(metadata i8 [[Y:%.*]], metadata [[META38:![0-9]+]], metadata !DIExpression(DIOpArg(0, i8), DIOpZExt(i32))), !dbg [[DBG44:![0-9]+]] +; DIOP-DBGINFO-NEXT: tail call void @llvm.dbg.value(metadata i8 [[Z:%.*]], metadata [[META39:![0-9]+]], metadata !DIExpression(DIOpArg(0, i8), DIOpZExt(i32))), !dbg [[DBG45:![0-9]+]] +; DIOP-DBGINFO-NEXT: [[D:%.*]] = add i8 [[X]], [[Y]], !dbg [[DBG46:![0-9]+]] +; DIOP-DBGINFO-NEXT: tail call void @llvm.dbg.value(metadata !DIArgList(i8 [[X]], i8 [[Y]]), metadata [[META40:![0-9]+]], metadata !DIExpression(DIOpArg(0, i8), DIOpZExt(i32), DIOpArg(1, i8), DIOpZExt(i32), DIOpAdd())), !dbg [[DBG46]] +; DIOP-DBGINFO-NEXT: [[E:%.*]] = select i1 [[COND:%.*]], i8 [[Z]], i8 [[D]], !dbg [[DBG47:![0-9]+]] +; DIOP-DBGINFO-NEXT: tail call void @llvm.dbg.value(metadata i32 poison, metadata [[META41:![0-9]+]], metadata !DIExpression(DIOpArg(0, i32))), !dbg [[DBG47]] +; DIOP-DBGINFO-NEXT: tail call void @llvm.dbg.value(metadata i8 [[E]], metadata [[META42:![0-9]+]], metadata !DIExpression(DIOpArg(0, i8))), !dbg [[DBG48:![0-9]+]] +; DIOP-DBGINFO-NEXT: ret i8 [[E]], !dbg [[DBG49:![0-9]+]] ; %A = zext i8 %x to i32 %B = zext i8 %y to i32 @@ -102,14 +137,25 @@ define i32 @eval_trunc_multi_use_in_one_inst(i32 %x) { ; ; DBGINFO-LABEL: @eval_trunc_multi_use_in_one_inst( ; DBGINFO-NEXT: [[Z:%.*]] = zext i32 [[X:%.*]] to i64, !dbg [[DBG57:![0-9]+]] -; DBGINFO-NEXT: call void @llvm.dbg.value(metadata i64 [[Z]], metadata [[META52:![0-9]+]], metadata !DIExpression()), !dbg [[DBG57]] +; DBGINFO-NEXT: tail call void @llvm.dbg.value(metadata i64 [[Z]], metadata [[META52:![0-9]+]], metadata !DIExpression()), !dbg [[DBG57]] ; DBGINFO-NEXT: [[A:%.*]] = add nuw nsw i64 [[Z]], 15, !dbg [[DBG58:![0-9]+]] -; DBGINFO-NEXT: call void @llvm.dbg.value(metadata i64 [[A]], metadata [[META54:![0-9]+]], metadata !DIExpression()), !dbg [[DBG58]] +; DBGINFO-NEXT: tail call void @llvm.dbg.value(metadata i64 [[A]], metadata [[META54:![0-9]+]], metadata !DIExpression()), !dbg [[DBG58]] ; DBGINFO-NEXT: [[M:%.*]] = mul i64 [[A]], [[A]], !dbg [[DBG59:![0-9]+]] -; DBGINFO-NEXT: call void @llvm.dbg.value(metadata i64 [[M]], metadata [[META55:![0-9]+]], metadata !DIExpression()), !dbg [[DBG59]] +; DBGINFO-NEXT: tail call void @llvm.dbg.value(metadata i64 [[M]], metadata [[META55:![0-9]+]], metadata !DIExpression()), !dbg [[DBG59]] ; DBGINFO-NEXT: [[T:%.*]] = trunc i64 [[M]] to i32, !dbg [[DBG60:![0-9]+]] -; DBGINFO-NEXT: call void @llvm.dbg.value(metadata i32 [[T]], metadata [[META56:![0-9]+]], metadata !DIExpression()), !dbg [[DBG60]] +; DBGINFO-NEXT: tail call void @llvm.dbg.value(metadata i32 [[T]], metadata [[META56:![0-9]+]], metadata !DIExpression()), !dbg [[DBG60]] ; DBGINFO-NEXT: ret i32 [[T]], !dbg [[DBG61:![0-9]+]] +; +; DIOP-DBGINFO-LABEL: @eval_trunc_multi_use_in_one_inst( +; DIOP-DBGINFO-NEXT: [[Z:%.*]] = zext i32 [[X:%.*]] to i64, !dbg [[DBG57:![0-9]+]] +; DIOP-DBGINFO-NEXT: tail call void @llvm.dbg.value(metadata i64 [[Z]], metadata [[META52:![0-9]+]], metadata !DIExpression(DIOpArg(0, i64))), !dbg [[DBG57]] +; DIOP-DBGINFO-NEXT: [[A:%.*]] = add nuw nsw i64 [[Z]], 15, !dbg [[DBG58:![0-9]+]] +; DIOP-DBGINFO-NEXT: tail call void @llvm.dbg.value(metadata i64 [[A]], metadata [[META54:![0-9]+]], metadata !DIExpression(DIOpArg(0, i64))), !dbg [[DBG58]] +; DIOP-DBGINFO-NEXT: [[M:%.*]] = mul i64 [[A]], [[A]], !dbg [[DBG59:![0-9]+]] +; DIOP-DBGINFO-NEXT: tail call void @llvm.dbg.value(metadata i64 [[M]], metadata [[META55:![0-9]+]], metadata !DIExpression(DIOpArg(0, i64))), !dbg [[DBG59]] +; DIOP-DBGINFO-NEXT: [[T:%.*]] = trunc i64 [[M]] to i32, !dbg [[DBG60:![0-9]+]] +; DIOP-DBGINFO-NEXT: tail call void @llvm.dbg.value(metadata i32 [[T]], metadata [[META56:![0-9]+]], metadata !DIExpression(DIOpArg(0, i32))), !dbg [[DBG60]] +; DIOP-DBGINFO-NEXT: ret i32 [[T]], !dbg [[DBG61:![0-9]+]] ; %z = zext i32 %x to i64 %a = add nsw nuw i64 %z, 15 @@ -128,14 +174,25 @@ define i32 @eval_zext_multi_use_in_one_inst(i32 %x) { ; ; DBGINFO-LABEL: @eval_zext_multi_use_in_one_inst( ; DBGINFO-NEXT: [[T:%.*]] = trunc i32 [[X:%.*]] to i16, !dbg [[DBG69:![0-9]+]] -; DBGINFO-NEXT: call void @llvm.dbg.value(metadata i16 [[T]], metadata [[META64:![0-9]+]], metadata !DIExpression()), !dbg [[DBG69]] +; DBGINFO-NEXT: tail call void @llvm.dbg.value(metadata i16 [[T]], metadata [[META64:![0-9]+]], metadata !DIExpression()), !dbg [[DBG69]] ; DBGINFO-NEXT: [[A:%.*]] = and i16 [[T]], 5, !dbg [[DBG70:![0-9]+]] -; DBGINFO-NEXT: call void @llvm.dbg.value(metadata i16 [[A]], metadata [[META66:![0-9]+]], metadata !DIExpression()), !dbg [[DBG70]] +; DBGINFO-NEXT: tail call void @llvm.dbg.value(metadata i16 [[A]], metadata [[META66:![0-9]+]], metadata !DIExpression()), !dbg [[DBG70]] ; DBGINFO-NEXT: [[M:%.*]] = mul nuw nsw i16 [[A]], [[A]], !dbg [[DBG71:![0-9]+]] -; DBGINFO-NEXT: call void @llvm.dbg.value(metadata i16 [[M]], metadata [[META67:![0-9]+]], metadata !DIExpression()), !dbg [[DBG71]] +; DBGINFO-NEXT: tail call void @llvm.dbg.value(metadata i16 [[M]], metadata [[META67:![0-9]+]], metadata !DIExpression()), !dbg [[DBG71]] ; DBGINFO-NEXT: [[R:%.*]] = zext nneg i16 [[M]] to i32, !dbg [[DBG72:![0-9]+]] -; DBGINFO-NEXT: call void @llvm.dbg.value(metadata i32 [[R]], metadata [[META68:![0-9]+]], metadata !DIExpression()), !dbg [[DBG72]] +; DBGINFO-NEXT: tail call void @llvm.dbg.value(metadata i32 [[R]], metadata [[META68:![0-9]+]], metadata !DIExpression()), !dbg [[DBG72]] ; DBGINFO-NEXT: ret i32 [[R]], !dbg [[DBG73:![0-9]+]] +; +; DIOP-DBGINFO-LABEL: @eval_zext_multi_use_in_one_inst( +; DIOP-DBGINFO-NEXT: [[T:%.*]] = trunc i32 [[X:%.*]] to i16, !dbg [[DBG69:![0-9]+]] +; DIOP-DBGINFO-NEXT: tail call void @llvm.dbg.value(metadata i16 [[T]], metadata [[META64:![0-9]+]], metadata !DIExpression(DIOpArg(0, i16))), !dbg [[DBG69]] +; DIOP-DBGINFO-NEXT: [[A:%.*]] = and i16 [[T]], 5, !dbg [[DBG70:![0-9]+]] +; DIOP-DBGINFO-NEXT: tail call void @llvm.dbg.value(metadata i16 [[A]], metadata [[META66:![0-9]+]], metadata !DIExpression(DIOpArg(0, i16))), !dbg [[DBG70]] +; DIOP-DBGINFO-NEXT: [[M:%.*]] = mul nuw nsw i16 [[A]], [[A]], !dbg [[DBG71:![0-9]+]] +; DIOP-DBGINFO-NEXT: tail call void @llvm.dbg.value(metadata i16 [[M]], metadata [[META67:![0-9]+]], metadata !DIExpression(DIOpArg(0, i16))), !dbg [[DBG71]] +; DIOP-DBGINFO-NEXT: [[R:%.*]] = zext nneg i16 [[M]] to i32, !dbg [[DBG72:![0-9]+]] +; DIOP-DBGINFO-NEXT: tail call void @llvm.dbg.value(metadata i32 [[R]], metadata [[META68:![0-9]+]], metadata !DIExpression(DIOpArg(0, i32))), !dbg [[DBG72]] +; DIOP-DBGINFO-NEXT: ret i32 [[R]], !dbg [[DBG73:![0-9]+]] ; %t = trunc i32 %x to i16 %a = and i16 %t, 5 @@ -155,16 +212,29 @@ define i32 @eval_sext_multi_use_in_one_inst(i32 %x) { ; ; DBGINFO-LABEL: @eval_sext_multi_use_in_one_inst( ; DBGINFO-NEXT: [[T:%.*]] = trunc i32 [[X:%.*]] to i16, !dbg [[DBG81:![0-9]+]] -; DBGINFO-NEXT: call void @llvm.dbg.value(metadata i16 [[T]], metadata [[META76:![0-9]+]], metadata !DIExpression()), !dbg [[DBG81]] +; DBGINFO-NEXT: tail call void @llvm.dbg.value(metadata i16 [[T]], metadata [[META76:![0-9]+]], metadata !DIExpression()), !dbg [[DBG81]] ; DBGINFO-NEXT: [[A:%.*]] = and i16 [[T]], 14, !dbg [[DBG82:![0-9]+]] -; DBGINFO-NEXT: call void @llvm.dbg.value(metadata i16 [[A]], metadata [[META77:![0-9]+]], metadata !DIExpression()), !dbg [[DBG82]] +; DBGINFO-NEXT: tail call void @llvm.dbg.value(metadata i16 [[A]], metadata [[META77:![0-9]+]], metadata !DIExpression()), !dbg [[DBG82]] ; DBGINFO-NEXT: [[M:%.*]] = mul nuw nsw i16 [[A]], [[A]], !dbg [[DBG83:![0-9]+]] -; DBGINFO-NEXT: call void @llvm.dbg.value(metadata i16 [[M]], metadata [[META78:![0-9]+]], metadata !DIExpression()), !dbg [[DBG83]] +; DBGINFO-NEXT: tail call void @llvm.dbg.value(metadata i16 [[M]], metadata [[META78:![0-9]+]], metadata !DIExpression()), !dbg [[DBG83]] ; DBGINFO-NEXT: [[O:%.*]] = or disjoint i16 [[M]], -32768, !dbg [[DBG84:![0-9]+]] -; DBGINFO-NEXT: call void @llvm.dbg.value(metadata i16 [[O]], metadata [[META79:![0-9]+]], metadata !DIExpression()), !dbg [[DBG84]] +; DBGINFO-NEXT: tail call void @llvm.dbg.value(metadata i16 [[O]], metadata [[META79:![0-9]+]], metadata !DIExpression()), !dbg [[DBG84]] ; DBGINFO-NEXT: [[R:%.*]] = sext i16 [[O]] to i32, !dbg [[DBG85:![0-9]+]] -; DBGINFO-NEXT: call void @llvm.dbg.value(metadata i32 [[R]], metadata [[META80:![0-9]+]], metadata !DIExpression()), !dbg [[DBG85]] +; DBGINFO-NEXT: tail call void @llvm.dbg.value(metadata i32 [[R]], metadata [[META80:![0-9]+]], metadata !DIExpression()), !dbg [[DBG85]] ; DBGINFO-NEXT: ret i32 [[R]], !dbg [[DBG86:![0-9]+]] +; +; DIOP-DBGINFO-LABEL: @eval_sext_multi_use_in_one_inst( +; DIOP-DBGINFO-NEXT: [[T:%.*]] = trunc i32 [[X:%.*]] to i16, !dbg [[DBG81:![0-9]+]] +; DIOP-DBGINFO-NEXT: tail call void @llvm.dbg.value(metadata i16 [[T]], metadata [[META76:![0-9]+]], metadata !DIExpression(DIOpArg(0, i16))), !dbg [[DBG81]] +; DIOP-DBGINFO-NEXT: [[A:%.*]] = and i16 [[T]], 14, !dbg [[DBG82:![0-9]+]] +; DIOP-DBGINFO-NEXT: tail call void @llvm.dbg.value(metadata i16 [[A]], metadata [[META77:![0-9]+]], metadata !DIExpression(DIOpArg(0, i16))), !dbg [[DBG82]] +; DIOP-DBGINFO-NEXT: [[M:%.*]] = mul nuw nsw i16 [[A]], [[A]], !dbg [[DBG83:![0-9]+]] +; DIOP-DBGINFO-NEXT: tail call void @llvm.dbg.value(metadata i16 [[M]], metadata [[META78:![0-9]+]], metadata !DIExpression(DIOpArg(0, i16))), !dbg [[DBG83]] +; DIOP-DBGINFO-NEXT: [[O:%.*]] = or disjoint i16 [[M]], -32768, !dbg [[DBG84:![0-9]+]] +; DIOP-DBGINFO-NEXT: tail call void @llvm.dbg.value(metadata i16 [[O]], metadata [[META79:![0-9]+]], metadata !DIExpression(DIOpArg(0, i16))), !dbg [[DBG84]] +; DIOP-DBGINFO-NEXT: [[R:%.*]] = sext i16 [[O]] to i32, !dbg [[DBG85:![0-9]+]] +; DIOP-DBGINFO-NEXT: tail call void @llvm.dbg.value(metadata i32 [[R]], metadata [[META80:![0-9]+]], metadata !DIExpression(DIOpArg(0, i32))), !dbg [[DBG85]] +; DIOP-DBGINFO-NEXT: ret i32 [[R]], !dbg [[DBG86:![0-9]+]] ; %t = trunc i32 %x to i16 %a = and i16 %t, 14 @@ -209,13 +279,13 @@ define void @PR36225(i32 %a, i32 %b, i1 %c1, i3 %v1, i3 %v2) { ; DBGINFO-NEXT: entry: ; DBGINFO-NEXT: br label [[WHILE_BODY:%.*]], !dbg [[DBG94:![0-9]+]] ; DBGINFO: while.body: -; DBGINFO-NEXT: call void @llvm.dbg.value(metadata i32 [[B:%.*]], metadata [[META89:![0-9]+]], metadata !DIExpression(DW_OP_constu, 0, DW_OP_eq, DW_OP_stack_value)), !dbg [[DBG95:![0-9]+]] +; DBGINFO-NEXT: tail call void @llvm.dbg.value(metadata i32 [[B:%.*]], metadata [[META89:![0-9]+]], metadata !DIExpression(DW_OP_constu, 0, DW_OP_eq, DW_OP_stack_value)), !dbg [[DBG95:![0-9]+]] ; DBGINFO-NEXT: br i1 [[C1:%.*]], label [[FOR_BODY3_US:%.*]], label [[FOR_BODY3:%.*]], !dbg [[DBG96:![0-9]+]] ; DBGINFO: for.body3.us: ; DBGINFO-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[B]], 0, !dbg [[DBG95]] -; DBGINFO-NEXT: call void @llvm.dbg.value(metadata i1 [[TOBOOL]], metadata [[META89]], metadata !DIExpression()), !dbg [[DBG95]] +; DBGINFO-NEXT: tail call void @llvm.dbg.value(metadata i1 [[TOBOOL]], metadata [[META89]], metadata !DIExpression()), !dbg [[DBG95]] ; DBGINFO-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[TOBOOL]], i8 0, i8 4, !dbg [[DBG97:![0-9]+]] -; DBGINFO-NEXT: call void @llvm.dbg.value(metadata i8 [[SPEC_SELECT]], metadata [[META90:![0-9]+]], metadata !DIExpression()), !dbg [[DBG97]] +; DBGINFO-NEXT: tail call void @llvm.dbg.value(metadata i8 [[SPEC_SELECT]], metadata [[META90:![0-9]+]], metadata !DIExpression()), !dbg [[DBG97]] ; DBGINFO-NEXT: switch i3 [[V1:%.*]], label [[EXIT:%.*]] [ ; DBGINFO-NEXT: i3 0, label [[FOR_END:%.*]] ; DBGINFO-NEXT: i3 -1, label [[FOR_END]] @@ -227,11 +297,11 @@ define void @PR36225(i32 %a, i32 %b, i1 %c1, i3 %v1, i3 %v2) { ; DBGINFO-NEXT: ], !dbg [[DBG99:![0-9]+]] ; DBGINFO: for.end: ; DBGINFO-NEXT: [[H:%.*]] = phi i8 [ [[SPEC_SELECT]], [[FOR_BODY3_US]] ], [ [[SPEC_SELECT]], [[FOR_BODY3_US]] ], [ 0, [[FOR_BODY3]] ], [ 0, [[FOR_BODY3]] ], !dbg [[DBG100:![0-9]+]] -; DBGINFO-NEXT: call void @llvm.dbg.value(metadata i8 [[H]], metadata [[META91:![0-9]+]], metadata !DIExpression()), !dbg [[DBG100]] +; DBGINFO-NEXT: tail call void @llvm.dbg.value(metadata i8 [[H]], metadata [[META91:![0-9]+]], metadata !DIExpression()), !dbg [[DBG100]] ; DBGINFO-NEXT: [[CONV:%.*]] = zext nneg i8 [[H]] to i32, !dbg [[DBG101:![0-9]+]] -; DBGINFO-NEXT: call void @llvm.dbg.value(metadata i32 [[CONV]], metadata [[META92:![0-9]+]], metadata !DIExpression()), !dbg [[DBG101]] +; DBGINFO-NEXT: tail call void @llvm.dbg.value(metadata i32 [[CONV]], metadata [[META92:![0-9]+]], metadata !DIExpression()), !dbg [[DBG101]] ; DBGINFO-NEXT: [[CMP:%.*]] = icmp slt i32 [[CONV]], [[A:%.*]], !dbg [[DBG102:![0-9]+]] -; DBGINFO-NEXT: call void @llvm.dbg.value(metadata i1 [[CMP]], metadata [[META93:![0-9]+]], metadata !DIExpression()), !dbg [[DBG102]] +; DBGINFO-NEXT: tail call void @llvm.dbg.value(metadata i1 [[CMP]], metadata [[META93:![0-9]+]], metadata !DIExpression()), !dbg [[DBG102]] ; DBGINFO-NEXT: br i1 [[CMP]], label [[EXIT]], label [[EXIT2:%.*]], !dbg [[DBG103:![0-9]+]] ; DBGINFO: exit2: ; DBGINFO-NEXT: unreachable, !dbg [[DBG104:![0-9]+]] @@ -277,8 +347,12 @@ define i1 @foo(i1 zeroext %b) { ; CHECK-NEXT: ret i1 [[B:%.*]] ; ; DBGINFO-LABEL: @foo( -; DBGINFO-NEXT: call void @llvm.dbg.value(metadata i1 [[B:%.*]], metadata [[META108:![0-9]+]], metadata !DIExpression(DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 8, DW_ATE_unsigned, DW_OP_stack_value)), !dbg [[DBG109:![0-9]+]] +; DBGINFO-NEXT: tail call void @llvm.dbg.value(metadata i1 [[B:%.*]], metadata [[META108:![0-9]+]], metadata !DIExpression(DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 8, DW_ATE_unsigned, DW_OP_stack_value)), !dbg [[DBG109:![0-9]+]] ; DBGINFO-NEXT: ret i1 [[B]], !dbg [[DBG110:![0-9]+]] +; +; DIOP-DBGINFO-LABEL: @foo( +; DIOP-DBGINFO-NEXT: tail call void @llvm.dbg.value(metadata i1 [[B:%.*]], metadata [[META108:![0-9]+]], metadata !DIExpression(DIOpArg(0, i1), DIOpZExt(i8))), !dbg [[DBG109:![0-9]+]] +; DIOP-DBGINFO-NEXT: ret i1 [[B]], !dbg [[DBG110:![0-9]+]] ; %frombool = zext i1 %b to i8 diff --git a/llvm/test/Transforms/InstCombine/debuginfo-variables.ll b/llvm/test/Transforms/InstCombine/debuginfo-variables.ll index 546433fc6779dd..8ffe5b3305ce7c 100644 --- a/llvm/test/Transforms/InstCombine/debuginfo-variables.ll +++ b/llvm/test/Transforms/InstCombine/debuginfo-variables.ll @@ -1,13 +1,21 @@ ; RUN: opt < %s -passes=debugify,instcombine -S | FileCheck %s ; RUN: opt < %s -passes=debugify,instcombine -S --try-experimental-debuginfo-iterators | FileCheck %s +; RUN: opt < %s -passes=debugify,instcombine --debugify-diop-diexprs --experimental-debuginfo-iterators=true -S | FileCheck %s --check-prefix DIOP-DBGINFO +; RUN: opt < %s -passes=debugify,instcombine --debugify-diop-diexprs --experimental-debuginfo-iterators=false -S | FileCheck %s --check-prefix DIOP-DBGINFO + declare void @escape32(i32) define i64 @test_sext_zext(i16 %A) { ; CHECK-LABEL: @test_sext_zext( ; CHECK-NEXT: [[C2:%.*]] = zext i16 %A to i64 -; CHECK-NEXT: call void @llvm.dbg.value(metadata i64 [[C2]], {{.*}}, metadata !DIExpression()) -; CHECK-NEXT: call void @llvm.dbg.value(metadata i64 [[C2]], {{.*}}, metadata !DIExpression()) +; CHECK-NEXT: tail call void @llvm.dbg.value(metadata i64 [[C2]], {{.*}}, metadata !DIExpression()) +; CHECK-NEXT: tail call void @llvm.dbg.value(metadata i64 [[C2]], {{.*}}, metadata !DIExpression()) + +; DIOP-DBGINFO-LABEL: @test_sext_zext( +; DIOP-DBGINFO-NEXT: [[C2:%.*]] = zext i16 %A to i64 +; DIOP-DBGINFO-NEXT: tail call void @llvm.dbg.value(metadata i64 [[C2]], {{.*}}, metadata !DIExpression(DIOpArg(0, i64), DIOpConvert(i32))) +; DIOP-DBGINFO-NEXT: tail call void @llvm.dbg.value(metadata i64 [[C2]], {{.*}}, metadata !DIExpression(DIOpArg(0, i64))) %c1 = zext i16 %A to i32 %c2 = sext i32 %c1 to i64 ret i64 %c2 @@ -16,11 +24,19 @@ define i64 @test_sext_zext(i16 %A) { define i64 @test_used_sext_zext(i16 %A) { ; CHECK-LABEL: @test_used_sext_zext( ; CHECK-NEXT: [[C1:%.*]] = zext i16 %A to i32 -; CHECK-NEXT: call void @llvm.dbg.value(metadata i32 [[C1]], {{.*}}, metadata !DIExpression()) +; CHECK-NEXT: tail call void @llvm.dbg.value(metadata i32 [[C1]], {{.*}}, metadata !DIExpression()) ; CHECK-NEXT: [[C2:%.*]] = zext i16 %A to i64 -; CHECK-NEXT: call void @llvm.dbg.value(metadata i64 [[C2]], {{.*}}, metadata !DIExpression()) +; CHECK-NEXT: tail call void @llvm.dbg.value(metadata i64 [[C2]], {{.*}}, metadata !DIExpression()) ; CHECK-NEXT: call void @escape32(i32 %c1) ; CHECK-NEXT: ret i64 %c2 + +; DIOP-DBGINFO-LABEL: @test_used_sext_zext( +; DIOP-DBGINFO-NEXT: [[C1:%.*]] = zext i16 %A to i32 +; DIOP-DBGINFO-NEXT: tail call void @llvm.dbg.value(metadata i32 [[C1]], {{.*}}, metadata !DIExpression(DIOpArg(0, i32))) +; DIOP-DBGINFO-NEXT: [[C2:%.*]] = zext i16 %A to i64 +; DIOP-DBGINFO-NEXT: tail call void @llvm.dbg.value(metadata i64 [[C2]], {{.*}}, metadata !DIExpression(DIOpArg(0, i64))) +; DIOP-DBGINFO-NEXT: call void @escape32(i32 %c1) +; DIOP-DBGINFO-NEXT: ret i64 %c2 %c1 = zext i16 %A to i32 %c2 = sext i32 %c1 to i64 call void @escape32(i32 %c1) @@ -30,9 +46,15 @@ define i64 @test_used_sext_zext(i16 %A) { define i32 @test_cast_select(i1 %cond) { ; CHECK-LABEL: @test_cast_select( ; CHECK-NEXT: [[sel:%.*]] = select i1 %cond, i32 3, i32 5 -; CHECK-NEXT: call void @llvm.dbg.value(metadata i32 [[sel]], {{.*}}, metadata !DIExpression()) -; CHECK-NEXT: call void @llvm.dbg.value(metadata i32 [[sel]], {{.*}}, metadata !DIExpression()) +; CHECK-NEXT: tail call void @llvm.dbg.value(metadata i32 [[sel]], {{.*}}, metadata !DIExpression()) +; CHECK-NEXT: tail call void @llvm.dbg.value(metadata i32 [[sel]], {{.*}}, metadata !DIExpression()) ; CHECK-NEXT: ret i32 [[sel]] + +; DIOP-DBGINFO-LABEL: @test_cast_select( +; DIOP-DBGINFO-NEXT: [[sel:%.*]] = select i1 %cond, i32 3, i32 5 +; DIOP-DBGINFO-NEXT: tail call void @llvm.dbg.value(metadata i32 [[sel]], {{.*}}, metadata !DIExpression(DIOpArg(0, i32), DIOpConvert(i16))) +; DIOP-DBGINFO-NEXT: tail call void @llvm.dbg.value(metadata i32 [[sel]], {{.*}}, metadata !DIExpression(DIOpArg(0, i32))) +; DIOP-DBGINFO-NEXT: ret i32 [[sel]] %sel = select i1 %cond, i16 3, i16 5 %cast = zext i16 %sel to i32 ret i32 %cast @@ -40,84 +62,149 @@ define i32 @test_cast_select(i1 %cond) { define void @test_or(i64 %A) { ; CHECK-LABEL: @test_or( -; CHECK-NEXT: call void @llvm.dbg.value(metadata i64 %A, {{.*}}, metadata !DIExpression(DW_OP_constu, 256, DW_OP_or, DW_OP_stack_value)) +; CHECK-NEXT: tail call void @llvm.dbg.value(metadata i64 %A, {{.*}}, metadata !DIExpression(DW_OP_constu, 256, DW_OP_or, DW_OP_stack_value)) + +; FIXME: No way to represent bitwise or in DIOp-DIExpressions. +; DIOP-DBGINFO-LABEL: @test_or( +; DIOP-DBGINFO-NEXT: tail call void @llvm.dbg.value(metadata i64 poison, {{.*}}, metadata !DIExpression(DIOpArg(0, i64))) %1 = or i64 %A, 256 ret void } define void @test_xor(i32 %A) { ; CHECK-LABEL: @test_xor( -; CHECK-NEXT: call void @llvm.dbg.value(metadata i32 %A, {{.*}}, metadata !DIExpression(DW_OP_constu, 1, DW_OP_xor, DW_OP_stack_value)) +; CHECK-NEXT: tail call void @llvm.dbg.value(metadata i32 %A, {{.*}}, metadata !DIExpression(DW_OP_constu, 1, DW_OP_xor, DW_OP_stack_value)) + +; FIXME: No way to represent bitwise xor in DIOp-DIExpressions. +; DIOP-DBGINFO-LABEL: @test_xor( +; DIOP-DBGINFO-NEXT: tail call void @llvm.dbg.value(metadata i32 poison, {{.*}}, metadata !DIExpression(DIOpArg(0, i32))) %1 = xor i32 %A, 1 ret void } define void @test_sub_neg(i64 %A) { ; CHECK-LABEL: @test_sub_neg( -; CHECK-NEXT: call void @llvm.dbg.value(metadata i64 %A, {{.*}}, metadata !DIExpression(DW_OP_plus_uconst, 1, DW_OP_stack_value)) +; CHECK-NEXT: tail call void @llvm.dbg.value(metadata i64 %A, {{.*}}, metadata !DIExpression(DW_OP_plus_uconst, 1, DW_OP_stack_value)) + +; DIOP-DBGINFO-LABEL: @test_sub_neg( +; DIOP-DBGINFO-NEXT: tail call void @llvm.dbg.value(metadata i64 %A, {{.*}}, metadata !DIExpression(DIOpArg(0, i64), DIOpConstant(i64 -1), DIOpSub())) %1 = sub i64 %A, -1 ret void } define void @test_sub_pos(i64 %A) { ; CHECK-LABEL: @test_sub_pos( -; CHECK-NEXT: call void @llvm.dbg.value(metadata i64 %A, {{.*}}, metadata !DIExpression(DW_OP_constu, 1, DW_OP_minus, DW_OP_stack_value)) +; CHECK-NEXT: tail call void @llvm.dbg.value(metadata i64 %A, {{.*}}, metadata !DIExpression(DW_OP_constu, 1, DW_OP_minus, DW_OP_stack_value)) + +; DIOP-DBGINFO-LABEL: @test_sub_pos( +; DIOP-DBGINFO-NEXT: tail call void @llvm.dbg.value(metadata i64 %A, {{.*}}, metadata !DIExpression(DIOpArg(0, i64), DIOpConstant(i64 1), DIOpSub())) %1 = sub i64 %A, 1 ret void } define void @test_shl(i64 %A) { ; CHECK-LABEL: @test_shl( -; CHECK-NEXT: call void @llvm.dbg.value(metadata i64 %A, {{.*}}, metadata !DIExpression(DW_OP_constu, 7, DW_OP_shl, DW_OP_stack_value)) +; CHECK-NEXT: tail call void @llvm.dbg.value(metadata i64 %A, {{.*}}, metadata !DIExpression(DW_OP_constu, 7, DW_OP_shl, DW_OP_stack_value)) + +; DIOP-DBGINFO-LABEL: @test_shl( +; DIOP-DBGINFO-NEXT: tail call void @llvm.dbg.value(metadata i64 %A, {{.*}}, metadata !DIExpression(DIOpArg(0, i64), DIOpConstant(i64 7), DIOpShl())) %1 = shl i64 %A, 7 ret void } define void @test_lshr(i64 %A) { ; CHECK-LABEL: @test_lshr( -; CHECK-NEXT: call void @llvm.dbg.value(metadata i64 %A, {{.*}}, metadata !DIExpression(DW_OP_constu, 7, DW_OP_shr, DW_OP_stack_value)) +; CHECK-NEXT: tail call void @llvm.dbg.value(metadata i64 %A, {{.*}}, metadata !DIExpression(DW_OP_constu, 7, DW_OP_shr, DW_OP_stack_value)) + +; DIOP-DBGINFO-LABEL: @test_lshr( +; DIOP-DBGINFO-NEXT: tail call void @llvm.dbg.value(metadata i64 %A, {{.*}}, metadata !DIExpression(DIOpArg(0, i64), DIOpConstant(i64 7), DIOpLShr())) %1 = lshr i64 %A, 7 ret void } define void @test_ashr(i64 %A) { ; CHECK-LABEL: @test_ashr( -; CHECK-NEXT: call void @llvm.dbg.value(metadata i64 %A, {{.*}}, metadata !DIExpression(DW_OP_constu, 7, DW_OP_shra, DW_OP_stack_value)) +; CHECK-NEXT: tail call void @llvm.dbg.value(metadata i64 %A, {{.*}}, metadata !DIExpression(DW_OP_constu, 7, DW_OP_shra, DW_OP_stack_value)) + +; DIOP-DBGINFO-LABEL: @test_ashr( +; DIOP-DBGINFO-NEXT: tail call void @llvm.dbg.value(metadata i64 %A, {{.*}}, metadata !DIExpression(DIOpArg(0, i64), DIOpConstant(i64 7), DIOpAShr())) %1 = ashr i64 %A, 7 ret void } define void @test_mul(i64 %A) { ; CHECK-LABEL: @test_mul( -; CHECK-NEXT: call void @llvm.dbg.value(metadata i64 %A, {{.*}}, metadata !DIExpression(DW_OP_constu, 7, DW_OP_mul, DW_OP_stack_value)) +; CHECK-NEXT: tail call void @llvm.dbg.value(metadata i64 %A, {{.*}}, metadata !DIExpression(DW_OP_constu, 7, DW_OP_mul, DW_OP_stack_value)) + +; DIOP-DBGINFO-LABEL: @test_mul( +; DIOP-DBGINFO-NEXT: tail call void @llvm.dbg.value(metadata i64 %A, {{.*}}, metadata !DIExpression(DIOpArg(0, i64), DIOpConstant(i64 7), DIOpMul())) %1 = mul i64 %A, 7 ret void } define void @test_sdiv(i64 %A) { ; CHECK-LABEL: @test_sdiv( -; CHECK-NEXT: call void @llvm.dbg.value(metadata i64 %A, {{.*}}, metadata !DIExpression(DW_OP_constu, 7, DW_OP_div, DW_OP_stack_value)) +; CHECK-NEXT: tail call void @llvm.dbg.value(metadata i64 %A, {{.*}}, metadata !DIExpression(DW_OP_constu, 7, DW_OP_div, DW_OP_stack_value)) + +; DIOP-DBGINFO-LABEL: @test_sdiv( +; DIOP-DBGINFO-NEXT: tail call void @llvm.dbg.value(metadata i64 %A, {{.*}}, metadata !DIExpression(DIOpArg(0, i64), DIOpConstant(i64 7), DIOpDiv())) %1 = sdiv i64 %A, 7 ret void } define void @test_srem(i64 %A) { ; CHECK-LABEL: @test_srem( -; CHECK-NEXT: call void @llvm.dbg.value(metadata i64 %A, {{.*}}, metadata !DIExpression(DW_OP_constu, 7, DW_OP_mod, DW_OP_stack_value)) +; CHECK-NEXT: tail call void @llvm.dbg.value(metadata i64 %A, {{.*}}, metadata !DIExpression(DW_OP_constu, 7, DW_OP_mod, DW_OP_stack_value)) + +; FIXME: No way to represent srem in DIOp-DIExpressions. +; DIOP-DBGINFO-LABEL: @test_srem( +; DIOP-DBGINFO-NEXT: tail call void @llvm.dbg.value(metadata i64 poison, {{.*}}, metadata !DIExpression(DIOpArg(0, i64))) %1 = srem i64 %A, 7 ret void } define void @test_ptrtoint(ptr %P) { ; CHECK-LABEL: @test_ptrtoint -; CHECK-NEXT: call void @llvm.dbg.value(metadata ptr %P, {{.*}}, metadata !DIExpression()) +; CHECK-NEXT: tail call void @llvm.dbg.value(metadata ptr %P, {{.*}}, metadata !DIExpression()) + +; DIOP-DBGINFO-LABEL: @test_ptrtoint +; DIOP-DBGINFO-NEXT: tail call void @llvm.dbg.value(metadata ptr %P, {{.*}}, metadata !DIExpression(DIOpArg(0, ptr), DIOpReinterpret(i64))) %1 = ptrtoint ptr %P to i64 ret void } define void @test_and(i64 %A) { ; CHECK-LABEL: @test_and( -; CHECK-NEXT: call void @llvm.dbg.value(metadata i64 %A, {{.*}}, metadata !DIExpression(DW_OP_constu, 256, DW_OP_and, DW_OP_stack_value)) +; CHECK-NEXT: tail call void @llvm.dbg.value(metadata i64 %A, {{.*}}, metadata !DIExpression(DW_OP_constu, 256, DW_OP_and, DW_OP_stack_value)) + +; FIXME: No way to represent bitwise and in DIOp-DIExpressions. +; DIOP-DBGINFO-LABEL: @test_and( +; DIOP-DBGINFO-NEXT: tail call void @llvm.dbg.value(metadata i64 poison, {{.*}}, metadata !DIExpression(DIOpArg(0, i64))) %1 = and i64 %A, 256 ret void } + +%struct.G = type { [4 x i16] } +%struct.S = type { i32, [10 x %struct.G] } + +define void @test_gep(ptr %A) { +; CHECK-LABEL: @test_gep( +; CHECK-NEXT: tail call void @llvm.dbg.value(metadata ptr %A, {{.*}}, metadata !DIExpression(DW_OP_plus_uconst, 4, DW_OP_stack_value)) + +; DIOP-DBGINFO-LABEL: @test_gep( +; DIOP-DBGINFO-NEXT: tail call void @llvm.dbg.value(metadata ptr %A, {{.*}}, metadata !DIExpression(DIOpArg(0, ptr), DIOpReinterpret(i64), DIOpConstant(i64 4), DIOpAdd(), DIOpReinterpret(ptr))) + %1 = getelementptr %struct.S, ptr %A, i32 0, i32 1 + ret void +} + +define void @test_gep_var_offset(ptr %A, i64 %B, i64 %C) { +; CHECK-LABEL: @test_gep_var_offset( +; CHECK-NEXT: tail call void @llvm.dbg.value(metadata !DIArgList(ptr %A, i64 %B, i64 %C), {{.*}}, metadata !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_LLVM_arg, 1, DW_OP_constu, 8, DW_OP_mul, DW_OP_plus, DW_OP_LLVM_arg, 2, DW_OP_constu, 2, DW_OP_mul, DW_OP_plus, DW_OP_plus_uconst, 88, DW_OP_stack_value)) + +; DIOP-DBGINFO-LABEL: @test_gep_var_offset( +; DIOP-DBGINFO-NEXT: tail call void @llvm.dbg.value(metadata !DIArgList(ptr %A, i64 %B, i64 %C), {{.*}}, metadata !DIExpression(DIOpArg(0, ptr), DIOpReinterpret(i64), DIOpArg(1, i64), DIOpConstant(i64 8), DIOpMul(), DIOpAdd(), DIOpArg(2, i64), DIOpConstant(i64 2), DIOpMul(), DIOpAdd(), DIOpConstant(i64 88), DIOpAdd(), DIOpReinterpret(ptr))) + + ; This is the following expression in infix: i64(A) + B*8 + C*2 + 88 + %1 = getelementptr %struct.S, ptr %A, i32 1, i32 1, i64 %B, i32 0, i64 %C + ret void +} diff --git a/llvm/test/Transforms/InstCombine/heterogeneous-poison-dbg-rauw.ll b/llvm/test/Transforms/InstCombine/heterogeneous-poison-dbg-rauw.ll new file mode 100644 index 00000000000000..a9c6dc97419c00 --- /dev/null +++ b/llvm/test/Transforms/InstCombine/heterogeneous-poison-dbg-rauw.ll @@ -0,0 +1,157 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 +; RUN: opt < %s -passes=instcombine --experimental-debuginfo-iterators=true -S | FileCheck %s +; RUN: opt < %s -passes=instcombine --experimental-debuginfo-iterators=false -S | FileCheck %s + +;; Test replaceAllDbgUsesWith(). InstCombine uses this function when there is a +;; cast of a cast it can eliminate (see InstCombinerImpl::commonCastTransforms). + +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +declare void @use_i32(i32) +declare void @use_i64(i32) +declare void @use_ptr(ptr) +declare void @llvm.dbg.value(metadata, metadata, metadata) #0 + +define void @test_int_ptr_int(i64 %A) !dbg !5 { +; CHECK-LABEL: define void @test_int_ptr_int( +; CHECK-SAME: i64 [[A:%.*]]) !dbg [[DBG5:![0-9]+]] { +; CHECK-NEXT: tail call void @llvm.dbg.value(metadata i64 [[A]], metadata [[META9:![0-9]+]], metadata !DIExpression(DIOpArg(0, i64), DIOpReinterpret(ptr))), !dbg [[DBG12:![0-9]+]] +; CHECK-NEXT: call void @use_i64(i64 [[A]]) +; CHECK-NEXT: ret void +; + %1 = inttoptr i64 %A to ptr + tail call void @llvm.dbg.value(metadata ptr %1, metadata !9, metadata !DIExpression(DIOpArg(0, ptr))), !dbg !12 + %2 = ptrtoint ptr %1 to i64 + call void @use_i64(i64 %2) + ret void +} + +define void @test_ptr_int_ptr(ptr %A) !dbg !13 { +; CHECK-LABEL: define void @test_ptr_int_ptr( +; CHECK-SAME: ptr [[A:%.*]]) !dbg [[DBG13:![0-9]+]] { +; CHECK-NEXT: tail call void @llvm.dbg.value(metadata ptr [[A]], metadata [[META15:![0-9]+]], metadata !DIExpression(DIOpArg(0, ptr), DIOpReinterpret(i64))), !dbg [[DBG17:![0-9]+]] +; CHECK-NEXT: call void @use_ptr(ptr [[A]]) +; CHECK-NEXT: ret void +; + %1 = ptrtoint ptr %A to i64 + tail call void @llvm.dbg.value(metadata i64 %1, metadata !15, metadata !DIExpression(DIOpArg(0, i64))), !dbg !17 + %2 = inttoptr i64 %1 to ptr + call void @use_ptr(ptr %2) + ret void +} + +define void @test_zext_trunc(i32 %A) !dbg !18 { +; CHECK-LABEL: define void @test_zext_trunc( +; CHECK-SAME: i32 [[A:%.*]]) !dbg [[DBG18:![0-9]+]] { +; CHECK-NEXT: tail call void @llvm.dbg.value(metadata i32 [[A]], metadata [[META20:![0-9]+]], metadata !DIExpression(DIOpArg(0, i32), DIOpZExt(i64))), !dbg [[DBG23:![0-9]+]] +; CHECK-NEXT: call void @use_i32(i32 [[A]]) +; CHECK-NEXT: ret void +; + %1 = zext i32 %A to i64 + tail call void @llvm.dbg.value(metadata i64 %1, metadata !20, metadata !DIExpression(DIOpArg(0, i64))), !dbg !23 + %2 = trunc i64 %1 to i32 + call void @use_i32(i32 %2) + ret void +} + +define void @test_trunc_zext(i64 %A) !dbg !24 { +; CHECK-LABEL: define void @test_trunc_zext( +; CHECK-SAME: i64 [[A:%.*]]) !dbg [[DBG24:![0-9]+]] { +; CHECK-NEXT: tail call void @llvm.dbg.value(metadata i64 [[A]], metadata [[META26:![0-9]+]], metadata !DIExpression(DIOpArg(0, i64), DIOpConvert(i32))), !dbg [[DBG28:![0-9]+]] +; CHECK-NEXT: [[TMP1:%.*]] = and i64 [[A]], 4294967295 +; CHECK-NEXT: call void @use_i64(i64 [[TMP1]]) +; CHECK-NEXT: ret void +; + %1 = trunc i64 %A to i32 + tail call void @llvm.dbg.value(metadata i32 %1, metadata !26, metadata !DIExpression(DIOpArg(0, i32))), !dbg !28 + %2 = zext i32 %1 to i64 + call void @use_i64(i64 %2) + ret void +} + +define void @test_sext_trunc(i32 %A) !dbg !29 { +; CHECK-LABEL: define void @test_sext_trunc( +; CHECK-SAME: i32 [[A:%.*]]) !dbg [[DBG29:![0-9]+]] { +; CHECK-NEXT: tail call void @llvm.dbg.value(metadata i32 [[A]], metadata [[META31:![0-9]+]], metadata !DIExpression(DIOpArg(0, i32), DIOpSExt(i64))), !dbg [[DBG33:![0-9]+]] +; CHECK-NEXT: call void @use_i32(i32 [[A]]) +; CHECK-NEXT: ret void +; + %1 = sext i32 %A to i64 + tail call void @llvm.dbg.value(metadata i64 %1, metadata !31, metadata !DIExpression(DIOpArg(0, i64))), !dbg !33 + %2 = trunc i64 %1 to i32 + call void @use_i32(i32 %2) + ret void +} + +!llvm.dbg.cu = !{!0} +!llvm.debugify = !{!2, !3} +!llvm.module.flags = !{!4} + +!0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, producer: "debugify", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug) +!1 = !DIFile(filename: "t.c", directory: "/") +!2 = !{i32 16} +!3 = !{i32 8} +!4 = !{i32 2, !"Debug Info Version", i32 3} +!5 = distinct !DISubprogram(name: "test_int_ptr_int", linkageName: "test_int_ptr_int", scope: null, file: !1, line: 1, type: !6, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !8) +!6 = !DISubroutineType(types: !7) +!7 = !{} +!8 = !{!9, !11} +!9 = !DILocalVariable(name: "1", scope: !5, file: !1, line: 1, type: !10) +!10 = !DIBasicType(name: "ty64", size: 64, encoding: DW_ATE_unsigned) +!11 = !DILocalVariable(name: "2", scope: !5, file: !1, line: 2, type: !10) +!12 = !DILocation(line: 1, column: 1, scope: !5) +!13 = distinct !DISubprogram(name: "test_ptr_int_ptr", linkageName: "test_ptr_int_ptr", scope: null, file: !1, line: 5, type: !6, scopeLine: 5, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !14) +!14 = !{!15, !16} +!15 = !DILocalVariable(name: "3", scope: !13, file: !1, line: 5, type: !10) +!16 = !DILocalVariable(name: "4", scope: !13, file: !1, line: 6, type: !10) +!17 = !DILocation(line: 5, column: 1, scope: !13) +!18 = distinct !DISubprogram(name: "test_zext_trunc", linkageName: "test_zext_trunc", scope: null, file: !1, line: 9, type: !6, scopeLine: 9, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !19) +!19 = !{!20, !21} +!20 = !DILocalVariable(name: "5", scope: !18, file: !1, line: 9, type: !10) +!21 = !DILocalVariable(name: "6", scope: !18, file: !1, line: 10, type: !22) +!22 = !DIBasicType(name: "ty32", size: 32, encoding: DW_ATE_unsigned) +!23 = !DILocation(line: 9, column: 1, scope: !18) +!24 = distinct !DISubprogram(name: "test_trunc_zext", linkageName: "test_trunc_zext", scope: null, file: !1, line: 13, type: !6, scopeLine: 13, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !25) +!25 = !{!26, !27} +!26 = !DILocalVariable(name: "7", scope: !24, file: !1, line: 13, type: !22) +!27 = !DILocalVariable(name: "8", scope: !24, file: !1, line: 14, type: !10) +!28 = !DILocation(line: 13, column: 1, scope: !24) +!29 = distinct !DISubprogram(name: "test_sext_trunc", linkageName: "test_sext_trunc", scope: null, file: !1, line: 13, type: !6, scopeLine: 13, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !30) +!30 = !{!31} +!31 = !DILocalVariable(name: "9", scope: !29, file: !1, line: 13, type: !32) +!32 = !DIBasicType(name: "tys32", size: 32, encoding: DW_ATE_signed) +!33 = !DILocation(line: 13, column: 1, scope: !29) +;. +; CHECK: [[META0:![0-9]+]] = distinct !DICompileUnit(language: DW_LANG_C, file: [[META1:![0-9]+]], producer: "debugify", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug) +; CHECK: [[META1]] = !DIFile(filename: "t.c", directory: {{.*}}) +; CHECK: [[DBG5]] = distinct !DISubprogram(name: "test_int_ptr_int", linkageName: "test_int_ptr_int", scope: null, file: [[META1]], line: 1, type: [[META6:![0-9]+]], scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: [[META0]], retainedNodes: [[META8:![0-9]+]]) +; CHECK: [[META6]] = !DISubroutineType(types: [[META7:![0-9]+]]) +; CHECK: [[META7]] = !{} +; CHECK: [[META8]] = !{[[META9]], [[META11:![0-9]+]]} +; CHECK: [[META9]] = !DILocalVariable(name: "1", scope: [[DBG5]], file: [[META1]], line: 1, type: [[META10:![0-9]+]]) +; CHECK: [[META10]] = !DIBasicType(name: "ty64", size: 64, encoding: DW_ATE_unsigned) +; CHECK: [[META11]] = !DILocalVariable(name: "2", scope: [[DBG5]], file: [[META1]], line: 2, type: [[META10]]) +; CHECK: [[DBG12]] = !DILocation(line: 1, column: 1, scope: [[DBG5]]) +; CHECK: [[DBG13]] = distinct !DISubprogram(name: "test_ptr_int_ptr", linkageName: "test_ptr_int_ptr", scope: null, file: [[META1]], line: 5, type: [[META6]], scopeLine: 5, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: [[META0]], retainedNodes: [[META14:![0-9]+]]) +; CHECK: [[META14]] = !{[[META15]], [[META16:![0-9]+]]} +; CHECK: [[META15]] = !DILocalVariable(name: "3", scope: [[DBG13]], file: [[META1]], line: 5, type: [[META10]]) +; CHECK: [[META16]] = !DILocalVariable(name: "4", scope: [[DBG13]], file: [[META1]], line: 6, type: [[META10]]) +; CHECK: [[DBG17]] = !DILocation(line: 5, column: 1, scope: [[DBG13]]) +; CHECK: [[DBG18]] = distinct !DISubprogram(name: "test_zext_trunc", linkageName: "test_zext_trunc", scope: null, file: [[META1]], line: 9, type: [[META6]], scopeLine: 9, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: [[META0]], retainedNodes: [[META19:![0-9]+]]) +; CHECK: [[META19]] = !{[[META20]], [[META21:![0-9]+]]} +; CHECK: [[META20]] = !DILocalVariable(name: "5", scope: [[DBG18]], file: [[META1]], line: 9, type: [[META10]]) +; CHECK: [[META21]] = !DILocalVariable(name: "6", scope: [[DBG18]], file: [[META1]], line: 10, type: [[META22:![0-9]+]]) +; CHECK: [[META22]] = !DIBasicType(name: "ty32", size: 32, encoding: DW_ATE_unsigned) +; CHECK: [[DBG23]] = !DILocation(line: 9, column: 1, scope: [[DBG18]]) +; CHECK: [[DBG24]] = distinct !DISubprogram(name: "test_trunc_zext", linkageName: "test_trunc_zext", scope: null, file: [[META1]], line: 13, type: [[META6]], scopeLine: 13, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: [[META0]], retainedNodes: [[META25:![0-9]+]]) +; CHECK: [[META25]] = !{[[META26]], [[META27:![0-9]+]]} +; CHECK: [[META26]] = !DILocalVariable(name: "7", scope: [[DBG24]], file: [[META1]], line: 13, type: [[META22]]) +; CHECK: [[META27]] = !DILocalVariable(name: "8", scope: [[DBG24]], file: [[META1]], line: 14, type: [[META10]]) +; CHECK: [[DBG28]] = !DILocation(line: 13, column: 1, scope: [[DBG24]]) +; CHECK: [[DBG29]] = distinct !DISubprogram(name: "test_sext_trunc", linkageName: "test_sext_trunc", scope: null, file: [[META1]], line: 13, type: [[META6]], scopeLine: 13, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: [[META0]], retainedNodes: [[META30:![0-9]+]]) +; CHECK: [[META30]] = !{[[META31]]} +; CHECK: [[META31]] = !DILocalVariable(name: "9", scope: [[DBG29]], file: [[META1]], line: 13, type: [[META32:![0-9]+]]) +; CHECK: [[META32]] = !DIBasicType(name: "tys32", size: 32, encoding: DW_ATE_signed) +; CHECK: [[DBG33]] = !DILocation(line: 13, column: 1, scope: [[DBG29]]) +;. diff --git a/llvm/test/Transforms/InstCombine/heterogeneous-poison-lower-dbg-declare.ll b/llvm/test/Transforms/InstCombine/heterogeneous-poison-lower-dbg-declare.ll new file mode 100644 index 00000000000000..ddcf2e0f06ae2e --- /dev/null +++ b/llvm/test/Transforms/InstCombine/heterogeneous-poison-lower-dbg-declare.ll @@ -0,0 +1,62 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 +; RUN: opt -passes='instcombine' -S --experimental-debuginfo-iterators=true < %s | FileCheck %s +; RUN: opt -passes='instcombine' -S --experimental-debuginfo-iterators=false < %s | FileCheck %s + +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +define i32 @foo() !dbg !5 { +; CHECK-LABEL: define i32 @foo( +; CHECK-SAME: ) !dbg [[DBG5:![0-9]+]] { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[VAR:%.*]] = alloca i32, align 4 +; CHECK-NEXT: tail call void @llvm.dbg.value(metadata i32 42, metadata [[META11:![0-9]+]], metadata !DIExpression(DIOpArg(0, i32))), !dbg [[DBG12:![0-9]+]] +; CHECK-NEXT: store i32 42, ptr [[VAR]], align 4 +; CHECK-NEXT: tail call void @llvm.dbg.value(metadata ptr [[VAR]], metadata [[META11]], metadata !DIExpression(DIOpArg(0, ptr), DIOpDeref(i32))), !dbg [[DBG12]] +; CHECK-NEXT: call void @escape(ptr nonnull [[VAR]]) +; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[VAR]], align 4 +; CHECK-NEXT: tail call void @llvm.dbg.value(metadata i32 [[TMP0]], metadata [[META11]], metadata !DIExpression(DIOpArg(0, i32))), !dbg [[DBG12]] +; CHECK-NEXT: ret i32 [[TMP0]] +; +entry: + %var = alloca i32, align 4 + tail call void @llvm.dbg.declare(metadata ptr %var, metadata !11, metadata !DIExpression(DIOpArg(0, ptr), DIOpDeref(i32))), !dbg !12 + store i32 42, ptr %var, align 4 + call void @escape(ptr %var) + %0 = load i32, ptr %var, align 4 + ret i32 %0 +} + +declare void @llvm.dbg.declare(metadata, metadata, metadata) + +declare void @escape(ptr) + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!2, !3} +!llvm.ident = !{!4} + +!0 = distinct !DICompileUnit(language: DW_LANG_C11, file: !1, producer: "clang 19.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None) +!1 = !DIFile(filename: "t.c", directory: "/") +!2 = !{i32 7, !"Dwarf Version", i32 5} +!3 = !{i32 2, !"Debug Info Version", i32 3} +!4 = !{!"clang 19.0.0"} +!5 = distinct !DISubprogram(name: "main", scope: !6, file: !6, line: 4, type: !7, scopeLine: 4, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !10) +!6 = !DIFile(filename: "t.cpp", directory: "/") +!7 = !DISubroutineType(types: !8) +!8 = !{!9} +!9 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!10 = !{!11} +!11 = !DILocalVariable(name: "var", scope: !5, file: !6, line: 5, type: !9) +!12 = !DILocation(line: 1, column: 1, scope: !5) +;. +; CHECK: [[META0:![0-9]+]] = distinct !DICompileUnit(language: DW_LANG_C11, file: [[META1:![0-9]+]], producer: "clang 19.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None) +; CHECK: [[META1]] = !DIFile(filename: "t.c", directory: {{.*}}) +; CHECK: [[DBG5]] = distinct !DISubprogram(name: "main", scope: [[META6:![0-9]+]], file: [[META6]], line: 4, type: [[META7:![0-9]+]], scopeLine: 4, spFlags: DISPFlagDefinition, unit: [[META0]], retainedNodes: [[META10:![0-9]+]]) +; CHECK: [[META6]] = !DIFile(filename: "t.cpp", directory: {{.*}}) +; CHECK: [[META7]] = !DISubroutineType(types: [[META8:![0-9]+]]) +; CHECK: [[META8]] = !{[[META9:![0-9]+]]} +; CHECK: [[META9]] = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +; CHECK: [[META10]] = !{[[META11]]} +; CHECK: [[META11]] = !DILocalVariable(name: "var", scope: [[DBG5]], file: [[META6]], line: 5, type: [[META9]]) +; CHECK: [[DBG12]] = !DILocation(line: 0, scope: [[DBG5]]) +;. diff --git a/llvm/test/Transforms/SROA/heterogeneous-poison.ll b/llvm/test/Transforms/SROA/heterogeneous-poison.ll new file mode 100644 index 00000000000000..f83c7f2c178b65 --- /dev/null +++ b/llvm/test/Transforms/SROA/heterogeneous-poison.ll @@ -0,0 +1,206 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 +; RUN: opt -passes='sroa' -S --experimental-debuginfo-iterators=true < %s | FileCheck %s +; RUN: opt -passes='sroa' -S --experimental-debuginfo-iterators=false < %s | FileCheck %s + +source_filename = "test/Transforms/SROA/heterogeneous-poison.ll" +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128" + +%struct.pair = type { i32, i32 } + +define i32 @t1() !dbg !9 { +; CHECK-LABEL: define i32 @t1( +; CHECK-SAME: ) !dbg [[DBG9:![0-9]+]] { +; CHECK-NEXT: tail call void @llvm.dbg.value(metadata i32 2, metadata [[META13:![0-9]+]], metadata !DIExpression(DIOpArg(0, i32))), !dbg [[DBG15:![0-9]+]] +; CHECK-NEXT: ret i32 2 +; + %local = alloca i32, align 4 + tail call void @llvm.dbg.declare(metadata ptr %local, metadata !13, metadata !DIExpression(DIOpArg(0, ptr addrspace(5)), DIOpDeref(i32))), !dbg !15 + store i32 2, ptr %local, align 4 + %read = load i32, ptr %local, align 4 + ret i32 %read +} + +define i32 @t2(i1 %cond) !dbg !16 { +; CHECK-LABEL: define i32 @t2( +; CHECK-SAME: i1 [[COND:%.*]]) !dbg [[DBG16:![0-9]+]] { +; CHECK-NEXT: br i1 [[COND]], label [[THEN:%.*]], label [[ELSE:%.*]] +; CHECK: then: +; CHECK-NEXT: tail call void @llvm.dbg.value(metadata i32 42, metadata [[META17:![0-9]+]], metadata !DIExpression(DIOpArg(0, i32))), !dbg [[DBG18:![0-9]+]] +; CHECK-NEXT: br label [[JOIN:%.*]] +; CHECK: else: +; CHECK-NEXT: tail call void @llvm.dbg.value(metadata i32 2, metadata [[META17]], metadata !DIExpression(DIOpArg(0, i32))), !dbg [[DBG18]] +; CHECK-NEXT: br label [[JOIN]] +; CHECK: join: +; CHECK-NEXT: [[LOCAL_0:%.*]] = phi i32 [ 42, [[THEN]] ], [ 2, [[ELSE]] ] +; CHECK-NEXT: tail call void @llvm.dbg.value(metadata i32 [[LOCAL_0]], metadata [[META17]], metadata !DIExpression(DIOpArg(0, i32))), !dbg [[DBG18]] +; CHECK-NEXT: ret i32 [[LOCAL_0]] +; + %local = alloca i32, align 4 + tail call void @llvm.dbg.declare(metadata ptr %local, metadata !17, metadata !DIExpression(DIOpArg(0, ptr addrspace(5)), DIOpDeref(i32))), !dbg !18 + br i1 %cond, label %then, label %else + +then: ; preds = %0 + store i32 42, ptr %local, align 4 + br label %join + +else: ; preds = %0 + store i32 2, ptr %local, align 4 + br label %join + +join: ; preds = %else, %then + %retval = load i32, ptr %local, align 4 + ret i32 %retval +} + +define void @t3() !dbg !19 { +; CHECK-LABEL: define void @t3( +; CHECK-SAME: ) !dbg [[DBG19:![0-9]+]] { +; CHECK-NEXT: tail call void @llvm.dbg.value(metadata i32 42, metadata [[META20:![0-9]+]], metadata !DIExpression(DIOpArg(0, i32), DIOpFragment(0, 32))), !dbg [[DBG25:![0-9]+]] +; CHECK-NEXT: tail call void @llvm.dbg.value(metadata i32 43, metadata [[META20]], metadata !DIExpression(DIOpArg(0, i32), DIOpFragment(32, 32))), !dbg [[DBG25]] +; CHECK-NEXT: ret void +; +; FIXME(diexpression-poison): A rework of SROA debug-info handling which adds a +; bespoke variant of DIExpression::createFragmentExpression (57539418bae45e3c972e8f4f0a88577f807e8697) +; breaks the support we added for newops. +; FIXME(diexpression-poison): #dbg_value(i32 42, [[META20:![0-9]+]], !DIExpression(DIOpArg(0, i32), DIOpFragment(0, 32)), [[META25:![0-9]+]]) +; FIXME(diexpression-poison): #dbg_value(i32 43, [[META20]], !DIExpression(DIOpArg(0, i32), DIOpFragment(32, 32)), [[META25]]) + %local = alloca %struct.pair, align 4 + tail call void @llvm.dbg.declare(metadata ptr %local, metadata !20, metadata !DIExpression(DIOpArg(0, ptr addrspace(5)), DIOpDeref(%struct.pair))), !dbg !25 + %first = getelementptr inbounds %struct.pair, ptr %local, i32 0, i32 0 + store i32 42, ptr %first, align 4 + %second = getelementptr inbounds %struct.pair, ptr %local, i32 0, i32 1 + store i32 43, ptr %second, align 4 + ret void +} + +define i32 @t4() !dbg !26 { +; CHECK-LABEL: define i32 @t4( +; CHECK-SAME: ) !dbg [[DBG26:![0-9]+]] { +; CHECK-NEXT: tail call void @llvm.dbg.value(metadata ptr undef, metadata [[META27:![0-9]+]], metadata !DIExpression(DIOpArg(0, ptr addrspace(5)), DIOpDeref(i32))), !dbg [[DBG28:![0-9]+]] +; CHECK-NEXT: ret i32 42 +; + + ;; FIXME(diexpression-poison): We could probably preserve debug info for the dbg.value here if + ;; necessary. Check that we at least do something sensible with it for now. + %local = alloca i32, align 4 + tail call void @llvm.dbg.value(metadata ptr %local, metadata !27, metadata !DIExpression(DIOpArg(0, ptr addrspace(5)), DIOpDeref(i32))), !dbg !28 + store i32 42, ptr %local, align 4 + %loaded = load i32, ptr %local, align 4 + ret i32 %loaded +} + +define i16 @t5(i1 %cond) !dbg !29 { +; CHECK-LABEL: define i16 @t5( +; CHECK-SAME: i1 [[COND:%.*]]) !dbg [[DBG29:![0-9]+]] { +; CHECK-NEXT: br i1 [[COND]], label [[THEN:%.*]], label [[ELSE:%.*]] +; CHECK: then: +; CHECK-NEXT: tail call void @llvm.dbg.value(metadata i16 42, metadata [[META30:![0-9]+]], metadata !DIExpression(DIOpArg(0, i16), DIOpSExt(i32))), !dbg [[DBG31:![0-9]+]] +; CHECK-NEXT: br label [[JOIN:%.*]] +; CHECK: else: +; CHECK-NEXT: tail call void @llvm.dbg.value(metadata i16 43, metadata [[META30]], metadata !DIExpression(DIOpArg(0, i16), DIOpSExt(i32))), !dbg [[DBG31]] +; CHECK-NEXT: br label [[JOIN]] +; CHECK: join: +; CHECK-NEXT: [[LOCAL_0:%.*]] = phi i16 [ 42, [[THEN]] ], [ 43, [[ELSE]] ] +; CHECK-NEXT: tail call void @llvm.dbg.value(metadata i16 [[LOCAL_0]], metadata [[META30]], metadata !DIExpression(DIOpArg(0, i16), DIOpSExt(i32))), !dbg [[DBG31]] +; CHECK-NEXT: ret i16 [[LOCAL_0]] +; + + ;; Verify that we still convert if the new value doesn't cover the entire size + ;; of the variable !30. This is something that old-style DIExpressions don't + ;; support. + + %local = alloca i16, align 4 + tail call void @llvm.dbg.declare(metadata ptr %local, metadata !30, metadata !DIExpression(DIOpArg(0, ptr addrspace(5)), DIOpDeref(i16), DIOpSExt(i32))), !dbg !31 + br i1 %cond, label %then, label %else + +then: ; preds = %0 + store i16 42, ptr %local, align 4 + br label %join + +else: ; preds = %0 + store i16 43, ptr %local, align 4 + br label %join + +join: ; preds = %else, %then + %loaded = load i16, ptr %local, align 4 + ret i16 %loaded +} + +; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none) +declare void @llvm.dbg.declare(metadata, metadata, metadata) #0 + +; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none) +declare void @llvm.dbg.value(metadata, metadata, metadata) #0 + +attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) } + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!2, !3, !4, !5, !6, !7} +!llvm.ident = !{!8} + +!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang 19", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None) +!1 = !DIFile(filename: "t.cpp", directory: "/") +!2 = !{i32 7, !"Dwarf Version", i32 5} +!3 = !{i32 2, !"Debug Info Version", i32 3} +!4 = !{i32 1, !"wchar_size", i32 4} +!5 = !{i32 8, !"PIC Level", i32 2} +!6 = !{i32 7, !"PIE Level", i32 2} +!7 = !{i32 7, !"uwtable", i32 2} +!8 = !{!"clang 19"} +!9 = distinct !DISubprogram(name: "t1", linkageName: "t1", scope: !1, file: !1, line: 7, type: !10, scopeLine: 7, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !12) +!10 = !DISubroutineType(types: !11) +!11 = !{null} +!12 = !{!13} +!13 = !DILocalVariable(name: "local", scope: !9, file: !1, line: 8, type: !14) +!14 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!15 = !DILocation(line: 8, column: 3, scope: !9) +!16 = distinct !DISubprogram(name: "t2", linkageName: "t2", scope: !1, file: !1, line: 7, type: !10, scopeLine: 7, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !12) +!17 = !DILocalVariable(name: "local", scope: !16, file: !1, line: 1, type: !14) +!18 = !DILocation(line: 1, column: 1, scope: !16) +!19 = distinct !DISubprogram(name: "t3", linkageName: "t3", scope: !1, file: !1, line: 7, type: !10, scopeLine: 7, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !12) +!20 = !DILocalVariable(name: "local", scope: !19, file: !1, line: 1, type: !21) +!21 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "pair", file: !1, line: 2, size: 64, flags: DIFlagTypePassByValue, elements: !22, identifier: "pair") +!22 = !{!23, !24} +!23 = !DIDerivedType(tag: DW_TAG_member, name: "s1", scope: !21, file: !1, line: 3, baseType: !14, size: 32) +!24 = !DIDerivedType(tag: DW_TAG_member, name: "s2", scope: !21, file: !1, line: 4, baseType: !14, size: 32, offset: 32) +!25 = !DILocation(line: 1, column: 1, scope: !19) +!26 = distinct !DISubprogram(name: "t4", linkageName: "t4", scope: !1, file: !1, line: 7, type: !10, scopeLine: 7, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !12) +!27 = !DILocalVariable(name: "local", scope: !26, file: !1, line: 1, type: !14) +!28 = !DILocation(line: 1, column: 1, scope: !26) +!29 = distinct !DISubprogram(name: "t5", linkageName: "t5", scope: !1, file: !1, line: 7, type: !10, scopeLine: 7, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !12) +!30 = !DILocalVariable(name: "local_i16", scope: !29, file: !1, line: 1, type: !14) +!31 = !DILocation(line: 1, column: 1, scope: !29) + +; FIXME(diexpression-poison): [[META20]] = !DILocalVariable(name: "local", scope: [[DBG19]], file: [[META1]], line: 1, type: [[META21:![0-9]+]]) +; FIXME(diexpression-poison): [[META21]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "pair", file: [[META1]], line: 2, size: 64, flags: DIFlagTypePassByValue, elements: [[META22:![0-9]+]], identifier: "pair") +; FIXME(diexpression-poison): [[META22]] = !{[[META23:![0-9]+]], [[META24:![0-9]+]]} +; FIXME(diexpression-poison): [[META23]] = !DIDerivedType(tag: DW_TAG_member, name: "s1", scope: [[META21]], file: [[META1]], line: 3, baseType: [[META14]], size: 32) +; FIXME(diexpression-poison): [[META24]] = !DIDerivedType(tag: DW_TAG_member, name: "s2", scope: [[META21]], file: [[META1]], line: 4, baseType: [[META14]], size: 32, offset: 32) +; FIXME(diexpression-poison): [[META25]] = !DILocation(line: 0, scope: [[DBG19]]) +;. +; CHECK: [[META0:![0-9]+]] = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: [[META1:![0-9]+]], producer: "clang 19", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None) +; CHECK: [[META1]] = !DIFile(filename: "t.cpp", directory: {{.*}}) +; CHECK: [[DBG9]] = distinct !DISubprogram(name: "t1", linkageName: "t1", scope: [[META1]], file: [[META1]], line: 7, type: [[META10:![0-9]+]], scopeLine: 7, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: [[META0]], retainedNodes: [[META12:![0-9]+]]) +; CHECK: [[META10]] = !DISubroutineType(types: [[META11:![0-9]+]]) +; CHECK: [[META11]] = !{null} +; CHECK: [[META12]] = !{[[META13]]} +; CHECK: [[META13]] = !DILocalVariable(name: "local", scope: [[DBG9]], file: [[META1]], line: 8, type: [[META14:![0-9]+]]) +; CHECK: [[META14]] = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +; CHECK: [[DBG15]] = !DILocation(line: 0, scope: [[DBG9]]) +; CHECK: [[DBG16]] = distinct !DISubprogram(name: "t2", linkageName: "t2", scope: [[META1]], file: [[META1]], line: 7, type: [[META10]], scopeLine: 7, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: [[META0]], retainedNodes: [[META12]]) +; CHECK: [[META17]] = !DILocalVariable(name: "local", scope: [[DBG16]], file: [[META1]], line: 1, type: [[META14]]) +; CHECK: [[DBG18]] = !DILocation(line: 0, scope: [[DBG16]]) +; CHECK: [[DBG19]] = distinct !DISubprogram(name: "t3", linkageName: "t3", scope: [[META1]], file: [[META1]], line: 7, type: [[META10]], scopeLine: 7, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: [[META0]], retainedNodes: [[META12]]) +; CHECK: [[META20]] = !DILocalVariable(name: "local", scope: [[DBG19]], file: [[META1]], line: 1, type: [[META21:![0-9]+]]) +; CHECK: [[META21]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "pair", file: [[META1]], line: 2, size: 64, flags: DIFlagTypePassByValue, elements: [[META22:![0-9]+]], identifier: "pair") +; CHECK: [[META22]] = !{[[META23:![0-9]+]], [[META24:![0-9]+]]} +; CHECK: [[META23]] = !DIDerivedType(tag: DW_TAG_member, name: "s1", scope: [[META21]], file: [[META1]], line: 3, baseType: [[META14]], size: 32) +; CHECK: [[META24]] = !DIDerivedType(tag: DW_TAG_member, name: "s2", scope: [[META21]], file: [[META1]], line: 4, baseType: [[META14]], size: 32, offset: 32) +; CHECK: [[DBG25]] = !DILocation(line: 0, scope: [[DBG19]]) +; CHECK: [[DBG26]] = distinct !DISubprogram(name: "t4", linkageName: "t4", scope: [[META1]], file: [[META1]], line: 7, type: [[META10]], scopeLine: 7, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: [[META0]], retainedNodes: [[META12]]) +; CHECK: [[META27]] = !DILocalVariable(name: "local", scope: [[DBG26]], file: [[META1]], line: 1, type: [[META14]]) +; CHECK: [[DBG28]] = !DILocation(line: 1, column: 1, scope: [[DBG26]]) +; CHECK: [[DBG29]] = distinct !DISubprogram(name: "t5", linkageName: "t5", scope: [[META1]], file: [[META1]], line: 7, type: [[META10]], scopeLine: 7, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: [[META0]], retainedNodes: [[META12]]) +; CHECK: [[META30]] = !DILocalVariable(name: "local_i16", scope: [[DBG29]], file: [[META1]], line: 1, type: [[META14]]) +; CHECK: [[DBG31]] = !DILocation(line: 0, scope: [[DBG29]]) +;. diff --git a/llvm/unittests/AsmParser/AsmParserTest.cpp b/llvm/unittests/AsmParser/AsmParserTest.cpp index 77dba5bfd4cae8..0569488efd2f8c 100644 --- a/llvm/unittests/AsmParser/AsmParserTest.cpp +++ b/llvm/unittests/AsmParser/AsmParserTest.cpp @@ -11,6 +11,7 @@ #include "llvm/AsmParser/SlotMapping.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DataLayout.h" +#include "llvm/IR/DebugInfoMetadata.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" #include "llvm/Support/Error.h" @@ -411,4 +412,51 @@ TEST(AsmParserTest, InvalidDataLayoutStringCallback) { EXPECT_EQ(Mod2->getDataLayout(), FixedDL); } +TEST(AsmParserTest, DIExpressionBodyAtBeginningWithSlotMappingParsing) { + LLVMContext Ctx; + SMDiagnostic Error; + StringRef Source = ""; + SlotMapping Mapping; + auto Mod = parseAssemblyString(Source, Error, Ctx, &Mapping); + ASSERT_TRUE(Mod != nullptr); + auto &M = *Mod; + unsigned Read; + + ASSERT_EQ(Mapping.MetadataNodes.size(), 0u); + + DIExpression *Expr; + + Expr = parseDIExpressionBodyAtBeginning("()", Read, Error, M, &Mapping); + ASSERT_TRUE(Expr); + ASSERT_EQ(Expr->getNumElements(), 0u); + + Expr = parseDIExpressionBodyAtBeginning("(0)", Read, Error, M, &Mapping); + ASSERT_TRUE(Expr); + ASSERT_EQ(Expr->getNumElements(), 1u); + + Expr = parseDIExpressionBodyAtBeginning("(DW_OP_LLVM_fragment, 0, 1)", Read, + Error, M, &Mapping); + ASSERT_TRUE(Expr); + ASSERT_EQ(Expr->getNumElements(), 3u); + + Expr = parseDIExpressionBodyAtBeginning( + "(DW_OP_LLVM_fragment, 0, 1) trailing source", Read, Error, M, &Mapping); + ASSERT_TRUE(Expr); + ASSERT_EQ(Expr->getNumElements(), 3u); + ASSERT_EQ(Read, StringRef("(DW_OP_LLVM_fragment, 0, 1) ").size()); + + Error = {}; + Expr = parseDIExpressionBodyAtBeginning("i32", Read, Error, M, &Mapping); + ASSERT_FALSE(Expr); + ASSERT_EQ(Error.getMessage(), "expected '(' here"); + + Error = {}; + Expr = parseDIExpressionBodyAtBeginning( + "!DIExpression(DW_OP_LLVM_fragment, 0, 1)", Read, Error, M, &Mapping); + ASSERT_FALSE(Expr); + ASSERT_EQ(Error.getMessage(), "expected '(' here"); + + ASSERT_EQ(Mapping.MetadataNodes.size(), 0u); +} + } // end anonymous namespace diff --git a/llvm/unittests/rocm-gdb-symbols/AsmParserTest.cpp b/llvm/unittests/rocm-gdb-symbols/AsmParserTest.cpp index b743b57ad5cf85..f22356b1c19920 100644 --- a/llvm/unittests/rocm-gdb-symbols/AsmParserTest.cpp +++ b/llvm/unittests/rocm-gdb-symbols/AsmParserTest.cpp @@ -81,6 +81,28 @@ TEST_F(DIExprAsmParserTest, Constant) { {DIOp::Constant(ConstantFP::get(Context, APFloat(2.0f)))})); } +TEST_F(DIExprAsmParserTest, Convert) { + parseNamedDIExpr(R"(!named = !{!DIExpr(DIOpConvert(ptr addrspace(5)))})"); + ASSERT_EQ(SmallVector(Expr->builder().range()), + SmallVector( + {DIOp::Convert(PointerType::get(Context, 5))})); +} + +TEST_F(DIExprAsmParserTest, ZExt) { + assert(false); + parseNamedDIExpr(R"(!named = !{!DIExpr(DIOpZExt(i32))})"); + ASSERT_EQ( + SmallVector(Expr->builder().range()), + SmallVector({DIOp::ZExt(IntegerType::get(Context, 32))})); +} + +TEST_F(DIExprAsmParserTest, SExt) { + parseNamedDIExpr(R"(!named = !{!DIExpr(DIOpSExt(i32))})"); + ASSERT_EQ( + SmallVector(Expr->builder().range()), + SmallVector({DIOp::SExt(IntegerType::get(Context, 32))})); +} + TEST_F(DIExprAsmParserTest, Reinterpret) { parseNamedDIExpr( R"(!named = !{!DIExpr(DIOpReinterpret(i32 addrspace(5)*))})"); @@ -161,10 +183,16 @@ TEST_F(DIExprAsmParserTest, Div) { SmallVector({DIOp::Div()})); } -TEST_F(DIExprAsmParserTest, Shr) { - parseNamedDIExpr(R"(!named = !{!DIExpr(DIOpShr())})"); +TEST_F(DIExprAsmParserTest, LShr) { + parseNamedDIExpr(R"(!named = !{!DIExpr(DIOpLShr())})"); ASSERT_EQ(SmallVector(Expr->builder().range()), - SmallVector({DIOp::Shr()})); + SmallVector({DIOp::LShr()})); +} + +TEST_F(DIExprAsmParserTest, AShr) { + parseNamedDIExpr(R"(!named = !{!DIExpr(DIOpAShr())})"); + ASSERT_EQ(SmallVector(Expr->builder().range()), + SmallVector({DIOp::AShr()})); } TEST_F(DIExprAsmParserTest, Shl) { @@ -179,6 +207,12 @@ TEST_F(DIExprAsmParserTest, PushLane) { SmallVector({DIOp::PushLane(Int32Ty)})); } +TEST_F(DIExprAsmParserTest, Fragment) { + parseNamedDIExpr(R"(!named = !{!DIExpr(DIOpFragment(0, 1))})"); + ASSERT_EQ(SmallVector(Expr->builder().range()), + SmallVector({DIOp::Fragment(0, 1)})); +} + TEST_F(DIExprAsmParserTest, MultipleOps) { parseNamedDIExpr(R"(!named = !{!DIExpr( DIOpArg(0, i8), @@ -196,4 +230,209 @@ TEST_F(DIExprAsmParserTest, MultipleOps) { DIOp::Reinterpret(PointerType::get(Int8Ty, 1))})); } +class DIExpressionAsmParserTest : public testing::Test { +protected: + LLVMContext Context; + Type *Int64Ty = Type::getInt64Ty(Context); + Type *Int32Ty = Type::getInt32Ty(Context); + Type *Int16Ty = Type::getInt16Ty(Context); + Type *Int8Ty = Type::getInt8Ty(Context); + Type *FloatTy = Type::getFloatTy(Context); + std::unique_ptr M; + const DIExpression *Expr; + + void parseNamedDIExpression(const char *IR) { + SMDiagnostic Err; + M = parseAssemblyString(IR, Err, Context); + if (!M) + GTEST_SKIP(); + bool BrokenDebugInfo = false; + bool HardError = verifyModule(*M, &errs(), &BrokenDebugInfo); + if (HardError || BrokenDebugInfo) + GTEST_SKIP(); + const NamedMDNode *N = M->getNamedMetadata("named"); + if (!N || N->getNumOperands() != 1u || + !isa(N->getOperand(0))) + GTEST_SKIP(); + Expr = cast(N->getOperand(0)); + } +}; + +TEST_F(DIExpressionAsmParserTest, Referrer) { + parseNamedDIExpression(R"(!named = !{!DIExpression(DIOpReferrer(i32))})"); + ASSERT_TRUE(Expr->holdsNewElements()); + ASSERT_EQ(SmallVector(*Expr->getNewElementsRef()), + SmallVector({DIOp::Referrer(Int32Ty)})); +} + +TEST_F(DIExpressionAsmParserTest, Arg) { + parseNamedDIExpression(R"(!named = !{!DIExpression(DIOpArg(3, float))})"); + ASSERT_TRUE(Expr->holdsNewElements()); + ASSERT_EQ(SmallVector(*Expr->getNewElementsRef()), + SmallVector({DIOp::Arg(3, FloatTy)})); +} + +TEST_F(DIExpressionAsmParserTest, TypeObject) { + parseNamedDIExpression(R"(!named = !{!DIExpression(DIOpTypeObject(i32))})"); + ASSERT_TRUE(Expr->holdsNewElements()); + ASSERT_EQ(SmallVector(*Expr->getNewElementsRef()), + SmallVector({DIOp::TypeObject(Int32Ty)})); +} + +TEST_F(DIExpressionAsmParserTest, Constant) { + parseNamedDIExpression( + R"(!named = !{!DIExpression(DIOpConstant(float 2.0))})"); + ASSERT_TRUE(Expr->holdsNewElements()); + DIExprBuilder Builder{Context, *Expr->getNewElementsRef()}; + ASSERT_EQ(SmallVector(Builder.range()), + SmallVector( + {DIOp::Constant(ConstantFP::get(Context, APFloat(2.0f)))})); +} + +TEST_F(DIExpressionAsmParserTest, Reinterpret) { + parseNamedDIExpression( + R"(!named = !{!DIExpression(DIOpReinterpret(i32 addrspace(5)*))})"); + ASSERT_TRUE(Expr->holdsNewElements()); + ASSERT_EQ(SmallVector(*Expr->getNewElementsRef()), + SmallVector( + {DIOp::Reinterpret(PointerType::get(Context, 5))})); +} + +TEST_F(DIExpressionAsmParserTest, BitOffset) { + parseNamedDIExpression(R"(!named = !{!DIExpression(DIOpBitOffset(i32))})"); + ASSERT_TRUE(Expr->holdsNewElements()); + ASSERT_EQ(SmallVector(*Expr->getNewElementsRef()), + SmallVector({DIOp::BitOffset(Int32Ty)})); +} + +TEST_F(DIExpressionAsmParserTest, ByteOffset) { + parseNamedDIExpression(R"(!named = !{!DIExpression(DIOpByteOffset(i32))})"); + ASSERT_TRUE(Expr->holdsNewElements()); + ASSERT_EQ(SmallVector(*Expr->getNewElementsRef()), + SmallVector({DIOp::ByteOffset(Int32Ty)})); +} + +TEST_F(DIExpressionAsmParserTest, Composite) { + parseNamedDIExpression(R"(!named = !{!DIExpression(DIOpComposite(2, i8))})"); + ASSERT_TRUE(Expr->holdsNewElements()); + ASSERT_EQ(SmallVector(*Expr->getNewElementsRef()), + SmallVector({DIOp::Composite(2, Int8Ty)})); +} + +TEST_F(DIExpressionAsmParserTest, Extend) { + parseNamedDIExpression(R"(!named = !{!DIExpression(DIOpExtend(2))})"); + ASSERT_TRUE(Expr->holdsNewElements()); + ASSERT_EQ(SmallVector(*Expr->getNewElementsRef()), + SmallVector({DIOp::Extend(2)})); +} + +TEST_F(DIExpressionAsmParserTest, Select) { + parseNamedDIExpression(R"(!named = !{!DIExpression(DIOpSelect())})"); + ASSERT_TRUE(Expr->holdsNewElements()); + ASSERT_EQ(SmallVector(*Expr->getNewElementsRef()), + SmallVector({DIOp::Select()})); +} + +TEST_F(DIExpressionAsmParserTest, AddrOf) { + parseNamedDIExpression(R"(!named = !{!DIExpression(DIOpAddrOf(7))})"); + ASSERT_TRUE(Expr->holdsNewElements()); + ASSERT_EQ(SmallVector(*Expr->getNewElementsRef()), + SmallVector({DIOp::AddrOf(7)})); +} + +TEST_F(DIExpressionAsmParserTest, Deref) { + parseNamedDIExpression(R"(!named = !{!DIExpression(DIOpDeref(i32))})"); + ASSERT_TRUE(Expr->holdsNewElements()); + ASSERT_EQ(SmallVector(*Expr->getNewElementsRef()), + SmallVector({DIOp::Deref(Int32Ty)})); +} + +TEST_F(DIExpressionAsmParserTest, Read) { + parseNamedDIExpression(R"(!named = !{!DIExpression(DIOpRead())})"); + ASSERT_TRUE(Expr->holdsNewElements()); + ASSERT_EQ(SmallVector(*Expr->getNewElementsRef()), + SmallVector({DIOp::Read()})); +} + +TEST_F(DIExpressionAsmParserTest, Add) { + parseNamedDIExpression(R"(!named = !{!DIExpression(DIOpAdd())})"); + ASSERT_TRUE(Expr->holdsNewElements()); + ASSERT_EQ(SmallVector(*Expr->getNewElementsRef()), + SmallVector({DIOp::Add()})); +} + +TEST_F(DIExpressionAsmParserTest, Sub) { + parseNamedDIExpression(R"(!named = !{!DIExpression(DIOpSub())})"); + ASSERT_TRUE(Expr->holdsNewElements()); + ASSERT_EQ(SmallVector(*Expr->getNewElementsRef()), + SmallVector({DIOp::Sub()})); +} + +TEST_F(DIExpressionAsmParserTest, Mul) { + parseNamedDIExpression(R"(!named = !{!DIExpression(DIOpMul())})"); + ASSERT_TRUE(Expr->holdsNewElements()); + ASSERT_EQ(SmallVector(*Expr->getNewElementsRef()), + SmallVector({DIOp::Mul()})); +} + +TEST_F(DIExpressionAsmParserTest, Div) { + parseNamedDIExpression(R"(!named = !{!DIExpression(DIOpDiv())})"); + ASSERT_TRUE(Expr->holdsNewElements()); + ASSERT_EQ(SmallVector(*Expr->getNewElementsRef()), + SmallVector({DIOp::Div()})); +} + +TEST_F(DIExpressionAsmParserTest, LShr) { + parseNamedDIExpression(R"(!named = !{!DIExpression(DIOpLShr())})"); + ASSERT_TRUE(Expr->holdsNewElements()); + ASSERT_EQ(SmallVector(*Expr->getNewElementsRef()), + SmallVector({DIOp::LShr()})); +} + +TEST_F(DIExpressionAsmParserTest, AShr) { + parseNamedDIExpression(R"(!named = !{!DIExpression(DIOpAShr())})"); + ASSERT_TRUE(Expr->holdsNewElements()); + ASSERT_EQ(SmallVector(*Expr->getNewElementsRef()), + SmallVector({DIOp::AShr()})); +} + +TEST_F(DIExpressionAsmParserTest, Shl) { + parseNamedDIExpression(R"(!named = !{!DIExpression(DIOpShl())})"); + ASSERT_TRUE(Expr->holdsNewElements()); + ASSERT_EQ(SmallVector(*Expr->getNewElementsRef()), + SmallVector({DIOp::Shl()})); +} + +TEST_F(DIExpressionAsmParserTest, PushLane) { + parseNamedDIExpression(R"(!named = !{!DIExpression(DIOpPushLane(i32))})"); + ASSERT_TRUE(Expr->holdsNewElements()); + ASSERT_EQ(SmallVector(*Expr->getNewElementsRef()), + SmallVector({DIOp::PushLane(Int32Ty)})); +} + +TEST_F(DIExpressionAsmParserTest, Fragment) { + parseNamedDIExpression(R"(!named = !{!DIExpression(DIOpFragment(0, 1))})"); + ASSERT_TRUE(Expr->holdsNewElements()); + ASSERT_EQ(SmallVector(*Expr->getNewElementsRef()), + SmallVector({DIOp::Fragment(0, 1)})); +} + +TEST_F(DIExpressionAsmParserTest, MultipleOps) { + parseNamedDIExpression(R"(!named = !{!DIExpression( + DIOpArg(0, i8), + DIOpArg(1, i8), + DIOpAdd(), + DIOpArg(2, i8), + DIOpComposite(2, i16), + DIOpReinterpret(i8 addrspace(1)*) + )} +)"); + ASSERT_TRUE(Expr->holdsNewElements()); + ASSERT_EQ(SmallVector(*Expr->getNewElementsRef()), + SmallVector( + {DIOp::Arg(0, Int8Ty), DIOp::Arg(1, Int8Ty), DIOp::Add(), + DIOp::Arg(2, Int8Ty), DIOp::Composite(2, Int16Ty), + DIOp::Reinterpret(PointerType::get(Int8Ty, 1))})); +} + } // end namespace diff --git a/llvm/unittests/rocm-gdb-symbols/AsmWriterTest.cpp b/llvm/unittests/rocm-gdb-symbols/AsmWriterTest.cpp index bec953a2ed9be7..c71b4991bad39f 100644 --- a/llvm/unittests/rocm-gdb-symbols/AsmWriterTest.cpp +++ b/llvm/unittests/rocm-gdb-symbols/AsmWriterTest.cpp @@ -66,6 +66,16 @@ TEST_F(DIExprAsmWriterTest, Convert) { EXPECT_EQ("!DIExpr(DIOpConvert(i64))", OS.str()); } +TEST_F(DIExprAsmWriterTest, ZExt) { + Builder.append(Int64Ty).intoExpr()->print(OS); + EXPECT_EQ("!DIExpr(DIOpZExt(i64))", OS.str()); +} + +TEST_F(DIExprAsmWriterTest, SExt) { + Builder.append(Int64Ty).intoExpr()->print(OS); + EXPECT_EQ("!DIExpr(DIOpSExt(i64))", OS.str()); +} + TEST_F(DIExprAsmWriterTest, Reinterpret) { Builder.append(Int64Ty).intoExpr()->print(OS); EXPECT_EQ("!DIExpr(DIOpReinterpret(i64))", OS.str()); @@ -131,9 +141,14 @@ TEST_F(DIExprAsmWriterTest, Div) { EXPECT_EQ("!DIExpr(DIOpDiv())", OS.str()); } -TEST_F(DIExprAsmWriterTest, Shr) { - Builder.append().intoExpr()->print(OS); - EXPECT_EQ("!DIExpr(DIOpShr())", OS.str()); +TEST_F(DIExprAsmWriterTest, LShr) { + Builder.append().intoExpr()->print(OS); + EXPECT_EQ("!DIExpr(DIOpLShr())", OS.str()); +} + +TEST_F(DIExprAsmWriterTest, AShr) { + Builder.append().intoExpr()->print(OS); + EXPECT_EQ("!DIExpr(DIOpAShr())", OS.str()); } TEST_F(DIExprAsmWriterTest, Shl) { @@ -156,4 +171,146 @@ TEST_F(DIExprAsmWriterTest, MultipleOps) { OS.str()); } +class DIExpressionAsmWriterTest : public testing::Test { +public: + DIExpressionAsmWriterTest() : Builder(Context), OS(S) {} + +protected: + LLVMContext Context; + Type *Int32Ty = Type::getInt32Ty(Context); + Type *Int64Ty = Type::getInt64Ty(Context); + DIExprBuilder Builder; + std::string S; + raw_string_ostream OS; +}; + +TEST_F(DIExpressionAsmWriterTest, Empty) { + DIExpression *Expr = Builder.intoExpression(); + EXPECT_FALSE(Expr->isValid()); +} + +TEST_F(DIExpressionAsmWriterTest, Referrer) { + Builder.append(Int64Ty).intoExpression()->print(OS); + EXPECT_EQ("!DIExpression(DIOpReferrer(i64))", OS.str()); +} + +TEST_F(DIExpressionAsmWriterTest, Arg) { + Builder.append(1, Int64Ty).intoExpression()->print(OS); + EXPECT_EQ("!DIExpression(DIOpArg(1, i64))", OS.str()); +} + +TEST_F(DIExpressionAsmWriterTest, TypeObject) { + Builder.append(Int64Ty).intoExpression()->print(OS); + EXPECT_EQ("!DIExpression(DIOpTypeObject(i64))", OS.str()); +} + +TEST_F(DIExpressionAsmWriterTest, Constant) { + Builder + .append( + static_cast(ConstantInt::get(Int32Ty, 1))) + .intoExpression() + ->print(OS); + EXPECT_EQ("!DIExpression(DIOpConstant(i32 1))", OS.str()); +} + +TEST_F(DIExpressionAsmWriterTest, Convert) { + Builder.append(Int64Ty).intoExpression()->print(OS); + EXPECT_EQ("!DIExpression(DIOpConvert(i64))", OS.str()); +} + +TEST_F(DIExpressionAsmWriterTest, Reinterpret) { + Builder.append(Int64Ty).intoExpression()->print(OS); + EXPECT_EQ("!DIExpression(DIOpReinterpret(i64))", OS.str()); +} + +TEST_F(DIExpressionAsmWriterTest, BitOffset) { + Builder.append(Int64Ty).intoExpression()->print(OS); + EXPECT_EQ("!DIExpression(DIOpBitOffset(i64))", OS.str()); +} + +TEST_F(DIExpressionAsmWriterTest, ByteOffset) { + Builder.append(Int64Ty).intoExpression()->print(OS); + EXPECT_EQ("!DIExpression(DIOpByteOffset(i64))", OS.str()); +} + +TEST_F(DIExpressionAsmWriterTest, Composite) { + Builder.append(2, Int64Ty).intoExpression()->print(OS); + EXPECT_EQ("!DIExpression(DIOpComposite(2, i64))", OS.str()); +} + +TEST_F(DIExpressionAsmWriterTest, Extend) { + Builder.append(2).intoExpression()->print(OS); + EXPECT_EQ("!DIExpression(DIOpExtend(2))", OS.str()); +} + +TEST_F(DIExpressionAsmWriterTest, Select) { + Builder.append().intoExpression()->print(OS); + EXPECT_EQ("!DIExpression(DIOpSelect())", OS.str()); +} + +TEST_F(DIExpressionAsmWriterTest, AddrOf) { + Builder.append(5).intoExpression()->print(OS); + EXPECT_EQ("!DIExpression(DIOpAddrOf(5))", OS.str()); +} + +TEST_F(DIExpressionAsmWriterTest, Deref) { + Builder.append(Int64Ty).intoExpression()->print(OS); + EXPECT_EQ("!DIExpression(DIOpDeref(i64))", OS.str()); +} + +TEST_F(DIExpressionAsmWriterTest, Read) { + Builder.append().intoExpression()->print(OS); + EXPECT_EQ("!DIExpression(DIOpRead())", OS.str()); +} + +TEST_F(DIExpressionAsmWriterTest, Add) { + Builder.append().intoExpression()->print(OS); + EXPECT_EQ("!DIExpression(DIOpAdd())", OS.str()); +} + +TEST_F(DIExpressionAsmWriterTest, Sub) { + Builder.append().intoExpression()->print(OS); + EXPECT_EQ("!DIExpression(DIOpSub())", OS.str()); +} + +TEST_F(DIExpressionAsmWriterTest, Mul) { + Builder.append().intoExpression()->print(OS); + EXPECT_EQ("!DIExpression(DIOpMul())", OS.str()); +} + +TEST_F(DIExpressionAsmWriterTest, Div) { + Builder.append().intoExpression()->print(OS); + EXPECT_EQ("!DIExpression(DIOpDiv())", OS.str()); +} + +TEST_F(DIExpressionAsmWriterTest, LShr) { + Builder.append().intoExpression()->print(OS); + EXPECT_EQ("!DIExpression(DIOpLShr())", OS.str()); +} + +TEST_F(DIExpressionAsmWriterTest, AShr) { + Builder.append().intoExpression()->print(OS); + EXPECT_EQ("!DIExpression(DIOpAShr())", OS.str()); +} + +TEST_F(DIExpressionAsmWriterTest, Shl) { + Builder.append().intoExpression()->print(OS); + EXPECT_EQ("!DIExpression(DIOpShl())", OS.str()); +} + +TEST_F(DIExpressionAsmWriterTest, PushLane) { + Builder.append(Int64Ty).intoExpression()->print(OS); + EXPECT_EQ("!DIExpression(DIOpPushLane(i64))", OS.str()); +} + +TEST_F(DIExpressionAsmWriterTest, MultipleOps) { + Builder.insert(Builder.begin(), + {DIOp::Variant{std::in_place_type, Int32Ty}, + DIOp::Variant{std::in_place_type, Int64Ty}, + DIOp::Variant{std::in_place_type}}); + Builder.intoExpression()->print(OS); + EXPECT_EQ("!DIExpression(DIOpReferrer(i32), DIOpReferrer(i64), DIOpAdd())", + OS.str()); +} + } // namespace diff --git a/llvm/unittests/rocm-gdb-symbols/MetadataTest.cpp b/llvm/unittests/rocm-gdb-symbols/MetadataTest.cpp index 57820bc7ea8a41..288b298a02733a 100644 --- a/llvm/unittests/rocm-gdb-symbols/MetadataTest.cpp +++ b/llvm/unittests/rocm-gdb-symbols/MetadataTest.cpp @@ -243,6 +243,241 @@ TEST_F(DIExprBuilderTest, Visitor) { visit(makeVisitor([](DIOp::Referrer) {}, [](auto) { FAIL(); }), Op); } +typedef MetadataTest DIExprBuilderDIExpressionTest; + +TEST_F(DIExprBuilderDIExpressionTest, EmptyBuilderGet) { + DIExprBuilder BuilderA(Context); + DIExpression *ExprA = BuilderA.intoExpression(); + EXPECT_NE(ExprA, nullptr); + DIExprBuilder BuilderB(Context); + EXPECT_EQ(ExprA, BuilderB.intoExpression()); +} + +TEST_F(DIExprBuilderDIExpressionTest, NonUnique) { + DIExprBuilder BuilderA(Context); + BuilderA.append(Int32Ty); + DIExprBuilder BuilderB(Context); + BuilderB.append(Int32Ty); + EXPECT_EQ(BuilderA.intoExpression(), BuilderB.intoExpression()); +} + +TEST_F(DIExprBuilderDIExpressionTest, Unique) { + DIExprBuilder BuilderA(Context); + BuilderA.append(Int32Ty); + DIExprBuilder BuilderB(Context); + BuilderB.append(Int64Ty); + EXPECT_NE(BuilderA.intoExpression(), BuilderB.intoExpression()); +} + +TEST_F(DIExprBuilderDIExpressionTest, EquivalentAppends) { + DIExprBuilder BuilderA(Context); + BuilderA.append(Int64Ty); + DIExprBuilder BuilderB(Context); + BuilderB.append(DIOp::Referrer(Int64Ty)); + DIExprBuilder BuilderC(Context); + BuilderC.append(DIOp::Variant(DIOp::Referrer(Int64Ty))); + DIExpression *ExprA = BuilderA.intoExpression(); + DIExpression *ExprB = BuilderB.intoExpression(); + DIExpression *ExprC = BuilderC.intoExpression(); + EXPECT_EQ(ExprA, ExprB); + EXPECT_EQ(ExprB, ExprC); +} + +TEST_F(DIExprBuilderDIExpressionTest, Iterator) { + DIExprBuilder Builder(Context); + DIOp::Variant Op(std::in_place_type, Int32Ty); + DIExpression *Expr = Builder.append(Op).intoExpression(); + DIExprBuilder ViewBuilder{*Expr}; + DIExprBuilder::Iterator I = ViewBuilder.begin(); + DIExprBuilder::Iterator E = ViewBuilder.end(); + EXPECT_EQ(*I, Op); + ++I; + EXPECT_EQ(I, E); + --I; + EXPECT_EQ(*I, Op); + I++; + EXPECT_EQ(I, E); + I--; + EXPECT_EQ(*I, Op); +} + +TEST_F(DIExprBuilderDIExpressionTest, IteratorRange) { + SmallVector Ops{ + DIOp::Variant{std::in_place_type, 0, Int64Ty}, + DIOp::Variant{std::in_place_type, 1, Int64Ty}, + DIOp::Variant{std::in_place_type}}; + DIExprBuilder Builder(Context); + for (auto &Op : Ops) + Builder.append(Op); + DIExpression *Expr = Builder.intoExpression(); + SmallVector Ops2; + ASSERT_TRUE(Expr->holdsNewElements()); + auto NewElements = Expr->getNewElementsRef(); + ASSERT_TRUE(NewElements); + for (auto &Op : *NewElements) + Ops2.push_back(Op); + EXPECT_EQ(Ops, Ops2); +} + +TEST_F(DIExprBuilderDIExpressionTest, InitializerList) { + std::initializer_list IL{ + DIOp::Variant{std::in_place_type, 0, Int64Ty}, + DIOp::Variant{std::in_place_type, 1, Int64Ty}, + DIOp::Variant{std::in_place_type}}; + DIExprBuilder BuilderA(Context, IL); + + DIExprBuilder BuilderB(Context); + BuilderB.insert(BuilderB.begin(), IL); + + DIExprBuilder BuilderC(Context); + for (auto &Op : IL) + BuilderC.append(Op); + + DIExpression *ExprA = BuilderA.intoExpression(); + DIExpression *ExprB = BuilderB.intoExpression(); + DIExpression *ExprC = BuilderC.intoExpression(); + + EXPECT_EQ(ExprA, ExprB); + EXPECT_EQ(ExprB, ExprC); +} + +TEST_F(DIExprBuilderDIExpressionTest, InsertByValue) { + DIOp::Variant V(std::in_place_type); + + { + DIExprBuilder BuilderA(Context); + BuilderA.insert(BuilderA.begin(), V); + DIExprBuilder ExpectedA(Context, + {DIOp::Variant{std::in_place_type}}); + EXPECT_EQ(BuilderA.intoExpression(), ExpectedA.intoExpression()); + } + + { + DIExprBuilder BuilderB(Context, + {DIOp::Variant{std::in_place_type}, + DIOp::Variant{std::in_place_type}}); + BuilderB.insert(BuilderB.begin() + 1, V); + DIExprBuilder ExpectedB(Context, + {DIOp::Variant{std::in_place_type}, + DIOp::Variant{std::in_place_type}, + DIOp::Variant{std::in_place_type}}); + EXPECT_EQ(BuilderB.intoExpression(), ExpectedB.intoExpression()); + } +} + +TEST_F(DIExprBuilderDIExpressionTest, InsertEmplace) { + { + DIExprBuilder BuilderA(Context); + BuilderA.insert(BuilderA.begin()); + DIExprBuilder ExpectedA(Context, + {DIOp::Variant{std::in_place_type}}); + EXPECT_EQ(BuilderA.intoExpression(), ExpectedA.intoExpression()); + } + + { + DIExprBuilder BuilderB(Context, + {DIOp::Variant{std::in_place_type}, + DIOp::Variant{std::in_place_type}}); + BuilderB.insert(BuilderB.begin() + 1); + DIExprBuilder ExpectedB(Context, + {DIOp::Variant{std::in_place_type}, + DIOp::Variant{std::in_place_type}, + DIOp::Variant{std::in_place_type}}); + EXPECT_EQ(BuilderB.intoExpression(), ExpectedB.intoExpression()); + } +} + +TEST_F(DIExprBuilderDIExpressionTest, InsertRange) { + SmallVector Vs{DIOp::Variant{std::in_place_type}, + DIOp::Variant{std::in_place_type}}; + + { + DIExprBuilder BuilderA(Context); + BuilderA.insert(BuilderA.begin(), Vs); + DIExprBuilder ExpectedA(Context, + {DIOp::Variant{std::in_place_type}, + DIOp::Variant{std::in_place_type}}); + EXPECT_EQ(BuilderA.intoExpression(), ExpectedA.intoExpression()); + } + + { + DIExprBuilder BuilderB(Context, + {DIOp::Variant{std::in_place_type}, + DIOp::Variant{std::in_place_type}}); + BuilderB.insert(BuilderB.begin() + 1, Vs); + DIExprBuilder ExpectedB(Context, + {DIOp::Variant{std::in_place_type}, + DIOp::Variant{std::in_place_type}, + DIOp::Variant{std::in_place_type}, + DIOp::Variant{std::in_place_type}}); + EXPECT_EQ(BuilderB.intoExpression(), ExpectedB.intoExpression()); + } +} + +TEST_F(DIExprBuilderDIExpressionTest, InsertFromTo) { + SmallVector Vs{DIOp::Variant{std::in_place_type}, + DIOp::Variant{std::in_place_type}}; + + { + DIExprBuilder BuilderA(Context); + BuilderA.insert(BuilderA.begin(), Vs.begin(), Vs.end()); + DIExprBuilder ExpectedA(Context, + {DIOp::Variant{std::in_place_type}, + DIOp::Variant{std::in_place_type}}); + EXPECT_EQ(BuilderA.intoExpression(), ExpectedA.intoExpression()); + } + + { + DIExprBuilder BuilderB(Context, + {DIOp::Variant{std::in_place_type}, + DIOp::Variant{std::in_place_type}}); + BuilderB.insert(BuilderB.begin() + 1, Vs.begin(), Vs.end()); + DIExprBuilder ExpectedB(Context, + {DIOp::Variant{std::in_place_type}, + DIOp::Variant{std::in_place_type}, + DIOp::Variant{std::in_place_type}, + DIOp::Variant{std::in_place_type}}); + EXPECT_EQ(BuilderB.intoExpression(), ExpectedB.intoExpression()); + } +} + +TEST_F(DIExprBuilderDIExpressionTest, Erase) { + DIExprBuilder BuilderA( + Context, {DIOp::Variant{std::in_place_type, Int64Ty}, + DIOp::Variant{std::in_place_type, 0, Int64Ty}, + DIOp::Variant{std::in_place_type}, + DIOp::Variant{std::in_place_type}}); + ASSERT_TRUE( + std::holds_alternative(*BuilderA.erase(++BuilderA.begin()))); + ASSERT_TRUE( + std::holds_alternative(*BuilderA.erase(BuilderA.begin()))); + auto I = BuilderA.erase(--BuilderA.end()); + ASSERT_EQ(I, BuilderA.end()); +} + +TEST_F(DIExprBuilderDIExpressionTest, Contains) { + DIExprBuilder ExprBuilder0(Context); + EXPECT_EQ(ExprBuilder0.contains(), false); + + DIExprBuilder ExprBuilder1(Context, + {DIOp::Variant{std::in_place_type}}); + EXPECT_EQ(ExprBuilder1.contains(), true); + EXPECT_EQ(ExprBuilder1.contains(), false); + + DIExprBuilder ExprBuilder2(Context, + {DIOp::Variant{std::in_place_type}, + DIOp::Variant{std::in_place_type}, + DIOp::Variant{std::in_place_type}}); + EXPECT_EQ(ExprBuilder2.contains(), true); + EXPECT_EQ(ExprBuilder2.contains(), true); + EXPECT_EQ(ExprBuilder2.contains(), false); +} + +TEST_F(DIExprBuilderDIExpressionTest, Visitor) { + DIOp::Variant Op(std::in_place_type, Int32Ty); + visit(makeVisitor([](DIOp::Referrer) {}, [](auto) { FAIL(); }), Op); +} + typedef MetadataTest DIExprOpsTest; TEST_F(DIExprOpsTest, Referrer) { @@ -278,6 +513,18 @@ TEST_F(DIExprOpsTest, Convert) { ASSERT_EQ(std::get(V).getResultType(), Int64Ty); } +TEST_F(DIExprOpsTest, ZExt) { + DIOp::Variant V{std::in_place_type, Int64Ty}; + ASSERT_TRUE(std::holds_alternative(V)); + ASSERT_EQ(std::get(V).getResultType(), Int64Ty); +} + +TEST_F(DIExprOpsTest, SExt) { + DIOp::Variant V{std::in_place_type, Int64Ty}; + ASSERT_TRUE(std::holds_alternative(V)); + ASSERT_EQ(std::get(V).getResultType(), Int64Ty); +} + TEST_F(DIExprOpsTest, Reinterpret) { DIOp::Variant V{std::in_place_type, Int64Ty}; ASSERT_TRUE(std::holds_alternative(V)); @@ -351,9 +598,14 @@ TEST_F(DIExprOpsTest, Div) { ASSERT_TRUE(std::holds_alternative(V)); } -TEST_F(DIExprOpsTest, Shr) { - DIOp::Variant V{std::in_place_type}; - ASSERT_TRUE(std::holds_alternative(V)); +TEST_F(DIExprOpsTest, LShr) { + DIOp::Variant V{std::in_place_type}; + ASSERT_TRUE(std::holds_alternative(V)); +} + +TEST_F(DIExprOpsTest, AShr) { + DIOp::Variant V{std::in_place_type}; + ASSERT_TRUE(std::holds_alternative(V)); } TEST_F(DIExprOpsTest, Shl) {