diff options
author | stozer <stephen.tozer@sony.com> | 2019-12-17 09:37:17 +0000 |
---|---|---|
committer | stozer <stephen.tozer@sony.com> | 2019-12-18 11:09:18 +0000 |
commit | bb1b0bc4e57428ce364d3d6c075ff03cb8973462 (patch) | |
tree | 94b07c626e27d7f5000cf1c316dfc6d6c600c8e4 /llvm/lib | |
parent | bc5b7e21e32b23603f4d6148adeb88cd34dd287e (diff) | |
download | bcm5719-llvm-bb1b0bc4e57428ce364d3d6c075ff03cb8973462.tar.gz bcm5719-llvm-bb1b0bc4e57428ce364d3d6c075ff03cb8973462.zip |
[DebugInfo] Correctly handle salvaged casts and split fragments at ISel
Previously, LLVM had no functional way of performing casts inside of a
DIExpression(), which made salvaging cast instructions other than Noop
casts impossible. This patch enables the salvaging of casts by using the
DW_OP_LLVM_convert operator for SExt and Trunc instructions.
There is another issue which is exposed by this fix, in which fragment
DIExpressions (which are preserved more readily by this patch) for
values that must be split across registers in ISel trigger an assertion,
as the 'split' fragments extend beyond the bounds of the fragment
DIExpression causing an error. This patch also fixes this issue by
checking the fragment status of DIExpressions which are to be split, and
dropping fragments that are invalid.
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp | 21 | ||||
-rw-r--r-- | llvm/lib/IR/DebugInfoMetadata.cpp | 13 | ||||
-rw-r--r-- | llvm/lib/Transforms/Utils/Local.cpp | 22 |
3 files changed, 45 insertions, 11 deletions
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp index 27ac489b35b..735ac67ebfc 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -5571,8 +5571,26 @@ bool SelectionDAGBuilder::EmitFuncArgumentDbgValue( = [&](ArrayRef<std::pair<unsigned, unsigned>> SplitRegs) { unsigned Offset = 0; for (auto RegAndSize : SplitRegs) { + // If the expression is already a fragment, the current register + // offset+size might extend beyond the fragment. In this case, only + // the register bits that are inside the fragment are relevant. + int RegFragmentSizeInBits = RegAndSize.second; + if (auto ExprFragmentInfo = Expr->getFragmentInfo()) { + uint64_t ExprFragmentSizeInBits = ExprFragmentInfo->SizeInBits; + // The register is entirely outside the expression fragment, + // so is irrelevant for debug info. + if (Offset >= ExprFragmentSizeInBits) + break; + // The register is partially outside the expression fragment, only + // the low bits within the fragment are relevant for debug info. + if (Offset + RegFragmentSizeInBits > ExprFragmentSizeInBits) { + RegFragmentSizeInBits = ExprFragmentSizeInBits - Offset; + } + } + auto FragmentExpr = DIExpression::createFragmentExpression( - Expr, Offset, RegAndSize.second); + Expr, Offset, RegFragmentSizeInBits); + Offset += RegAndSize.second; // If a valid fragment expression cannot be created, the variable's // correct value cannot be determined and so it is set as Undef. if (!FragmentExpr) { @@ -5585,7 +5603,6 @@ bool SelectionDAGBuilder::EmitFuncArgumentDbgValue( FuncInfo.ArgDbgValues.push_back( BuildMI(MF, DL, TII->get(TargetOpcode::DBG_VALUE), false, RegAndSize.first, Variable, *FragmentExpr)); - Offset += RegAndSize.second; } }; diff --git a/llvm/lib/IR/DebugInfoMetadata.cpp b/llvm/lib/IR/DebugInfoMetadata.cpp index 9b42a5a0e1b..8970fc15576 100644 --- a/llvm/lib/IR/DebugInfoMetadata.cpp +++ b/llvm/lib/IR/DebugInfoMetadata.cpp @@ -1196,13 +1196,18 @@ bool DIExpression::isConstant() const { return true; } +DIExpression::ExtOps DIExpression::getExtOps(unsigned FromSize, unsigned ToSize, + bool Signed) { + dwarf::TypeKind TK = Signed ? dwarf::DW_ATE_signed : dwarf::DW_ATE_unsigned; + DIExpression::ExtOps Ops({dwarf::DW_OP_LLVM_convert, FromSize, TK, + dwarf::DW_OP_LLVM_convert, ToSize, TK}); + return Ops; +} + DIExpression *DIExpression::appendExt(const DIExpression *Expr, unsigned FromSize, unsigned ToSize, bool Signed) { - dwarf::TypeKind TK = Signed ? dwarf::DW_ATE_signed : dwarf::DW_ATE_unsigned; - uint64_t Ops[] = {dwarf::DW_OP_LLVM_convert, FromSize, TK, - dwarf::DW_OP_LLVM_convert, ToSize, TK}; - return appendToStack(Expr, Ops); + return appendToStack(Expr, getExtOps(FromSize, ToSize, Signed)); } DIGlobalVariableExpression * diff --git a/llvm/lib/Transforms/Utils/Local.cpp b/llvm/lib/Transforms/Utils/Local.cpp index d5690a04f53..b2d511c7c9a 100644 --- a/llvm/lib/Transforms/Utils/Local.cpp +++ b/llvm/lib/Transforms/Utils/Local.cpp @@ -1676,9 +1676,8 @@ DIExpression *llvm::salvageDebugInfoImpl(Instruction &I, }; // initializer-list helper for applying operators to the source DIExpression. - auto applyOps = - [&](std::initializer_list<uint64_t> Opcodes) -> DIExpression * { - SmallVector<uint64_t, 8> Ops(Opcodes); + auto applyOps = [&](ArrayRef<uint64_t> Opcodes) -> DIExpression * { + SmallVector<uint64_t, 8> Ops(Opcodes.begin(), Opcodes.end()); return doSalvage(Ops); }; @@ -1686,8 +1685,21 @@ DIExpression *llvm::salvageDebugInfoImpl(Instruction &I, // No-op casts and zexts are irrelevant for debug info. if (CI->isNoopCast(DL) || isa<ZExtInst>(&I)) return SrcDIExpr; - return nullptr; - } else if (auto *GEP = dyn_cast<GetElementPtrInst>(&I)) { + + Type *Type = CI->getType(); + // Casts other than Trunc or SExt to scalar types cannot be salvaged. + if (Type->isVectorTy() || (!isa<TruncInst>(&I) && !isa<SExtInst>(&I))) + return nullptr; + + Value *FromValue = CI->getOperand(0); + unsigned FromTypeBitSize = FromValue->getType()->getScalarSizeInBits(); + unsigned ToTypeBitSize = Type->getScalarSizeInBits(); + + return applyOps(DIExpression::getExtOps(FromTypeBitSize, ToTypeBitSize, + isa<SExtInst>(&I))); + } + + if (auto *GEP = dyn_cast<GetElementPtrInst>(&I)) { unsigned BitWidth = M.getDataLayout().getIndexSizeInBits(GEP->getPointerAddressSpace()); // Rewrite a constant GEP into a DIExpression. |