Skip to content

Commit 1e55e30

Browse files
committed
Merge pull request #1621 from adrian-prantl/master
Debug Info: Retrieve the layout information of exploded values from the
2 parents 4b447e2 + 1f48b05 commit 1e55e30

File tree

3 files changed

+104
-130
lines changed

3 files changed

+104
-130
lines changed

lib/IRGen/IRGenDebugInfo.cpp

Lines changed: 94 additions & 127 deletions
Original file line numberDiff line numberDiff line change
@@ -885,74 +885,6 @@ llvm::DIFile *IRGenDebugInfo::getFile(llvm::DIScope *Scope) {
885885
return cast<llvm::DIFile>(Scope);
886886
}
887887

888-
/// Return the storage size of an explosion value.
889-
static uint64_t getSizeFromExplosionValue(const clang::TargetInfo &TI,
890-
llvm::Value *V) {
891-
llvm::Type *Ty = V->getType();
892-
if (unsigned PrimitiveSize = Ty->getPrimitiveSizeInBits())
893-
return PrimitiveSize;
894-
else if (Ty->isPointerTy())
895-
return TI.getPointerWidth(0);
896-
else
897-
llvm_unreachable("unhandled type of explosion value");
898-
}
899-
900-
/// A generator that recursively returns the size of each element of a
901-
/// composite type.
902-
class ElementSizes {
903-
const TrackingDIRefMap &DIRefMap;
904-
llvm::SmallPtrSetImpl<const llvm::DIType *> &IndirectEnums;
905-
llvm::SmallVector<const llvm::DIType *, 12> Stack;
906-
public:
907-
ElementSizes(const llvm::DIType *DITy, const TrackingDIRefMap &DIRefMap,
908-
llvm::SmallPtrSetImpl<const llvm::DIType *> &IndirectEnums)
909-
: DIRefMap(DIRefMap), IndirectEnums(IndirectEnums), Stack(1, DITy) {}
910-
911-
struct SizeAlign {
912-
uint64_t SizeInBits, AlignInBits;
913-
};
914-
915-
struct SizeAlign getNext() {
916-
if (Stack.empty())
917-
return {0, 0};
918-
919-
auto *Cur = Stack.pop_back_val();
920-
if (isa<llvm::DICompositeType>(Cur) &&
921-
Cur->getTag() != llvm::dwarf::DW_TAG_subroutine_type) {
922-
auto *CTy = cast<llvm::DICompositeType>(Cur);
923-
auto Elts = CTy->getElements();
924-
unsigned N = Cur->getTag() == llvm::dwarf::DW_TAG_union_type
925-
? std::min(1U, Elts.size()) // For unions, pick any one.
926-
: Elts.size();
927-
928-
if (N) {
929-
// Push all elements in reverse order.
930-
// FIXME: With a little more state we don't need to actually
931-
// store them on the Stack.
932-
for (unsigned I = N; I > 0; --I)
933-
Stack.push_back(cast<llvm::DIType>(Elts[I - 1]));
934-
return getNext();
935-
}
936-
}
937-
switch (Cur->getTag()) {
938-
case llvm::dwarf::DW_TAG_member:
939-
// FIXME: Correctly handle the explosion value for enum types
940-
// with indirect members.
941-
if (IndirectEnums.count(Cur))
942-
return {0, 0};
943-
[[clang::fallthrough]];
944-
case llvm::dwarf::DW_TAG_typedef: {
945-
// Replace top of stack.
946-
auto *DTy = cast<llvm::DIDerivedType>(Cur);
947-
Stack.push_back(DTy->getBaseType().resolve(DIRefMap));
948-
return getNext();
949-
}
950-
default:
951-
return {Cur->getSizeInBits(), Cur->getAlignInBits()};
952-
}
953-
}
954-
};
955-
956888
static Size
957889
getStorageSize(const llvm::DataLayout &DL, ArrayRef<llvm::Value *> Storage) {
958890
unsigned size = 0;
@@ -1012,13 +944,16 @@ void IRGenDebugInfo::emitVariableDeclaration(
1012944
Optimized, Flags);
1013945

1014946
// Insert a debug intrinsic into the current block.
1015-
unsigned OffsetInBits = 0;
1016947
auto *BB = Builder.GetInsertBlock();
1017948
bool IsPiece = Storage.size() > 1;
1018949
uint64_t SizeOfByte = CI.getTargetInfo().getCharWidth();
1019950
unsigned VarSizeInBits = getSizeInBits(Var, DIRefMap);
1020-
ElementSizes EltSizes(DITy, DIRefMap, IndirectEnumCases);
1021-
auto Dim = EltSizes.getNext();
951+
952+
// Running variables for the current/previous piece.
953+
unsigned SizeInBits = 0;
954+
unsigned AlignInBits = SizeOfByte;
955+
unsigned OffsetInBits = 0;
956+
1022957
for (llvm::Value *Piece : Storage) {
1023958
SmallVector<uint64_t, 3> Operands;
1024959
if (Indirection)
@@ -1030,35 +965,22 @@ void IRGenDebugInfo::emitVariableDeclaration(
1030965
Piece = llvm::ConstantInt::get(llvm::Type::getInt64Ty(M.getContext()), 0);
1031966

1032967
if (IsPiece) {
1033-
// Try to get the size from the type if possible.
1034-
auto StorageSize = getSizeFromExplosionValue(CI.getTargetInfo(), Piece);
1035-
// FIXME: The TypeInfo for bound generic enum types reports a
1036-
// type <{}> (with size 0) but a concrete instance may still
1037-
// have storage allocated for it. rdar://problem/21470869
1038-
if (!Dim.SizeInBits || (StorageSize && Dim.SizeInBits > StorageSize))
1039-
Dim.SizeInBits = StorageSize;
1040-
1041-
// FIXME: Occasionally we miss out that the Storage is actually a
1042-
// refcount wrapper. Silently skip these for now.
1043-
if (OffsetInBits+Dim.SizeInBits > VarSizeInBits)
1044-
break;
1045-
if (OffsetInBits == 0 && Dim.SizeInBits == VarSizeInBits)
1046-
break;
1047-
if (Dim.SizeInBits == 0)
1048-
break;
1049-
1050-
assert(Dim.SizeInBits < VarSizeInBits
1051-
&& "piece covers entire var");
1052-
assert(OffsetInBits+Dim.SizeInBits <= VarSizeInBits && "pars > totum");
968+
// Advance the offset and align it for the next piece.
969+
OffsetInBits += llvm::alignTo(SizeInBits, AlignInBits);
970+
SizeInBits = IGM.DataLayout.getTypeSizeInBits(Piece->getType());
971+
AlignInBits = IGM.DataLayout.getABITypeAlignment(Piece->getType());
972+
if (!AlignInBits)
973+
AlignInBits = SizeOfByte;
974+
975+
// Sanity checks.
976+
assert(SizeInBits && "zero-sized piece");
977+
assert(SizeInBits < VarSizeInBits && "piece covers entire var");
978+
assert(OffsetInBits+SizeInBits <= VarSizeInBits && "pars > totum");
979+
980+
// Add the piece DWARF expression.
1053981
Operands.push_back(llvm::dwarf::DW_OP_bit_piece);
1054982
Operands.push_back(OffsetInBits);
1055-
Operands.push_back(Dim.SizeInBits);
1056-
1057-
auto Size = Dim.SizeInBits;
1058-
Dim = EltSizes.getNext();
1059-
OffsetInBits +=
1060-
llvm::alignTo(Size, Dim.AlignInBits ? Dim.AlignInBits
1061-
: SizeOfByte);
983+
Operands.push_back(SizeInBits);
1062984
}
1063985
emitDbgIntrinsic(BB, Piece, Var, DBuilder.createExpression(Operands), Line,
1064986
Loc.Column, Scope, DS);
@@ -1343,14 +1265,46 @@ llvm::DIType *IRGenDebugInfo::createPointerSizedStruct(
13431265
unsigned PtrAlign = CI.getTargetInfo().getPointerAlign(0);
13441266
auto PtrTy = DBuilder.createPointerType(PointeeTy, PtrSize, PtrAlign);
13451267
llvm::Metadata *Elements[] = {
1346-
DBuilder.createMemberType(Scope, "pointer", File, 0,
1268+
DBuilder.createMemberType(Scope, "ptr", File, 0,
13471269
PtrSize, PtrAlign, 0, Flags, PtrTy)
13481270
};
13491271
return DBuilder.createStructType(
13501272
Scope, Name, File, Line, PtrSize, PtrAlign, Flags,
1351-
nullptr, // DerivedFrom
1352-
DBuilder.getOrCreateArray(Elements), llvm::dwarf::DW_LANG_Swift,
1353-
nullptr, MangledName);
1273+
/* DerivedFrom */ nullptr, DBuilder.getOrCreateArray(Elements),
1274+
llvm::dwarf::DW_LANG_Swift, nullptr, MangledName);
1275+
}
1276+
1277+
/// Create a 2*pointer-sized struct with a mangled name and a single
1278+
/// member of PointeeTy.
1279+
llvm::DIType *IRGenDebugInfo::createDoublePointerSizedStruct(
1280+
llvm::DIScope *Scope, StringRef Name, llvm::DIType *PointeeTy,
1281+
llvm::DIFile *File, unsigned Line, unsigned Flags, StringRef MangledName) {
1282+
unsigned PtrSize = CI.getTargetInfo().getPointerWidth(0);
1283+
unsigned PtrAlign = CI.getTargetInfo().getPointerAlign(0);
1284+
llvm::Metadata *Elements[] = {
1285+
DBuilder.createMemberType(
1286+
Scope, "ptr", File, 0, PtrSize, PtrAlign, 0, Flags,
1287+
DBuilder.createPointerType(PointeeTy, PtrSize, PtrAlign)),
1288+
DBuilder.createMemberType(
1289+
Scope, "_", File, 0, PtrSize, PtrAlign, 0, Flags,
1290+
DBuilder.createPointerType(nullptr, PtrSize, PtrAlign))};
1291+
return DBuilder.createStructType(
1292+
Scope, Name, File, Line, 2*PtrSize, PtrAlign, Flags,
1293+
/* DerivedFrom */ nullptr, DBuilder.getOrCreateArray(Elements),
1294+
llvm::dwarf::DW_LANG_Swift, nullptr, MangledName);
1295+
}
1296+
1297+
/// Create an opaque struct with a mangled name.
1298+
llvm::DIType *
1299+
IRGenDebugInfo::createOpaqueStruct(llvm::DIScope *Scope, StringRef Name,
1300+
llvm::DIFile *File, unsigned Line,
1301+
unsigned SizeInBits, unsigned AlignInBits,
1302+
unsigned Flags, StringRef MangledName) {
1303+
return DBuilder.createStructType(
1304+
Scope, Name, File, Line, SizeInBits, AlignInBits, Flags,
1305+
/* DerivedFrom */ nullptr,
1306+
DBuilder.getOrCreateArray(ArrayRef<llvm::Metadata *>()),
1307+
llvm::dwarf::DW_LANG_Swift, nullptr, MangledName);
13541308
}
13551309

13561310
/// Construct a DIType from a DebugTypeInfo object.
@@ -1506,6 +1460,7 @@ llvm::DIType *IRGenDebugInfo::createType(DebugTypeInfo DbgTy,
15061460
}
15071461
Scope = getOrCreateModule(ModuleName, TheCU, ModuleName, ModulePath);
15081462
}
1463+
assert(SizeInBits == CI.getTargetInfo().getPointerWidth(0));
15091464
return createPointerSizedStruct(Scope, Decl->getNameStr(),
15101465
getOrCreateFile(L.Filename), L.Line, Flags,
15111466
MangledName);
@@ -1517,9 +1472,9 @@ llvm::DIType *IRGenDebugInfo::createType(DebugTypeInfo DbgTy,
15171472
// FIXME: (LLVM branch) This should probably be a DW_TAG_interface_type.
15181473
auto L = getDebugLoc(SM, Decl);
15191474
auto File = getOrCreateFile(L.Filename);
1520-
return createPointerSizedStruct(Scope,
1521-
Decl ? Decl->getNameStr() : MangledName,
1522-
File, L.Line, Flags, MangledName);
1475+
return createOpaqueStruct(Scope, Decl ? Decl->getNameStr() : MangledName,
1476+
File, L.Line, SizeInBits, AlignInBits, Flags,
1477+
MangledName);
15231478
}
15241479

15251480
case TypeKind::ProtocolComposition: {
@@ -1529,15 +1484,16 @@ llvm::DIType *IRGenDebugInfo::createType(DebugTypeInfo DbgTy,
15291484

15301485
// FIXME: emit types
15311486
// auto ProtocolCompositionTy = BaseTy->castTo<ProtocolCompositionType>();
1532-
return createPointerSizedStruct(Scope,
1533-
Decl ? Decl->getNameStr() : MangledName,
1534-
File, L.Line, Flags, MangledName);
1487+
return createOpaqueStruct(Scope, Decl ? Decl->getNameStr() : MangledName,
1488+
File, L.Line, SizeInBits, AlignInBits, Flags,
1489+
MangledName);
15351490
}
15361491

15371492
case TypeKind::UnboundGeneric: {
15381493
auto *UnboundTy = BaseTy->castTo<UnboundGenericType>();
15391494
auto *Decl = UnboundTy->getDecl();
15401495
auto L = getDebugLoc(SM, Decl);
1496+
assert(SizeInBits == CI.getTargetInfo().getPointerWidth(0));
15411497
return createPointerSizedStruct(Scope,
15421498
Decl ? Decl->getNameStr() : MangledName,
15431499
File, L.Line, Flags, MangledName);
@@ -1547,9 +1503,9 @@ llvm::DIType *IRGenDebugInfo::createType(DebugTypeInfo DbgTy,
15471503
auto *StructTy = BaseTy->castTo<BoundGenericStructType>();
15481504
auto *Decl = StructTy->getDecl();
15491505
auto L = getDebugLoc(SM, Decl);
1550-
return createPointerSizedStruct(Scope,
1551-
Decl ? Decl->getNameStr() : MangledName,
1552-
File, L.Line, Flags, MangledName);
1506+
return createOpaqueStruct(Scope, Decl ? Decl->getNameStr() : MangledName,
1507+
File, L.Line, SizeInBits, AlignInBits, Flags,
1508+
MangledName);
15531509
}
15541510

15551511
case TypeKind::BoundGenericClass: {
@@ -1558,6 +1514,7 @@ llvm::DIType *IRGenDebugInfo::createType(DebugTypeInfo DbgTy,
15581514
auto L = getDebugLoc(SM, Decl);
15591515
// TODO: We may want to peek at Decl->isObjC() and set this
15601516
// attribute accordingly.
1517+
assert(SizeInBits == CI.getTargetInfo().getPointerWidth(0));
15611518
return createPointerSizedStruct(Scope,
15621519
Decl ? Decl->getNameStr() : MangledName,
15631520
File, L.Line, Flags, MangledName);
@@ -1649,39 +1606,49 @@ llvm::DIType *IRGenDebugInfo::createType(DebugTypeInfo DbgTy,
16491606
case TypeKind::Function:
16501607
case TypeKind::PolymorphicFunction:
16511608
case TypeKind::GenericFunction: {
1652-
auto FwdDecl = llvm::TempDINode(
1653-
DBuilder.createReplaceableCompositeType(
1609+
auto FwdDecl = llvm::TempDINode(DBuilder.createReplaceableCompositeType(
16541610
llvm::dwarf::DW_TAG_subroutine_type, MangledName, Scope, File, 0,
1655-
llvm::dwarf::DW_LANG_Swift, SizeInBits, AlignInBits, Flags,
1656-
MangledName));
1657-
1611+
llvm::dwarf::DW_LANG_Swift, SizeInBits, AlignInBits, Flags,
1612+
MangledName));
1613+
16581614
auto TH = llvm::TrackingMDNodeRef(FwdDecl.get());
16591615
DITypeCache[DbgTy.getType()] = TH;
16601616

1661-
CanSILFunctionType FunctionTy;
1617+
CanSILFunctionType FunTy;
16621618
if (auto *SILFnTy = dyn_cast<SILFunctionType>(BaseTy))
1663-
FunctionTy = CanSILFunctionType(SILFnTy);
1619+
FunTy = CanSILFunctionType(SILFnTy);
16641620
// FIXME: Handling of generic parameters in SIL type lowering is in flux.
16651621
// DebugInfo doesn't appear to care about the generic context, so just
16661622
// throw it away before lowering.
16671623
else if (isa<GenericFunctionType>(BaseTy) ||
16681624
isa<PolymorphicFunctionType>(BaseTy)) {
16691625
auto *fTy = cast<AnyFunctionType>(BaseTy);
16701626
auto *nongenericTy = FunctionType::get(fTy->getInput(), fTy->getResult(),
1671-
fTy->getExtInfo());
1627+
fTy->getExtInfo());
16721628

1673-
FunctionTy = IGM.SILMod->Types.getLoweredType(nongenericTy)
1674-
.castTo<SILFunctionType>();
1629+
FunTy = IGM.SILMod->Types.getLoweredType(nongenericTy)
1630+
.castTo<SILFunctionType>();
16751631
} else
1676-
FunctionTy =
1632+
FunTy =
16771633
IGM.SILMod->Types.getLoweredType(BaseTy).castTo<SILFunctionType>();
1678-
auto Params = createParameterTypes(FunctionTy, DbgTy.getDeclContext());
1634+
auto Params = createParameterTypes(FunTy, DbgTy.getDeclContext());
16791635

1680-
// Functions are actually stored as a Pointer or a FunctionPairTy:
1681-
// { i8*, %swift.refcounted* }
16821636
auto FnTy = DBuilder.createSubroutineType(Params, Flags);
1683-
auto DITy = createPointerSizedStruct(Scope, MangledName, FnTy,
1684-
MainFile, 0, Flags, MangledName);
1637+
llvm::DIType *DITy;
1638+
if (FunTy->getRepresentation() == SILFunctionType::Representation::Thick) {
1639+
if (SizeInBits == 2 * CI.getTargetInfo().getPointerWidth(0))
1640+
// This is a FunctionPairTy: { i8*, %swift.refcounted* }.
1641+
DITy = createDoublePointerSizedStruct(Scope, MangledName, FnTy,
1642+
MainFile, 0, Flags, MangledName);
1643+
else
1644+
// This is a generic function as noted above.
1645+
DITy = createOpaqueStruct(Scope, MangledName, MainFile, 0, SizeInBits,
1646+
AlignInBits, Flags, MangledName);
1647+
} else {
1648+
assert(SizeInBits == CI.getTargetInfo().getPointerWidth(0));
1649+
DITy = createPointerSizedStruct(Scope, MangledName, FnTy, MainFile, 0,
1650+
Flags, MangledName);
1651+
}
16851652
DBuilder.replaceTemporary(std::move(FwdDecl), DITy);
16861653
return DITy;
16871654
}

lib/IRGen/IRGenDebugInfo.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,13 @@ class IRGenDebugInfo {
264264
llvm::DIType *PointeeTy,
265265
llvm::DIFile *File, unsigned Line,
266266
unsigned Flags, StringRef MangledName);
267+
llvm::DIType *createDoublePointerSizedStruct(
268+
llvm::DIScope *Scope, StringRef Name, llvm::DIType *PointeeTy,
269+
llvm::DIFile *File, unsigned Line, unsigned Flags, StringRef MangledName);
270+
llvm::DIType *createOpaqueStruct(llvm::DIScope *Scope, StringRef Name,
271+
llvm::DIFile *File, unsigned Line,
272+
unsigned SizeInBits, unsigned AlignInBits,
273+
unsigned Flags, StringRef MangledName);
267274
uint64_t getSizeOfBasicType(DebugTypeInfo DbgTy);
268275
TypeAliasDecl *getMetadataType();
269276
};

test/DebugInfo/fnptr.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ func main() -> Int64 {
1313
// CHECK-DAG: !DILocalVariable(name: "bar_function_pointer",{{.*}} line: [[@LINE+1]],{{.*}} type: !"[[BARPT:[^,]+]]"
1414
var bar_function_pointer = bar
1515
// CHECK-DAG: !DICompositeType(tag: DW_TAG_structure_type, name: "[[BARPT]]",{{.*}} elements: ![[BARMEMBERS:[0-9]+]]
16-
// CHECK-DAG: ![[BARMEMBERS]] = !{![[BARMEMBER:.*]]}
16+
// CHECK-DAG: ![[BARMEMBERS]] = !{![[BARMEMBER:.*]], {{.*}}}
1717
// CHECK-DAG: ![[BARMEMBER]] = !DIDerivedType(tag: DW_TAG_member,{{.*}} baseType: ![[BARPTR:[0-9]+]]
1818
// CHECK-DAG: ![[BARPTR]] = !DIDerivedType(tag: DW_TAG_pointer_type,{{.*}} baseType: ![[BART:[0-9]+]]
1919
// CHECK-DAG: ![[BART]] = !DISubroutineType(types: ![[BARARGS:[0-9]+]])
@@ -22,7 +22,7 @@ func main() -> Int64 {
2222

2323
// CHECK-DAG: !DILocalVariable(name: "baz_function_pointer",{{.*}} type: !"[[BAZPT:[^,]+]]"
2424
// CHECK-DAG: !DICompositeType(tag: DW_TAG_structure_type, name: "[[BAZPT]]",{{.*}} elements: ![[BAZMEMBERS:[0-9]+]]
25-
// CHECK-DAG: ![[BAZMEMBERS]] = !{![[BAZMEMBER:.*]]}
25+
// CHECK-DAG: ![[BAZMEMBERS]] = !{![[BAZMEMBER:.*]], {{.*}}}
2626
// CHECK-DAG: ![[BAZMEMBER]] = !DIDerivedType(tag: DW_TAG_member,{{.*}} baseType: ![[BAZPTR:[0-9]+]]
2727
// CHECK-DAG: ![[BAZPTR]] = !DIDerivedType(tag: DW_TAG_pointer_type,{{.*}} baseType: ![[BAZT:[0-9]+]]
2828
// CHECK-DAG: ![[BAZT]] = !DISubroutineType(types: ![[BAZARGS:.*]])
@@ -32,7 +32,7 @@ func main() -> Int64 {
3232

3333
// CHECK-DAG: !DILocalVariable(name: "barz_function_pointer",{{.*}} type: !"[[BARZPT:[^,]+]]"
3434
// CHECK-DAG: !DICompositeType(tag: DW_TAG_structure_type, name: "[[BARZPT]]",{{.*}} elements: ![[BARZMEMBERS:[0-9]+]]
35-
// CHECK-DAG: ![[BARZMEMBERS]] = !{![[BARZMEMBER:.*]]}
35+
// CHECK-DAG: ![[BARZMEMBERS]] = !{![[BARZMEMBER:.*]], {{.*}}}
3636
// CHECK-DAG: ![[BARZMEMBER]] = !DIDerivedType(tag: DW_TAG_member,{{.*}} baseType: ![[BARZPTR:[0-9]+]]
3737
// CHECK-DAG: ![[BARZPTR]] = !DIDerivedType(tag: DW_TAG_pointer_type,{{.*}} baseType: ![[BARZT:[0-9]+]]
3838
// CHECK-DAG: ![[BARZT]] = !DISubroutineType(types: ![[BARZARGS:.*]])

0 commit comments

Comments
 (0)