static int64_t GetOffsetFromIndex(const GEPOperator *GEP, unsigned Idx, bool &VariableIdxFound, const TargetData &TD) { // Skip over the first indices. gep_type_iterator GTI = gep_type_begin(GEP); for (unsigned i = 1; i != Idx; ++i, ++GTI) /*skip along*/; // Compute the offset implied by the rest of the indices. int64_t Offset = 0; for (unsigned i = Idx, e = GEP->getNumOperands(); i != e; ++i, ++GTI) { ConstantInt *OpC = dyn_cast<ConstantInt>(GEP->getOperand(i)); if (OpC == 0) return VariableIdxFound = true; if (OpC->isZero()) continue; // No offset. // Handle struct indices, which add their field offset to the pointer. if (StructType *STy = dyn_cast<StructType>(*GTI)) { Offset += TD.getStructLayout(STy)->getElementOffset(OpC->getZExtValue()); continue; } // Otherwise, we have a sequential type like an array or vector. Multiply // the index by the ElementSize. uint64_t Size = TD.getTypeAllocSize(GTI.getIndexedType()); Offset += Size*OpC->getSExtValue(); } return Offset; }
static void ComputeStructureFieldIndices(const Type *Ty, unsigned Offset, std::vector<unsigned> &Idxs, const TargetData &TD) { if (Ty->isFirstClassType()) { assert(Offset == 0 && "Illegal structure index!"); return; } if (const SequentialType *STy = dyn_cast<SequentialType>(Ty)) { ComputeStructureFieldIndices(STy->getElementType(), Offset, Idxs, TD); } else if (const StructType *STy = dyn_cast<StructType>(Ty)) { const StructLayout *SL = TD.getStructLayout(STy); std::vector<uint64_t>::const_iterator SI = std::upper_bound(SL->MemberOffsets.begin(), SL->MemberOffsets.end(), Offset); assert(SI != SL->MemberOffsets.begin() && "Offset not in structure type!"); --SI; assert(*SI <= Offset && "upper_bound didn't work"); assert((SI == SL->MemberOffsets.begin() || *(SI-1) < Offset) && (SI+1 == SL->MemberOffsets.end() || *(SI+1) > Offset) && "Upper bound didn't work!"); Offset -= *SI; // Skip over the offset to this structure field. unsigned Idx = SI - SL->MemberOffsets.begin(); assert(Idx < STy->getNumElements() && "Illegal structure index"); Idxs.push_back(Idx); ComputeStructureFieldIndices(STy->getElementType(Idx), Offset, Idxs, TD); } else { assert(0 && "Unknown type to index into!"); } }
static unsigned getTypeSize(TargetData &TD, Type *type) { if (type->isFunctionTy()) /* it is not sized, weird */ return TD.getPointerSize(); if (!type->isSized()) return 100; /* FIXME */ if (StructType *ST = dyn_cast<StructType>(type)) return TD.getStructLayout(ST)->getSizeInBytes(); return TD.getTypeAllocSize(type); }
/// IsConstantOffsetFromGlobal - If this constant is actually a constant offset /// from a global, return the global and the constant. Because of /// constantexprs, this function is recursive. static bool IsConstantOffsetFromGlobal(Constant *C, GlobalValue *&GV, int64_t &Offset, const TargetData &TD) { // Trivial case, constant is the global. if ((GV = dyn_cast<GlobalValue>(C))) { Offset = 0; return true; } // Otherwise, if this isn't a constant expr, bail out. ConstantExpr *CE = dyn_cast<ConstantExpr>(C); if (!CE) return false; // Look through ptr->int and ptr->ptr casts. if (CE->getOpcode() == Instruction::PtrToInt || CE->getOpcode() == Instruction::BitCast) return IsConstantOffsetFromGlobal(CE->getOperand(0), GV, Offset, TD); // i32* getelementptr ([5 x i32]* @a, i32 0, i32 5) if (CE->getOpcode() == Instruction::GetElementPtr) { // Cannot compute this if the element type of the pointer is missing size // info. if (!cast<PointerType>(CE->getOperand(0)->getType())->getElementType()->isSized()) return false; // If the base isn't a global+constant, we aren't either. if (!IsConstantOffsetFromGlobal(CE->getOperand(0), GV, Offset, TD)) return false; // Otherwise, add any offset that our operands provide. gep_type_iterator GTI = gep_type_begin(CE); for (unsigned i = 1, e = CE->getNumOperands(); i != e; ++i, ++GTI) { ConstantInt *CI = dyn_cast<ConstantInt>(CE->getOperand(i)); if (!CI) return false; // Index isn't a simple constant? if (CI->getZExtValue() == 0) continue; // Not adding anything. if (const StructType *ST = dyn_cast<StructType>(*GTI)) { // N = N + Offset Offset += TD.getStructLayout(ST)->getElementOffset(CI->getZExtValue()); } else { const SequentialType *SQT = cast<SequentialType>(*GTI); Offset += TD.getTypeSize(SQT->getElementType())*CI->getSExtValue(); } } return true; } return false; }