@@ -885,6 +885,74 @@ llvm::DIFile *IRGenDebugInfo::getFile(llvm::DIScope *Scope) {
885
885
return cast<llvm::DIFile>(Scope);
886
886
}
887
887
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
+
888
956
static Size
889
957
getStorageSize (const llvm::DataLayout &DL, ArrayRef<llvm::Value *> Storage) {
890
958
unsigned size = 0 ;
@@ -944,16 +1012,13 @@ void IRGenDebugInfo::emitVariableDeclaration(
944
1012
Optimized, Flags);
945
1013
946
1014
// Insert a debug intrinsic into the current block.
1015
+ unsigned OffsetInBits = 0 ;
947
1016
auto *BB = Builder.GetInsertBlock ();
948
1017
bool IsPiece = Storage.size () > 1 ;
949
1018
uint64_t SizeOfByte = CI.getTargetInfo ().getCharWidth ();
950
1019
unsigned VarSizeInBits = getSizeInBits (Var, DIRefMap);
951
-
952
- // Running variables for the current/previous piece.
953
- unsigned SizeInBits = 0 ;
954
- unsigned AlignInBits = SizeOfByte;
955
- unsigned OffsetInBits = 0 ;
956
-
1020
+ ElementSizes EltSizes (DITy, DIRefMap, IndirectEnumCases);
1021
+ auto Dim = EltSizes.getNext ();
957
1022
for (llvm::Value *Piece : Storage) {
958
1023
SmallVector<uint64_t , 3 > Operands;
959
1024
if (Indirection)
@@ -965,22 +1030,32 @@ void IRGenDebugInfo::emitVariableDeclaration(
965
1030
Piece = llvm::ConstantInt::get (llvm::Type::getInt64Ty (M.getContext ()), 0 );
966
1031
967
1032
if (IsPiece) {
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.
1033
+ // Try to get the size from the type if possible.
1034
+ auto StorageSize = getSizeFromExplosionValue (CI.getTargetInfo (), Piece);
1035
+ assert ((Dim.SizeInBits != 0 || StorageSize != 0 ) &&
1036
+ " zero-sized variable with nonzero storage size" );
1037
+
1038
+ // FIXME: Occasionally we miss out that the Storage is actually a
1039
+ // refcount wrapper. Silently skip these for now.
1040
+ if (OffsetInBits+Dim.SizeInBits > VarSizeInBits)
1041
+ break ;
1042
+ if (OffsetInBits == 0 && Dim.SizeInBits == VarSizeInBits)
1043
+ break ;
1044
+ if (Dim.SizeInBits == 0 )
1045
+ break ;
1046
+
1047
+ assert (Dim.SizeInBits < VarSizeInBits
1048
+ && " piece covers entire var" );
1049
+ assert (OffsetInBits+Dim.SizeInBits <= VarSizeInBits && " pars > totum" );
981
1050
Operands.push_back (llvm::dwarf::DW_OP_bit_piece);
982
1051
Operands.push_back (OffsetInBits);
983
- Operands.push_back (SizeInBits);
1052
+ Operands.push_back (Dim.SizeInBits );
1053
+
1054
+ auto Size = Dim.SizeInBits ;
1055
+ Dim = EltSizes.getNext ();
1056
+ OffsetInBits +=
1057
+ llvm::alignTo (Size, Dim.AlignInBits ? Dim.AlignInBits
1058
+ : SizeOfByte);
984
1059
}
985
1060
emitDbgIntrinsic (BB, Piece, Var, DBuilder.createExpression (Operands), Line,
986
1061
Loc.Column , Scope, DS);
@@ -1259,46 +1334,14 @@ llvm::DIType *IRGenDebugInfo::createPointerSizedStruct(
1259
1334
unsigned PtrAlign = CI.getTargetInfo ().getPointerAlign (0 );
1260
1335
auto PtrTy = DBuilder.createPointerType (PointeeTy, PtrSize, PtrAlign);
1261
1336
llvm::Metadata *Elements[] = {
1262
- DBuilder.createMemberType (Scope, " ptr " , File, 0 ,
1337
+ DBuilder.createMemberType (Scope, " pointer " , File, 0 ,
1263
1338
PtrSize, PtrAlign, 0 , Flags, PtrTy)
1264
1339
};
1265
1340
return DBuilder.createStructType (
1266
1341
Scope, Name, File, Line, PtrSize, PtrAlign, Flags,
1267
- /* DerivedFrom */ nullptr , DBuilder.getOrCreateArray (Elements),
1268
- llvm::dwarf::DW_LANG_Swift, nullptr , MangledName);
1269
- }
1270
-
1271
- // / Create a 2*pointer-sized struct with a mangled name and a single
1272
- // / member of PointeeTy.
1273
- llvm::DIType *IRGenDebugInfo::createDoublePointerSizedStruct (
1274
- llvm::DIScope *Scope, StringRef Name, llvm::DIType *PointeeTy,
1275
- llvm::DIFile *File, unsigned Line, unsigned Flags, StringRef MangledName) {
1276
- unsigned PtrSize = CI.getTargetInfo ().getPointerWidth (0 );
1277
- unsigned PtrAlign = CI.getTargetInfo ().getPointerAlign (0 );
1278
- llvm::Metadata *Elements[] = {
1279
- DBuilder.createMemberType (
1280
- Scope, " ptr" , File, 0 , PtrSize, PtrAlign, 0 , Flags,
1281
- DBuilder.createPointerType (PointeeTy, PtrSize, PtrAlign)),
1282
- DBuilder.createMemberType (
1283
- Scope, " _" , File, 0 , PtrSize, PtrAlign, 0 , Flags,
1284
- DBuilder.createPointerType (nullptr , PtrSize, PtrAlign))};
1285
- return DBuilder.createStructType (
1286
- Scope, Name, File, Line, 2 *PtrSize, PtrAlign, Flags,
1287
- /* DerivedFrom */ nullptr , DBuilder.getOrCreateArray (Elements),
1288
- llvm::dwarf::DW_LANG_Swift, nullptr , MangledName);
1289
- }
1290
-
1291
- // / Create an opaque struct with a mangled name.
1292
- llvm::DIType *
1293
- IRGenDebugInfo::createOpaqueStruct (llvm::DIScope *Scope, StringRef Name,
1294
- llvm::DIFile *File, unsigned Line,
1295
- unsigned SizeInBits, unsigned AlignInBits,
1296
- unsigned Flags, StringRef MangledName) {
1297
- return DBuilder.createStructType (
1298
- Scope, Name, File, Line, SizeInBits, AlignInBits, Flags,
1299
- /* DerivedFrom */ nullptr ,
1300
- DBuilder.getOrCreateArray (ArrayRef<llvm::Metadata *>()),
1301
- llvm::dwarf::DW_LANG_Swift, nullptr , MangledName);
1342
+ nullptr , // DerivedFrom
1343
+ DBuilder.getOrCreateArray (Elements), llvm::dwarf::DW_LANG_Swift,
1344
+ nullptr , MangledName);
1302
1345
}
1303
1346
1304
1347
// / Construct a DIType from a DebugTypeInfo object.
@@ -1454,7 +1497,6 @@ llvm::DIType *IRGenDebugInfo::createType(DebugTypeInfo DbgTy,
1454
1497
}
1455
1498
Scope = getOrCreateModule (ModuleName, TheCU, ModuleName, ModulePath);
1456
1499
}
1457
- assert (SizeInBits == CI.getTargetInfo ().getPointerWidth (0 ));
1458
1500
return createPointerSizedStruct (Scope, Decl->getNameStr (),
1459
1501
getOrCreateFile (L.Filename ), L.Line , Flags,
1460
1502
MangledName);
@@ -1466,9 +1508,9 @@ llvm::DIType *IRGenDebugInfo::createType(DebugTypeInfo DbgTy,
1466
1508
// FIXME: (LLVM branch) This should probably be a DW_TAG_interface_type.
1467
1509
auto L = getDebugLoc (SM, Decl);
1468
1510
auto File = getOrCreateFile (L.Filename );
1469
- return createOpaqueStruct (Scope, Decl ? Decl-> getNameStr () : MangledName ,
1470
- File, L. Line , SizeInBits, AlignInBits, Flags ,
1471
- MangledName);
1511
+ return createPointerSizedStruct (Scope,
1512
+ Decl ? Decl-> getNameStr () : MangledName ,
1513
+ File, L. Line , Flags, MangledName);
1472
1514
}
1473
1515
1474
1516
case TypeKind::ProtocolComposition: {
@@ -1478,16 +1520,15 @@ llvm::DIType *IRGenDebugInfo::createType(DebugTypeInfo DbgTy,
1478
1520
1479
1521
// FIXME: emit types
1480
1522
// auto ProtocolCompositionTy = BaseTy->castTo<ProtocolCompositionType>();
1481
- return createOpaqueStruct (Scope, Decl ? Decl-> getNameStr () : MangledName ,
1482
- File, L. Line , SizeInBits, AlignInBits, Flags ,
1483
- MangledName);
1523
+ return createPointerSizedStruct (Scope,
1524
+ Decl ? Decl-> getNameStr () : MangledName ,
1525
+ File, L. Line , Flags, MangledName);
1484
1526
}
1485
1527
1486
1528
case TypeKind::UnboundGeneric: {
1487
1529
auto *UnboundTy = BaseTy->castTo <UnboundGenericType>();
1488
1530
auto *Decl = UnboundTy->getDecl ();
1489
1531
auto L = getDebugLoc (SM, Decl);
1490
- assert (SizeInBits == CI.getTargetInfo ().getPointerWidth (0 ));
1491
1532
return createPointerSizedStruct (Scope,
1492
1533
Decl ? Decl->getNameStr () : MangledName,
1493
1534
File, L.Line , Flags, MangledName);
@@ -1497,9 +1538,9 @@ llvm::DIType *IRGenDebugInfo::createType(DebugTypeInfo DbgTy,
1497
1538
auto *StructTy = BaseTy->castTo <BoundGenericStructType>();
1498
1539
auto *Decl = StructTy->getDecl ();
1499
1540
auto L = getDebugLoc (SM, Decl);
1500
- return createOpaqueStruct (Scope, Decl ? Decl-> getNameStr () : MangledName ,
1501
- File, L. Line , SizeInBits, AlignInBits, Flags ,
1502
- MangledName);
1541
+ return createPointerSizedStruct (Scope,
1542
+ Decl ? Decl-> getNameStr () : MangledName ,
1543
+ File, L. Line , Flags, MangledName);
1503
1544
}
1504
1545
1505
1546
case TypeKind::BoundGenericClass: {
@@ -1508,7 +1549,6 @@ llvm::DIType *IRGenDebugInfo::createType(DebugTypeInfo DbgTy,
1508
1549
auto L = getDebugLoc (SM, Decl);
1509
1550
// TODO: We may want to peek at Decl->isObjC() and set this
1510
1551
// attribute accordingly.
1511
- assert (SizeInBits == CI.getTargetInfo ().getPointerWidth (0 ));
1512
1552
return createPointerSizedStruct (Scope,
1513
1553
Decl ? Decl->getNameStr () : MangledName,
1514
1554
File, L.Line , Flags, MangledName);
@@ -1600,49 +1640,39 @@ llvm::DIType *IRGenDebugInfo::createType(DebugTypeInfo DbgTy,
1600
1640
case TypeKind::Function:
1601
1641
case TypeKind::PolymorphicFunction:
1602
1642
case TypeKind::GenericFunction: {
1603
- auto FwdDecl = llvm::TempDINode (DBuilder.createReplaceableCompositeType (
1643
+ auto FwdDecl = llvm::TempDINode (
1644
+ DBuilder.createReplaceableCompositeType (
1604
1645
llvm::dwarf::DW_TAG_subroutine_type, MangledName, Scope, File, 0 ,
1605
- llvm::dwarf::DW_LANG_Swift, SizeInBits, AlignInBits, Flags,
1606
- MangledName));
1607
-
1646
+ llvm::dwarf::DW_LANG_Swift, SizeInBits, AlignInBits, Flags,
1647
+ MangledName));
1648
+
1608
1649
auto TH = llvm::TrackingMDNodeRef (FwdDecl.get ());
1609
1650
DITypeCache[DbgTy.getType ()] = TH;
1610
1651
1611
- CanSILFunctionType FunTy ;
1652
+ CanSILFunctionType FunctionTy ;
1612
1653
if (auto *SILFnTy = dyn_cast<SILFunctionType>(BaseTy))
1613
- FunTy = CanSILFunctionType (SILFnTy);
1654
+ FunctionTy = CanSILFunctionType (SILFnTy);
1614
1655
// FIXME: Handling of generic parameters in SIL type lowering is in flux.
1615
1656
// DebugInfo doesn't appear to care about the generic context, so just
1616
1657
// throw it away before lowering.
1617
1658
else if (isa<GenericFunctionType>(BaseTy) ||
1618
1659
isa<PolymorphicFunctionType>(BaseTy)) {
1619
1660
auto *fTy = cast<AnyFunctionType>(BaseTy);
1620
1661
auto *nongenericTy = FunctionType::get (fTy ->getInput (), fTy ->getResult (),
1621
- fTy ->getExtInfo ());
1662
+ fTy ->getExtInfo ());
1622
1663
1623
- FunTy = IGM.SILMod ->Types .getLoweredType (nongenericTy)
1624
- .castTo <SILFunctionType>();
1664
+ FunctionTy = IGM.SILMod ->Types .getLoweredType (nongenericTy)
1665
+ .castTo <SILFunctionType>();
1625
1666
} else
1626
- FunTy =
1667
+ FunctionTy =
1627
1668
IGM.SILMod ->Types .getLoweredType (BaseTy).castTo <SILFunctionType>();
1628
- auto Params = createParameterTypes (FunTy , DbgTy.getDeclContext ());
1669
+ auto Params = createParameterTypes (FunctionTy , DbgTy.getDeclContext ());
1629
1670
1671
+ // Functions are actually stored as a Pointer or a FunctionPairTy:
1672
+ // { i8*, %swift.refcounted* }
1630
1673
auto FnTy = DBuilder.createSubroutineType (Params, Flags);
1631
- llvm::DIType *DITy;
1632
- if (FunTy->getRepresentation () == SILFunctionType::Representation::Thick) {
1633
- if (SizeInBits == 2 * CI.getTargetInfo ().getPointerWidth (0 ))
1634
- // This is a FunctionPairTy: { i8*, %swift.refcounted* }.
1635
- DITy = createDoublePointerSizedStruct (Scope, MangledName, FnTy,
1636
- MainFile, 0 , Flags, MangledName);
1637
- else
1638
- // This is a generic function as noted above.
1639
- DITy = createOpaqueStruct (Scope, MangledName, MainFile, 0 , SizeInBits,
1640
- AlignInBits, Flags, MangledName);
1641
- } else {
1642
- assert (SizeInBits == CI.getTargetInfo ().getPointerWidth (0 ));
1643
- DITy = createPointerSizedStruct (Scope, MangledName, FnTy, MainFile, 0 ,
1644
- Flags, MangledName);
1645
- }
1674
+ auto DITy = createPointerSizedStruct (Scope, MangledName, FnTy,
1675
+ MainFile, 0 , Flags, MangledName);
1646
1676
DBuilder.replaceTemporary (std::move (FwdDecl), DITy);
1647
1677
return DITy;
1648
1678
}
0 commit comments