Sink isFixedBuffer into DebugTypeInfo and ensure the enclosed types aren't

emitted with the size of the fixed buffer.
This commit is contained in:
Adrian Prantl
2022-12-14 14:18:28 -08:00
parent 7731ee9a83
commit 06a54432ab
9 changed files with 130 additions and 88 deletions

View File

@@ -17,6 +17,7 @@
#include "DebugTypeInfo.h"
#include "FixedTypeInfo.h"
#include "IRGenModule.h"
#include "swift/SIL/SILGlobalVariable.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
@@ -27,23 +28,12 @@ using namespace irgen;
DebugTypeInfo::DebugTypeInfo(swift::Type Ty, llvm::Type *FragmentStorageTy,
Optional<Size::int_type> SizeInBits,
Alignment Align, bool HasDefaultAlignment,
bool IsMetadata, bool SizeIsFragmentSize)
bool IsMetadata, bool SizeIsFragmentSize,
bool IsFixedBuffer)
: Type(Ty.getPointer()), FragmentStorageType(FragmentStorageTy),
SizeInBits(SizeInBits), Align(Align),
DefaultAlignment(HasDefaultAlignment), IsMetadataType(IsMetadata),
SizeIsFragmentSize(SizeIsFragmentSize) {
assert(Align.getValue() != 0);
}
DebugTypeInfo::DebugTypeInfo(swift::Type Ty, llvm::Type *FragmentStorageTy,
Optional<Size> SizeInBytes, Alignment Align,
bool HasDefaultAlignment, bool IsMetadata,
bool SizeIsFragmentSize)
: Type(Ty.getPointer()), FragmentStorageType(FragmentStorageTy),
Align(Align), DefaultAlignment(HasDefaultAlignment),
IsMetadataType(IsMetadata), SizeIsFragmentSize(SizeIsFragmentSize) {
if (SizeInBytes)
SizeInBits = SizeInBytes->getValue() * 8;
SizeIsFragmentSize(SizeIsFragmentSize), IsFixedBuffer(IsFixedBuffer) {
assert(Align.getValue() != 0);
}
@@ -56,17 +46,20 @@ static bool hasDefaultAlignment(swift::Type Ty) {
return true;
}
DebugTypeInfo DebugTypeInfo::getFromTypeInfo(swift::Type Ty,
const TypeInfo &Info,
DebugTypeInfo DebugTypeInfo::getFromTypeInfo(swift::Type Ty, const TypeInfo &TI,
bool IsFragmentTypeInfo) {
Optional<Size> size;
if (Info.isFixedSize()) {
const FixedTypeInfo &FixTy = *cast<const FixedTypeInfo>(&Info);
size = FixTy.getFixedSize();
Optional<Size::int_type> SizeInBits;
llvm::Type *StorageType = TI.getStorageType();
if (TI.isFixedSize()) {
const FixedTypeInfo &FixTy = *cast<const FixedTypeInfo>(&TI);
Size::int_type Size = FixTy.getFixedSize().getValue() * 8;
//if (!StorageType->isPointerTy())
// Size -= FixTy.getSpareBits().asAPInt().countTrailingOnes();
SizeInBits = Size;
}
assert(Info.getStorageType() && "StorageType is a nullptr");
return DebugTypeInfo(Ty.getPointer(), Info.getStorageType(), size,
Info.getBestKnownAlignment(), ::hasDefaultAlignment(Ty),
assert(TI.getStorageType() && "StorageType is a nullptr");
return DebugTypeInfo(Ty.getPointer(), StorageType, SizeInBits,
TI.getBestKnownAlignment(), ::hasDefaultAlignment(Ty),
false, IsFragmentTypeInfo);
}
@@ -92,8 +85,8 @@ DebugTypeInfo DebugTypeInfo::getLocalVariable(VarDecl *Decl, swift::Type Ty,
DebugTypeInfo DebugTypeInfo::getGlobalMetadata(swift::Type Ty,
llvm::Type *StorageTy, Size size,
Alignment align) {
DebugTypeInfo DbgTy(Ty.getPointer(), StorageTy, size,
align, true, false, false);
DebugTypeInfo DbgTy(Ty.getPointer(), StorageTy, size.getValue() * 8, align,
true, false, false);
assert(StorageTy && "StorageType is a nullptr");
assert(!DbgTy.isContextArchetype() &&
"type metadata cannot contain an archetype");
@@ -103,8 +96,8 @@ DebugTypeInfo DebugTypeInfo::getGlobalMetadata(swift::Type Ty,
DebugTypeInfo DebugTypeInfo::getTypeMetadata(swift::Type Ty,
llvm::Type *StorageTy, Size size,
Alignment align) {
DebugTypeInfo DbgTy(Ty.getPointer(), StorageTy, size,
align, true, true, false);
DebugTypeInfo DbgTy(Ty.getPointer(), StorageTy, size.getValue() * 8, align,
true, true, false);
assert(StorageTy && "StorageType is a nullptr");
assert(!DbgTy.isContextArchetype() &&
"type metadata cannot contain an archetype");
@@ -117,8 +110,8 @@ DebugTypeInfo DebugTypeInfo::getForwardDecl(swift::Type Ty) {
}
DebugTypeInfo DebugTypeInfo::getGlobal(SILGlobalVariable *GV,
llvm::Type *StorageTy, Size size,
Alignment align) {
llvm::Type *FragmentStorageType,
IRGenModule &IGM) {
// Prefer the original, potentially sugared version of the type if
// the type hasn't been mucked with by an optimization pass.
auto LowTy = GV->getLoweredType().getASTType();
@@ -128,20 +121,41 @@ DebugTypeInfo DebugTypeInfo::getGlobal(SILGlobalVariable *GV,
if (DeclType->isEqual(LowTy))
Type = DeclType.getPointer();
}
DebugTypeInfo DbgTy(Type, StorageTy, size, align, ::hasDefaultAlignment(Type),
false, false);
assert(StorageTy && "FragmentStorageType is a nullptr");
auto &TI = IGM.getTypeInfoForUnlowered(Type);
DebugTypeInfo DbgTy = getFromTypeInfo(Type, TI, false);
assert(FragmentStorageType && "FragmentStorageType is a nullptr");
assert(!DbgTy.isContextArchetype() &&
"type of global variable cannot be an archetype");
return DbgTy;
}
DebugTypeInfo
DebugTypeInfo::getGlobalFixedBuffer(SILGlobalVariable *GV,
llvm::Type *FragmentStorageType,
Size SizeInBytes, Alignment Align) {
// Prefer the original, potentially sugared version of the type if
// the type hasn't been mucked with by an optimization pass.
auto LowTy = GV->getLoweredType().getASTType();
auto *Type = LowTy.getPointer();
if (auto *Decl = GV->getDecl()) {
auto DeclType = Decl->getType();
if (DeclType->isEqual(LowTy))
Type = DeclType.getPointer();
}
DebugTypeInfo DbgTy(Type, FragmentStorageType, SizeInBytes.getValue() * 8,
Align, ::hasDefaultAlignment(Type), false, false, true);
assert(FragmentStorageType && "FragmentStorageType is a nullptr");
assert(!DbgTy.isContextArchetype() &&
"type of global variable cannot be an archetype");
assert(align.getValue() != 0);
return DbgTy;
}
DebugTypeInfo DebugTypeInfo::getObjCClass(ClassDecl *theClass,
llvm::Type *FragmentStorageType,
Size size, Alignment align) {
Size SizeInBytes, Alignment align) {
DebugTypeInfo DbgTy(theClass->getInterfaceType().getPointer(),
FragmentStorageType, size, align, true, false, false);
FragmentStorageType, SizeInBytes.getValue() * 8, align,
true, false, false);
assert(FragmentStorageType && "FragmentStorageType is a nullptr");
assert(!DbgTy.isContextArchetype() &&
"type of objc class cannot be an archetype");
@@ -149,10 +163,13 @@ DebugTypeInfo DebugTypeInfo::getObjCClass(ClassDecl *theClass,
}
DebugTypeInfo DebugTypeInfo::getErrorResult(swift::Type Ty,
llvm::Type *StorageType, Size size,
Alignment align) {
llvm::Type *StorageType,
IRGenModule &IGM) {
auto &TI = IGM.getTypeInfoForUnlowered(Ty);
assert(TI.getStorageType() == StorageType);
DebugTypeInfo DbgTy = getFromTypeInfo(Ty, TI, false);
assert(StorageType && "FragmentStorageType is a nullptr");
return {Ty, StorageType, size, align, true, false, false};
return DbgTy;
}
bool DebugTypeInfo::operator==(DebugTypeInfo T) const {

View File

@@ -32,6 +32,7 @@ class SILGlobalVariable;
namespace irgen {
class TypeInfo;
class IRGenModule;
/// This data structure holds everything needed to emit debug info
/// for a type.
@@ -47,7 +48,8 @@ protected:
Alignment Align;
bool DefaultAlignment = true;
bool IsMetadataType = false;
bool SizeIsFragmentSize;
bool SizeIsFragmentSize = false;
bool IsFixedBuffer = false;
public:
DebugTypeInfo() = default;
@@ -55,11 +57,7 @@ public:
Optional<Size::int_type> SizeInBits = {},
Alignment AlignInBytes = Alignment(1),
bool HasDefaultAlignment = true, bool IsMetadataType = false,
bool IsFragmentTypeInfo = false);
DebugTypeInfo(swift::Type Ty, llvm::Type *StorageTy,
Optional<Size> SizeInBytes, Alignment AlignInBytes,
bool HasDefaultAlignment, bool IsMetadataType,
bool IsFragmentTypeInfo);
bool IsFragmentTypeInfo = false, bool IsFixedBuffer = false);
/// Create type for a local variable.
static DebugTypeInfo getLocalVariable(VarDecl *Decl, swift::Type Ty,
@@ -80,15 +78,17 @@ public:
bool IsFragmentTypeInfo);
/// Global variables.
static DebugTypeInfo getGlobal(SILGlobalVariable *GV,
llvm::Type *StorageType, Size size,
Alignment align);
llvm::Type *StorageType, IRGenModule &IGM);
static DebugTypeInfo getGlobalFixedBuffer(SILGlobalVariable *GV,
llvm::Type *StorageType,
Size SizeInBytes, Alignment align);
/// ObjC classes.
static DebugTypeInfo getObjCClass(ClassDecl *theClass,
llvm::Type *StorageType, Size size,
Alignment align);
/// Error type.
static DebugTypeInfo getErrorResult(swift::Type Ty, llvm::Type *StorageType,
Size size, Alignment align);
IRGenModule &IGM);
TypeBase *getType() const { return Type; }
@@ -119,6 +119,7 @@ public:
bool isMetadataType() const { return IsMetadataType; }
bool hasDefaultAlignment() const { return DefaultAlignment; }
bool isSizeFragmentSize() const { return SizeIsFragmentSize; }
bool isFixedBuffer() const { return IsFixedBuffer; }
bool operator==(DebugTypeInfo T) const;
bool operator!=(DebugTypeInfo T) const;
@@ -159,8 +160,8 @@ template <> struct DenseMapInfo<swift::irgen::DebugTypeInfo> {
}
static swift::irgen::DebugTypeInfo getTombstoneKey() {
return swift::irgen::DebugTypeInfo(
llvm::DenseMapInfo<swift::TypeBase *>::getTombstoneKey(), nullptr,
swift::irgen::Size(0), swift::irgen::Alignment(), false, false, false);
llvm::DenseMapInfo<swift::TypeBase *>::getTombstoneKey(), nullptr, 0,
swift::irgen::Alignment(), false, false, false);
}
static unsigned getHashValue(swift::irgen::DebugTypeInfo Val) {
return DenseMapInfo<swift::CanType>::getHashValue(Val.getType());

View File

@@ -2354,7 +2354,7 @@ llvm::Function *irgen::createFunction(IRGenModule &IGM, LinkInfo &linkInfo,
llvm::GlobalVariable *swift::irgen::createVariable(
IRGenModule &IGM, LinkInfo &linkInfo, llvm::Type *storageType,
Alignment alignment, DebugTypeInfo DbgTy, Optional<SILLocation> DebugLoc,
StringRef DebugName, bool inFixedBuffer) {
StringRef DebugName) {
auto name = linkInfo.getName();
llvm::GlobalValue *existingValue = IGM.Module.getNamedGlobal(name);
if (existingValue) {
@@ -2384,7 +2384,7 @@ llvm::GlobalVariable *swift::irgen::createVariable(
if (IGM.DebugInfo && !DbgTy.isNull() && linkInfo.isForDefinition())
IGM.DebugInfo->emitGlobalVariableDeclaration(
var, DebugName.empty() ? name : DebugName, name, DbgTy,
var->hasInternalLinkage(), inFixedBuffer, DebugLoc);
var->hasInternalLinkage(), DebugLoc);
return var;
}
@@ -2666,10 +2666,13 @@ Address IRGenModule::getAddrOfSILGlobalVariable(SILGlobalVariable *var,
loc = var->getLocation();
name = var->getName();
}
auto DbgTy = DebugTypeInfo::getGlobal(var, storageTypeWithContainer,
fixedSize, fixedAlignment);
DebugTypeInfo DbgTy =
inFixedBuffer
? DebugTypeInfo::getGlobalFixedBuffer(
var, storageTypeWithContainer, fixedSize, fixedAlignment)
: DebugTypeInfo::getGlobal(var, storageTypeWithContainer, *this);
gvar = createVariable(*this, link, storageTypeWithContainer,
fixedAlignment, DbgTy, loc, name, inFixedBuffer);
fixedAlignment, DbgTy, loc, name);
}
/// Add a zero initializer.
if (forDefinition)

View File

@@ -51,7 +51,7 @@ namespace irgen {
createVariable(IRGenModule &IGM, LinkInfo &linkInfo, llvm::Type *objectType,
Alignment alignment, DebugTypeInfo DebugType = DebugTypeInfo(),
Optional<SILLocation> DebugLoc = None,
StringRef DebugName = StringRef(), bool heapAllocated = false);
StringRef DebugName = StringRef());
llvm::GlobalVariable *
createLinkerDirectiveVariable(IRGenModule &IGM, StringRef Name);

View File

@@ -43,11 +43,10 @@ void IRGenModule::emitSILGlobalVariable(SILGlobalVariable *var) {
// variable directly, don't actually emit it; just return undef.
if (ti.isKnownEmpty(expansion)) {
if (DebugInfo && var->getDecl()) {
auto DbgTy = DebugTypeInfo::getGlobal(var, Int8Ty, Size(0), Alignment(1));
auto DbgTy = DebugTypeInfo::getGlobal(var, Int8Ty, *this);
DebugInfo->emitGlobalVariableDeclaration(
nullptr, var->getDecl()->getName().str(), "", DbgTy,
var->getLinkage() != SILLinkage::Public,
IRGenDebugInfo::NotHeapAllocated, SILLocation(var->getDecl()));
var->getLinkage() != SILLinkage::Public, SILLocation(var->getDecl()));
}
return;
}

View File

@@ -240,7 +240,7 @@ public:
void emitGlobalVariableDeclaration(llvm::GlobalVariable *Storage,
StringRef Name, StringRef LinkageName,
DebugTypeInfo DebugType,
bool IsLocalToUnit, bool InFixedBuffer,
bool IsLocalToUnit,
Optional<SILLocation> Loc);
void emitTypeMetadata(IRGenFunction &IGF, llvm::Value *Metadata,
unsigned Depth, unsigned Index, StringRef Name);
@@ -640,9 +640,10 @@ private:
void createParameterType(llvm::SmallVectorImpl<llvm::Metadata *> &Parameters,
SILType type) {
bool IsFragment = false;
auto RealType = type.getASTType();
auto DbgTy = DebugTypeInfo::getFromTypeInfo(RealType, IGM.getTypeInfo(type),
/*isFragment*/ false);
IsFragment);
Parameters.push_back(getOrCreateType(DbgTy));
}
@@ -991,7 +992,7 @@ private:
if (auto DbgTy = CompletedDebugTypeInfo::getFromTypeInfo(
VD->getInterfaceType(),
IGM.getTypeInfoForUnlowered(
IGM.getSILTypes().getAbstractionPattern(VD), memberTy)))
IGM.getSILTypes().getAbstractionPattern(VD), memberTy)))
Elements.push_back(createMemberType(*DbgTy, VD->getName().str(),
OffsetInBits, Scope, File, Flags));
else
@@ -1061,7 +1062,7 @@ private:
// as the element type; there is no storage here.
Type IntTy = IGM.Context.getIntType();
ElemDbgTy = CompletedDebugTypeInfo::get(
DebugTypeInfo(IntTy, DbgTy.getFragmentStorageType(), Size(0),
DebugTypeInfo(IntTy, DbgTy.getFragmentStorageType(), 0,
Alignment(1), true, false, false));
}
if (!ElemDbgTy) {
@@ -1338,7 +1339,6 @@ private:
llvm::DINode::DIFlags Flags = llvm::DINode::FlagZero;
TypeBase *BaseTy = DbgTy.getType();
if (!BaseTy) {
LLVM_DEBUG(llvm::dbgs() << "Type without TypeBase: ";
DbgTy.getType()->dump(llvm::dbgs()); llvm::dbgs() << "\n");
@@ -1445,12 +1445,16 @@ private:
SizeInBits, AlignInBits, Flags, nullptr,
llvm::dwarf::DW_LANG_Swift, MangledName);
StringRef Name = Decl->getName().str();
if (DbgTy.getTypeSizeInBits())
return createOpaqueStruct(Scope, Name, File, FwdDeclLine, SizeInBits,
AlignInBits, Flags, MangledName);
return DBuilder.createForwardDecl(
llvm::dwarf::DW_TAG_structure_type, Name, Scope, File, FwdDeclLine,
llvm::dwarf::DW_LANG_Swift, 0, AlignInBits, MangledName);
if (!DbgTy.getTypeSizeInBits())
return DBuilder.createForwardDecl(
llvm::dwarf::DW_TAG_structure_type, Name, Scope, File, FwdDeclLine,
llvm::dwarf::DW_LANG_Swift, 0, AlignInBits, MangledName);
if (DbgTy.isFixedBuffer())
return DBuilder.createForwardDecl(
llvm::dwarf::DW_TAG_structure_type, Name, Scope, File, FwdDeclLine,
llvm::dwarf::DW_LANG_Swift, 0, AlignInBits, MangledName);
return createOpaqueStruct(Scope, Name, File, FwdDeclLine, SizeInBits,
AlignInBits, Flags, MangledName);
}
case TypeKind::Class: {
@@ -1782,13 +1786,13 @@ private:
#if SWIFT_DEBUGINFO_CACHE_VERIFICATION
if (auto SizeInBits = DbgTy.getTypeSizeInBits()) {
if (unsigned CachedSizeInBits = getSizeInBits(DITy)) {
if (llvm::alignTo(CachedSizeInBits, 8) != *SizeInBits) {
if (CachedSizeInBits != *SizeInBits) {
DITy->dump();
DbgTy.dump();
llvm::errs() << "SizeInBits = " << *SizeInBits << "\n";
llvm::errs() << "CachedSizeInBits = " << CachedSizeInBits << "\n";
}
assert(llvm::alignTo(CachedSizeInBits, 8) == *SizeInBits);
assert(CachedSizeInBits == *SizeInBits);
}
}
#endif
@@ -2381,12 +2385,12 @@ IRGenDebugInfoImpl::emitFunction(const SILDebugScope *DS, llvm::Function *Fn,
llvm::DITypeArray Error = nullptr;
if (FnTy)
if (auto ErrorInfo = FnTy->getOptionalErrorResult()) {
SILType SILTy = IGM.silConv.getSILType(
*ErrorInfo, FnTy, IGM.getMaximalTypeExpansionContext());
auto DTI = DebugTypeInfo::getFromTypeInfo(
ErrorInfo->getReturnValueType(IGM.getSILModule(), FnTy,
IGM.getMaximalTypeExpansionContext()),
IGM.getTypeInfo(IGM.silConv.getSILType(
*ErrorInfo, FnTy, IGM.getMaximalTypeExpansionContext())),
false);
IGM.getTypeInfo(SILTy), false);
Error = DBuilder.getOrCreateArray({getOrCreateType(DTI)}).get();
}
@@ -2873,8 +2877,7 @@ void IRGenDebugInfoImpl::emitDbgIntrinsic(
void IRGenDebugInfoImpl::emitGlobalVariableDeclaration(
llvm::GlobalVariable *Var, StringRef Name, StringRef LinkageName,
DebugTypeInfo DbgTy, bool IsLocalToUnit, bool InFixedBuffer,
Optional<SILLocation> Loc) {
DebugTypeInfo DbgTy, bool IsLocalToUnit, Optional<SILLocation> Loc) {
if (Opts.DebugInfoLevel <= IRGenDebugInfoLevel::LineTables)
return;
@@ -2897,7 +2900,7 @@ void IRGenDebugInfoImpl::emitGlobalVariableDeclaration(
// would confuse both the user and LLDB.
return;
if (InFixedBuffer)
if (DbgTy.isFixedBuffer())
DITy = createFixedValueBufferStruct(DITy);
auto L = getStartLocation(Loc);
@@ -3061,10 +3064,9 @@ void IRGenDebugInfo::emitDbgIntrinsic(IRBuilder &Builder, llvm::Value *Storage,
void IRGenDebugInfo::emitGlobalVariableDeclaration(
llvm::GlobalVariable *Storage, StringRef Name, StringRef LinkageName,
DebugTypeInfo DebugType, bool IsLocalToUnit, bool InFixedBuffer,
Optional<SILLocation> Loc) {
DebugTypeInfo DebugType, bool IsLocalToUnit, Optional<SILLocation> Loc) {
static_cast<IRGenDebugInfoImpl *>(this)->emitGlobalVariableDeclaration(
Storage, Name, LinkageName, DebugType, IsLocalToUnit, InFixedBuffer, Loc);
Storage, Name, LinkageName, DebugType, IsLocalToUnit, Loc);
}
void IRGenDebugInfo::emitTypeMetadata(IRGenFunction &IGF, llvm::Value *Metadata,

View File

@@ -177,13 +177,11 @@ public:
const SILDebugScope *DS, bool InCoroContext = false,
AddrDbgInstrKind = AddrDbgInstrKind::DbgDeclare);
enum { NotHeapAllocated = false };
/// Create debug metadata for a global variable.
void emitGlobalVariableDeclaration(llvm::GlobalVariable *Storage,
StringRef Name, StringRef LinkageName,
DebugTypeInfo DebugType,
bool IsLocalToUnit, bool InFixedBuffer,
bool IsLocalToUnit,
Optional<SILLocation> Loc);
/// Emit debug metadata for type metadata (for generic types). So meta.

View File

@@ -4878,8 +4878,7 @@ void IRGenSILFunction::emitErrorResultVar(CanSILFunctionType FnTy,
auto DbgTy = DebugTypeInfo::getErrorResult(
ErrorInfo.getReturnValueType(IGM.getSILModule(), FnTy,
IGM.getMaximalTypeExpansionContext()),
ErrorResultSlot->getType(), IGM.getPointerSize(),
IGM.getPointerAlignment());
ErrorResultSlot->getType(), IGM);
IGM.DebugInfo->emitVariableDeclaration(Builder, Storage, DbgTy,
getDebugScope(), {}, *Var,
IndirectValue, ArtificialValue);

View File

@@ -6,8 +6,8 @@
// RUN: -emit-module-path=%t/resilient_struct.swiftmodule \
// RUN: -module-name=resilient_struct %S/../Inputs/resilient_struct.swift
//
// RUN: %target-swift-frontend -g -I %t -emit-ir -enable-library-evolution %s -o - \
// RUN: | %FileCheck %s
// RUN: %target-swift-frontend -g -I %t -emit-ir -enable-library-evolution \
// RUN: %s -o - | %FileCheck %s
import resilient_struct
// Fits in buffer
@@ -16,18 +16,33 @@ let small = Size(w: 1, h: 2)
// Needs out-of-line allocation
let large = Rectangle(p: Point(x: 1, y: 2), s: Size(w: 3, h: 4), color: 5)
let tuple = (Size(w: 1, h: 2), Size(w: 3, h: 4))
// CHECK: @"$s17global_resilience5small16resilient_struct4SizeVvp" =
// CHECK-SAME: !dbg ![[SMALL:[0-9]+]]
// CHECK: @"$s17global_resilience5large16resilient_struct9RectangleVvp" =
// CHECK-SAME: !dbg ![[LARGE:[0-9]+]]
// CHECK: @"$s17global_resilience5tuple
// CHECK-SAME: !dbg ![[TUPLE:[0-9]+]]
// CHECK: ![[SMALL]] = !DIGlobalVariableExpression(
// CHECK-SAME: var: ![[VAR_SMALL:[0-9]+]]
// CHECK-SAME: expr: !DIExpression())
// CHECK: ![[VAR_SMALL]] = distinct !DIGlobalVariable(
// CHECK-SAME: type: ![[SMALL_TY:[0-9]+]]
// CHECK: ![[SMALL_TY]] = !DICompositeType(tag: DW_TAG_structure_type,
// CHECK-SAME: name: "$swift.fixedbuffer",
// CHECK-SAME: name: "$swift.fixedbuffer",
// CHECK-SAME: elements: ![[SMALL_TY_EL:[0-9]+]]
// CHECK: ![[SMALL_TY_EL]] = !{![[SMALL_TY_M:[0-9]+]]}
// CHECK: ![[SMALL_TY_M]] = !DIDerivedType(tag: DW_TAG_member,
// CHECK-SAME: baseType: ![[SMALL_TY_CT:[0-9]+]]
// CHECK: ![[SMALL_TY_CT]] = !DIDerivedType(tag: DW_TAG_const_type,
// CHECK-SAME: baseType: ![[SMALL_TY_TY:[0-9]+]]
// CHECK: ![[SMALL_TY_TY]] = !DICompositeType(
// CHECK-NOT: size:
// CHECK-SAME: DIFlagFwdDecl
// CHECK: ![[LARGE]] = !DIGlobalVariableExpression(
// CHECK-SAME: var: ![[VAR_LARGE:[0-9]+]]
// CHECK-SAME: expr: !DIExpression())
@@ -35,3 +50,11 @@ let large = Rectangle(p: Point(x: 1, y: 2), s: Size(w: 3, h: 4), color: 5)
// CHECK-SAME: type: ![[LARGE_TY:[0-9]+]]
// CHECK: ![[LARGE_TY]] = !DICompositeType(tag: DW_TAG_structure_type,
// CHECK-SAME: name: "$swift.fixedbuffer",
// CHECK: ![[TUPLE]] = !DIGlobalVariableExpression(
// CHECK-SAME: var: ![[VAR_TUPLE:[0-9]+]]
// CHECK-SAME: expr: !DIExpression())
// CHECK: ![[VAR_TUPLE]] = distinct !DIGlobalVariable(
// CHECK-SAME: type: ![[TUPLE_TY:[0-9]+]]
// CHECK: ![[TUPLE_TY]] = !DICompositeType(tag: DW_TAG_structure_type,
// CHECK-SAME: name: "$swift.fixedbuffer",