|
37 | 37 | #include "llvm/IR/BasicBlock.h" |
38 | 38 | #include "llvm/IR/DerivedTypes.h" |
39 | 39 | #include "llvm/IR/Function.h" |
| 40 | +#include "llvm/IR/GetElementPtrTypeIterator.h" |
40 | 41 | #include "llvm/IR/IRBuilder.h" |
41 | 42 | #include "llvm/IR/InlineAsm.h" |
42 | 43 | #include "llvm/IR/Module.h" |
@@ -2648,3 +2649,67 @@ CountTrackedPointers::CountTrackedPointers(Type *T) { |
2648 | 2649 | if (count == 0) |
2649 | 2650 | all = false; |
2650 | 2651 | } |
| 2652 | + |
| 2653 | +bool collectOffset(GetElementPtrInst *gep, const DataLayout &DL, |
| 2654 | + unsigned BitWidth, |
| 2655 | + MapVector<Value *, APInt> &VariableOffsets, |
| 2656 | + APInt &ConstantOffset) { |
| 2657 | +#if LLVM_VERSION_MAJOR >= 13 |
| 2658 | + return cast<GEPOperator>(gep)->collectOffset(DL, BitWidth, VariableOffsets, |
| 2659 | + ConstantOffset); |
| 2660 | +#else |
| 2661 | + assert(BitWidth == DL.getIndexSizeInBits(gep->getPointerAddressSpace()) && |
| 2662 | + "The offset bit width does not match DL specification."); |
| 2663 | + |
| 2664 | + auto CollectConstantOffset = [&](APInt Index, uint64_t Size) { |
| 2665 | + Index = Index.sextOrTrunc(BitWidth); |
| 2666 | + APInt IndexedSize = APInt(BitWidth, Size); |
| 2667 | + ConstantOffset += Index * IndexedSize; |
| 2668 | + }; |
| 2669 | + |
| 2670 | + for (gep_type_iterator GTI = gep_type_begin(gep), GTE = gep_type_end(gep); |
| 2671 | + GTI != GTE; ++GTI) { |
| 2672 | + // Scalable vectors are multiplied by a runtime constant. |
| 2673 | + bool ScalableType = isa<ScalableVectorType>(GTI.getIndexedType()); |
| 2674 | + |
| 2675 | + Value *V = GTI.getOperand(); |
| 2676 | + StructType *STy = GTI.getStructTypeOrNull(); |
| 2677 | + // Handle ConstantInt if possible. |
| 2678 | + if (auto ConstOffset = dyn_cast<ConstantInt>(V)) { |
| 2679 | + if (ConstOffset->isZero()) |
| 2680 | + continue; |
| 2681 | + // If the type is scalable and the constant is not zero (vscale * n * 0 = |
| 2682 | + // 0) bailout. |
| 2683 | + // TODO: If the runtime value is accessible at any point before DWARF |
| 2684 | + // emission, then we could potentially keep a forward reference to it |
| 2685 | + // in the debug value to be filled in later. |
| 2686 | + if (ScalableType) |
| 2687 | + return false; |
| 2688 | + // Handle a struct index, which adds its field offset to the pointer. |
| 2689 | + if (STy) { |
| 2690 | + unsigned ElementIdx = ConstOffset->getZExtValue(); |
| 2691 | + const StructLayout *SL = DL.getStructLayout(STy); |
| 2692 | + // Element offset is in bytes. |
| 2693 | + CollectConstantOffset(APInt(BitWidth, SL->getElementOffset(ElementIdx)), |
| 2694 | + 1); |
| 2695 | + continue; |
| 2696 | + } |
| 2697 | + CollectConstantOffset(ConstOffset->getValue(), |
| 2698 | + DL.getTypeAllocSize(GTI.getIndexedType())); |
| 2699 | + continue; |
| 2700 | + } |
| 2701 | + |
| 2702 | + if (STy || ScalableType) |
| 2703 | + return false; |
| 2704 | + APInt IndexedSize = |
| 2705 | + APInt(BitWidth, DL.getTypeAllocSize(GTI.getIndexedType())); |
| 2706 | + // Insert an initial offset of 0 for V iff none exists already, then |
| 2707 | + // increment the offset by IndexedSize. |
| 2708 | + if (IndexedSize != 0) { |
| 2709 | + VariableOffsets.insert({V, APInt(BitWidth, 0)}); |
| 2710 | + VariableOffsets[V] += IndexedSize; |
| 2711 | + } |
| 2712 | + } |
| 2713 | + return true; |
| 2714 | +#endif |
| 2715 | +} |
0 commit comments