| //===-- iMemory.cpp - Implement Memory instructions -----------------------===// |
| // |
| // The LLVM Compiler Infrastructure |
| // |
| // This file was developed by the LLVM research group and is distributed under |
| // the University of Illinois Open Source License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // This file implements the various memory related classes defined in iMemory.h |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "llvm/iMemory.h" |
| #include "llvm/Constants.h" |
| #include "llvm/DerivedTypes.h" |
| |
| using namespace llvm; |
| |
| AllocationInst::AllocationInst(const Type *Ty, Value *ArraySize, unsigned iTy, |
| const std::string &Name, Instruction *InsertBef) |
| : Instruction(PointerType::get(Ty), iTy, Name, InsertBef) { |
| |
| // ArraySize defaults to 1. |
| if (!ArraySize) ArraySize = ConstantUInt::get(Type::UIntTy, 1); |
| |
| Operands.reserve(1); |
| assert(ArraySize->getType() == Type::UIntTy && |
| "Malloc/Allocation array size != UIntTy!"); |
| |
| Operands.push_back(Use(ArraySize, this)); |
| } |
| |
| bool AllocationInst::isArrayAllocation() const { |
| return getOperand(0) != ConstantUInt::get(Type::UIntTy, 1); |
| } |
| |
| const Type *AllocationInst::getAllocatedType() const { |
| return getType()->getElementType(); |
| } |
| |
| AllocaInst::AllocaInst(const AllocaInst &AI) |
| : AllocationInst(AI.getType()->getElementType(), (Value*)AI.getOperand(0), |
| Instruction::Alloca) { |
| } |
| |
| MallocInst::MallocInst(const MallocInst &MI) |
| : AllocationInst(MI.getType()->getElementType(), (Value*)MI.getOperand(0), |
| Instruction::Malloc) { |
| } |
| |
| //===----------------------------------------------------------------------===// |
| // FreeInst Implementation |
| //===----------------------------------------------------------------------===// |
| |
| FreeInst::FreeInst(Value *Ptr, Instruction *InsertBefore) |
| : Instruction(Type::VoidTy, Free, "", InsertBefore) { |
| assert(isa<PointerType>(Ptr->getType()) && "Can't free nonpointer!"); |
| Operands.reserve(1); |
| Operands.push_back(Use(Ptr, this)); |
| } |
| |
| |
| //===----------------------------------------------------------------------===// |
| // LoadInst Implementation |
| //===----------------------------------------------------------------------===// |
| |
| LoadInst::LoadInst(Value *Ptr, const std::string &Name, Instruction *InsertBef) |
| : Instruction(cast<PointerType>(Ptr->getType())->getElementType(), |
| Load, Name, InsertBef), Volatile(false) { |
| Operands.reserve(1); |
| Operands.push_back(Use(Ptr, this)); |
| } |
| |
| LoadInst::LoadInst(Value *Ptr, const std::string &Name, bool isVolatile, |
| Instruction *InsertBef) |
| : Instruction(cast<PointerType>(Ptr->getType())->getElementType(), |
| Load, Name, InsertBef), Volatile(isVolatile) { |
| Operands.reserve(1); |
| Operands.push_back(Use(Ptr, this)); |
| } |
| |
| //===----------------------------------------------------------------------===// |
| // StoreInst Implementation |
| //===----------------------------------------------------------------------===// |
| |
| StoreInst::StoreInst(Value *Val, Value *Ptr, Instruction *InsertBefore) |
| : Instruction(Type::VoidTy, Store, "", InsertBefore), Volatile(false) { |
| |
| Operands.reserve(2); |
| Operands.push_back(Use(Val, this)); |
| Operands.push_back(Use(Ptr, this)); |
| } |
| |
| StoreInst::StoreInst(Value *Val, Value *Ptr, bool isVolatile, |
| Instruction *InsertBefore) |
| : Instruction(Type::VoidTy, Store, "", InsertBefore), Volatile(isVolatile) { |
| |
| Operands.reserve(2); |
| Operands.push_back(Use(Val, this)); |
| Operands.push_back(Use(Ptr, this)); |
| } |
| |
| |
| //===----------------------------------------------------------------------===// |
| // GetElementPtrInst Implementation |
| //===----------------------------------------------------------------------===// |
| |
| // checkType - Simple wrapper function to give a better assertion failure |
| // message on bad indexes for a gep instruction. |
| // |
| static inline const Type *checkType(const Type *Ty) { |
| assert(Ty && "Invalid indices for type!"); |
| return Ty; |
| } |
| |
| GetElementPtrInst::GetElementPtrInst(Value *Ptr, const std::vector<Value*> &Idx, |
| const std::string &Name, Instruction *InBe) |
| : Instruction(PointerType::get(checkType(getIndexedType(Ptr->getType(), |
| Idx, true))), |
| GetElementPtr, Name, InBe) { |
| Operands.reserve(1+Idx.size()); |
| Operands.push_back(Use(Ptr, this)); |
| |
| for (unsigned i = 0, E = Idx.size(); i != E; ++i) |
| Operands.push_back(Use(Idx[i], this)); |
| } |
| |
| // getIndexedType - Returns the type of the element that would be loaded with |
| // a load instruction with the specified parameters. |
| // |
| // A null type is returned if the indices are invalid for the specified |
| // pointer type. |
| // |
| const Type* GetElementPtrInst::getIndexedType(const Type *Ptr, |
| const std::vector<Value*> &Idx, |
| bool AllowCompositeLeaf) { |
| if (!isa<PointerType>(Ptr)) return 0; // Type isn't a pointer type! |
| |
| // Handle the special case of the empty set index set... |
| if (Idx.empty()) return cast<PointerType>(Ptr)->getElementType(); |
| |
| unsigned CurIdx = 0; |
| while (const CompositeType *CT = dyn_cast<CompositeType>(Ptr)) { |
| if (Idx.size() == CurIdx) { |
| if (AllowCompositeLeaf || CT->isFirstClassType()) return Ptr; |
| return 0; // Can't load a whole structure or array!?!? |
| } |
| |
| Value *Index = Idx[CurIdx++]; |
| if (isa<PointerType>(CT) && CurIdx != 1) |
| return 0; // Can only index into pointer types at the first index! |
| if (!CT->indexValid(Index)) return 0; |
| Ptr = CT->getTypeAtIndex(Index); |
| } |
| return CurIdx == Idx.size() ? Ptr : 0; |
| } |