diff options
author | Adrian Prantl <aprantl@apple.com> | 2016-12-05 18:04:47 +0000 |
---|---|---|
committer | Adrian Prantl <aprantl@apple.com> | 2016-12-05 18:04:47 +0000 |
commit | 941fa7588bbee856a8d3f634c5b88f101089d30f (patch) | |
tree | a27a566046fe17ba1ab5691911b2468395a91e52 /llvm/lib/Transforms | |
parent | fc78d7cb8e5c0c849950fca7d69d81485f3513e1 (diff) | |
download | bcm5719-llvm-941fa7588bbee856a8d3f634c5b88f101089d30f.tar.gz bcm5719-llvm-941fa7588bbee856a8d3f634c5b88f101089d30f.zip |
[DIExpression] Introduce a dedicated DW_OP_LLVM_fragment operation
so we can stop using DW_OP_bit_piece with the wrong semantics.
The entire back story can be found here:
http://lists.llvm.org/pipermail/llvm-commits/Week-of-Mon-20161114/405934.html
The gist is that in LLVM we've been misinterpreting DW_OP_bit_piece's
offset field to mean the offset into the source variable rather than
the offset into the location at the top the DWARF expression stack. In
order to be able to fix this in a subsequent patch, this patch
introduces a dedicated DW_OP_LLVM_fragment operation with the
semantics that we used to apply to DW_OP_bit_piece, which is what we
actually need while inside of LLVM. This patch is complete with a
bitcode upgrade for expressions using the old format. It does not yet
fix the DWARF backend to use DW_OP_bit_piece correctly.
Implementation note: We discussed several options for implementing
this, including reserving a dedicated field in DIExpression for the
fragment size and offset, but using an custom operator at the end of
the expression works just fine and is more efficient because we then
only pay for it when we need it.
Differential Revision: https://reviews.llvm.org/D27361
rdar://problem/29335809
llvm-svn: 288683
Diffstat (limited to 'llvm/lib/Transforms')
-rw-r--r-- | llvm/lib/Transforms/Scalar/SROA.cpp | 42 | ||||
-rw-r--r-- | llvm/lib/Transforms/Utils/Local.cpp | 18 |
2 files changed, 31 insertions, 29 deletions
diff --git a/llvm/lib/Transforms/Scalar/SROA.cpp b/llvm/lib/Transforms/Scalar/SROA.cpp index 1f9d08528ef..887818bfdde 100644 --- a/llvm/lib/Transforms/Scalar/SROA.cpp +++ b/llvm/lib/Transforms/Scalar/SROA.cpp @@ -3982,16 +3982,16 @@ bool SROA::splitAlloca(AllocaInst &AI, AllocaSlices &AS) { if (!IsSorted) std::sort(AS.begin(), AS.end()); - /// \brief Describes the allocas introduced by rewritePartition - /// in order to migrate the debug info. - struct Piece { + /// Describes the allocas introduced by rewritePartition in order to migrate + /// the debug info. + struct Fragment { AllocaInst *Alloca; uint64_t Offset; uint64_t Size; - Piece(AllocaInst *AI, uint64_t O, uint64_t S) + Fragment(AllocaInst *AI, uint64_t O, uint64_t S) : Alloca(AI), Offset(O), Size(S) {} }; - SmallVector<Piece, 4> Pieces; + SmallVector<Fragment, 4> Fragments; // Rewrite each partition. for (auto &P : AS.partitions()) { @@ -4002,7 +4002,7 @@ bool SROA::splitAlloca(AllocaInst &AI, AllocaSlices &AS) { uint64_t AllocaSize = DL.getTypeSizeInBits(NewAI->getAllocatedType()); // Don't include any padding. uint64_t Size = std::min(AllocaSize, P.size() * SizeOfByte); - Pieces.push_back(Piece(NewAI, P.beginOffset() * SizeOfByte, Size)); + Fragments.push_back(Fragment(NewAI, P.beginOffset() * SizeOfByte, Size)); } } ++NumPartitions; @@ -4019,32 +4019,34 @@ bool SROA::splitAlloca(AllocaInst &AI, AllocaSlices &AS) { auto *Expr = DbgDecl->getExpression(); DIBuilder DIB(*AI.getModule(), /*AllowUnresolved*/ false); uint64_t AllocaSize = DL.getTypeSizeInBits(AI.getAllocatedType()); - for (auto Piece : Pieces) { - // Create a piece expression describing the new partition or reuse AI's + for (auto Fragment : Fragments) { + // Create a fragment expression describing the new partition or reuse AI's // expression if there is only one partition. - auto *PieceExpr = Expr; - if (Piece.Size < AllocaSize || Expr->isBitPiece()) { + auto *FragmentExpr = Expr; + if (Fragment.Size < AllocaSize || Expr->isFragment()) { // If this alloca is already a scalar replacement of a larger aggregate, - // Piece.Offset describes the offset inside the scalar. - uint64_t Offset = Expr->isBitPiece() ? Expr->getBitPieceOffset() : 0; - uint64_t Start = Offset + Piece.Offset; - uint64_t Size = Piece.Size; - if (Expr->isBitPiece()) { - uint64_t AbsEnd = Expr->getBitPieceOffset() + Expr->getBitPieceSize(); + // Fragment.Offset describes the offset inside the scalar. + uint64_t Offset = + Expr->isFragment() ? Expr->getFragmentOffsetInBits() : 0; + uint64_t Start = Offset + Fragment.Offset; + uint64_t Size = Fragment.Size; + if (Expr->isFragment()) { + uint64_t AbsEnd = + Expr->getFragmentOffsetInBits() + Expr->getFragmentSizeInBits(); if (Start >= AbsEnd) // No need to describe a SROAed padding. continue; Size = std::min(Size, AbsEnd - Start); } - PieceExpr = DIB.createBitPieceExpression(Start, Size); + FragmentExpr = DIB.createFragmentExpression(Start, Size); } // Remove any existing dbg.declare intrinsic describing the same alloca. - if (DbgDeclareInst *OldDDI = FindAllocaDbgDeclare(Piece.Alloca)) + if (DbgDeclareInst *OldDDI = FindAllocaDbgDeclare(Fragment.Alloca)) OldDDI->eraseFromParent(); - DIB.insertDeclare(Piece.Alloca, Var, PieceExpr, DbgDecl->getDebugLoc(), - &AI); + DIB.insertDeclare(Fragment.Alloca, Var, FragmentExpr, + DbgDecl->getDebugLoc(), &AI); } } return Changed; diff --git a/llvm/lib/Transforms/Utils/Local.cpp b/llvm/lib/Transforms/Utils/Local.cpp index 01a5579e1ed..6de0f34e94c 100644 --- a/llvm/lib/Transforms/Utils/Local.cpp +++ b/llvm/lib/Transforms/Utils/Local.cpp @@ -1102,26 +1102,26 @@ void llvm::ConvertDebugDeclareToDebugValue(DbgDeclareInst *DDI, if (SExtInst *SExt = dyn_cast<SExtInst>(SI->getOperand(0))) ExtendedArg = dyn_cast<Argument>(SExt->getOperand(0)); if (ExtendedArg) { - // We're now only describing a subset of the variable. The piece we're + // We're now only describing a subset of the variable. The fragment we're // describing will always be smaller than the variable size, because // VariableSize == Size of Alloca described by DDI. Since SI stores // to the alloca described by DDI, if it's first operand is an extend, // we're guaranteed that before extension, the value was narrower than // the size of the alloca, hence the size of the described variable. SmallVector<uint64_t, 3> Ops; - unsigned PieceOffset = 0; - // If this already is a bit piece, we drop the bit piece from the expression - // and record the offset. - if (DIExpr->isBitPiece()) { + unsigned FragmentOffset = 0; + // If this already is a bit fragment, we drop the bit fragment from the + // expression and record the offset. + if (DIExpr->isFragment()) { Ops.append(DIExpr->elements_begin(), DIExpr->elements_end()-3); - PieceOffset = DIExpr->getBitPieceOffset(); + FragmentOffset = DIExpr->getFragmentOffsetInBits(); } else { Ops.append(DIExpr->elements_begin(), DIExpr->elements_end()); } - Ops.push_back(dwarf::DW_OP_bit_piece); - Ops.push_back(PieceOffset); // Offset + Ops.push_back(dwarf::DW_OP_LLVM_fragment); + Ops.push_back(FragmentOffset); const DataLayout &DL = DDI->getModule()->getDataLayout(); - Ops.push_back(DL.getTypeSizeInBits(ExtendedArg->getType())); // Size + Ops.push_back(DL.getTypeSizeInBits(ExtendedArg->getType())); auto NewDIExpr = Builder.createExpression(Ops); if (!LdStHasDebugValue(DIVar, NewDIExpr, SI)) Builder.insertDbgValueIntrinsic(ExtendedArg, 0, DIVar, NewDIExpr, |