1 //===-- Operator.cpp - Implement the LLVM operators -----------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file implements the non-inline methods for the LLVM Operator classes. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "llvm/IR/Operator.h" 14 #include "llvm/IR/DataLayout.h" 15 #include "llvm/IR/GetElementPtrTypeIterator.h" 16 #include "llvm/IR/Instructions.h" 17 #include "llvm/IR/Type.h" 18 19 #include "ConstantsContext.h" 20 21 namespace llvm { 22 Type *GEPOperator::getSourceElementType() const { 23 if (auto *I = dyn_cast<GetElementPtrInst>(this)) 24 return I->getSourceElementType(); 25 return cast<GetElementPtrConstantExpr>(this)->getSourceElementType(); 26 } 27 28 Type *GEPOperator::getResultElementType() const { 29 if (auto *I = dyn_cast<GetElementPtrInst>(this)) 30 return I->getResultElementType(); 31 return cast<GetElementPtrConstantExpr>(this)->getResultElementType(); 32 } 33 34 bool GEPOperator::accumulateConstantOffset( 35 const DataLayout &DL, APInt &Offset, 36 function_ref<bool(Value &, APInt &)> ExternalAnalysis) const { 37 assert(Offset.getBitWidth() == 38 DL.getIndexSizeInBits(getPointerAddressSpace()) && 39 "The offset bit width does not match DL specification."); 40 41 bool UsedExternalAnalysis = false; 42 auto AccumulateOffset = [&](APInt Index, uint64_t Size) -> bool { 43 Index = Index.sextOrTrunc(Offset.getBitWidth()); 44 APInt IndexedSize = APInt(Offset.getBitWidth(), Size); 45 // For array or vector indices, scale the index by the size of the type. 46 if (!UsedExternalAnalysis) { 47 Offset += Index * IndexedSize; 48 } else { 49 // External Analysis can return a result higher/lower than the value 50 // represents. We need to detect overflow/underflow. 51 bool Overflow = false; 52 APInt OffsetPlus = Index.smul_ov(IndexedSize, Overflow); 53 if (Overflow) 54 return false; 55 Offset = Offset.sadd_ov(OffsetPlus, Overflow); 56 if (Overflow) 57 return false; 58 } 59 return true; 60 }; 61 62 for (gep_type_iterator GTI = gep_type_begin(this), GTE = gep_type_end(this); 63 GTI != GTE; ++GTI) { 64 // Scalable vectors are multiplied by a runtime constant. 65 bool ScalableType = false; 66 if (isa<ScalableVectorType>(GTI.getIndexedType())) 67 ScalableType = true; 68 69 Value *V = GTI.getOperand(); 70 StructType *STy = GTI.getStructTypeOrNull(); 71 // Handle ConstantInt if possible. 72 if (auto ConstOffset = dyn_cast<ConstantInt>(V)) { 73 if (ConstOffset->isZero()) 74 continue; 75 // if the type is scalable and the constant is not zero (vscale * n * 0 = 76 // 0) bailout. 77 if (ScalableType) 78 return false; 79 // Handle a struct index, which adds its field offset to the pointer. 80 if (STy) { 81 unsigned ElementIdx = ConstOffset->getZExtValue(); 82 const StructLayout *SL = DL.getStructLayout(STy); 83 // Element offset is in bytes. 84 if (!AccumulateOffset( 85 APInt(Offset.getBitWidth(), SL->getElementOffset(ElementIdx)), 86 1)) 87 return false; 88 continue; 89 } 90 if (!AccumulateOffset(ConstOffset->getValue(), 91 DL.getTypeAllocSize(GTI.getIndexedType()))) 92 return false; 93 continue; 94 } 95 96 // The operand is not constant, check if an external analysis was provided. 97 // External analsis is not applicable to a struct type. 98 if (!ExternalAnalysis || STy || ScalableType) 99 return false; 100 APInt AnalysisIndex; 101 if (!ExternalAnalysis(*V, AnalysisIndex)) 102 return false; 103 UsedExternalAnalysis = true; 104 if (!AccumulateOffset(AnalysisIndex, 105 DL.getTypeAllocSize(GTI.getIndexedType()))) 106 return false; 107 } 108 return true; 109 } 110 } 111