aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/IR/IntrinsicInst.cpp
diff options
context:
space:
mode:
authorgbtozers <stephen.tozer@sony.com>2020-09-30 16:30:14 +0100
committerStephen Tozer <Stephen.Tozer@Sony.com>2021-03-08 14:36:13 +0000
commite5d958c45629ccd2f5b5f7432756be1d0fcf052c (patch)
tree389c3a4794fbacd6ec238523f5999656d46e6fbe /llvm/lib/IR/IntrinsicInst.cpp
parent08d9e2ceec60f4801b19243c6a4fcacb33aa043c (diff)
downloadllvm-e5d958c45629ccd2f5b5f7432756be1d0fcf052c.zip
llvm-e5d958c45629ccd2f5b5f7432756be1d0fcf052c.tar.gz
llvm-e5d958c45629ccd2f5b5f7432756be1d0fcf052c.tar.bz2
[DebugInfo] Support DIArgList in DbgVariableIntrinsic
This patch updates DbgVariableIntrinsics to support use of a DIArgList for the location operand, resulting in a significant change to its interface. This patch does not update all IR passes to support multiple location operands in a dbg.value; the only change is to update the DbgVariableIntrinsic interface and its uses. All code outside of the intrinsic classes assumes that an intrinsic will always have exactly one location operand; they will still support DIArgLists, but only if they contain exactly one Value. Among other changes, the setOperand and setArgOperand functions in DbgVariableIntrinsic have been made private. This is to prevent code from setting the operands of these intrinsics directly, which could easily result in incorrect/invalid operands being set. This does not prevent these functions from being called on a debug intrinsic at all, as they can still be called on any CallInst pointer; it is assumed that any code directly setting the operands on a generic call instruction is doing so safely. The intention for making these functions private is to prevent DIArgLists from being overwritten by code that's naively trying to replace one of the Values it points to, and also to fail fast if a DbgVariableIntrinsic is updated to use a DIArgList without a valid corresponding DIExpression.
Diffstat (limited to 'llvm/lib/IR/IntrinsicInst.cpp')
-rw-r--r--llvm/lib/IR/IntrinsicInst.cpp65
1 files changed, 56 insertions, 9 deletions
diff --git a/llvm/lib/IR/IntrinsicInst.cpp b/llvm/lib/IR/IntrinsicInst.cpp
index 3d1ea28..3d3f734 100644
--- a/llvm/lib/IR/IntrinsicInst.cpp
+++ b/llvm/lib/IR/IntrinsicInst.cpp
@@ -38,18 +38,65 @@ using namespace llvm;
/// intrinsics for variables.
///
-Value *DbgVariableIntrinsic::getVariableLocation(bool AllowNullOp) const {
- Value *Op = getArgOperand(0);
- if (AllowNullOp && !Op)
+iterator_range<DbgVariableIntrinsic::location_op_iterator>
+DbgVariableIntrinsic::location_ops() const {
+ auto *MD = getRawLocation();
+ assert(MD && "First operand of DbgVariableIntrinsic should be non-null.");
+
+ // If operand is ValueAsMetadata, return a range over just that operand.
+ if (auto *VAM = dyn_cast<ValueAsMetadata>(MD)) {
+ return {location_op_iterator(VAM), location_op_iterator(VAM + 1)};
+ }
+ // If operand is DIArgList, return a range over its args.
+ if (auto *AL = dyn_cast<DIArgList>(MD))
+ return {location_op_iterator(AL->args_begin()),
+ location_op_iterator(AL->args_end())};
+ // Operand must be an empty metadata tuple, so return empty iterator.
+ return {location_op_iterator(static_cast<ValueAsMetadata *>(nullptr)),
+ location_op_iterator(static_cast<ValueAsMetadata *>(nullptr))};
+}
+
+Value *DbgVariableIntrinsic::getVariableLocationOp(unsigned OpIdx) const {
+ auto *MD = getRawLocation();
+ assert(MD && "First operand of DbgVariableIntrinsic should be non-null.");
+ if (auto *AL = dyn_cast<DIArgList>(MD))
+ return AL->getArgs()[OpIdx]->getValue();
+ if (isa<MDNode>(MD))
return nullptr;
+ assert(
+ isa<ValueAsMetadata>(MD) &&
+ "Attempted to get location operand from DbgVariableIntrinsic with none.");
+ auto *V = cast<ValueAsMetadata>(MD);
+ assert(OpIdx == 0 && "Operand Index must be 0 for a debug intrinsic with a "
+ "single location operand.");
+ return V->getValue();
+}
- auto *MD = cast<MetadataAsValue>(Op)->getMetadata();
- if (auto *V = dyn_cast<ValueAsMetadata>(MD))
- return V->getValue();
+static ValueAsMetadata *getAsMetadata(Value *V) {
+ return isa<MetadataAsValue>(V) ? dyn_cast<ValueAsMetadata>(
+ cast<MetadataAsValue>(V)->getMetadata())
+ : ValueAsMetadata::get(V);
+}
- // When the value goes to null, it gets replaced by an empty MDNode.
- assert(!cast<MDNode>(MD)->getNumOperands() && "Expected an empty MDNode");
- return nullptr;
+void DbgVariableIntrinsic::replaceVariableLocationOp(Value *OldValue,
+ Value *NewValue) {
+ assert(NewValue && "Values must be non-null");
+ auto Locations = location_ops();
+ auto OldIt = find(Locations, OldValue);
+ assert(OldIt != Locations.end() && "OldValue must be a current location");
+ if (!hasArgList()) {
+ Value *NewOperand = isa<MetadataAsValue>(NewValue)
+ ? NewValue
+ : MetadataAsValue::get(
+ getContext(), ValueAsMetadata::get(NewValue));
+ return setArgOperand(0, NewOperand);
+ }
+ SmallVector<ValueAsMetadata *, 4> MDs;
+ ValueAsMetadata *NewOperand = getAsMetadata(NewValue);
+ for (auto *VMD : Locations)
+ MDs.push_back(VMD == *OldIt ? NewOperand : getAsMetadata(VMD));
+ setArgOperand(
+ 0, MetadataAsValue::get(getContext(), DIArgList::get(getContext(), MDs)));
}
Optional<uint64_t> DbgVariableIntrinsic::getFragmentSizeInBits() const {