mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Debug Info: Retreive the layout information of exploded values from the
explosion schema rather than from the debug type information and retire a bunch of heuristics that are no longer necessary. To enable this, this commit also includes a bugfix to debug info for opaque data structures with the correct size and alignment information. <rdar://problem/21470869+22707597>
This commit is contained in:
@@ -885,74 +885,6 @@ llvm::DIFile *IRGenDebugInfo::getFile(llvm::DIScope *Scope) {
|
|||||||
return cast<llvm::DIFile>(Scope);
|
return cast<llvm::DIFile>(Scope);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the storage size of an explosion value.
|
|
||||||
static uint64_t getSizeFromExplosionValue(const clang::TargetInfo &TI,
|
|
||||||
llvm::Value *V) {
|
|
||||||
llvm::Type *Ty = V->getType();
|
|
||||||
if (unsigned PrimitiveSize = Ty->getPrimitiveSizeInBits())
|
|
||||||
return PrimitiveSize;
|
|
||||||
else if (Ty->isPointerTy())
|
|
||||||
return TI.getPointerWidth(0);
|
|
||||||
else
|
|
||||||
llvm_unreachable("unhandled type of explosion value");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A generator that recursively returns the size of each element of a
|
|
||||||
/// composite type.
|
|
||||||
class ElementSizes {
|
|
||||||
const TrackingDIRefMap &DIRefMap;
|
|
||||||
llvm::SmallPtrSetImpl<const llvm::DIType *> &IndirectEnums;
|
|
||||||
llvm::SmallVector<const llvm::DIType *, 12> Stack;
|
|
||||||
public:
|
|
||||||
ElementSizes(const llvm::DIType *DITy, const TrackingDIRefMap &DIRefMap,
|
|
||||||
llvm::SmallPtrSetImpl<const llvm::DIType *> &IndirectEnums)
|
|
||||||
: DIRefMap(DIRefMap), IndirectEnums(IndirectEnums), Stack(1, DITy) {}
|
|
||||||
|
|
||||||
struct SizeAlign {
|
|
||||||
uint64_t SizeInBits, AlignInBits;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct SizeAlign getNext() {
|
|
||||||
if (Stack.empty())
|
|
||||||
return {0, 0};
|
|
||||||
|
|
||||||
auto *Cur = Stack.pop_back_val();
|
|
||||||
if (isa<llvm::DICompositeType>(Cur) &&
|
|
||||||
Cur->getTag() != llvm::dwarf::DW_TAG_subroutine_type) {
|
|
||||||
auto *CTy = cast<llvm::DICompositeType>(Cur);
|
|
||||||
auto Elts = CTy->getElements();
|
|
||||||
unsigned N = Cur->getTag() == llvm::dwarf::DW_TAG_union_type
|
|
||||||
? std::min(1U, Elts.size()) // For unions, pick any one.
|
|
||||||
: Elts.size();
|
|
||||||
|
|
||||||
if (N) {
|
|
||||||
// Push all elements in reverse order.
|
|
||||||
// FIXME: With a little more state we don't need to actually
|
|
||||||
// store them on the Stack.
|
|
||||||
for (unsigned I = N; I > 0; --I)
|
|
||||||
Stack.push_back(cast<llvm::DIType>(Elts[I - 1]));
|
|
||||||
return getNext();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
switch (Cur->getTag()) {
|
|
||||||
case llvm::dwarf::DW_TAG_member:
|
|
||||||
// FIXME: Correctly handle the explosion value for enum types
|
|
||||||
// with indirect members.
|
|
||||||
if (IndirectEnums.count(Cur))
|
|
||||||
return {0, 0};
|
|
||||||
[[clang::fallthrough]];
|
|
||||||
case llvm::dwarf::DW_TAG_typedef: {
|
|
||||||
// Replace top of stack.
|
|
||||||
auto *DTy = cast<llvm::DIDerivedType>(Cur);
|
|
||||||
Stack.push_back(DTy->getBaseType().resolve(DIRefMap));
|
|
||||||
return getNext();
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
return {Cur->getSizeInBits(), Cur->getAlignInBits()};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
static Size
|
static Size
|
||||||
getStorageSize(const llvm::DataLayout &DL, ArrayRef<llvm::Value *> Storage) {
|
getStorageSize(const llvm::DataLayout &DL, ArrayRef<llvm::Value *> Storage) {
|
||||||
unsigned size = 0;
|
unsigned size = 0;
|
||||||
@@ -1012,13 +944,16 @@ void IRGenDebugInfo::emitVariableDeclaration(
|
|||||||
Optimized, Flags);
|
Optimized, Flags);
|
||||||
|
|
||||||
// Insert a debug intrinsic into the current block.
|
// Insert a debug intrinsic into the current block.
|
||||||
unsigned OffsetInBits = 0;
|
|
||||||
auto *BB = Builder.GetInsertBlock();
|
auto *BB = Builder.GetInsertBlock();
|
||||||
bool IsPiece = Storage.size() > 1;
|
bool IsPiece = Storage.size() > 1;
|
||||||
uint64_t SizeOfByte = CI.getTargetInfo().getCharWidth();
|
uint64_t SizeOfByte = CI.getTargetInfo().getCharWidth();
|
||||||
unsigned VarSizeInBits = getSizeInBits(Var, DIRefMap);
|
unsigned VarSizeInBits = getSizeInBits(Var, DIRefMap);
|
||||||
ElementSizes EltSizes(DITy, DIRefMap, IndirectEnumCases);
|
|
||||||
auto Dim = EltSizes.getNext();
|
// Running variables for the current/previous piece.
|
||||||
|
unsigned SizeInBits = 0;
|
||||||
|
unsigned AlignInBits = SizeOfByte;
|
||||||
|
unsigned OffsetInBits = 0;
|
||||||
|
|
||||||
for (llvm::Value *Piece : Storage) {
|
for (llvm::Value *Piece : Storage) {
|
||||||
SmallVector<uint64_t, 3> Operands;
|
SmallVector<uint64_t, 3> Operands;
|
||||||
if (Indirection)
|
if (Indirection)
|
||||||
@@ -1030,32 +965,22 @@ void IRGenDebugInfo::emitVariableDeclaration(
|
|||||||
Piece = llvm::ConstantInt::get(llvm::Type::getInt64Ty(M.getContext()), 0);
|
Piece = llvm::ConstantInt::get(llvm::Type::getInt64Ty(M.getContext()), 0);
|
||||||
|
|
||||||
if (IsPiece) {
|
if (IsPiece) {
|
||||||
// Try to get the size from the type if possible.
|
// Advance the offset and align it for the next piece.
|
||||||
auto StorageSize = getSizeFromExplosionValue(CI.getTargetInfo(), Piece);
|
OffsetInBits += llvm::alignTo(SizeInBits, AlignInBits);
|
||||||
assert((Dim.SizeInBits != 0 || StorageSize != 0) &&
|
SizeInBits = IGM.DataLayout.getTypeSizeInBits(Piece->getType());
|
||||||
"zero-sized variable with nonzero storage size");
|
AlignInBits = IGM.DataLayout.getABITypeAlignment(Piece->getType());
|
||||||
|
if (!AlignInBits)
|
||||||
|
AlignInBits = SizeOfByte;
|
||||||
|
|
||||||
// FIXME: Occasionally we miss out that the Storage is actually a
|
// Sanity checks.
|
||||||
// refcount wrapper. Silently skip these for now.
|
assert(SizeInBits && "zero-sized piece");
|
||||||
if (OffsetInBits+Dim.SizeInBits > VarSizeInBits)
|
assert(SizeInBits < VarSizeInBits && "piece covers entire var");
|
||||||
break;
|
assert(OffsetInBits+SizeInBits <= VarSizeInBits && "pars > totum");
|
||||||
if (OffsetInBits == 0 && Dim.SizeInBits == VarSizeInBits)
|
|
||||||
break;
|
|
||||||
if (Dim.SizeInBits == 0)
|
|
||||||
break;
|
|
||||||
|
|
||||||
assert(Dim.SizeInBits < VarSizeInBits
|
// Add the piece DWARF expression.
|
||||||
&& "piece covers entire var");
|
|
||||||
assert(OffsetInBits+Dim.SizeInBits <= VarSizeInBits && "pars > totum");
|
|
||||||
Operands.push_back(llvm::dwarf::DW_OP_bit_piece);
|
Operands.push_back(llvm::dwarf::DW_OP_bit_piece);
|
||||||
Operands.push_back(OffsetInBits);
|
Operands.push_back(OffsetInBits);
|
||||||
Operands.push_back(Dim.SizeInBits);
|
Operands.push_back(SizeInBits);
|
||||||
|
|
||||||
auto Size = Dim.SizeInBits;
|
|
||||||
Dim = EltSizes.getNext();
|
|
||||||
OffsetInBits +=
|
|
||||||
llvm::alignTo(Size, Dim.AlignInBits ? Dim.AlignInBits
|
|
||||||
: SizeOfByte);
|
|
||||||
}
|
}
|
||||||
emitDbgIntrinsic(BB, Piece, Var, DBuilder.createExpression(Operands), Line,
|
emitDbgIntrinsic(BB, Piece, Var, DBuilder.createExpression(Operands), Line,
|
||||||
Loc.Column, Scope, DS);
|
Loc.Column, Scope, DS);
|
||||||
@@ -1334,14 +1259,46 @@ llvm::DIType *IRGenDebugInfo::createPointerSizedStruct(
|
|||||||
unsigned PtrAlign = CI.getTargetInfo().getPointerAlign(0);
|
unsigned PtrAlign = CI.getTargetInfo().getPointerAlign(0);
|
||||||
auto PtrTy = DBuilder.createPointerType(PointeeTy, PtrSize, PtrAlign);
|
auto PtrTy = DBuilder.createPointerType(PointeeTy, PtrSize, PtrAlign);
|
||||||
llvm::Metadata *Elements[] = {
|
llvm::Metadata *Elements[] = {
|
||||||
DBuilder.createMemberType(Scope, "pointer", File, 0,
|
DBuilder.createMemberType(Scope, "ptr", File, 0,
|
||||||
PtrSize, PtrAlign, 0, Flags, PtrTy)
|
PtrSize, PtrAlign, 0, Flags, PtrTy)
|
||||||
};
|
};
|
||||||
return DBuilder.createStructType(
|
return DBuilder.createStructType(
|
||||||
Scope, Name, File, Line, PtrSize, PtrAlign, Flags,
|
Scope, Name, File, Line, PtrSize, PtrAlign, Flags,
|
||||||
nullptr, // DerivedFrom
|
/* DerivedFrom */ nullptr, DBuilder.getOrCreateArray(Elements),
|
||||||
DBuilder.getOrCreateArray(Elements), llvm::dwarf::DW_LANG_Swift,
|
llvm::dwarf::DW_LANG_Swift, nullptr, MangledName);
|
||||||
nullptr, MangledName);
|
}
|
||||||
|
|
||||||
|
/// Create a 2*pointer-sized struct with a mangled name and a single
|
||||||
|
/// member of PointeeTy.
|
||||||
|
llvm::DIType *IRGenDebugInfo::createDoublePointerSizedStruct(
|
||||||
|
llvm::DIScope *Scope, StringRef Name, llvm::DIType *PointeeTy,
|
||||||
|
llvm::DIFile *File, unsigned Line, unsigned Flags, StringRef MangledName) {
|
||||||
|
unsigned PtrSize = CI.getTargetInfo().getPointerWidth(0);
|
||||||
|
unsigned PtrAlign = CI.getTargetInfo().getPointerAlign(0);
|
||||||
|
llvm::Metadata *Elements[] = {
|
||||||
|
DBuilder.createMemberType(
|
||||||
|
Scope, "ptr", File, 0, PtrSize, PtrAlign, 0, Flags,
|
||||||
|
DBuilder.createPointerType(PointeeTy, PtrSize, PtrAlign)),
|
||||||
|
DBuilder.createMemberType(
|
||||||
|
Scope, "_", File, 0, PtrSize, PtrAlign, 0, Flags,
|
||||||
|
DBuilder.createPointerType(nullptr, PtrSize, PtrAlign))};
|
||||||
|
return DBuilder.createStructType(
|
||||||
|
Scope, Name, File, Line, 2*PtrSize, PtrAlign, Flags,
|
||||||
|
/* DerivedFrom */ nullptr, DBuilder.getOrCreateArray(Elements),
|
||||||
|
llvm::dwarf::DW_LANG_Swift, nullptr, MangledName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create an opaque struct with a mangled name.
|
||||||
|
llvm::DIType *
|
||||||
|
IRGenDebugInfo::createOpaqueStruct(llvm::DIScope *Scope, StringRef Name,
|
||||||
|
llvm::DIFile *File, unsigned Line,
|
||||||
|
unsigned SizeInBits, unsigned AlignInBits,
|
||||||
|
unsigned Flags, StringRef MangledName) {
|
||||||
|
return DBuilder.createStructType(
|
||||||
|
Scope, Name, File, Line, SizeInBits, AlignInBits, Flags,
|
||||||
|
/* DerivedFrom */ nullptr,
|
||||||
|
DBuilder.getOrCreateArray(ArrayRef<llvm::Metadata *>()),
|
||||||
|
llvm::dwarf::DW_LANG_Swift, nullptr, MangledName);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Construct a DIType from a DebugTypeInfo object.
|
/// Construct a DIType from a DebugTypeInfo object.
|
||||||
@@ -1497,6 +1454,7 @@ llvm::DIType *IRGenDebugInfo::createType(DebugTypeInfo DbgTy,
|
|||||||
}
|
}
|
||||||
Scope = getOrCreateModule(ModuleName, TheCU, ModuleName, ModulePath);
|
Scope = getOrCreateModule(ModuleName, TheCU, ModuleName, ModulePath);
|
||||||
}
|
}
|
||||||
|
assert(SizeInBits == CI.getTargetInfo().getPointerWidth(0));
|
||||||
return createPointerSizedStruct(Scope, Decl->getNameStr(),
|
return createPointerSizedStruct(Scope, Decl->getNameStr(),
|
||||||
getOrCreateFile(L.Filename), L.Line, Flags,
|
getOrCreateFile(L.Filename), L.Line, Flags,
|
||||||
MangledName);
|
MangledName);
|
||||||
@@ -1508,9 +1466,9 @@ llvm::DIType *IRGenDebugInfo::createType(DebugTypeInfo DbgTy,
|
|||||||
// FIXME: (LLVM branch) This should probably be a DW_TAG_interface_type.
|
// FIXME: (LLVM branch) This should probably be a DW_TAG_interface_type.
|
||||||
auto L = getDebugLoc(SM, Decl);
|
auto L = getDebugLoc(SM, Decl);
|
||||||
auto File = getOrCreateFile(L.Filename);
|
auto File = getOrCreateFile(L.Filename);
|
||||||
return createPointerSizedStruct(Scope,
|
return createOpaqueStruct(Scope, Decl ? Decl->getNameStr() : MangledName,
|
||||||
Decl ? Decl->getNameStr() : MangledName,
|
File, L.Line, SizeInBits, AlignInBits, Flags,
|
||||||
File, L.Line, Flags, MangledName);
|
MangledName);
|
||||||
}
|
}
|
||||||
|
|
||||||
case TypeKind::ProtocolComposition: {
|
case TypeKind::ProtocolComposition: {
|
||||||
@@ -1520,15 +1478,16 @@ llvm::DIType *IRGenDebugInfo::createType(DebugTypeInfo DbgTy,
|
|||||||
|
|
||||||
// FIXME: emit types
|
// FIXME: emit types
|
||||||
// auto ProtocolCompositionTy = BaseTy->castTo<ProtocolCompositionType>();
|
// auto ProtocolCompositionTy = BaseTy->castTo<ProtocolCompositionType>();
|
||||||
return createPointerSizedStruct(Scope,
|
return createOpaqueStruct(Scope, Decl ? Decl->getNameStr() : MangledName,
|
||||||
Decl ? Decl->getNameStr() : MangledName,
|
File, L.Line, SizeInBits, AlignInBits, Flags,
|
||||||
File, L.Line, Flags, MangledName);
|
MangledName);
|
||||||
}
|
}
|
||||||
|
|
||||||
case TypeKind::UnboundGeneric: {
|
case TypeKind::UnboundGeneric: {
|
||||||
auto *UnboundTy = BaseTy->castTo<UnboundGenericType>();
|
auto *UnboundTy = BaseTy->castTo<UnboundGenericType>();
|
||||||
auto *Decl = UnboundTy->getDecl();
|
auto *Decl = UnboundTy->getDecl();
|
||||||
auto L = getDebugLoc(SM, Decl);
|
auto L = getDebugLoc(SM, Decl);
|
||||||
|
assert(SizeInBits == CI.getTargetInfo().getPointerWidth(0));
|
||||||
return createPointerSizedStruct(Scope,
|
return createPointerSizedStruct(Scope,
|
||||||
Decl ? Decl->getNameStr() : MangledName,
|
Decl ? Decl->getNameStr() : MangledName,
|
||||||
File, L.Line, Flags, MangledName);
|
File, L.Line, Flags, MangledName);
|
||||||
@@ -1538,9 +1497,9 @@ llvm::DIType *IRGenDebugInfo::createType(DebugTypeInfo DbgTy,
|
|||||||
auto *StructTy = BaseTy->castTo<BoundGenericStructType>();
|
auto *StructTy = BaseTy->castTo<BoundGenericStructType>();
|
||||||
auto *Decl = StructTy->getDecl();
|
auto *Decl = StructTy->getDecl();
|
||||||
auto L = getDebugLoc(SM, Decl);
|
auto L = getDebugLoc(SM, Decl);
|
||||||
return createPointerSizedStruct(Scope,
|
return createOpaqueStruct(Scope, Decl ? Decl->getNameStr() : MangledName,
|
||||||
Decl ? Decl->getNameStr() : MangledName,
|
File, L.Line, SizeInBits, AlignInBits, Flags,
|
||||||
File, L.Line, Flags, MangledName);
|
MangledName);
|
||||||
}
|
}
|
||||||
|
|
||||||
case TypeKind::BoundGenericClass: {
|
case TypeKind::BoundGenericClass: {
|
||||||
@@ -1549,6 +1508,7 @@ llvm::DIType *IRGenDebugInfo::createType(DebugTypeInfo DbgTy,
|
|||||||
auto L = getDebugLoc(SM, Decl);
|
auto L = getDebugLoc(SM, Decl);
|
||||||
// TODO: We may want to peek at Decl->isObjC() and set this
|
// TODO: We may want to peek at Decl->isObjC() and set this
|
||||||
// attribute accordingly.
|
// attribute accordingly.
|
||||||
|
assert(SizeInBits == CI.getTargetInfo().getPointerWidth(0));
|
||||||
return createPointerSizedStruct(Scope,
|
return createPointerSizedStruct(Scope,
|
||||||
Decl ? Decl->getNameStr() : MangledName,
|
Decl ? Decl->getNameStr() : MangledName,
|
||||||
File, L.Line, Flags, MangledName);
|
File, L.Line, Flags, MangledName);
|
||||||
@@ -1640,18 +1600,17 @@ llvm::DIType *IRGenDebugInfo::createType(DebugTypeInfo DbgTy,
|
|||||||
case TypeKind::Function:
|
case TypeKind::Function:
|
||||||
case TypeKind::PolymorphicFunction:
|
case TypeKind::PolymorphicFunction:
|
||||||
case TypeKind::GenericFunction: {
|
case TypeKind::GenericFunction: {
|
||||||
auto FwdDecl = llvm::TempDINode(
|
auto FwdDecl = llvm::TempDINode(DBuilder.createReplaceableCompositeType(
|
||||||
DBuilder.createReplaceableCompositeType(
|
|
||||||
llvm::dwarf::DW_TAG_subroutine_type, MangledName, Scope, File, 0,
|
llvm::dwarf::DW_TAG_subroutine_type, MangledName, Scope, File, 0,
|
||||||
llvm::dwarf::DW_LANG_Swift, SizeInBits, AlignInBits, Flags,
|
llvm::dwarf::DW_LANG_Swift, SizeInBits, AlignInBits, Flags,
|
||||||
MangledName));
|
MangledName));
|
||||||
|
|
||||||
auto TH = llvm::TrackingMDNodeRef(FwdDecl.get());
|
auto TH = llvm::TrackingMDNodeRef(FwdDecl.get());
|
||||||
DITypeCache[DbgTy.getType()] = TH;
|
DITypeCache[DbgTy.getType()] = TH;
|
||||||
|
|
||||||
CanSILFunctionType FunctionTy;
|
CanSILFunctionType FunTy;
|
||||||
if (auto *SILFnTy = dyn_cast<SILFunctionType>(BaseTy))
|
if (auto *SILFnTy = dyn_cast<SILFunctionType>(BaseTy))
|
||||||
FunctionTy = CanSILFunctionType(SILFnTy);
|
FunTy = CanSILFunctionType(SILFnTy);
|
||||||
// FIXME: Handling of generic parameters in SIL type lowering is in flux.
|
// FIXME: Handling of generic parameters in SIL type lowering is in flux.
|
||||||
// DebugInfo doesn't appear to care about the generic context, so just
|
// DebugInfo doesn't appear to care about the generic context, so just
|
||||||
// throw it away before lowering.
|
// throw it away before lowering.
|
||||||
@@ -1659,20 +1618,31 @@ llvm::DIType *IRGenDebugInfo::createType(DebugTypeInfo DbgTy,
|
|||||||
isa<PolymorphicFunctionType>(BaseTy)) {
|
isa<PolymorphicFunctionType>(BaseTy)) {
|
||||||
auto *fTy = cast<AnyFunctionType>(BaseTy);
|
auto *fTy = cast<AnyFunctionType>(BaseTy);
|
||||||
auto *nongenericTy = FunctionType::get(fTy->getInput(), fTy->getResult(),
|
auto *nongenericTy = FunctionType::get(fTy->getInput(), fTy->getResult(),
|
||||||
fTy->getExtInfo());
|
fTy->getExtInfo());
|
||||||
|
|
||||||
FunctionTy = IGM.SILMod->Types.getLoweredType(nongenericTy)
|
FunTy = IGM.SILMod->Types.getLoweredType(nongenericTy)
|
||||||
.castTo<SILFunctionType>();
|
.castTo<SILFunctionType>();
|
||||||
} else
|
} else
|
||||||
FunctionTy =
|
FunTy =
|
||||||
IGM.SILMod->Types.getLoweredType(BaseTy).castTo<SILFunctionType>();
|
IGM.SILMod->Types.getLoweredType(BaseTy).castTo<SILFunctionType>();
|
||||||
auto Params = createParameterTypes(FunctionTy, DbgTy.getDeclContext());
|
auto Params = createParameterTypes(FunTy, DbgTy.getDeclContext());
|
||||||
|
|
||||||
// Functions are actually stored as a Pointer or a FunctionPairTy:
|
|
||||||
// { i8*, %swift.refcounted* }
|
|
||||||
auto FnTy = DBuilder.createSubroutineType(Params, Flags);
|
auto FnTy = DBuilder.createSubroutineType(Params, Flags);
|
||||||
auto DITy = createPointerSizedStruct(Scope, MangledName, FnTy,
|
llvm::DIType *DITy;
|
||||||
MainFile, 0, Flags, MangledName);
|
if (FunTy->getRepresentation() == SILFunctionType::Representation::Thick) {
|
||||||
|
if (SizeInBits == 2 * CI.getTargetInfo().getPointerWidth(0))
|
||||||
|
// This is a FunctionPairTy: { i8*, %swift.refcounted* }.
|
||||||
|
DITy = createDoublePointerSizedStruct(Scope, MangledName, FnTy,
|
||||||
|
MainFile, 0, Flags, MangledName);
|
||||||
|
else
|
||||||
|
// This is a generic function as noted above.
|
||||||
|
DITy = createOpaqueStruct(Scope, MangledName, MainFile, 0, SizeInBits,
|
||||||
|
AlignInBits, Flags, MangledName);
|
||||||
|
} else {
|
||||||
|
assert(SizeInBits == CI.getTargetInfo().getPointerWidth(0));
|
||||||
|
DITy = createPointerSizedStruct(Scope, MangledName, FnTy, MainFile, 0,
|
||||||
|
Flags, MangledName);
|
||||||
|
}
|
||||||
DBuilder.replaceTemporary(std::move(FwdDecl), DITy);
|
DBuilder.replaceTemporary(std::move(FwdDecl), DITy);
|
||||||
return DITy;
|
return DITy;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -264,6 +264,13 @@ private:
|
|||||||
llvm::DIType *PointeeTy,
|
llvm::DIType *PointeeTy,
|
||||||
llvm::DIFile *File, unsigned Line,
|
llvm::DIFile *File, unsigned Line,
|
||||||
unsigned Flags, StringRef MangledName);
|
unsigned Flags, StringRef MangledName);
|
||||||
|
llvm::DIType *createDoublePointerSizedStruct(
|
||||||
|
llvm::DIScope *Scope, StringRef Name, llvm::DIType *PointeeTy,
|
||||||
|
llvm::DIFile *File, unsigned Line, unsigned Flags, StringRef MangledName);
|
||||||
|
llvm::DIType *createOpaqueStruct(llvm::DIScope *Scope, StringRef Name,
|
||||||
|
llvm::DIFile *File, unsigned Line,
|
||||||
|
unsigned SizeInBits, unsigned AlignInBits,
|
||||||
|
unsigned Flags, StringRef MangledName);
|
||||||
uint64_t getSizeOfBasicType(DebugTypeInfo DbgTy);
|
uint64_t getSizeOfBasicType(DebugTypeInfo DbgTy);
|
||||||
TypeAliasDecl *getMetadataType();
|
TypeAliasDecl *getMetadataType();
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ func main() -> Int64 {
|
|||||||
// CHECK-DAG: !DILocalVariable(name: "bar_function_pointer",{{.*}} line: [[@LINE+1]],{{.*}} type: !"[[BARPT:[^,]+]]"
|
// CHECK-DAG: !DILocalVariable(name: "bar_function_pointer",{{.*}} line: [[@LINE+1]],{{.*}} type: !"[[BARPT:[^,]+]]"
|
||||||
var bar_function_pointer = bar
|
var bar_function_pointer = bar
|
||||||
// CHECK-DAG: !DICompositeType(tag: DW_TAG_structure_type, name: "[[BARPT]]",{{.*}} elements: ![[BARMEMBERS:[0-9]+]]
|
// CHECK-DAG: !DICompositeType(tag: DW_TAG_structure_type, name: "[[BARPT]]",{{.*}} elements: ![[BARMEMBERS:[0-9]+]]
|
||||||
// CHECK-DAG: ![[BARMEMBERS]] = !{![[BARMEMBER:.*]]}
|
// CHECK-DAG: ![[BARMEMBERS]] = !{![[BARMEMBER:.*]], {{.*}}}
|
||||||
// CHECK-DAG: ![[BARMEMBER]] = !DIDerivedType(tag: DW_TAG_member,{{.*}} baseType: ![[BARPTR:[0-9]+]]
|
// CHECK-DAG: ![[BARMEMBER]] = !DIDerivedType(tag: DW_TAG_member,{{.*}} baseType: ![[BARPTR:[0-9]+]]
|
||||||
// CHECK-DAG: ![[BARPTR]] = !DIDerivedType(tag: DW_TAG_pointer_type,{{.*}} baseType: ![[BART:[0-9]+]]
|
// CHECK-DAG: ![[BARPTR]] = !DIDerivedType(tag: DW_TAG_pointer_type,{{.*}} baseType: ![[BART:[0-9]+]]
|
||||||
// CHECK-DAG: ![[BART]] = !DISubroutineType(types: ![[BARARGS:[0-9]+]])
|
// CHECK-DAG: ![[BART]] = !DISubroutineType(types: ![[BARARGS:[0-9]+]])
|
||||||
@@ -22,7 +22,7 @@ func main() -> Int64 {
|
|||||||
|
|
||||||
// CHECK-DAG: !DILocalVariable(name: "baz_function_pointer",{{.*}} type: !"[[BAZPT:[^,]+]]"
|
// CHECK-DAG: !DILocalVariable(name: "baz_function_pointer",{{.*}} type: !"[[BAZPT:[^,]+]]"
|
||||||
// CHECK-DAG: !DICompositeType(tag: DW_TAG_structure_type, name: "[[BAZPT]]",{{.*}} elements: ![[BAZMEMBERS:[0-9]+]]
|
// CHECK-DAG: !DICompositeType(tag: DW_TAG_structure_type, name: "[[BAZPT]]",{{.*}} elements: ![[BAZMEMBERS:[0-9]+]]
|
||||||
// CHECK-DAG: ![[BAZMEMBERS]] = !{![[BAZMEMBER:.*]]}
|
// CHECK-DAG: ![[BAZMEMBERS]] = !{![[BAZMEMBER:.*]], {{.*}}}
|
||||||
// CHECK-DAG: ![[BAZMEMBER]] = !DIDerivedType(tag: DW_TAG_member,{{.*}} baseType: ![[BAZPTR:[0-9]+]]
|
// CHECK-DAG: ![[BAZMEMBER]] = !DIDerivedType(tag: DW_TAG_member,{{.*}} baseType: ![[BAZPTR:[0-9]+]]
|
||||||
// CHECK-DAG: ![[BAZPTR]] = !DIDerivedType(tag: DW_TAG_pointer_type,{{.*}} baseType: ![[BAZT:[0-9]+]]
|
// CHECK-DAG: ![[BAZPTR]] = !DIDerivedType(tag: DW_TAG_pointer_type,{{.*}} baseType: ![[BAZT:[0-9]+]]
|
||||||
// CHECK-DAG: ![[BAZT]] = !DISubroutineType(types: ![[BAZARGS:.*]])
|
// CHECK-DAG: ![[BAZT]] = !DISubroutineType(types: ![[BAZARGS:.*]])
|
||||||
@@ -32,7 +32,7 @@ func main() -> Int64 {
|
|||||||
|
|
||||||
// CHECK-DAG: !DILocalVariable(name: "barz_function_pointer",{{.*}} type: !"[[BARZPT:[^,]+]]"
|
// CHECK-DAG: !DILocalVariable(name: "barz_function_pointer",{{.*}} type: !"[[BARZPT:[^,]+]]"
|
||||||
// CHECK-DAG: !DICompositeType(tag: DW_TAG_structure_type, name: "[[BARZPT]]",{{.*}} elements: ![[BARZMEMBERS:[0-9]+]]
|
// CHECK-DAG: !DICompositeType(tag: DW_TAG_structure_type, name: "[[BARZPT]]",{{.*}} elements: ![[BARZMEMBERS:[0-9]+]]
|
||||||
// CHECK-DAG: ![[BARZMEMBERS]] = !{![[BARZMEMBER:.*]]}
|
// CHECK-DAG: ![[BARZMEMBERS]] = !{![[BARZMEMBER:.*]], {{.*}}}
|
||||||
// CHECK-DAG: ![[BARZMEMBER]] = !DIDerivedType(tag: DW_TAG_member,{{.*}} baseType: ![[BARZPTR:[0-9]+]]
|
// CHECK-DAG: ![[BARZMEMBER]] = !DIDerivedType(tag: DW_TAG_member,{{.*}} baseType: ![[BARZPTR:[0-9]+]]
|
||||||
// CHECK-DAG: ![[BARZPTR]] = !DIDerivedType(tag: DW_TAG_pointer_type,{{.*}} baseType: ![[BARZT:[0-9]+]]
|
// CHECK-DAG: ![[BARZPTR]] = !DIDerivedType(tag: DW_TAG_pointer_type,{{.*}} baseType: ![[BARZT:[0-9]+]]
|
||||||
// CHECK-DAG: ![[BARZT]] = !DISubroutineType(types: ![[BARZARGS:.*]])
|
// CHECK-DAG: ![[BARZT]] = !DISubroutineType(types: ![[BARZARGS:.*]])
|
||||||
|
|||||||
Reference in New Issue
Block a user