1*0b57cec5SDimitry Andric //===-- Operator.cpp - Implement the LLVM operators -----------------------===// 2*0b57cec5SDimitry Andric // 3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0b57cec5SDimitry Andric // 7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 8*0b57cec5SDimitry Andric // 9*0b57cec5SDimitry Andric // This file implements the non-inline methods for the LLVM Operator classes. 10*0b57cec5SDimitry Andric // 11*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 12*0b57cec5SDimitry Andric 13*0b57cec5SDimitry Andric #include "llvm/IR/Operator.h" 14*0b57cec5SDimitry Andric #include "llvm/IR/DataLayout.h" 15*0b57cec5SDimitry Andric #include "llvm/IR/GetElementPtrTypeIterator.h" 16*0b57cec5SDimitry Andric #include "llvm/IR/Instructions.h" 17*0b57cec5SDimitry Andric #include "llvm/IR/Type.h" 18*0b57cec5SDimitry Andric 19*0b57cec5SDimitry Andric #include "ConstantsContext.h" 20*0b57cec5SDimitry Andric 21*0b57cec5SDimitry Andric namespace llvm { 22*0b57cec5SDimitry Andric Type *GEPOperator::getSourceElementType() const { 23*0b57cec5SDimitry Andric if (auto *I = dyn_cast<GetElementPtrInst>(this)) 24*0b57cec5SDimitry Andric return I->getSourceElementType(); 25*0b57cec5SDimitry Andric return cast<GetElementPtrConstantExpr>(this)->getSourceElementType(); 26*0b57cec5SDimitry Andric } 27*0b57cec5SDimitry Andric 28*0b57cec5SDimitry Andric Type *GEPOperator::getResultElementType() const { 29*0b57cec5SDimitry Andric if (auto *I = dyn_cast<GetElementPtrInst>(this)) 30*0b57cec5SDimitry Andric return I->getResultElementType(); 31*0b57cec5SDimitry Andric return cast<GetElementPtrConstantExpr>(this)->getResultElementType(); 32*0b57cec5SDimitry Andric } 33*0b57cec5SDimitry Andric 34*0b57cec5SDimitry Andric bool GEPOperator::accumulateConstantOffset(const DataLayout &DL, 35*0b57cec5SDimitry Andric APInt &Offset) const { 36*0b57cec5SDimitry Andric assert(Offset.getBitWidth() == 37*0b57cec5SDimitry Andric DL.getIndexSizeInBits(getPointerAddressSpace()) && 38*0b57cec5SDimitry Andric "The offset bit width does not match DL specification."); 39*0b57cec5SDimitry Andric 40*0b57cec5SDimitry Andric for (gep_type_iterator GTI = gep_type_begin(this), GTE = gep_type_end(this); 41*0b57cec5SDimitry Andric GTI != GTE; ++GTI) { 42*0b57cec5SDimitry Andric ConstantInt *OpC = dyn_cast<ConstantInt>(GTI.getOperand()); 43*0b57cec5SDimitry Andric if (!OpC) 44*0b57cec5SDimitry Andric return false; 45*0b57cec5SDimitry Andric if (OpC->isZero()) 46*0b57cec5SDimitry Andric continue; 47*0b57cec5SDimitry Andric 48*0b57cec5SDimitry Andric // Handle a struct index, which adds its field offset to the pointer. 49*0b57cec5SDimitry Andric if (StructType *STy = GTI.getStructTypeOrNull()) { 50*0b57cec5SDimitry Andric unsigned ElementIdx = OpC->getZExtValue(); 51*0b57cec5SDimitry Andric const StructLayout *SL = DL.getStructLayout(STy); 52*0b57cec5SDimitry Andric Offset += APInt(Offset.getBitWidth(), SL->getElementOffset(ElementIdx)); 53*0b57cec5SDimitry Andric continue; 54*0b57cec5SDimitry Andric } 55*0b57cec5SDimitry Andric 56*0b57cec5SDimitry Andric // For array or vector indices, scale the index by the size of the type. 57*0b57cec5SDimitry Andric APInt Index = OpC->getValue().sextOrTrunc(Offset.getBitWidth()); 58*0b57cec5SDimitry Andric Offset += Index * APInt(Offset.getBitWidth(), 59*0b57cec5SDimitry Andric DL.getTypeAllocSize(GTI.getIndexedType())); 60*0b57cec5SDimitry Andric } 61*0b57cec5SDimitry Andric return true; 62*0b57cec5SDimitry Andric } 63*0b57cec5SDimitry Andric } 64