Debug Info: Encode let-bindings using DW_TAG_const_type.

This allows the debugger to distinguish constant "let" values from
mutable "var" variables.

rdar://problem/16042546
This commit is contained in:
Adrian Prantl
2019-09-24 16:06:40 -07:00
parent 56edd08fa2
commit ff22da20c3
20 changed files with 168 additions and 125 deletions

View File

@@ -5056,6 +5056,10 @@ bool VarDecl::isSettable(const DeclContext *UseDC,
if (!isLet())
return supportsMutation();
// Debugger expression 'let's are initialized through a side-channel.
if (isDebuggerVar())
return false;
// We have a 'let'; we must be checking settability from a specific
// DeclContext to go on further.
if (UseDC == nullptr)

View File

@@ -168,8 +168,7 @@ public:
void emitVariableDeclaration(IRBuilder &Builder,
ArrayRef<llvm::Value *> Storage,
DebugTypeInfo Ty, const SILDebugScope *DS,
ValueDecl *VarDecl, StringRef Name,
unsigned ArgNo = 0,
ValueDecl *VarDecl, SILDebugVariable VarInfo,
IndirectionKind = DirectValue,
ArtificialKind = RealValue);
void emitDbgIntrinsic(IRBuilder &Builder, llvm::Value *Storage,
@@ -2145,7 +2144,7 @@ void IRGenDebugInfoImpl::emitArtificialFunction(IRBuilder &Builder,
void IRGenDebugInfoImpl::emitVariableDeclaration(
IRBuilder &Builder, ArrayRef<llvm::Value *> Storage, DebugTypeInfo DbgTy,
const SILDebugScope *DS, ValueDecl *VarDecl, StringRef Name, unsigned ArgNo,
const SILDebugScope *DS, ValueDecl *VarDecl, SILDebugVariable VarInfo,
IndirectionKind Indirection, ArtificialKind Artificial) {
assert(DS && "variable has no scope");
@@ -2165,7 +2164,7 @@ void IRGenDebugInfoImpl::emitVariableDeclaration(
// FIXME: this should be the scope of the type's declaration.
// If this is an argument, attach it to the current function scope.
if (ArgNo > 0) {
if (VarInfo.ArgNo > 0) {
while (isa<llvm::DILexicalBlock>(Scope))
Scope = cast<llvm::DILexicalBlock>(Scope)->getScope();
}
@@ -2173,11 +2172,13 @@ void IRGenDebugInfoImpl::emitVariableDeclaration(
llvm::DIFile *Unit = getFile(Scope);
llvm::DIType *DITy = getOrCreateType(DbgTy);
assert(DITy && "could not determine debug type of variable");
if (VarInfo.Constant)
DITy = DBuilder.createQualifiedType(llvm::dwarf::DW_TAG_const_type, DITy);
unsigned Line = Loc.Line;
// Self is always an artificial argument, so are variables without location.
if (!Line || (ArgNo > 0 && Name == IGM.Context.Id_self.str()))
if (!Line || (VarInfo.ArgNo > 0 && VarInfo.Name == IGM.Context.Id_self.str()))
Artificial = ArtificialValue;
llvm::DINode::DIFlags Flags = llvm::DINode::FlagZero;
@@ -2188,10 +2189,11 @@ void IRGenDebugInfoImpl::emitVariableDeclaration(
bool Optimized = false;
// Create the descriptor for the variable.
llvm::DILocalVariable *Var =
(ArgNo > 0) ? DBuilder.createParameterVariable(
Scope, Name, ArgNo, Unit, Line, DITy, Optimized, Flags)
: DBuilder.createAutoVariable(Scope, Name, Unit, Line, DITy,
Optimized, Flags);
(VarInfo.ArgNo > 0)
? DBuilder.createParameterVariable(Scope, VarInfo.Name, VarInfo.ArgNo,
Unit, Line, DITy, Optimized, Flags)
: DBuilder.createAutoVariable(Scope, VarInfo.Name, Unit, Line, DITy,
Optimized, Flags);
// Running variables for the current/previous piece.
bool IsPiece = Storage.size() > 1;
@@ -2275,8 +2277,14 @@ void IRGenDebugInfoImpl::emitGlobalVariableDeclaration(
if (Opts.DebugInfoLevel <= IRGenDebugInfoLevel::LineTables)
return;
llvm::DIType *Ty = getOrCreateType(DbgTy);
if (Ty->isArtificial() || Ty == InternalType || !Loc)
llvm::DIType *DITy = getOrCreateType(DbgTy);
VarDecl *VD = nullptr;
if (Loc)
VD = dyn_cast_or_null<VarDecl>(Loc->getAsASTNode<Decl>());
if (!VD || VD->isLet())
DITy = DBuilder.createQualifiedType(llvm::dwarf::DW_TAG_const_type, DITy);
if (DITy->isArtificial() || DITy == InternalType || !Loc)
// FIXME: Really these should be marked as artificial, but LLVM
// currently has no support for flags to be put on global
// variables. In the mean time, elide these variables, they
@@ -2284,7 +2292,7 @@ void IRGenDebugInfoImpl::emitGlobalVariableDeclaration(
return;
if (InFixedBuffer)
Ty = createFixedValueBufferStruct(Ty);
DITy = createFixedValueBufferStruct(DITy);
auto L = getStartLocation(Loc);
auto File = getOrCreateFile(L.Filename);
@@ -2294,7 +2302,7 @@ void IRGenDebugInfoImpl::emitGlobalVariableDeclaration(
if (!Var)
Expr = DBuilder.createConstantValueExpression(0);
auto *GV = DBuilder.createGlobalVariableExpression(
MainModule, Name, LinkageName, File, L.Line, Ty, IsLocalToUnit, Expr);
MainModule, Name, LinkageName, File, L.Line, DITy, IsLocalToUnit, Expr);
if (Var)
Var->addDebugInfo(GV);
}
@@ -2320,7 +2328,7 @@ void IRGenDebugInfoImpl::emitTypeMetadata(IRGenFunction &IGF,
Metadata->getType(), Size(CI.getTargetInfo().getPointerWidth(0)),
Alignment(CI.getTargetInfo().getPointerAlign(0)));
emitVariableDeclaration(IGF.Builder, Metadata, DbgTy, IGF.getDebugScope(),
nullptr, OS.str().str(), 0,
nullptr, {OS.str().str(), 0, false},
// swift.type is already a pointer type,
// having a shadow copy doesn't add another
// layer of indirection.
@@ -2419,11 +2427,10 @@ void IRGenDebugInfo::emitArtificialFunction(IRBuilder &Builder,
void IRGenDebugInfo::emitVariableDeclaration(
IRBuilder &Builder, ArrayRef<llvm::Value *> Storage, DebugTypeInfo Ty,
const SILDebugScope *DS, ValueDecl *VarDecl, StringRef Name,
unsigned ArgNo, IndirectionKind Indirection,
ArtificialKind Artificial) {
const SILDebugScope *DS, ValueDecl *VarDecl, SILDebugVariable VarInfo,
IndirectionKind Indirection, ArtificialKind Artificial) {
static_cast<IRGenDebugInfoImpl *>(this)->emitVariableDeclaration(
Builder, Storage, Ty, DS, VarDecl, Name, ArgNo, Indirection, Artificial);
Builder, Storage, Ty, DS, VarDecl, VarInfo, Indirection, Artificial);
}
void IRGenDebugInfo::emitDbgIntrinsic(IRBuilder &Builder, llvm::Value *Storage,

View File

@@ -17,6 +17,7 @@
#ifndef SWIFT_IRGEN_DEBUGINFO_H
#define SWIFT_IRGEN_DEBUGINFO_H
#include <swift/SIL/SILInstruction.h>
#include "DebugTypeInfo.h"
#include "IRGenFunction.h"
@@ -133,8 +134,7 @@ public:
void emitVariableDeclaration(IRBuilder &Builder,
ArrayRef<llvm::Value *> Storage,
DebugTypeInfo Ty, const SILDebugScope *DS,
ValueDecl *VarDecl, StringRef Name,
unsigned ArgNo = 0,
ValueDecl *VarDecl, SILDebugVariable VarInfo,
IndirectionKind Indirection = DirectValue,
ArtificialKind Artificial = RealValue);

View File

@@ -761,13 +761,14 @@ public:
/// Unconditionally emit a stack shadow copy of an \c llvm::Value.
llvm::Value *emitShadowCopy(llvm::Value *Storage, const SILDebugScope *Scope,
StringRef Name, unsigned ArgNo, Alignment Align) {
SILDebugVariable VarInfo, Alignment Align) {
if (Align.isZero())
Align = IGM.getPointerAlignment();
auto &Alloca = ShadowStackSlots[{ArgNo, {Scope, Name}}];
unsigned ArgNo = VarInfo.ArgNo;
auto &Alloca = ShadowStackSlots[{ArgNo, {Scope, VarInfo.Name}}];
if (!Alloca.isValid())
Alloca = createAlloca(Storage->getType(), Align, Name+".debug");
Alloca = createAlloca(Storage->getType(), Align, VarInfo.Name + ".debug");
zeroInit(cast<llvm::AllocaInst>(Alloca.getAddress()));
ArtificialLocation AutoRestore(Scope, IGM.DebugInfo.get(), Builder);
@@ -781,7 +782,7 @@ public:
/// shadow copies, we lose the precise lifetime.
llvm::Value *emitShadowCopyIfNeeded(llvm::Value *Storage,
const SILDebugScope *Scope,
StringRef Name, unsigned ArgNo,
SILDebugVariable VarInfo,
bool IsAnonymous,
Alignment Align = Alignment(0)) {
// Never emit shadow copies when optimizing, or if already on the stack.
@@ -792,7 +793,7 @@ public:
return Storage;
// Always emit shadow copies for function arguments.
if (ArgNo == 0)
if (VarInfo.ArgNo == 0)
// Otherwise only if debug value range extension is not feasible.
if (!needsShadowCopy(Storage)) {
// Mark for debug value range extension unless this is a constant, or
@@ -809,22 +810,22 @@ public:
return Storage;
}
return emitShadowCopy(Storage, Scope, Name, ArgNo, Align);
return emitShadowCopy(Storage, Scope, VarInfo, Align);
}
/// Like \c emitShadowCopyIfNeeded() but takes an \c Address instead of an
/// \c llvm::Value.
llvm::Value *emitShadowCopyIfNeeded(Address Storage,
const SILDebugScope *Scope,
StringRef Name, unsigned ArgNo,
SILDebugVariable VarInfo,
bool IsAnonymous) {
return emitShadowCopyIfNeeded(Storage.getAddress(), Scope, Name, ArgNo,
return emitShadowCopyIfNeeded(Storage.getAddress(), Scope, VarInfo,
IsAnonymous, Storage.getAlignment());
}
/// Like \c emitShadowCopyIfNeeded() but takes an exploded value.
void emitShadowCopyIfNeeded(SILValue &SILVal, const SILDebugScope *Scope,
StringRef Name, unsigned ArgNo, bool IsAnonymous,
SILDebugVariable VarInfo, bool IsAnonymous,
llvm::SmallVectorImpl<llvm::Value *> &copy) {
Explosion e = getLoweredExplosion(SILVal);
@@ -840,13 +841,13 @@ public:
auto vals = e.claimAll();
for (auto val : vals)
copy.push_back(
emitShadowCopyIfNeeded(val, Scope, Name, ArgNo, IsAnonymous));
emitShadowCopyIfNeeded(val, Scope, VarInfo, IsAnonymous));
return;
}
SILType Type = SILVal->getType();
auto &LTI = cast<LoadableTypeInfo>(IGM.getTypeInfo(Type));
auto Alloca = LTI.allocateStack(*this, Type, Name+".debug");
auto Alloca = LTI.allocateStack(*this, Type, VarInfo.Name + ".debug");
zeroInit(cast<llvm::AllocaInst>(Alloca.getAddress().getAddress()));
ArtificialLocation AutoRestore(Scope, IGM.DebugInfo.get(), Builder);
LTI.initialize(*this, e, Alloca.getAddress(), false /* isOutlined */);
@@ -867,22 +868,18 @@ public:
/// Emit debug info for a function argument or a local variable.
template <typename StorageType>
void emitDebugVariableDeclaration(StorageType Storage,
DebugTypeInfo Ty,
SILType SILTy,
const SILDebugScope *DS,
VarDecl *VarDecl,
StringRef Name,
unsigned ArgNo = 0,
void emitDebugVariableDeclaration(StorageType Storage, DebugTypeInfo Ty,
SILType SILTy, const SILDebugScope *DS,
VarDecl *VarDecl, SILDebugVariable VarInfo,
IndirectionKind Indirection = DirectValue) {
assert(IGM.DebugInfo && "debug info not enabled");
if (ArgNo) {
if (VarInfo.ArgNo) {
PrologueLocation AutoRestore(IGM.DebugInfo.get(), Builder);
IGM.DebugInfo->emitVariableDeclaration(Builder, Storage, Ty, DS, VarDecl,
Name, ArgNo, Indirection);
VarInfo, Indirection);
} else
IGM.DebugInfo->emitVariableDeclaration(Builder, Storage, Ty, DS, VarDecl,
Name, 0, Indirection);
VarInfo, Indirection);
}
void emitFailBB() {
@@ -3649,17 +3646,16 @@ void IRGenSILFunction::emitErrorResultVar(SILResultInfo ErrorInfo,
auto ErrorResultSlot = getErrorResultSlot(IGM.silConv.getSILType(ErrorInfo));
auto Var = DbgValue->getVarInfo();
assert(Var && "error result without debug info");
auto Storage =
emitShadowCopyIfNeeded(ErrorResultSlot.getAddress(), getDebugScope(),
Var->Name, Var->ArgNo, false);
auto Storage = emitShadowCopyIfNeeded(ErrorResultSlot.getAddress(),
getDebugScope(), *Var, false);
if (!IGM.DebugInfo)
return;
auto DbgTy = DebugTypeInfo::getErrorResult(
ErrorInfo.getType(), ErrorResultSlot->getType(), IGM.getPointerSize(),
IGM.getPointerAlignment());
IGM.DebugInfo->emitVariableDeclaration(
Builder, Storage, DbgTy, getDebugScope(), nullptr, Var->Name, Var->ArgNo,
IndirectValue, ArtificialValue);
IGM.DebugInfo->emitVariableDeclaration(Builder, Storage, DbgTy,
getDebugScope(), nullptr, *Var,
IndirectValue, ArtificialValue);
}
void IRGenSILFunction::visitDebugValueInst(DebugValueInst *i) {
@@ -3680,7 +3676,7 @@ void IRGenSILFunction::visitDebugValueInst(DebugValueInst *i) {
}
bool IsAnonymous = false;
StringRef Name = getVarName(i, IsAnonymous);
VarInfo->Name = getVarName(i, IsAnonymous);
DebugTypeInfo DbgTy;
SILType SILTy = SILVal->getType();
auto RealTy = SILVal->getType().getASTType();
@@ -3688,7 +3684,7 @@ void IRGenSILFunction::visitDebugValueInst(DebugValueInst *i) {
DbgTy = DebugTypeInfo::getLocalVariable(
Decl, RealTy, getTypeInfo(SILVal->getType()));
} else if (i->getFunction()->isBare() &&
!SILTy.hasArchetype() && !Name.empty()) {
!SILTy.hasArchetype() && !VarInfo->Name.empty()) {
// Preliminary support for .sil debug information.
DbgTy = DebugTypeInfo::getFromTypeInfo(RealTy, getTypeInfo(SILTy));
} else
@@ -3696,14 +3692,14 @@ void IRGenSILFunction::visitDebugValueInst(DebugValueInst *i) {
// Put the value into a stack slot at -Onone.
llvm::SmallVector<llvm::Value *, 8> Copy;
emitShadowCopyIfNeeded(SILVal, i->getDebugScope(), Name, VarInfo->ArgNo,
IsAnonymous, Copy);
emitShadowCopyIfNeeded(SILVal, i->getDebugScope(), *VarInfo, IsAnonymous,
Copy);
bindArchetypes(DbgTy.getType());
if (!IGM.DebugInfo)
return;
emitDebugVariableDeclaration(Copy, DbgTy, SILTy, i->getDebugScope(),
i->getDecl(), Name, VarInfo->ArgNo);
i->getDecl(), *VarInfo);
}
void IRGenSILFunction::visitDebugValueAddrInst(DebugValueAddrInst *i) {
@@ -3722,7 +3718,7 @@ void IRGenSILFunction::visitDebugValueAddrInst(DebugValueAddrInst *i) {
assert(VarInfo && "debug_value_addr without debug info");
bool IsAnonymous = false;
bool IsLoadablyByAddress = isa<AllocStackInst>(SILVal);
StringRef Name = getVarName(i, IsAnonymous);
VarInfo->Name = getVarName(i, IsAnonymous);
auto Addr = getLoweredAddress(SILVal).getAddress();
SILType SILTy = SILVal->getType();
auto RealType = SILTy.getASTType();
@@ -3736,9 +3732,8 @@ void IRGenSILFunction::visitDebugValueAddrInst(DebugValueAddrInst *i) {
// Put the value's address into a stack slot at -Onone and emit a debug
// intrinsic.
emitDebugVariableDeclaration(
emitShadowCopyIfNeeded(Addr, i->getDebugScope(), Name, VarInfo->ArgNo,
IsAnonymous),
DbgTy, SILType(), i->getDebugScope(), Decl, Name, VarInfo->ArgNo,
emitShadowCopyIfNeeded(Addr, i->getDebugScope(), *VarInfo, IsAnonymous),
DbgTy, SILType(), i->getDebugScope(), Decl, *VarInfo,
(IsLoadablyByAddress) ? DirectValue : IndirectValue);
}
@@ -4001,7 +3996,7 @@ void IRGenSILFunction::emitDebugInfoForAllocStack(AllocStackInst *i,
return;
bool IsAnonymous = false;
StringRef Name = getVarName(i, IsAnonymous);
VarInfo->Name = getVarName(i, IsAnonymous);
// At this point addr must be an alloca or an undef.
assert(isa<llvm::AllocaInst>(addr) || isa<llvm::UndefValue>(addr) ||
@@ -4012,8 +4007,7 @@ void IRGenSILFunction::emitDebugInfoForAllocStack(AllocStackInst *i,
if (auto *Alloca = dyn_cast<llvm::AllocaInst>(addr))
if (!Alloca->isStaticAlloca()) {
// Store the address of the dynamic alloca on the stack.
addr = emitShadowCopy(addr, DS, Name, VarInfo->ArgNo,
IGM.getPointerAlignment());
addr = emitShadowCopy(addr, DS, *VarInfo, IGM.getPointerAlignment());
Indirection = IndirectValue;
}
@@ -4032,8 +4026,8 @@ void IRGenSILFunction::emitDebugInfoForAllocStack(AllocStackInst *i,
bindArchetypes(DbgTy.getType());
if (IGM.DebugInfo)
emitDebugVariableDeclaration(addr, DbgTy, SILTy, DS, Decl, Name,
VarInfo->ArgNo, Indirection);
emitDebugVariableDeclaration(addr, DbgTy, SILTy, DS, Decl, *VarInfo,
Indirection);
}
void IRGenSILFunction::visitAllocStackInst(swift::AllocStackInst *i) {
@@ -4233,16 +4227,18 @@ void IRGenSILFunction::visitAllocBoxInst(swift::AllocBoxInst *i) {
auto RealType = SILTy.getASTType();
auto DbgTy = DebugTypeInfo::getLocalVariable(Decl, RealType, type);
auto VarInfo = i->getVarInfo();
assert(VarInfo && "debug_value without debug info");
auto Storage = emitShadowCopyIfNeeded(
boxWithAddr.getAddress(), i->getDebugScope(), Name, 0, IsAnonymous);
boxWithAddr.getAddress(), i->getDebugScope(), *VarInfo, IsAnonymous);
if (!IGM.DebugInfo)
return;
IGM.DebugInfo->emitVariableDeclaration(
Builder,
Storage,
DbgTy, i->getDebugScope(), Decl, Name, 0, IndirectValue);
IGM.DebugInfo->emitVariableDeclaration(Builder, Storage, DbgTy,
i->getDebugScope(), Decl, *VarInfo,
IndirectValue);
}
void IRGenSILFunction::visitProjectBoxInst(swift::ProjectBoxInst *i) {

View File

@@ -360,10 +360,13 @@ func testBlocksWithGenerics(hba: HasBlockArray) -> Any {
// CHECK: attributes [[NOUNWIND]] = { nounwind }
// CHECK: ![[SWIFT_NAME_ALIAS_VAR]] = !DILocalVariable(name: "obj", arg: 1, scope: !{{[0-9]+}}, file: !{{[0-9]+}}, line: {{[0-9]+}}, type: ![[SWIFT_NAME_ALIAS_TYPE:[0-9]+]])
// CHECK: ![[LET_SWIFT_NAME_ALIAS_TYPE:[0-9]+]] = !DIDerivedType(tag: DW_TAG_const_type, baseType: ![[SWIFT_NAME_ALIAS_TYPE:[0-9]+]])
// CHECK: ![[SWIFT_NAME_ALIAS_TYPE]] = !DIDerivedType(tag: DW_TAG_typedef, name: "$sSo14SwiftNameAliasaD", scope: !{{[0-9]+}}, file: !{{[0-9]+}}, line: {{[0-9]+}}, baseType: !{{[0-9]+}})
// CHECK: ![[SWIFT_GENERIC_NAME_ALIAS_VAR]] = !DILocalVariable(name: "generic_obj", arg: 1, scope: !{{[0-9]+}}, file: !{{[0-9]+}}, line: {{[0-9]+}}, type: ![[SWIFT_GENERIC_NAME_ALIAS_TYPE:[0-9]+]])
// CHECK: ![[SWIFT_GENERIC_NAME_ALIAS_VAR]] = !DILocalVariable(name: "generic_obj", arg: 1, scope: !{{[0-9]+}}, file: !{{[0-9]+}}, line: {{[0-9]+}}, type: ![[LET_SWIFT_GENERIC_NAME_ALIAS_TYPE:[0-9]+]])
// CHECK: ![[LET_SWIFT_GENERIC_NAME_ALIAS_TYPE:[0-9]+]] = !DIDerivedType(tag: DW_TAG_const_type, baseType: ![[SWIFT_GENERIC_NAME_ALIAS_TYPE:[0-9]+]])
// CHECK: ![[SWIFT_GENERIC_NAME_ALIAS_TYPE]] = !DIDerivedType(tag: DW_TAG_typedef, name: "$sSo21SwiftGenericNameAliasaySo8NSNumberCGD", scope: !{{[0-9]+}}, file: !{{[0-9]+}}, line: {{[0-9]+}}, baseType: !{{[0-9]+}})
// CHECK: ![[SWIFT_CONSTR_GENERIC_NAME_ALIAS_VAR]] = !DILocalVariable(name: "constr_generic_obj", arg: 1, scope: !{{[0-9]+}}, file: !{{[0-9]+}}, line: {{[0-9]+}}, type: ![[SWIFT_CONSTR_GENERIC_NAME_ALIAS_TYPE:[0-9]+]])
// CHECK: ![[SWIFT_CONSTR_GENERIC_NAME_ALIAS_VAR]] = !DILocalVariable(name: "constr_generic_obj", arg: 1, scope: !{{[0-9]+}}, file: !{{[0-9]+}}, line: {{[0-9]+}}, type: ![[LET_SWIFT_CONSTR_GENERIC_NAME_ALIAS_TYPE:[0-9]+]])
// CHECK: ![[LET_SWIFT_CONSTR_GENERIC_NAME_ALIAS_TYPE:[0-9]+]] = !DIDerivedType(tag: DW_TAG_const_type, baseType: ![[SWIFT_CONSTR_GENERIC_NAME_ALIAS_TYPE:[0-9]+]])
// CHECK: ![[SWIFT_CONSTR_GENERIC_NAME_ALIAS_TYPE]] = !DIDerivedType(tag: DW_TAG_typedef, name: "$sSo27SwiftConstrGenericNameAliasaySo8NSNumberCGD", scope: !{{[0-9]+}}, file: !{{[0-9]+}}, line: {{[0-9]+}}, baseType: !{{[0-9]+}})

View File

@@ -16,7 +16,7 @@ extension C {
// CHECK: ![[SELFTY]] = !DIDerivedType(tag: DW_TAG_typedef,
// CHECK-SAME: name: "$s11DynamicSelf1CCXDD",
// CHECK-SAME: baseType: ![[BASE]])
let r = self.init(number: 0)
var r = self.init(number: 0)
return r
}
}

View File

@@ -4,9 +4,15 @@ func markUsed<T>(_ t: T) {}
class C<A> {
// CHECK: ![[A:.*]] = !DICompositeType(tag: DW_TAG_structure_type,{{.*}}identifier: "$sxD"
// CHECK: ![[LET_A:[0-9]+]] = !DIDerivedType(tag: DW_TAG_const_type,
// CHECK-SAME: baseType: ![[A]])
// CHECK: ![[B:[0-9]+]] = !DICompositeType(tag: DW_TAG_structure_type,{{.*}}identifier: "$sqd__D")
// CHECK: !DILocalVariable(name: "x", arg: 1,{{.*}}line: [[@LINE+2]],{{.*}}type: ![[A]]
// CHECK: !DILocalVariable(name: "y", arg: 2,{{.*}}line: [[@LINE+1]],{{.*}}type: ![[B]])
// CHECK: !DILocalVariable(name: "x", arg: 1,{{.*}}line: [[@LINE+6]],
// CHECK-SAME: type: ![[LET_A]]
// CHECK: !DILocalVariable(name: "y", arg: 2,{{.*}}line: [[@LINE+4]],
// CHECK-SAME: type: ![[LET_B:[0-9]+]]
// CHECK: ![[LET_B]] = !DIDerivedType(tag: DW_TAG_const_type,
// CHECK-SAME: baseType: ![[B]])
func foo<B>(_ x: A, y :B) {
markUsed("hello world")
}

View File

@@ -80,7 +80,8 @@ public enum Tuple<P> {
func bar<T>(_ x : Tuple<T>) -> Tuple<T> { return x }
// CHECK: ![[LIST:.*]] = !DICompositeType({{.*}}identifier: "$s4enum4ListOyxGD"
// CHECK: !DILocalVariable(name: "self", arg: 1, {{.*}} line: [[@LINE+4]], type: ![[LIST]], flags: DIFlagArtificial)
// CHECK-DAG: ![[LET_LIST:.*]] = !DIDerivedType(tag: DW_TAG_const_type, baseType: ![[LIST]])
// CHECK-DAG: !DILocalVariable(name: "self", arg: 1, {{.*}} line: [[@LINE+4]], type: ![[LET_LIST]], flags: DIFlagArtificial)
public enum List<T> {
indirect case Tail(List, T)
case End

View File

@@ -10,11 +10,13 @@ func foo<T>(_ x: T) -> () {
// CHECK-SAME: metadata ![[X1:.*]], metadata !DIExpression(DW_OP_deref))
// CHECK: store %swift.type* %T, %swift.type** %[[T]],
// CHECK: store %swift.opaque* %0, %swift.opaque** %[[X]],
// CHECK: ![[TY2:.*]] = !DICompositeType({{.*}}identifier: "$sxD")
// CHECK: ![[TY2:[0-9]+]] = !DICompositeType({{.*}}identifier: "$sxD")
// CHECK: ![[T1]] = !DILocalVariable(name: "$\CF\84_0_0",
// CHECK-SAME: flags: DIFlagArtificial)
// CHECK: ![[X1]] = !DILocalVariable(name: "x", arg: 1,
// CHECK-SAME: line: 3, type: ![[TY2]])
// CHECK-SAME: line: 3, type: ![[LET_TY2:[0-9]+]])
// CHECK: ![[LET_TY2]] = !DIDerivedType(tag: DW_TAG_const_type,
// CHECK-SAME: baseType: ![[TY2]])
_blackHole(x)
}

View File

@@ -10,7 +10,9 @@ public func f<Type>(_ value : Type)
// CHECK: store %swift.opaque* %1, %swift.opaque** %[[ALLOCA]], align
// No deref here.
// CHECK: ![[TY:.*]] = !DICompositeType({{.*}}identifier: "$sxD"
// CHECK: ![[LET_TY:[0-9]+]] = !DIDerivedType(tag: DW_TAG_const_type,
// CHECK-SAME: baseType: ![[TY]])
// CHECK: ![[ARG]] = !DILocalVariable(name: "arg", arg: 1,
// CHECK-SAME: line: [[@LINE+1]], type: ![[TY]])
// CHECK-SAME: line: [[@LINE+1]], type: ![[LET_TY]])
apply(value) { arg in return arg }
}

View File

@@ -12,11 +12,13 @@ public func foo<Type>(_ values : [S<Type>])
// CHECK-SAME: metadata ![[ARG:[0-9]+]],
// CHECK-SAME: metadata !DIExpression(DW_OP_deref))
// CHECK: store %[[TY]]* %1, %[[TY]]** %[[ALLOCA]], align
// CHECK: ![[TYP:.*]] = !DICompositeType({{.*}}, identifier: "$s12generic_arg51SVyxGD")
// CHECK: ![[TYP:[0-9]+]] = !DICompositeType({{.*}}, identifier: "$s12generic_arg51SVyxGD")
// The argument is a by-ref struct and thus needs to be dereferenced.
// CHECK: ![[ARG]] = !DILocalVariable(name: "arg", arg: 1,
// CHECK-SAME: line: [[@LINE+2]],
// CHECK-SAME: type: ![[TYP]])
// CHECK-SAME: line: [[@LINE+4]],
// CHECK-SAME: type: ![[LET_TYP:[0-9]+]])
// CHECK: ![[LET_TYP]] = !DIDerivedType(tag: DW_TAG_const_type,
// CHECK-SAME: baseType: ![[TYP]])
let _ = values.flatMap { arg in
return .some(arg)
}

View File

@@ -1,4 +1,3 @@
// RUN: %target-swift-frontend -module-name generic_args -primary-file %s -emit-ir -verify -g -o - | %FileCheck %s -allow-deprecated-dag-overlap
func markUsed<T>(_ t: T) {}
@@ -13,10 +12,12 @@ class AnotherClass : AProtocol {
func f() -> String { return "B" }
}
// CHECK-DAG: !DICompositeType(tag: DW_TAG_structure_type, name: "$sq_D",{{.*}}
// CHECK-DAG: !DILocalVariable(name: "x", arg: 1,{{.*}} type: ![[T:.*]])
// CHECK-DAG: !DICompositeType(tag: DW_TAG_structure_type, name: "$sq_D",
// CHECK-DAG: !DILocalVariable(name: "x", arg: 1,{{.*}} type: ![[LET_T:.*]])
// CHECK-DAG: ![[LET_T]] = !DIDerivedType(tag: DW_TAG_const_type, baseType: ![[T:.*]])
// CHECK-DAG: ![[T]] = !DICompositeType(tag: DW_TAG_structure_type, name: "$sxD"
// CHECK-DAG: !DILocalVariable(name: "y", arg: 2,{{.*}} type: ![[Q:.*]])
// CHECK-DAG: !DILocalVariable(name: "y", arg: 2,{{.*}} type: ![[LET_Q:.*]])
// CHECK-DAG: ![[LET_Q]] = !DIDerivedType(tag: DW_TAG_const_type, baseType: ![[Q:.*]])
// CHECK-DAG: ![[Q]] = !DICompositeType(tag: DW_TAG_structure_type, name: "$sq_D"
func aFunction<T : AProtocol, Q : AProtocol>(_ x: T, _ y: Q, _ z: String) {
markUsed("I am in \(z): \(x.f()) \(y.f())")
@@ -43,7 +44,8 @@ struct Wrapper<T: AProtocol> {
}
// CHECK-DAG: ![[FNTY:.*]] = !DICompositeType({{.*}}identifier: "$sxq_Ignr_D"
// CHECK-DAG: !DILocalVariable(name: "f", {{.*}}, line: [[@LINE+1]], type: ![[FNTY]])
// CHECK-DAG: ![[LET_FNTY:.*]] = !DIDerivedType(tag: DW_TAG_const_type, baseType: ![[FNTY]])
// CHECK-DAG: !DILocalVariable(name: "f", {{.*}}, line: [[@LINE+1]], type: ![[LET_FNTY]])
func apply<T, U> (_ x: T, f: (T) -> (U)) -> U {
return f(x)
}

View File

@@ -83,30 +83,35 @@ public class C<R> {
}
// IR: ![[BOOL:[0-9]+]] = !DICompositeType({{.*}}name: "Bool"
// IR: ![[LET_BOOL:[0-9]+]] = !DIDerivedType(tag: DW_TAG_const_type, baseType: ![[BOOL]])
// IR: ![[INT:[0-9]+]] = !DICompositeType({{.*}}name: "Int"
// IR: ![[LET_INT:[0-9]+]] = !DIDerivedType(tag: DW_TAG_const_type, baseType: ![[INT]])
// IR: ![[TAU_0_0:[0-9]+]] = {{.*}}DW_TAG_structure_type, name: "$sxD",
// IR: ![[LET_TAU_0_0:[0-9]+]] = !DIDerivedType(tag: DW_TAG_const_type, baseType: ![[TAU_0_0]])
// IR: ![[TAU_1_0:[0-9]+]] = {{.*}}DW_TAG_structure_type, name: "$sqd__D",
// IR: ![[MD_1_0]] = !DILocalVariable(name: "$\CF\84_1_0"
// IR: ![[S]] = !DILocalVariable(name: "s", {{.*}} type: ![[TAU_1_0]]
// IR: ![[GS_T]] = !DILocalVariable(name: "t", {{.*}} scope: ![[SP_GS_T:[0-9]+]], {{.*}} type: ![[TAU_1_0]])
// IR: ![[S]] = !DILocalVariable(name: "s", {{.*}} type: ![[LET_TAU_1_0:[0-9]+]]
// IR: ![[LET_TAU_1_0]] = !DIDerivedType(tag: DW_TAG_const_type, baseType: ![[TAU_1_0]])
// IR: ![[GS_T]] = !DILocalVariable(name: "t", {{.*}} scope: ![[SP_GS_T:[0-9]+]], {{.*}} type: ![[LET_TAU_1_0]])
// IR: ![[SP_GS_T]] = {{.*}}linkageName: "$s1A1gyyxlFqd___Ti5"
// IR: ![[GS_U]] = !DILocalVariable(name: "u", {{.*}} scope: ![[SP_GS_U:[0-9]+]], {{.*}} type: ![[TAU_1_0]])
// IR: ![[GS_U]] = !DILocalVariable(name: "u", {{.*}} scope: ![[SP_GS_U:[0-9]+]], {{.*}} type: ![[LET_TAU_1_0]])
// IR: ![[SP_GS_U]] = {{.*}}linkageName: "$s1A1hyyxlFqd___Ti5"
// IR: ![[GR_T]] = !DILocalVariable(name: "t", {{.*}} scope: ![[SP_GR_T:[0-9]+]], {{.*}}type: ![[TAU_0_0]])
// IR: ![[GR_T]] = !DILocalVariable(name: "t", {{.*}} scope: ![[SP_GR_T:[0-9]+]], {{.*}}type: ![[LET_TAU_0_0]])
// S has the same generic parameter numbering s T and U.
// IR: ![[SP_GR_T]] = {{.*}}linkageName: "$s1A1gyyxlF"
// IR: ![[GR_U]] = !DILocalVariable(name: "u", {{.*}} scope: ![[SP_GR_U:[0-9]+]], {{.*}}type: ![[TAU_0_0]])
// IR: ![[GR_U]] = !DILocalVariable(name: "u", {{.*}} scope: ![[SP_GR_U:[0-9]+]], {{.*}}type: ![[LET_TAU_0_0]])
// IR: ![[SP_GR_U]] = {{.*}}linkageName: "$s1A1hyyxlF"
// IR: ![[GRS_T]] = !DILocalVariable(name: "t", {{.*}} scope: ![[SP_GRS_T:[0-9]+]], {{.*}}type: ![[TUPLE:[0-9]+]]
// IR: ![[GRS_T]] = !DILocalVariable(name: "t", {{.*}} scope: ![[SP_GRS_T:[0-9]+]], {{.*}}type: ![[LET_TUPLE:[0-9]+]]
// IR: ![[SP_GRS_T]] = {{.*}}linkageName: "$s1A1gyyxlFx_qd__t_Ti5"
// IR: ![[LET_TUPLE]] = !DIDerivedType(tag: DW_TAG_const_type, baseType: ![[TUPLE:[0-9]+]])
// IR: ![[TUPLE]] = {{.*}}DW_TAG_structure_type, name: "$sx_qd__tD"
// IR: ![[GRS_U]] = !DILocalVariable(name: "u", {{.*}} scope: ![[SP_GRS_U:[0-9]+]], {{.*}}type: ![[TUPLE]]
// IR: ![[GRS_U]] = !DILocalVariable(name: "u", {{.*}} scope: ![[SP_GRS_U:[0-9]+]], {{.*}}type: ![[LET_TUPLE]]
// IR: ![[SP_GRS_U]] = {{.*}}linkageName: "$s1A1hyyxlFx_qd__t_Ti5"
// IR-DAG: ![[GI_T]] = !DILocalVariable(name: "t", {{.*}} scope: ![[SP_GI_G:[0-9]+]], {{.*}}type: ![[INT]])
// IR-DAG: ![[GI_T]] = !DILocalVariable(name: "t", {{.*}} scope: ![[SP_GI_G:[0-9]+]], {{.*}}type: ![[LET_INT]])
// IR-DAG: ![[SP_GI_G]] = {{.*}}linkageName: "$s1A1gyyxlFSi_Tg5"
// IR-DAG: ![[GI_U]] = !DILocalVariable(name: "u", {{.*}} scope: ![[SP_GI_U:[0-9]+]], {{.*}}type: ![[INT]])
// IR-DAG: ![[GI_U]] = !DILocalVariable(name: "u", {{.*}} scope: ![[SP_GI_U:[0-9]+]], {{.*}}type: ![[LET_INT]])
// IR-DAG: ![[SP_GI_U]] = {{.*}}linkageName: "$s1A1hyyxlFSi_TG5"
// IR-DAG: ![[GB_T]] = !DILocalVariable(name: "t", {{.*}} scope: ![[SP_GB_G:[0-9]+]], {{.*}}type: ![[BOOL]])
// IR-DAG: ![[GB_T]] = !DILocalVariable(name: "t", {{.*}} scope: ![[SP_GB_G:[0-9]+]], {{.*}}type: ![[LET_BOOL]])
// IR-DAG: ![[SP_GB_G]] = {{.*}}linkageName: "$s1A1gyyxlFSb_Tg5"
// IR-DAG: ![[GB_U]] = !DILocalVariable(name: "u", {{.*}} scope: ![[SP_GB_U:[0-9]+]], {{.*}}type: ![[BOOL]])
// IR-DAG: ![[GB_U]] = !DILocalVariable(name: "u", {{.*}} scope: ![[SP_GB_U:[0-9]+]], {{.*}}type: ![[LET_BOOL]])
// IR-DAG: ![[SP_GB_U]] = {{.*}}linkageName: "$s1A1hyyxlFSb_TG5"

View File

@@ -38,12 +38,13 @@ func modifyFooHeap(_ a: inout Int64,
// Inout reference type.
// FOO-CHECK: define {{.*}}@"$s5inout9modifyFooyys5Int64Vz_SftF"
// FOO-CHECK: call void @llvm.dbg.declare(metadata %Ts5Int64V** %
// FOO-CHECK-SAME: metadata ![[U:[0-9]+]], metadata !DIExpression(DW_OP_deref))
// FOO-CHECK-SAME: metadata ![[U:[0-9]+]], metadata !DIExpression(DW_OP_deref))
func modifyFoo(_ u: inout Int64,
// FOO-CHECK-DAG: !DILocalVariable(name: "v", arg: 2{{.*}} line: [[@LINE+3]],{{.*}} type: ![[MYFLOAT:[0-9]+]]
// FOO-CHECK-DAG: [[U]] = !DILocalVariable(name: "u", arg: 1{{.*}} line: [[@LINE-2]],{{.*}} type: ![[RINT:[0-9]+]]
// FOO-CHECK-DAG: ![[RINT]] = !DICompositeType({{.*}}identifier: "$ss5Int64VD"
_ v: MyFloat)
// FOO-CHECK-DAG: !DILocalVariable(name: "v", arg: 2{{.*}} line: [[@LINE+3]],{{.*}} type: ![[LET_MYFLOAT:[0-9]+]]
// FOO-CHECK-DAG: [[U]] = !DILocalVariable(name: "u", arg: 1,{{.*}} line: [[@LINE-2]],{{.*}} type: ![[RINT:[0-9]+]]
// FOO-CHECK-DAG: ![[RINT]] = !DICompositeType({{.*}}identifier: "$ss5Int64VD"
_ v: MyFloat)
// FOO-CHECK-DAG: ![[LET_MYFLOAT]] = !DIDerivedType(tag: DW_TAG_const_type, baseType: ![[MYFLOAT:[0-9]+]])
// FOO-CHECK-DAG: ![[MYFLOAT]] = !DIDerivedType(tag: DW_TAG_typedef, name: "$s5inout7MyFloataD",{{.*}} baseType: ![[FLOAT:[0-9]+]]
// FOO-CHECK-DAG: ![[FLOAT]] = !DICompositeType({{.*}}identifier: "$sSfD"
{

View File

@@ -11,8 +11,10 @@ public class Foo {
// CHECK1: call void @llvm.dbg.value(metadata i{{.*}} 0,
// CHECK1-SAME: metadata ![[TYPE:.*]], metadata
// CHECK1: ![[TYPE]] = !DILocalVariable(name: "type",
// CHECK1-SAME: line: [[@LINE+4]],
// CHECK1-SAME: type: ![[METAFOO:[0-9]+]]
// CHECK1-SAME: line: [[@LINE+6]],
// CHECK1-SAME: type: ![[LET_METAFOO:[0-9]+]]
// CHECK1: ![[LET_METAFOO]] = !DIDerivedType(tag: DW_TAG_const_type,
// CHECK1-SAME: baseType: ![[METAFOO:[0-9]+]])
// CHECK1: ![[METAFOO]] = !DICompositeType(tag: DW_TAG_structure_type,
// CHECK1-SAME: flags:
let type = Swift.type(of: self)

View File

@@ -19,8 +19,12 @@ public func printSomeNumbers(_ gen: IGiveOutInts) {
// FIXME: Should be DW_TAG_interface_type
// CHECK: ![[PT:[0-9]+]] = !DICompositeType(tag: DW_TAG_structure_type, name: "IGiveOutInts"
// CHECK: ![[ARG]] = !DILocalVariable(name: "gen", arg: 1,
// CHECK-SAME: line: [[@LINE-5]], type: ![[PT]]
// CHECK: ![[VAR]] = !DILocalVariable(name: "gen", {{.*}} line: [[@LINE-5]]
// CHECK-SAME: line: [[@LINE-5]],
// CHECK-SAME: type: ![[LET_PT:[0-9]+]]
// CHECK: ![[LET_PT]] = !DIDerivedType(tag: DW_TAG_const_type,
// CHECK-SAME: baseType: ![[PT]])
// CHECK: ![[VAR]] = !DILocalVariable(name: "gen", {{.*}} line: [[@LINE-8]],
// CHECK-SAME: type: ![[PT]]
markUsed(gen.callMe())
use(&gen)
}

View File

@@ -31,5 +31,6 @@ func f() {
f()
// CHECK: ![[TY:[0-9]+]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Size",
// CHECK: ![[V1]] = !DILocalVariable(name: "s1", {{.*}}type: ![[TY]])
// CHECK: ![[LET_TY:[0-9]+]] = !DIDerivedType(tag: DW_TAG_const_type,
// CHECK-SAME: baseType: ![[TY:[0-9]+]])
// CHECK: ![[V1]] = !DILocalVariable(name: "s1", {{.*}}type: ![[LET_TY]])

View File

@@ -13,7 +13,8 @@ func test(_ x : A) {
// CHECK: define hidden {{.*}}void @"$s7structs4test{{[_0-9a-zA-Z]*}}F"
// CHECK: [[X_DBG:%.*]] = alloca
// CHECK: call void @llvm.dbg.declare(metadata {{.*}}* [[X_DBG]], metadata [[X_MD:!.*]], metadata
// CHECK: ![[A_DI:.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "A",{{.*}}identifier
// CHECK: ![[A:.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "A",
// CHECK-SAME: identifier
class C {
var lots_of_extra_storage: (Int, Int, Int) = (1, 2, 3)
@@ -21,7 +22,8 @@ class C {
}
// CHECK: [[X_MD]] = !DILocalVariable(name: "x", arg: 1
// CHECK-SAME: type: ![[A_DI]]
// CHECK-SAME: type: ![[LET_A:[0-9]+]]
// CHECK: ![[LET_A]] = !DIDerivedType(tag: DW_TAG_const_type, baseType: ![[A]])
// A class is represented by a pointer, so B's total size should be PTRSIZE.
// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "B",{{.*}}size: [[PTRSIZE]]

View File

@@ -37,40 +37,40 @@ public protocol P {
public func main() {
// CHECK-DAG: !DILocalVariable(name: "a",{{.*}} type: ![[DIEOFFSET]]
let a : DWARF.DIEOffset = 123
var a : DWARF.DIEOffset = 123
markUsed(a)
// CHECK-DAG: !DILocalVariable(name: "b",{{.*}} type: ![[DIEOFFSET]]
let b = DWARF.DIEOffset(456) as DWARF.DIEOffset
var b = DWARF.DIEOffset(456) as DWARF.DIEOffset
markUsed(b)
// CHECK-DAG: !DILocalVariable(name: "c",{{.*}} type: ![[PRIVATETYPE]]
let c = DWARF.usePrivateType()
var c = DWARF.usePrivateType()
markUsed(c);
// CHECK-DAG: !DILocalVariable(name: "d", {{.*}} type: [[NONGENERIC_TYPE:![0-9]+]])
// CHECK: [[NONGENERIC_TYPE]] = !DICompositeType(tag: DW_TAG_structure_type{{.*}} identifier: "$s9typealias7GenericV5InnerOySi_GD"
let d: Specific.Inner = .value
// CHECK-DAG: [[NONGENERIC_TYPE]] = !DICompositeType(tag: DW_TAG_structure_type{{.*}} identifier: "$s9typealias7GenericV5InnerOySi_GD"
var d: Specific.Inner = .value
markUsed(d)
// CHECK-DAG: !DILocalVariable(name: "e", {{.*}} type: [[INNER_TYPE]])
let e: Outer.T.Inner = .x
var e: Outer.T.Inner = .x
markUsed(e)
// CHECK-DAG: !DILocalVariable(name: "f", {{.*}} type: [[OUTER_T_TYPE:![0-9]+]])
// CHECK: [[OUTER_T_TYPE]] = !DIDerivedType(tag: DW_TAG_typedef, name: "$s9typealias1PP1TayAA5OuterV_GD"
let f: Outer.T = Outer()
// CHECK-DAG: [[OUTER_T_TYPE]] = !DIDerivedType(tag: DW_TAG_typedef, name: "$s9typealias1PP1TayAA5OuterV_GD"
var f: Outer.T = Outer()
markUsed(f)
// CHECK-DAG: !DILocalVariable(name: "g", {{.*}} type: [[GENERIC_TYPE:![0-9]+]])
// CHECK: [[GENERIC_TYPE]] = !DIDerivedType(tag: DW_TAG_typedef, name: "$s9typealias11NotSpecificaySiGD"
let g: NotSpecific<Int> = .value
// CHECK-DAG: [[GENERIC_TYPE]] = !DIDerivedType(tag: DW_TAG_typedef, name: "$s9typealias11NotSpecificaySiGD"
var g: NotSpecific<Int> = .value
markUsed(g)
// Make sure we're not using the abbreviation for this obsolete type that was replaced with a typealias in Swift 4
//
// CHECK-DAG: !DILocalVariable(name: "h", {{.*}} type: [[UNICODE_SCALAR_TYPE:![0-9]+]])
// CHECK: [[UNICODE_SCALAR_TYPE]] = !DIDerivedType(tag: DW_TAG_typedef, name: "$ss13UnicodeScalaraD"
let h: UnicodeScalar = "a"
// CHECK-DAG: [[UNICODE_SCALAR_TYPE]] = !DIDerivedType(tag: DW_TAG_typedef, name: "$ss13UnicodeScalaraD"
var h: UnicodeScalar = "a"
markUsed(h)
}

View File

@@ -49,9 +49,12 @@ public func bar<T: P>(genericValue: T) {
use(opaqueSubValue)
}
// CHECK-DAG: [[OPAQUE_TYPE:![0-9]+]] = !DICompositeType({{.*}} name: "$s24opaque_result_type_debug3fooQryFQOyQo_D"
// CHECK-DAG: [[OPAQUE_PROP_TYPE:![0-9]+]] = !DICompositeType({{.*}} name: "$s24opaque_result_type_debug4propQrvpQOyQo_D"
// CHECK-DAG: [[OPAQUE_SUB_TYPE:![0-9]+]] = !DICompositeType({{.*}} name: "$s24opaque_result_type_debug3FooVQrycipQOy_Qo_D"
// CHECK-DAG: {{![0-9]+}} = !DILocalVariable(name: "opaqueValue",{{.*}} type: [[OPAQUE_TYPE]])
// CHECK-DAG: {{![0-9]+}} = !DILocalVariable(name: "opaquePropValue",{{.*}} type: [[OPAQUE_PROP_TYPE]])
// CHECK-DAG: {{![0-9]+}} = !DILocalVariable(name: "opaqueSubValue",{{.*}} type: [[OPAQUE_SUB_TYPE]])
// CHECK-DAG: ![[OPAQUE_TYPE:[0-9]+]] = !DICompositeType({{.*}} name: "$s24opaque_result_type_debug3fooQryFQOyQo_D"
// CHECK-DAG: ![[LET_OPAQUE_TYPE:[0-9]+]] = !DIDerivedType(tag: DW_TAG_const_type, baseType: ![[OPAQUE_TYPE]])
// CHECK-DAG: ![[OPAQUE_PROP_TYPE:[0-9]+]] = !DICompositeType({{.*}} name: "$s24opaque_result_type_debug4propQrvpQOyQo_D"
// CHECK-DAG: ![[LET_OPAQUE_PROP_TYPE:[0-9]+]] = !DIDerivedType(tag: DW_TAG_const_type, baseType: ![[OPAQUE_PROP_TYPE]])
// CHECK-DAG: ![[OPAQUE_SUB_TYPE:[0-9]+]] = !DICompositeType({{.*}} name: "$s24opaque_result_type_debug3FooVQrycipQOy_Qo_D"
// CHECK-DAG: ![[LET_OPAQUE_SUB_TYPE:[0-9]+]] = !DIDerivedType(tag: DW_TAG_const_type, baseType: ![[OPAQUE_SUB_TYPE]])
// CHECK-DAG: {{![0-9]+}} = !DILocalVariable(name: "opaqueValue",{{.*}} type: ![[LET_OPAQUE_TYPE]])
// CHECK-DAG: {{![0-9]+}} = !DILocalVariable(name: "opaquePropValue",{{.*}} type: ![[LET_OPAQUE_PROP_TYPE]])
// CHECK-DAG: {{![0-9]+}} = !DILocalVariable(name: "opaqueSubValue",{{.*}} type: ![[LET_OPAQUE_SUB_TYPE]])