forked from OSchip/llvm-project
Remove addBlockByrefAddress(), it is dead code as far as clang is concerned.
This patch removes addBlockByrefAddress(), it is dead code as far as clang is concerned: Every byref block capture is emitted with a complex expression that is equivalent to what this function does. rdar://problem/31629055 Differential Revision: https://reviews.llvm.org/D51763 llvm-svn: 341737
This commit is contained in:
parent
4357ca653a
commit
609bf36952
|
@ -978,8 +978,6 @@ void DwarfCompileUnit::addVariableAddress(const DbgVariable &DV, DIE &Die,
|
|||
"block byref variable without a complex expression");
|
||||
if (DV.hasComplexAddress())
|
||||
addComplexAddress(DV, Die, dwarf::DW_AT_location, Location);
|
||||
else if (DV.isBlockByrefVariable())
|
||||
addBlockByrefAddress(DV, Die, dwarf::DW_AT_location, Location);
|
||||
else
|
||||
addAddress(Die, dwarf::DW_AT_location, Location);
|
||||
}
|
||||
|
|
|
@ -427,138 +427,6 @@ void DwarfUnit::addSourceLine(DIE &Die, const DIObjCProperty *Ty) {
|
|||
addSourceLine(Die, Ty->getLine(), Ty->getFile());
|
||||
}
|
||||
|
||||
/* Byref variables, in Blocks, are declared by the programmer as "SomeType
|
||||
VarName;", but the compiler creates a __Block_byref_x_VarName struct, and
|
||||
gives the variable VarName either the struct, or a pointer to the struct, as
|
||||
its type. This is necessary for various behind-the-scenes things the
|
||||
compiler needs to do with by-reference variables in Blocks.
|
||||
|
||||
However, as far as the original *programmer* is concerned, the variable
|
||||
should still have type 'SomeType', as originally declared.
|
||||
|
||||
The function getBlockByrefType dives into the __Block_byref_x_VarName
|
||||
struct to find the original type of the variable, which is then assigned to
|
||||
the variable's Debug Information Entry as its real type. So far, so good.
|
||||
However now the debugger will expect the variable VarName to have the type
|
||||
SomeType. So we need the location attribute for the variable to be an
|
||||
expression that explains to the debugger how to navigate through the
|
||||
pointers and struct to find the actual variable of type SomeType.
|
||||
|
||||
The following function does just that. We start by getting
|
||||
the "normal" location for the variable. This will be the location
|
||||
of either the struct __Block_byref_x_VarName or the pointer to the
|
||||
struct __Block_byref_x_VarName.
|
||||
|
||||
The struct will look something like:
|
||||
|
||||
struct __Block_byref_x_VarName {
|
||||
... <various fields>
|
||||
struct __Block_byref_x_VarName *forwarding;
|
||||
... <various other fields>
|
||||
SomeType VarName;
|
||||
... <maybe more fields>
|
||||
};
|
||||
|
||||
If we are given the struct directly (as our starting point) we
|
||||
need to tell the debugger to:
|
||||
|
||||
1). Add the offset of the forwarding field.
|
||||
|
||||
2). Follow that pointer to get the real __Block_byref_x_VarName
|
||||
struct to use (the real one may have been copied onto the heap).
|
||||
|
||||
3). Add the offset for the field VarName, to find the actual variable.
|
||||
|
||||
If we started with a pointer to the struct, then we need to
|
||||
dereference that pointer first, before the other steps.
|
||||
Translating this into DWARF ops, we will need to append the following
|
||||
to the current location description for the variable:
|
||||
|
||||
DW_OP_deref -- optional, if we start with a pointer
|
||||
DW_OP_plus_uconst <forward_fld_offset>
|
||||
DW_OP_deref
|
||||
DW_OP_plus_uconst <varName_fld_offset>
|
||||
|
||||
That is what this function does. */
|
||||
|
||||
void DwarfUnit::addBlockByrefAddress(const DbgVariable &DV, DIE &Die,
|
||||
dwarf::Attribute Attribute,
|
||||
const MachineLocation &Location) {
|
||||
const DIType *Ty = DV.getType();
|
||||
const DIType *TmpTy = Ty;
|
||||
uint16_t Tag = Ty->getTag();
|
||||
bool isPointer = false;
|
||||
|
||||
StringRef varName = DV.getName();
|
||||
|
||||
if (Tag == dwarf::DW_TAG_pointer_type) {
|
||||
auto *DTy = cast<DIDerivedType>(Ty);
|
||||
TmpTy = resolve(DTy->getBaseType());
|
||||
isPointer = true;
|
||||
}
|
||||
|
||||
// Find the __forwarding field and the variable field in the __Block_byref
|
||||
// struct.
|
||||
DINodeArray Fields = cast<DICompositeType>(TmpTy)->getElements();
|
||||
const DIDerivedType *varField = nullptr;
|
||||
const DIDerivedType *forwardingField = nullptr;
|
||||
|
||||
for (unsigned i = 0, N = Fields.size(); i < N; ++i) {
|
||||
auto *DT = cast<DIDerivedType>(Fields[i]);
|
||||
StringRef fieldName = DT->getName();
|
||||
if (fieldName == "__forwarding")
|
||||
forwardingField = DT;
|
||||
else if (fieldName == varName)
|
||||
varField = DT;
|
||||
}
|
||||
|
||||
// Get the offsets for the forwarding field and the variable field.
|
||||
unsigned forwardingFieldOffset = forwardingField->getOffsetInBits() >> 3;
|
||||
unsigned varFieldOffset = varField->getOffsetInBits() >> 2;
|
||||
|
||||
// Decode the original location, and use that as the start of the byref
|
||||
// variable's location.
|
||||
DIELoc *Loc = new (DIEValueAllocator) DIELoc;
|
||||
DIEDwarfExpression DwarfExpr(*Asm, *this, *Loc);
|
||||
if (Location.isIndirect())
|
||||
DwarfExpr.setMemoryLocationKind();
|
||||
|
||||
SmallVector<uint64_t, 6> Ops;
|
||||
// If we started with a pointer to the __Block_byref... struct, then
|
||||
// the first thing we need to do is dereference the pointer (DW_OP_deref).
|
||||
if (isPointer)
|
||||
Ops.push_back(dwarf::DW_OP_deref);
|
||||
|
||||
// Next add the offset for the '__forwarding' field:
|
||||
// DW_OP_plus_uconst ForwardingFieldOffset. Note there's no point in
|
||||
// adding the offset if it's 0.
|
||||
if (forwardingFieldOffset > 0) {
|
||||
Ops.push_back(dwarf::DW_OP_plus_uconst);
|
||||
Ops.push_back(forwardingFieldOffset);
|
||||
}
|
||||
|
||||
// Now dereference the __forwarding field to get to the real __Block_byref
|
||||
// struct: DW_OP_deref.
|
||||
Ops.push_back(dwarf::DW_OP_deref);
|
||||
|
||||
// Now that we've got the real __Block_byref... struct, add the offset
|
||||
// for the variable's field to get to the location of the actual variable:
|
||||
// DW_OP_plus_uconst varFieldOffset. Again, don't add if it's 0.
|
||||
if (varFieldOffset > 0) {
|
||||
Ops.push_back(dwarf::DW_OP_plus_uconst);
|
||||
Ops.push_back(varFieldOffset);
|
||||
}
|
||||
|
||||
DIExpressionCursor Cursor(Ops);
|
||||
const TargetRegisterInfo &TRI = *Asm->MF->getSubtarget().getRegisterInfo();
|
||||
if (!DwarfExpr.addMachineRegExpression(TRI, Cursor, Location.getReg()))
|
||||
return;
|
||||
DwarfExpr.addExpression(std::move(Cursor));
|
||||
|
||||
// Now attach the location information to the DIE.
|
||||
addBlock(Die, Attribute, DwarfExpr.finalize());
|
||||
}
|
||||
|
||||
/// Return true if type encoding is unsigned.
|
||||
static bool isUnsignedDIType(DwarfDebug *DD, const DIType *Ty) {
|
||||
if (auto *CTy = dyn_cast<DICompositeType>(Ty)) {
|
||||
|
|
|
@ -4534,6 +4534,14 @@ void Verifier::visitDbgIntrinsic(StringRef Kind, DbgVariableIntrinsic &DII) {
|
|||
&DII, BB, F, Var, Var->getScope()->getSubprogram(), Loc,
|
||||
Loc->getScope()->getSubprogram());
|
||||
|
||||
// This check is redundant with one in visitLocalVariable().
|
||||
AssertDI(isType(Var->getRawType()), "invalid type ref", Var,
|
||||
Var->getRawType());
|
||||
if (auto *Type = dyn_cast_or_null<DIType>(Var->getRawType()))
|
||||
if (Type->isBlockByrefStruct())
|
||||
AssertDI(DII.getExpression() && DII.getExpression()->getNumElements(),
|
||||
"BlockByRef variable without complex expression", Var, &DII);
|
||||
|
||||
verifyFnArgs(DII);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
; RUN: llvm-as -disable-output <%s 2>&1| FileCheck %s
|
||||
|
||||
; CHECK: BlockByRef variable without complex expression
|
||||
; CHECK: warning: ignoring invalid debug info
|
||||
|
||||
define void @foo() {
|
||||
entry:
|
||||
%s = alloca i32
|
||||
call void @llvm.dbg.declare(metadata i32* %s, metadata !2, metadata !DIExpression()), !dbg !DILocation(scope: !1)
|
||||
ret void
|
||||
}
|
||||
|
||||
declare void @llvm.dbg.declare(metadata, metadata, metadata)
|
||||
|
||||
!llvm.module.flags = !{!0}
|
||||
!0 = !{i32 2, !"Debug Info Version", i32 3}
|
||||
!1 = distinct !DISubprogram()
|
||||
!2 = !DILocalVariable(scope: !1, type: !3)
|
||||
!3 = !DICompositeType(tag: DW_TAG_structure_type, flags: DIFlagBlockByrefStruct)
|
Loading…
Reference in New Issue