// getElementOffset - The workhorse for getelementptr. // GenericValue Interpreter::executeGEPOperation(Value *Ptr, gep_type_iterator I, gep_type_iterator E, ExecutionContext &SF) { assert(isa<PointerType>(Ptr->getType()) && "Cannot getElementOffset of a nonpointer type!"); PointerTy Total = 0; for (; I != E; ++I) { if (const StructType *STy = dyn_cast<StructType>(*I)) { const StructLayout *SLO = TD.getStructLayout(STy); const ConstantUInt *CPU = cast<ConstantUInt>(I.getOperand()); unsigned Index = CPU->getValue(); Total += SLO->MemberOffsets[Index]; } else { const SequentialType *ST = cast<SequentialType>(*I); // Get the index number for the array... which must be long type... GenericValue IdxGV = getOperandValue(I.getOperand(), SF); uint64_t Idx; switch (I.getOperand()->getType()->getTypeID()) { default: assert(0 && "Illegal getelementptr index for sequential type!"); case Type::SByteTyID: Idx = IdxGV.SByteVal; break; case Type::ShortTyID: Idx = IdxGV.ShortVal; break; case Type::IntTyID: Idx = IdxGV.IntVal; break; case Type::LongTyID: Idx = IdxGV.LongVal; break; case Type::UByteTyID: Idx = IdxGV.UByteVal; break; case Type::UShortTyID: Idx = IdxGV.UShortVal; break; case Type::UIntTyID: Idx = IdxGV.UIntVal; break; case Type::ULongTyID: Idx = IdxGV.ULongVal; break; } Total += TD.getTypeSize(ST->getElementType())*Idx; } } GenericValue Result; Result.PointerVal = getOperandValue(Ptr, SF).PointerVal + Total; return Result; }
/** * Print a getelementptr instruction. * * @param v the aggregate data structure to index * @param i an iterator to the first type indexed by the instruction * @param e an iterator specifying the upper bound on the types indexed by the * instruction */ void JVMWriter::printGepInstruction(const Value *v, gep_type_iterator i, gep_type_iterator e) { // load address printCastInstruction(Instruction::IntToPtr, v, NULL, v->getType()); // calculate offset for(; i != e; i++) { unsigned int size = 0; const Value *indexValue = i.getOperand(); if(const StructType *structTy = dyn_cast<StructType>(*i)) { for(unsigned int f = 0, fieldIndex = cast<ConstantInt>(indexValue)->getZExtValue(); f < fieldIndex; f++) size = alignOffset( size + targetData->getTypeAllocSize( structTy->getContainedType(f)), targetData->getABITypeAlignment( structTy->getContainedType(f + 1))); printPtrLoad(size); printSimpleInstruction("iadd"); } else { if(const SequentialType *seqTy = dyn_cast<SequentialType>(*i)) size = targetData->getTypeAllocSize(seqTy->getElementType()); else size = targetData->getTypeAllocSize(*i); if(const ConstantInt *c = dyn_cast<ConstantInt>(indexValue)) { // constant optimisation if(c->isNullValue()) { // do nothing } else if(c->getValue().isNegative()) { printPtrLoad(c->getValue().abs().getZExtValue() * size); printSimpleInstruction("isub"); } else { printPtrLoad(c->getZExtValue() * size); printSimpleInstruction("iadd"); } } else { printPtrLoad(size); printCastInstruction(Instruction::IntToPtr, indexValue, NULL, indexValue->getType()); printSimpleInstruction("imul"); printSimpleInstruction("iadd"); } } } }