diff options
author | Alkis Evlogimenos <alkis@evlogimenos.com> | 2004-07-29 12:33:25 +0000 |
---|---|---|
committer | Alkis Evlogimenos <alkis@evlogimenos.com> | 2004-07-29 12:33:25 +0000 |
commit | 91366a85413285d15cbe462591f1ceef2ea1f6d7 (patch) | |
tree | a0dc8ce29a595609d8a9e2edc62b16c8a3891a49 /lib/VMCore/Instructions.cpp | |
parent | eb62bc77b68e8d2350453d15aca300f481a612d5 (diff) |
Merge i*.cpp definitions into Instructions.cpp as part of bug403.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@15326 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/VMCore/Instructions.cpp')
-rw-r--r-- | lib/VMCore/Instructions.cpp | 802 |
1 files changed, 802 insertions, 0 deletions
diff --git a/lib/VMCore/Instructions.cpp b/lib/VMCore/Instructions.cpp new file mode 100644 index 0000000000..4d33bb0eb0 --- /dev/null +++ b/lib/VMCore/Instructions.cpp @@ -0,0 +1,802 @@ +//===-- Instructions.cpp - Implement the LLVM 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 LLVM instructions... +// +//===----------------------------------------------------------------------===// + +#include "llvm/BasicBlock.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Function.h" +#include "llvm/Instructions.h" +#include "llvm/Support/CallSite.h" +using namespace llvm; + +//===----------------------------------------------------------------------===// +// CallInst Implementation +//===----------------------------------------------------------------------===// + +void CallInst::init(Value *Func, const std::vector<Value*> &Params) +{ + Operands.reserve(1+Params.size()); + Operands.push_back(Use(Func, this)); + + const FunctionType *FTy = + cast<FunctionType>(cast<PointerType>(Func->getType())->getElementType()); + + assert((Params.size() == FTy->getNumParams() || + (FTy->isVarArg() && Params.size() > FTy->getNumParams())) && + "Calling a function with bad signature"); + for (unsigned i = 0; i != Params.size(); i++) + Operands.push_back(Use(Params[i], this)); +} + +void CallInst::init(Value *Func, Value *Actual1, Value *Actual2) +{ + Operands.reserve(3); + Operands.push_back(Use(Func, this)); + + const FunctionType *MTy = + cast<FunctionType>(cast<PointerType>(Func->getType())->getElementType()); + + assert((MTy->getNumParams() == 2 || + (MTy->isVarArg() && MTy->getNumParams() == 0)) && + "Calling a function with bad signature"); + Operands.push_back(Use(Actual1, this)); + Operands.push_back(Use(Actual2, this)); +} + +void CallInst::init(Value *Func, Value *Actual) +{ + Operands.reserve(2); + Operands.push_back(Use(Func, this)); + + const FunctionType *MTy = + cast<FunctionType>(cast<PointerType>(Func->getType())->getElementType()); + + assert((MTy->getNumParams() == 1 || + (MTy->isVarArg() && MTy->getNumParams() == 0)) && + "Calling a function with bad signature"); + Operands.push_back(Use(Actual, this)); +} + +void CallInst::init(Value *Func) +{ + Operands.reserve(1); + Operands.push_back(Use(Func, this)); + + const FunctionType *MTy = + cast<FunctionType>(cast<PointerType>(Func->getType())->getElementType()); + + assert(MTy->getNumParams() == 0 && "Calling a function with bad signature"); +} + +CallInst::CallInst(Value *Func, const std::vector<Value*> &Params, + const std::string &Name, Instruction *InsertBefore) + : Instruction(cast<FunctionType>(cast<PointerType>(Func->getType()) + ->getElementType())->getReturnType(), + Instruction::Call, Name, InsertBefore) { + init(Func, Params); +} + +CallInst::CallInst(Value *Func, const std::vector<Value*> &Params, + const std::string &Name, BasicBlock *InsertAtEnd) + : Instruction(cast<FunctionType>(cast<PointerType>(Func->getType()) + ->getElementType())->getReturnType(), + Instruction::Call, Name, InsertAtEnd) { + init(Func, Params); +} + +CallInst::CallInst(Value *Func, Value *Actual1, Value *Actual2, + const std::string &Name, Instruction *InsertBefore) + : Instruction(cast<FunctionType>(cast<PointerType>(Func->getType()) + ->getElementType())->getReturnType(), + Instruction::Call, Name, InsertBefore) { + init(Func, Actual1, Actual2); +} + +CallInst::CallInst(Value *Func, Value *Actual1, Value *Actual2, + const std::string &Name, BasicBlock *InsertAtEnd) + : Instruction(cast<FunctionType>(cast<PointerType>(Func->getType()) + ->getElementType())->getReturnType(), + Instruction::Call, Name, InsertAtEnd) { + init(Func, Actual1, Actual2); +} + +CallInst::CallInst(Value *Func, Value* Actual, const std::string &Name, + Instruction *InsertBefore) + : Instruction(cast<FunctionType>(cast<PointerType>(Func->getType()) + ->getElementType())->getReturnType(), + Instruction::Call, Name, InsertBefore) { + init(Func, Actual); +} + +CallInst::CallInst(Value *Func, Value* Actual, const std::string &Name, + BasicBlock *InsertAtEnd) + : Instruction(cast<FunctionType>(cast<PointerType>(Func->getType()) + ->getElementType())->getReturnType(), + Instruction::Call, Name, InsertAtEnd) { + init(Func, Actual); +} + +CallInst::CallInst(Value *Func, const std::string &Name, + Instruction *InsertBefore) + : Instruction(cast<FunctionType>(cast<PointerType>(Func->getType()) + ->getElementType())->getReturnType(), + Instruction::Call, Name, InsertBefore) { + init(Func); +} + +CallInst::CallInst(Value *Func, const std::string &Name, + BasicBlock *InsertAtEnd) + : Instruction(cast<FunctionType>(cast<PointerType>(Func->getType()) + ->getElementType())->getReturnType(), + Instruction::Call, Name, InsertAtEnd) { + init(Func); +} + +CallInst::CallInst(const CallInst &CI) + : Instruction(CI.getType(), Instruction::Call) { + Operands.reserve(CI.Operands.size()); + for (unsigned i = 0; i < CI.Operands.size(); ++i) + Operands.push_back(Use(CI.Operands[i], this)); +} + +const Function *CallInst::getCalledFunction() const { + if (const Function *F = dyn_cast<Function>(Operands[0])) + return F; + return 0; +} +Function *CallInst::getCalledFunction() { + if (Function *F = dyn_cast<Function>(Operands[0])) + return F; + return 0; +} + + +//===----------------------------------------------------------------------===// +// InvokeInst Implementation +//===----------------------------------------------------------------------===// + +void InvokeInst::init(Value *Fn, BasicBlock *IfNormal, BasicBlock *IfException, + const std::vector<Value*> &Params) +{ + Operands.reserve(3+Params.size()); + Operands.push_back(Use(Fn, this)); + Operands.push_back(Use((Value*)IfNormal, this)); + Operands.push_back(Use((Value*)IfException, this)); + const FunctionType *MTy = + cast<FunctionType>(cast<PointerType>(Fn->getType())->getElementType()); + + assert((Params.size() == MTy->getNumParams()) || + (MTy->isVarArg() && Params.size() > MTy->getNumParams()) && + "Calling a function with bad signature"); + + for (unsigned i = 0; i < Params.size(); i++) + Operands.push_back(Use(Params[i], this)); +} + +InvokeInst::InvokeInst(Value *Fn, BasicBlock *IfNormal, + BasicBlock *IfException, + const std::vector<Value*> &Params, + const std::string &Name, Instruction *InsertBefore) + : TerminatorInst(cast<FunctionType>(cast<PointerType>(Fn->getType()) + ->getElementType())->getReturnType(), + Instruction::Invoke, Name, InsertBefore) { + init(Fn, IfNormal, IfException, Params); +} + +InvokeInst::InvokeInst(Value *Fn, BasicBlock *IfNormal, + BasicBlock *IfException, + const std::vector<Value*> &Params, + const std::string &Name, BasicBlock *InsertAtEnd) + : TerminatorInst(cast<FunctionType>(cast<PointerType>(Fn->getType()) + ->getElementType())->getReturnType(), + Instruction::Invoke, Name, InsertAtEnd) { + init(Fn, IfNormal, IfException, Params); +} + +InvokeInst::InvokeInst(const InvokeInst &CI) + : TerminatorInst(CI.getType(), Instruction::Invoke) { + Operands.reserve(CI.Operands.size()); + for (unsigned i = 0; i < CI.Operands.size(); ++i) + Operands.push_back(Use(CI.Operands[i], this)); +} + +const Function *InvokeInst::getCalledFunction() const { + if (const Function *F = dyn_cast<Function>(Operands[0])) + return F; + return 0; +} +Function *InvokeInst::getCalledFunction() { + if (Function *F = dyn_cast<Function>(Operands[0])) + return F; + return 0; +} + +// FIXME: Is this supposed to be here? +Function *CallSite::getCalledFunction() const { + Value *Callee = getCalledValue(); + if (Function *F = dyn_cast<Function>(Callee)) + return F; + return 0; +} + +//===----------------------------------------------------------------------===// +// ReturnInst Implementation +//===----------------------------------------------------------------------===// + +// Out-of-line ReturnInst method, put here so the C++ compiler can choose to +// emit the vtable for the class in this translation unit. +void ReturnInst::setSuccessor(unsigned idx, BasicBlock *NewSucc) { + assert(0 && "ReturnInst has no successors!"); +} + +//===----------------------------------------------------------------------===// +// UnwindInst Implementation +//===----------------------------------------------------------------------===// + +// Likewise for UnwindInst +void UnwindInst::setSuccessor(unsigned idx, BasicBlock *NewSucc) { + assert(0 && "UnwindInst has no successors!"); +} + +//===----------------------------------------------------------------------===// +// BranchInst Implementation +//===----------------------------------------------------------------------===// + +void BranchInst::init(BasicBlock *IfTrue) +{ + assert(IfTrue != 0 && "Branch destination may not be null!"); + Operands.reserve(1); + Operands.push_back(Use(IfTrue, this)); +} + +void BranchInst::init(BasicBlock *IfTrue, BasicBlock *IfFalse, Value *Cond) +{ + assert(IfTrue && IfFalse && Cond && + "Branch destinations and condition may not be null!"); + assert(Cond && Cond->getType() == Type::BoolTy && + "May only branch on boolean predicates!"); + Operands.reserve(3); + Operands.push_back(Use(IfTrue, this)); + Operands.push_back(Use(IfFalse, this)); + Operands.push_back(Use(Cond, this)); +} + +BranchInst::BranchInst(const BranchInst &BI) : TerminatorInst(Instruction::Br) { + Operands.reserve(BI.Operands.size()); + Operands.push_back(Use(BI.Operands[0], this)); + if (BI.Operands.size() != 1) { + assert(BI.Operands.size() == 3 && "BR can have 1 or 3 operands!"); + Operands.push_back(Use(BI.Operands[1], this)); + Operands.push_back(Use(BI.Operands[2], this)); + } +} + +//===----------------------------------------------------------------------===// +// AllocationInst Implementation +//===----------------------------------------------------------------------===// + +void AllocationInst::init(const Type *Ty, Value *ArraySize, unsigned iTy) { + assert(Ty != Type::VoidTy && "Cannot allocate void elements!"); + // 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)); +} + +AllocationInst::AllocationInst(const Type *Ty, Value *ArraySize, unsigned iTy, + const std::string &Name, + Instruction *InsertBefore) + : Instruction(PointerType::get(Ty), iTy, Name, InsertBefore) { + init(Ty, ArraySize, iTy); +} + +AllocationInst::AllocationInst(const Type *Ty, Value *ArraySize, unsigned iTy, + const std::string &Name, + BasicBlock *InsertAtEnd) + : Instruction(PointerType::get(Ty), iTy, Name, InsertAtEnd) { + init(Ty, ArraySize, iTy); +} + +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 +//===----------------------------------------------------------------------===// + +void FreeInst::init(Value *Ptr) +{ + assert(Ptr && isa<PointerType>(Ptr->getType()) && "Can't free nonpointer!"); + Operands.reserve(1); + Operands.push_back(Use(Ptr, this)); +} + +FreeInst::FreeInst(Value *Ptr, Instruction *InsertBefore) + : Instruction(Type::VoidTy, Free, "", InsertBefore) { + init(Ptr); +} + +FreeInst::FreeInst(Value *Ptr, BasicBlock *InsertAtEnd) + : Instruction(Type::VoidTy, Free, "", InsertAtEnd) { + init(Ptr); +} + + +//===----------------------------------------------------------------------===// +// LoadInst Implementation +//===----------------------------------------------------------------------===// + +void LoadInst::init(Value *Ptr) { + assert(Ptr && isa<PointerType>(Ptr->getType()) && + "Ptr must have pointer type."); + Operands.reserve(1); + Operands.push_back(Use(Ptr, this)); +} + +LoadInst::LoadInst(Value *Ptr, const std::string &Name, Instruction *InsertBef) + : Instruction(cast<PointerType>(Ptr->getType())->getElementType(), + Load, Name, InsertBef), Volatile(false) { + init(Ptr); +} + +LoadInst::LoadInst(Value *Ptr, const std::string &Name, BasicBlock *InsertAE) + : Instruction(cast<PointerType>(Ptr->getType())->getElementType(), + Load, Name, InsertAE), Volatile(false) { + init(Ptr); +} + +LoadInst::LoadInst(Value *Ptr, const std::string &Name, bool isVolatile, + Instruction *InsertBef) + : Instruction(cast<PointerType>(Ptr->getType())->getElementType(), + Load, Name, InsertBef), Volatile(isVolatile) { + init(Ptr); +} + +LoadInst::LoadInst(Value *Ptr, const std::string &Name, bool isVolatile, + BasicBlock *InsertAE) + : Instruction(cast<PointerType>(Ptr->getType())->getElementType(), + Load, Name, InsertAE), Volatile(isVolatile) { + init(Ptr); +} + + +//===----------------------------------------------------------------------===// +// StoreInst Implementation +//===----------------------------------------------------------------------===// + +StoreInst::StoreInst(Value *Val, Value *Ptr, Instruction *InsertBefore) + : Instruction(Type::VoidTy, Store, "", InsertBefore), Volatile(false) { + init(Val, Ptr); +} + +StoreInst::StoreInst(Value *Val, Value *Ptr, BasicBlock *InsertAtEnd) + : Instruction(Type::VoidTy, Store, "", InsertAtEnd), Volatile(false) { + init(Val, Ptr); +} + +StoreInst::StoreInst(Value *Val, Value *Ptr, bool isVolatile, + Instruction *InsertBefore) + : Instruction(Type::VoidTy, Store, "", InsertBefore), Volatile(isVolatile) { + init(Val, Ptr); +} + +StoreInst::StoreInst(Value *Val, Value *Ptr, bool isVolatile, + BasicBlock *InsertAtEnd) + : Instruction(Type::VoidTy, Store, "", InsertAtEnd), Volatile(isVolatile) { + init(Val, Ptr); +} + +void StoreInst::init(Value *Val, Value *Ptr) { + assert(isa<PointerType>(Ptr->getType()) && + Val->getType() == cast<PointerType>(Ptr->getType())->getElementType() + && "Ptr must have pointer type."); + + 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; +} + +void GetElementPtrInst::init(Value *Ptr, const std::vector<Value*> &Idx) +{ + 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)); +} + +void GetElementPtrInst::init(Value *Ptr, Value *Idx0, Value *Idx1) { + Operands.reserve(3); + Operands.push_back(Use(Ptr, this)); + Operands.push_back(Use(Idx0, this)); + Operands.push_back(Use(Idx1, this)); +} + +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) { + init(Ptr, Idx); +} + +GetElementPtrInst::GetElementPtrInst(Value *Ptr, const std::vector<Value*> &Idx, + const std::string &Name, BasicBlock *IAE) + : Instruction(PointerType::get(checkType(getIndexedType(Ptr->getType(), + Idx, true))), + GetElementPtr, Name, IAE) { + init(Ptr, Idx); +} + +GetElementPtrInst::GetElementPtrInst(Value *Ptr, Value *Idx0, Value *Idx1, + const std::string &Name, Instruction *InBe) + : Instruction(PointerType::get(checkType(getIndexedType(Ptr->getType(), + Idx0, Idx1, true))), + GetElementPtr, Name, InBe) { + init(Ptr, Idx0, Idx1); +} + +GetElementPtrInst::GetElementPtrInst(Value *Ptr, Value *Idx0, Value *Idx1, + const std::string &Name, BasicBlock *IAE) + : Instruction(PointerType::get(checkType(getIndexedType(Ptr->getType(), + Idx0, Idx1, true))), + GetElementPtr, Name, IAE) { + init(Ptr, Idx0, Idx1); +} + +// 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()) + if (AllowCompositeLeaf || + cast<PointerType>(Ptr)->getElementType()->isFirstClassType()) + return cast<PointerType>(Ptr)->getElementType(); + else + return 0; + + 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); + + // If the new type forwards to another type, then it is in the middle + // of being refined to another type (and hence, may have dropped all + // references to what it was using before). So, use the new forwarded + // type. + if (const Type * Ty = Ptr->getForwardedType()) { + Ptr = Ty; + } + } + return CurIdx == Idx.size() ? Ptr : 0; +} + +const Type* GetElementPtrInst::getIndexedType(const Type *Ptr, + Value *Idx0, Value *Idx1, + bool AllowCompositeLeaf) { + const PointerType *PTy = dyn_cast<PointerType>(Ptr); + if (!PTy) return 0; // Type isn't a pointer type! + + // Check the pointer index. + if (!PTy->indexValid(Idx0)) return 0; + + const CompositeType *CT = dyn_cast<CompositeType>(PTy->getElementType()); + if (!CT || !CT->indexValid(Idx1)) return 0; + + const Type *ElTy = CT->getTypeAtIndex(Idx1); + if (AllowCompositeLeaf || ElTy->isFirstClassType()) + return ElTy; + return 0; +} + +//===----------------------------------------------------------------------===// +// BinaryOperator Class +//===----------------------------------------------------------------------===// + +void BinaryOperator::init(BinaryOps iType, Value *S1, Value *S2) +{ + Operands.reserve(2); + Operands.push_back(Use(S1, this)); + Operands.push_back(Use(S2, this)); + assert(S1 && S2 && S1->getType() == S2->getType()); + +#ifndef NDEBUG + switch (iType) { + case Add: case Sub: + case Mul: case Div: + case Rem: + assert(getType() == S1->getType() && + "Arithmetic operation should return same type as operands!"); + assert((getType()->isInteger() || getType()->isFloatingPoint()) && + "Tried to create an arithmetic operation on a non-arithmetic type!"); + break; + case And: case Or: + case Xor: + assert(getType() == S1->getType() && + "Logical operation should return same type as operands!"); + assert(getType()->isIntegral() && + "Tried to create an logical operation on a non-integral type!"); + break; + case SetLT: case SetGT: case SetLE: + case SetGE: case SetEQ: case SetNE: + assert(getType() == Type::BoolTy && "Setcc must return bool!"); + default: + break; + } +#endif +} + +BinaryOperator *BinaryOperator::create(BinaryOps Op, Value *S1, Value *S2, + const std::string &Name, + Instruction *InsertBefore) { + assert(S1->getType() == S2->getType() && + "Cannot create binary operator with two operands of differing type!"); + switch (Op) { + // Binary comparison operators... + case SetLT: case SetGT: case SetLE: + case SetGE: case SetEQ: case SetNE: + return new SetCondInst(Op, S1, S2, Name, InsertBefore); + + default: + return new BinaryOperator(Op, S1, S2, S1->getType(), Name, InsertBefore); + } +} + +BinaryOperator *BinaryOperator::create(BinaryOps Op, Value *S1, Value *S2, + const std::string &Name, + BasicBlock *InsertAtEnd) { + BinaryOperator *Res = create(Op, S1, S2, Name); + InsertAtEnd->getInstList().push_back(Res); + return Res; +} + +BinaryOperator *BinaryOperator::createNeg(Value *Op, const std::string &Name, + Instruction *InsertBefore) { + if (!Op->getType()->isFloatingPoint()) + return new BinaryOperator(Instruction::Sub, + Constant::getNullValue(Op->getType()), Op, + Op->getType(), Name, InsertBefore); + else + return new BinaryOperator(Instruction::Sub, + ConstantFP::get(Op->getType(), -0.0), Op, + Op->getType(), Name, InsertBefore); +} + +BinaryOperator *BinaryOperator::createNeg(Value *Op, const std::string &Name, + BasicBlock *InsertAtEnd) { + if (!Op->getType()->isFloatingPoint()) + return new BinaryOperator(Instruction::Sub, + Constant::getNullValue(Op->getType()), Op, + Op->getType(), Name, InsertAtEnd); + else + return new BinaryOperator(Instruction::Sub, + ConstantFP::get(Op->getType(), -0.0), Op, + Op->getType(), Name, InsertAtEnd); +} + +BinaryOperator *BinaryOperator::createNot(Value *Op, const std::string &Name, + Instruction *InsertBefore) { + return new BinaryOperator(Instruction::Xor, Op, + ConstantIntegral::getAllOnesValue(Op->getType()), + Op->getType(), Name, InsertBefore); +} + +BinaryOperator *BinaryOperator::createNot(Value *Op, const std::string &Name, + BasicBlock *InsertAtEnd) { + return new BinaryOperator(Instruction::Xor, Op, + ConstantIntegral::getAllOnesValue(Op->getType()), + Op->getType(), Name, InsertAtEnd); +} + + +// isConstantAllOnes - Helper function for several functions below +static inline bool isConstantAllOnes(const Value *V) { + return isa<ConstantIntegral>(V) &&cast<ConstantIntegral>(V)->isAllOnesValue(); +} + +bool BinaryOperator::isNeg(const Value *V) { + if (const BinaryOperator *Bop = dyn_cast<BinaryOperator>(V)) + if (Bop->getOpcode() == Instruction::Sub) + if (!V->getType()->isFloatingPoint()) + return Bop->getOperand(0) == Constant::getNullValue(Bop->getType()); + else + return Bop->getOperand(0) == ConstantFP::get(Bop->getType(), -0.0); + return false; +} + +bool BinaryOperator::isNot(const Value *V) { + if (const BinaryOperator *Bop = dyn_cast<BinaryOperator>(V)) + return (Bop->getOpcode() == Instruction::Xor && + (isConstantAllOnes(Bop->getOperand(1)) || + isConstantAllOnes(Bop->getOperand(0)))); + return false; +} + +Value *BinaryOperator::getNegArgument(BinaryOperator *Bop) { + assert(isNeg(Bop) && "getNegArgument from non-'neg' instruction!"); + return Bop->getOperand(1); +} + +const Value *BinaryOperator::getNegArgument(const BinaryOperator *Bop) { + return getNegArgument((BinaryOperator*)Bop); +} + +Value *BinaryOperator::getNotArgument(BinaryOperator *Bop) { + assert(isNot(Bop) && "getNotArgument on non-'not' instruction!"); + Value *Op0 = Bop->getOperand(0); + Value *Op1 = Bop->getOperand(1); + if (isConstantAllOnes(Op0)) return Op1; + + assert(isConstantAllOnes(Op1)); + return Op0; +} + +const Value *BinaryOperator::getNotArgument(const BinaryOperator *Bop) { + return getNotArgument((BinaryOperator*)Bop); +} + + +// swapOperands - Exchange the two operands to this instruction. This +// instruction is safe to use on any binary instruction and does not +// modify the semantics of the instruction. If the instruction is +// order dependent (SetLT f.e.) the opcode is changed. +// +bool BinaryOperator::swapOperands() { + if (isCommutative()) + ; // If the instruction is commutative, it is safe to swap the operands + else if (SetCondInst *SCI = dyn_cast<SetCondInst>(this)) + /// FIXME: SetCC instructions shouldn't all have different opcodes. + setOpcode(SCI->getSwappedCondition()); + else + return true; // Can't commute operands + + std::swap(Operands[0], Operands[1]); + return false; +} + + +//===----------------------------------------------------------------------===// +// SetCondInst Class +//===----------------------------------------------------------------------===// + +SetCondInst::SetCondInst(BinaryOps Opcode, Value *S1, Value *S2, + const std::string &Name, Instruction *InsertBefore) + : BinaryOperator(Opcode, S1, S2, Type::BoolTy, Name, InsertBefore) { + + // Make sure it's a valid type... getInverseCondition will assert out if not. + assert(getInverseCondition(Opcode)); +} + +SetCondInst::SetCondInst(BinaryOps Opcode, Value *S1, Value *S2, + const std::string &Name, BasicBlock *InsertAtEnd) + : BinaryOperator(Opcode, S1, S2, Type::BoolTy, Name, InsertAtEnd) { + + // Make sure it's a valid type... getInverseCondition will assert out if not. + assert(getInverseCondition(Opcode)); +} + +// getInverseCondition - Return the inverse of the current condition opcode. +// For example seteq -> setne, setgt -> setle, setlt -> setge, etc... +// +Instruction::BinaryOps SetCondInst::getInverseCondition(BinaryOps Opcode) { + switch (Opcode) { + default: + assert(0 && "Unknown setcc opcode!"); + case SetEQ: return SetNE; + case SetNE: return SetEQ; + case SetGT: return SetLE; + case SetLT: return SetGE; + case SetGE: return SetLT; + case SetLE: return SetGT; + } +} + +// getSwappedCondition - Return the condition opcode that would be the result +// of exchanging the two operands of the setcc instruction without changing +// the result produced. Thus, seteq->seteq, setle->setge, setlt->setgt, etc. +// +Instruction::BinaryOps SetCondInst::getSwappedCondition(BinaryOps Opcode) { + switch (Opcode) { + default: assert(0 && "Unknown setcc instruction!"); + case SetEQ: case SetNE: return Opcode; + case SetGT: return SetLT; + case SetLT: return SetGT; + case SetGE: return SetLE; + case SetLE: return SetGE; + } +} + +//===----------------------------------------------------------------------===// +// SwitchInst Implementation +//===----------------------------------------------------------------------===// + +void SwitchInst::init(Value *Value, BasicBlock *Default) +{ + assert(Value && Default); + Operands.push_back(Use(Value, this)); + Operands.push_back(Use(Default, this)); +} + +SwitchInst::SwitchInst(const SwitchInst &SI) + : TerminatorInst(Instruction::Switch) { + Operands.reserve(SI.Operands.size()); + + for (unsigned i = 0, E = SI.Operands.size(); i != E; i+=2) { + Operands.push_back(Use(SI.Operands[i], this)); + Operands.push_back(Use(SI.Operands[i+1], this)); + } +} + +/// addCase - Add an entry to the switch instruction... +/// +void SwitchInst::addCase(Constant *OnVal, BasicBlock *Dest) { + Operands.push_back(Use((Value*)OnVal, this)); + Operands.push_back(Use((Value*)Dest, this)); +} + +/// removeCase - This method removes the specified successor from the switch +/// instruction. Note that this cannot be used to remove the default +/// destination (successor #0). +/// +void SwitchInst::removeCase(unsigned idx) { + assert(idx != 0 && "Cannot remove the default case!"); + assert(idx*2 < Operands.size() && "Successor index out of range!!!"); + Operands.erase(Operands.begin()+idx*2, Operands.begin()+(idx+1)*2); +} |