summaryrefslogtreecommitdiff
path: root/llvm/lib/IR/Operator.cpp
diff options
context:
space:
mode:
authorStephen Tozer <Stephen.Tozer@Sony.com>2021-05-20 20:17:33 +0100
committerStephen Tozer <Stephen.Tozer@Sony.com>2021-05-21 11:06:20 +0100
commit36ec97f76ac0d8be76fb16ac521f55126766267d (patch)
tree9d3136fa7fa260f6def0c6545b7cb1967b3fc76a /llvm/lib/IR/Operator.cpp
parent5a476987f7d653eb7ce2d8ba0ddf0125f481117e (diff)
3rd Reapply "[DebugInfo] Use variadic debug values to salvage BinOps and GEP instrs with non-const operands"
This reapplies c0f3dfb9, which was reverted following the discovery of crashes on linux kernel and chromium builds - these issues have since been fixed, allowing this patch to re-land. This reverts commit 4397b7095d640f9b9426c4d0135e999c5a1de1c5.
Diffstat (limited to 'llvm/lib/IR/Operator.cpp')
-rw-r--r--llvm/lib/IR/Operator.cpp57
1 files changed, 57 insertions, 0 deletions
diff --git a/llvm/lib/IR/Operator.cpp b/llvm/lib/IR/Operator.cpp
index 69181f35827b..e030cb552275 100644
--- a/llvm/lib/IR/Operator.cpp
+++ b/llvm/lib/IR/Operator.cpp
@@ -142,4 +142,61 @@ bool GEPOperator::accumulateConstantOffset(
}
return true;
}
+
+bool GEPOperator::collectOffset(
+ const DataLayout &DL, unsigned BitWidth,
+ SmallDenseMap<Value *, APInt, 8> &VariableOffsets,
+ APInt &ConstantOffset) const {
+ assert(BitWidth == DL.getIndexSizeInBits(getPointerAddressSpace()) &&
+ "The offset bit width does not match DL specification.");
+
+ auto CollectConstantOffset = [&](APInt Index, uint64_t Size) {
+ Index = Index.sextOrTrunc(BitWidth);
+ APInt IndexedSize = APInt(BitWidth, Size);
+ ConstantOffset += Index * IndexedSize;
+ };
+
+ for (gep_type_iterator GTI = gep_type_begin(this), GTE = gep_type_end(this);
+ GTI != GTE; ++GTI) {
+ // Scalable vectors are multiplied by a runtime constant.
+ bool ScalableType = isa<ScalableVectorType>(GTI.getIndexedType());
+
+ Value *V = GTI.getOperand();
+ StructType *STy = GTI.getStructTypeOrNull();
+ // Handle ConstantInt if possible.
+ if (auto ConstOffset = dyn_cast<ConstantInt>(V)) {
+ if (ConstOffset->isZero())
+ continue;
+ // If the type is scalable and the constant is not zero (vscale * n * 0 =
+ // 0) bailout.
+ // TODO: If the runtime value is accessible at any point before DWARF
+ // emission, then we could potentially keep a forward reference to it
+ // in the debug value to be filled in later.
+ if (ScalableType)
+ return false;
+ // Handle a struct index, which adds its field offset to the pointer.
+ if (STy) {
+ unsigned ElementIdx = ConstOffset->getZExtValue();
+ const StructLayout *SL = DL.getStructLayout(STy);
+ // Element offset is in bytes.
+ CollectConstantOffset(APInt(BitWidth, SL->getElementOffset(ElementIdx)),
+ 1);
+ continue;
+ }
+ CollectConstantOffset(ConstOffset->getValue(),
+ DL.getTypeAllocSize(GTI.getIndexedType()));
+ continue;
+ }
+
+ if (STy || ScalableType)
+ return false;
+ // Insert an initial offset of 0 for V iff none exists already, then
+ // increment the offset by IndexedSize.
+ VariableOffsets.try_emplace(V, BitWidth, 0);
+ APInt IndexedSize =
+ APInt(BitWidth, DL.getTypeAllocSize(GTI.getIndexedType()));
+ VariableOffsets[V] += IndexedSize;
+ }
+ return true;
+}
} // namespace llvm