mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-02-19 06:31:18 +00:00
Changed the fundemental architecture of Operands for Instructions. Now
Operands are maintained as a vector<Use> in the User class, and operator iterators are provided as before. Getting an operand no longer requires a virtual function call. WARNING: getOperand(x) where x >= getNumOperands() will now assert instead of returning null! git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@149 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
f0d0e9c262
commit
c8b25d40cb
@ -28,11 +28,8 @@
|
||||
|
||||
class Instruction;
|
||||
class Method;
|
||||
class BasicBlock;
|
||||
class TerminatorInst;
|
||||
|
||||
typedef UseTy<BasicBlock> BasicBlockUse;
|
||||
|
||||
class BasicBlock : public Value { // Basic blocks are data objects also
|
||||
public:
|
||||
typedef ValueHolder<Instruction, BasicBlock> InstListType;
|
||||
|
@ -20,9 +20,6 @@ class StructType;
|
||||
// ConstPoolVal Class
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
class ConstPoolVal;
|
||||
typedef UseTy<ConstPoolVal> ConstPoolUse;
|
||||
|
||||
class ConstPoolVal : public User {
|
||||
SymTabValue *Parent;
|
||||
|
||||
@ -53,17 +50,6 @@ public:
|
||||
|
||||
inline const SymTabValue *getParent() const { return Parent; }
|
||||
inline SymTabValue *getParent() { return Parent; }
|
||||
|
||||
// if i > the number of operands, then getOperand() returns 0, and setOperand
|
||||
// returns false. setOperand() may also return false if the operand is of
|
||||
// the wrong type.
|
||||
//
|
||||
// Note that some subclasses may change this default no argument behavior
|
||||
//
|
||||
virtual Value *getOperand(unsigned i) { return 0; }
|
||||
virtual const Value *getOperand(unsigned i) const { return 0; }
|
||||
virtual bool setOperand(unsigned i, Value *Val) { return false; }
|
||||
virtual void dropAllReferences() {}
|
||||
};
|
||||
|
||||
|
||||
@ -172,7 +158,6 @@ public:
|
||||
// ConstPoolArray - Constant Array Declarations
|
||||
//
|
||||
class ConstPoolArray : public ConstPoolVal {
|
||||
vector<ConstPoolUse> Val;
|
||||
ConstPoolArray(const ConstPoolArray &CPT);
|
||||
public:
|
||||
ConstPoolArray(const ArrayType *T, vector<ConstPoolVal*> &V,
|
||||
@ -183,20 +168,7 @@ public:
|
||||
virtual string getStrValue() const;
|
||||
virtual bool equals(const ConstPoolVal *V) const;
|
||||
|
||||
inline const vector<ConstPoolUse> &getValues() const { return Val; }
|
||||
|
||||
// Implement User stuff...
|
||||
//
|
||||
virtual Value *getOperand(unsigned i) {
|
||||
return (i < Val.size()) ? Val[i] : 0;
|
||||
}
|
||||
virtual const Value *getOperand(unsigned i) const {
|
||||
return (i < Val.size()) ? Val[i] : 0;
|
||||
}
|
||||
|
||||
// setOperand fails! You can't change a constant!
|
||||
virtual bool setOperand(unsigned i, Value *Val) { return false; }
|
||||
virtual void dropAllReferences() { Val.clear(); }
|
||||
inline const vector<Use> &getValues() const { return Operands; }
|
||||
};
|
||||
|
||||
|
||||
@ -204,7 +176,6 @@ public:
|
||||
// ConstPoolStruct - Constant Struct Declarations
|
||||
//
|
||||
class ConstPoolStruct : public ConstPoolVal {
|
||||
vector<ConstPoolUse> Val;
|
||||
ConstPoolStruct(const ConstPoolStruct &CPT);
|
||||
public:
|
||||
ConstPoolStruct(const StructType *T, vector<ConstPoolVal*> &V,
|
||||
@ -215,20 +186,7 @@ public:
|
||||
virtual string getStrValue() const;
|
||||
virtual bool equals(const ConstPoolVal *V) const;
|
||||
|
||||
inline const vector<ConstPoolUse> &getValues() const { return Val; }
|
||||
|
||||
// Implement User stuff...
|
||||
//
|
||||
virtual Value *getOperand(unsigned i) {
|
||||
return (i < Val.size()) ? Val[i] : 0;
|
||||
}
|
||||
virtual const Value *getOperand(unsigned i) const {
|
||||
return (i < Val.size()) ? Val[i] : 0;
|
||||
}
|
||||
|
||||
// setOperand fails! You can't change a constant!
|
||||
virtual bool setOperand(unsigned i, Value *Val) { return false; }
|
||||
virtual void dropAllReferences() { Val.clear(); }
|
||||
inline const vector<Use> &getValues() const { return Operands; }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -19,11 +19,8 @@ class Instruction;
|
||||
class BasicBlock;
|
||||
class MethodArgument;
|
||||
class MethodType;
|
||||
class Method;
|
||||
class Module;
|
||||
|
||||
typedef UseTy<Method> MethodUse;
|
||||
|
||||
class Method : public SymTabValue {
|
||||
public:
|
||||
typedef ValueHolder<MethodArgument, Method> ArgumentListType;
|
||||
|
@ -30,15 +30,8 @@ public:
|
||||
|
||||
// Terminators must implement the methods required by Instruction...
|
||||
virtual Instruction *clone() const = 0;
|
||||
virtual void dropAllReferences() = 0;
|
||||
virtual string getOpcode() const = 0;
|
||||
|
||||
virtual bool setOperand(unsigned i, Value *Val) = 0;
|
||||
virtual const Value *getOperand(unsigned i) const = 0;
|
||||
inline Value *getOperand(unsigned i) {
|
||||
return (Value*)((const Instruction *)this)->getOperand(i);
|
||||
}
|
||||
|
||||
// Additionally, they must provide a method to get at the successors of this
|
||||
// terminator instruction. If 'idx' is out of range, a null pointer shall be
|
||||
// returned.
|
||||
@ -57,7 +50,6 @@ public:
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
class UnaryOperator : public Instruction {
|
||||
Use Source;
|
||||
public:
|
||||
|
||||
// create() - Construct a unary instruction, given the opcode
|
||||
@ -66,33 +58,17 @@ public:
|
||||
static UnaryOperator *create(unsigned Op, Value *Source);
|
||||
|
||||
UnaryOperator(Value *S, unsigned iType, const string &Name = "")
|
||||
: Instruction(S->getType(), iType, Name), Source(S, this) {
|
||||
: Instruction(S->getType(), iType, Name) {
|
||||
Operands.reserve(1);
|
||||
Operands.push_back(Use(S, this));
|
||||
}
|
||||
inline ~UnaryOperator() { dropAllReferences(); }
|
||||
|
||||
virtual Instruction *clone() const {
|
||||
return create(getInstType(), Source);
|
||||
}
|
||||
|
||||
virtual void dropAllReferences() {
|
||||
Source = 0;
|
||||
return create(getInstType(), Operands[0]);
|
||||
}
|
||||
|
||||
virtual string getOpcode() const = 0;
|
||||
|
||||
virtual unsigned getNumOperands() const { return 1; }
|
||||
inline Value *getOperand(unsigned i) {
|
||||
return (i == 0) ? Source : 0;
|
||||
}
|
||||
virtual const Value *getOperand(unsigned i) const {
|
||||
return (i == 0) ? Source : 0;
|
||||
}
|
||||
virtual bool setOperand(unsigned i, Value *Val) {
|
||||
// assert(Val && "operand must not be null!");
|
||||
if (i) return false;
|
||||
Source = Val;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -102,7 +78,6 @@ public:
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
class BinaryOperator : public Instruction {
|
||||
Use Source1, Source2;
|
||||
public:
|
||||
|
||||
// create() - Construct a binary instruction, given the opcode
|
||||
@ -113,41 +88,20 @@ public:
|
||||
|
||||
BinaryOperator(unsigned iType, Value *S1, Value *S2,
|
||||
const string &Name = "")
|
||||
: Instruction(S1->getType(), iType, Name), Source1(S1, this),
|
||||
Source2(S2, this){
|
||||
assert(S1 && S2 && S1->getType() == S2->getType());
|
||||
: Instruction(S1->getType(), iType, Name) {
|
||||
Operands.reserve(2);
|
||||
Operands.push_back(Use(S1, this));
|
||||
Operands.push_back(Use(S2, this));
|
||||
assert(Operands[0] && Operands[1] &&
|
||||
Operands[0]->getType() == Operands[1]->getType());
|
||||
}
|
||||
inline ~BinaryOperator() { dropAllReferences(); }
|
||||
|
||||
virtual Instruction *clone() const {
|
||||
return create(getInstType(), Source1, Source2);
|
||||
}
|
||||
|
||||
virtual void dropAllReferences() {
|
||||
Source1 = Source2 = 0;
|
||||
return create(getInstType(), Operands[0], Operands[1]);
|
||||
}
|
||||
|
||||
virtual string getOpcode() const = 0;
|
||||
|
||||
virtual unsigned getNumOperands() const { return 2; }
|
||||
virtual const Value *getOperand(unsigned i) const {
|
||||
return (i == 0) ? Source1 : ((i == 1) ? Source2 : 0);
|
||||
}
|
||||
inline Value *getOperand(unsigned i) {
|
||||
return (i == 0) ? Source1 : ((i == 1) ? Source2 : 0);
|
||||
}
|
||||
|
||||
virtual bool setOperand(unsigned i, Value *Val) {
|
||||
// assert(Val && "operand must not be null!");
|
||||
if (i == 0) {
|
||||
Source1 = Val; //assert(Val->getType() == Source2->getType());
|
||||
} else if (i == 1) {
|
||||
Source2 = Val; //assert(Val->getType() == Source1->getType());
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -41,32 +41,6 @@ public:
|
||||
inline BasicBlock *getParent() { return Parent; }
|
||||
bool hasSideEffects() const { return false; } // Memory & Call insts = true
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Implement the User interface
|
||||
// if i > the number of operands, then getOperand() returns 0, and setOperand
|
||||
// returns false. setOperand() may also return false if the operand is of
|
||||
// the wrong type.
|
||||
//
|
||||
inline Value *getOperand(unsigned i) {
|
||||
return (Value*)((const Instruction *)this)->getOperand(i);
|
||||
}
|
||||
virtual const Value *getOperand(unsigned i) const = 0;
|
||||
virtual bool setOperand(unsigned i, Value *Val) = 0;
|
||||
virtual unsigned getNumOperands() const = 0;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Operand Iterator interface...
|
||||
//
|
||||
template <class _Inst, class _Val> class OperandIterator;
|
||||
typedef OperandIterator<Instruction *, Value *> op_iterator;
|
||||
typedef OperandIterator<const Instruction *, const Value *> op_const_iterator;
|
||||
|
||||
inline op_iterator op_begin() ;
|
||||
inline op_const_iterator op_begin() const;
|
||||
inline op_iterator op_end() ;
|
||||
inline op_const_iterator op_end() const;
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Subclass classification... getInstType() returns a member of
|
||||
// one of the enums that is coming soon (down below)...
|
||||
@ -148,52 +122,6 @@ public:
|
||||
NumOps, // Must be the last 'op' defined.
|
||||
UserOp1, UserOp2 // May be used internally to a pass...
|
||||
};
|
||||
|
||||
public:
|
||||
template <class _Inst, class _Val> // Operand Iterator Implementation
|
||||
class OperandIterator {
|
||||
const _Inst Inst;
|
||||
unsigned idx;
|
||||
public:
|
||||
typedef OperandIterator<_Inst, _Val> _Self;
|
||||
typedef bidirectional_iterator_tag iterator_category;
|
||||
typedef _Val pointer;
|
||||
|
||||
inline OperandIterator(_Inst T) : Inst(T), idx(0) {} // begin iterator
|
||||
inline OperandIterator(_Inst T, bool)
|
||||
: Inst(T), idx(Inst->getNumOperands()) {} // end iterator
|
||||
|
||||
inline bool operator==(const _Self& x) const { return idx == x.idx; }
|
||||
inline bool operator!=(const _Self& x) const { return !operator==(x); }
|
||||
|
||||
inline pointer operator*() const { return Inst->getOperand(idx); }
|
||||
inline pointer *operator->() const { return &(operator*()); }
|
||||
|
||||
inline _Self& operator++() { ++idx; return *this; } // Preincrement
|
||||
inline _Self operator++(int) { // Postincrement
|
||||
_Self tmp = *this; ++*this; return tmp;
|
||||
}
|
||||
|
||||
inline _Self& operator--() { --idx; return *this; } // Predecrement
|
||||
inline _Self operator--(int) { // Postdecrement
|
||||
_Self tmp = *this; --*this; return tmp;
|
||||
}
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
inline Instruction::op_iterator Instruction::op_begin() {
|
||||
return op_iterator(this);
|
||||
}
|
||||
inline Instruction::op_const_iterator Instruction::op_begin() const {
|
||||
return op_const_iterator(this);
|
||||
}
|
||||
inline Instruction::op_iterator Instruction::op_end() {
|
||||
return op_iterator(this,true);
|
||||
}
|
||||
inline Instruction::op_const_iterator Instruction::op_end() const {
|
||||
return op_const_iterator(this,true);
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -13,20 +13,40 @@
|
||||
#define LLVM_USER_H
|
||||
|
||||
#include "llvm/Value.h"
|
||||
#include <vector>
|
||||
|
||||
class User : public Value {
|
||||
User(const User &); // Do not implement
|
||||
protected:
|
||||
vector<Use> Operands;
|
||||
public:
|
||||
User(const Type *Ty, ValueTy vty, const string &name = "");
|
||||
virtual ~User() {}
|
||||
virtual ~User() { dropAllReferences(); }
|
||||
|
||||
// if i > the number of operands, then getOperand() returns 0, and setOperand
|
||||
// returns false. setOperand() may also return false if the operand is of
|
||||
// the wrong type.
|
||||
inline Value *getOperand(unsigned i) {
|
||||
assert(i < Operands.size() && "getOperand() out of range!");
|
||||
return Operands[i];
|
||||
}
|
||||
inline const Value *getOperand(unsigned i) const {
|
||||
assert(i < Operands.size() && "getOperand() const out of range!");
|
||||
return Operands[i];
|
||||
}
|
||||
inline void setOperand(unsigned i, Value *Val) {
|
||||
assert(i < Operands.size() && "setOperand() out of range!");
|
||||
Operands[i] = Val;
|
||||
}
|
||||
inline unsigned getNumOperands() const { return Operands.size(); }
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Operand Iterator interface...
|
||||
//
|
||||
virtual Value *getOperand(unsigned i) = 0;
|
||||
virtual const Value *getOperand(unsigned i) const = 0;
|
||||
virtual bool setOperand(unsigned i, Value *Val) = 0;
|
||||
typedef vector<Use>::iterator op_iterator;
|
||||
typedef vector<Use>::const_iterator op_const_iterator;
|
||||
|
||||
inline op_iterator op_begin() { return Operands.begin(); }
|
||||
inline op_const_iterator op_begin() const { return Operands.end(); }
|
||||
inline op_iterator op_end() { return Operands.end(); }
|
||||
inline op_const_iterator op_end() const { return Operands.end(); }
|
||||
|
||||
// dropAllReferences() - This virtual function should be overridden to "let
|
||||
// go" of all references that this user is maintaining. This allows one to
|
||||
@ -36,7 +56,9 @@ public:
|
||||
// valid on an object that has "dropped all references", except operator
|
||||
// delete.
|
||||
//
|
||||
virtual void dropAllReferences() = 0;
|
||||
virtual void dropAllReferences() {
|
||||
Operands.clear();
|
||||
}
|
||||
|
||||
// replaceUsesOfWith - Replaces all references to the "From" definition with
|
||||
// references to the "To" definition. (defined in Value.cpp)
|
||||
|
@ -10,31 +10,24 @@
|
||||
|
||||
#include "llvm/Instruction.h"
|
||||
#include "llvm/DerivedTypes.h"
|
||||
#include "llvm/ConstPoolVals.h"
|
||||
|
||||
class ConstPoolType;
|
||||
|
||||
class AllocationInst : public Instruction {
|
||||
protected:
|
||||
UseTy<ConstPoolType> TyVal;
|
||||
Use ArraySize;
|
||||
public:
|
||||
AllocationInst(ConstPoolType *tyVal, Value *arrSize, unsigned iTy,
|
||||
const string &Name = "")
|
||||
: Instruction(tyVal->getValue(), iTy, Name),
|
||||
TyVal(tyVal, this), ArraySize(arrSize, this) {
|
||||
AllocationInst(const Type *Ty, Value *ArraySize, unsigned iTy,
|
||||
const string &Name = "")
|
||||
: Instruction(Ty, iTy, Name) {
|
||||
assert(Ty->isPointerType() && "Can't allocate a non pointer type!");
|
||||
|
||||
// Make sure they didn't try to specify a size for an invalid type...
|
||||
assert(arrSize == 0 ||
|
||||
(getType()->getValueType()->isArrayType() &&
|
||||
((const ArrayType*)getType()->getValueType())->isUnsized()) &&
|
||||
"Trying to allocate something other than unsized array, with size!");
|
||||
if (ArraySize) {
|
||||
// Make sure they didn't try to specify a size for !(unsized array) type...
|
||||
assert((getType()->getValueType()->isArrayType() &&
|
||||
((const ArrayType*)getType()->getValueType())->isUnsized()) &&
|
||||
"Trying to allocate something other than unsized array, with size!");
|
||||
|
||||
// Make sure that if a size is specified, that it is a uint!
|
||||
assert(arrSize == 0 || arrSize->getType() == Type::UIntTy &&
|
||||
"Malloc SIZE is not a 'uint'!");
|
||||
Operands.reserve(1);
|
||||
Operands.push_back(Use(ArraySize, this));
|
||||
}
|
||||
}
|
||||
inline ~AllocationInst() {}
|
||||
|
||||
// getType - Overload to return most specific pointer type...
|
||||
inline const PointerType *getType() const {
|
||||
@ -42,46 +35,15 @@ public:
|
||||
}
|
||||
|
||||
virtual Instruction *clone() const = 0;
|
||||
|
||||
inline virtual void dropAllReferences() { TyVal = 0; ArraySize = 0; }
|
||||
virtual bool setOperand(unsigned i, Value *Val) {
|
||||
if (i == 0) {
|
||||
assert(!Val || Val->getValueType() == Value::ConstantVal);
|
||||
TyVal = (ConstPoolType*)Val;
|
||||
return true;
|
||||
} else if (i == 1) {
|
||||
// Make sure they didn't try to specify a size for an invalid type...
|
||||
assert(Val == 0 ||
|
||||
(getType()->getValueType()->isArrayType() &&
|
||||
((const ArrayType*)getType()->getValueType())->isUnsized()) &&
|
||||
"Trying to allocate something other than unsized array, with size!");
|
||||
|
||||
// Make sure that if a size is specified, that it is a uint!
|
||||
assert(Val == 0 || Val->getType() == Type::UIntTy &&
|
||||
"Malloc SIZE is not a 'uint'!");
|
||||
|
||||
ArraySize = Val;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual unsigned getNumOperands() const { return 2; }
|
||||
|
||||
virtual const Value *getOperand(unsigned i) const {
|
||||
return i == 0 ? TyVal : (i == 1 ? ArraySize : 0);
|
||||
}
|
||||
};
|
||||
|
||||
class MallocInst : public AllocationInst {
|
||||
public:
|
||||
MallocInst(ConstPoolType *tyVal, Value *ArraySize = 0,
|
||||
const string &Name = "")
|
||||
: AllocationInst(tyVal, ArraySize, Instruction::Malloc, Name) {}
|
||||
inline ~MallocInst() {}
|
||||
MallocInst(const Type *Ty, Value *ArraySize = 0, const string &Name = "")
|
||||
: AllocationInst(Ty, ArraySize, Instruction::Malloc, Name) {}
|
||||
|
||||
virtual Instruction *clone() const {
|
||||
return new MallocInst(TyVal, ArraySize);
|
||||
return new MallocInst(getType(), Operands.size() ? Operands[1] : 0);
|
||||
}
|
||||
|
||||
virtual string getOpcode() const { return "malloc"; }
|
||||
@ -89,13 +51,11 @@ public:
|
||||
|
||||
class AllocaInst : public AllocationInst {
|
||||
public:
|
||||
AllocaInst(ConstPoolType *tyVal, Value *ArraySize = 0,
|
||||
const string &Name = "")
|
||||
: AllocationInst(tyVal, ArraySize, Instruction::Alloca, Name) {}
|
||||
inline ~AllocaInst() {}
|
||||
AllocaInst(const Type *Ty, Value *ArraySize = 0, const string &Name = "")
|
||||
: AllocationInst(Ty, ArraySize, Instruction::Alloca, Name) {}
|
||||
|
||||
virtual Instruction *clone() const {
|
||||
return new AllocaInst(TyVal, ArraySize);
|
||||
return new AllocaInst(getType(), Operands.size() ? Operands[1] : 0);
|
||||
}
|
||||
|
||||
virtual string getOpcode() const { return "alloca"; }
|
||||
@ -104,35 +64,16 @@ public:
|
||||
|
||||
|
||||
class FreeInst : public Instruction {
|
||||
protected:
|
||||
Use Pointer;
|
||||
public:
|
||||
FreeInst(Value *Ptr, const string &Name = "")
|
||||
: Instruction(Type::VoidTy, Instruction::Free, Name),
|
||||
Pointer(Ptr, this) {
|
||||
|
||||
: Instruction(Type::VoidTy, Instruction::Free, Name) {
|
||||
assert(Ptr->getType()->isPointerType() && "Can't free nonpointer!");
|
||||
Operands.reserve(1);
|
||||
Operands.push_back(Use(Ptr, this));
|
||||
}
|
||||
inline ~FreeInst() {}
|
||||
|
||||
virtual Instruction *clone() const { return new FreeInst(Pointer); }
|
||||
|
||||
inline virtual void dropAllReferences() { Pointer = 0; }
|
||||
|
||||
virtual bool setOperand(unsigned i, Value *Val) {
|
||||
if (i == 0) {
|
||||
assert(!Val || Val->getType()->isPointerType() &&
|
||||
"Can't free nonpointer!");
|
||||
Pointer = Val;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual unsigned getNumOperands() const { return 1; }
|
||||
virtual const Value *getOperand(unsigned i) const {
|
||||
return i == 0 ? Pointer : 0;
|
||||
}
|
||||
virtual Instruction *clone() const { return new FreeInst(Operands[0]); }
|
||||
|
||||
virtual string getOpcode() const { return "free"; }
|
||||
};
|
||||
|
@ -21,42 +21,31 @@
|
||||
// scientist's overactive imagination.
|
||||
//
|
||||
class PHINode : public Instruction {
|
||||
typedef pair<Use,BasicBlockUse> PairTy;
|
||||
vector<PairTy> IncomingValues;
|
||||
|
||||
PHINode(const PHINode &PN);
|
||||
public:
|
||||
PHINode(const Type *Ty, const string &Name = "");
|
||||
inline ~PHINode() { dropAllReferences(); }
|
||||
|
||||
virtual Instruction *clone() const { return new PHINode(*this); }
|
||||
|
||||
// Implement all of the functionality required by User...
|
||||
//
|
||||
virtual void dropAllReferences();
|
||||
virtual const Value *getOperand(unsigned i) const {
|
||||
if (i >= IncomingValues.size()*2) return 0;
|
||||
if (i & 1) return IncomingValues[i/2].second;
|
||||
else return IncomingValues[i/2].first;
|
||||
}
|
||||
inline Value *getOperand(unsigned i) {
|
||||
return (Value*)((const PHINode*)this)->getOperand(i);
|
||||
}
|
||||
virtual unsigned getNumOperands() const { return IncomingValues.size()*2; }
|
||||
virtual bool setOperand(unsigned i, Value *Val);
|
||||
virtual string getOpcode() const { return "phi"; }
|
||||
|
||||
// getNumIncomingValues - Return the number of incoming edges the PHI node has
|
||||
inline unsigned getNumIncomingValues() const { return IncomingValues.size(); }
|
||||
inline unsigned getNumIncomingValues() const { return Operands.size()/2; }
|
||||
|
||||
// getIncomingValue - Return incoming value #x
|
||||
inline Value *getIncomingValue(unsigned i) const {
|
||||
return IncomingValues[i].first;
|
||||
inline const Value *getIncomingValue(unsigned i) const {
|
||||
return Operands[i*2];
|
||||
}
|
||||
inline Value *getIncomingValue(unsigned i) {
|
||||
return Operands[i*2];
|
||||
}
|
||||
|
||||
// getIncomingBlock - Return incoming basic block #x
|
||||
inline BasicBlock *getIncomingBlock(unsigned i) const {
|
||||
return IncomingValues[i].second;
|
||||
inline const BasicBlock *getIncomingBlock(unsigned i) const {
|
||||
return Operands[i*2+1]->castBasicBlockAsserting();
|
||||
}
|
||||
inline BasicBlock *getIncomingBlock(unsigned i) {
|
||||
return Operands[i*2+1]->castBasicBlockAsserting();
|
||||
}
|
||||
|
||||
// addIncoming - Add an incoming value to the end of the PHI list
|
||||
@ -97,8 +86,6 @@ public:
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
class CallInst : public Instruction {
|
||||
MethodUse M;
|
||||
vector<Use> Params;
|
||||
CallInst(const CallInst &CI);
|
||||
public:
|
||||
CallInst(Method *M, vector<Value*> ¶ms, const string &Name = "");
|
||||
@ -110,21 +97,12 @@ public:
|
||||
bool hasSideEffects() const { return true; }
|
||||
|
||||
|
||||
const Method *getCalledMethod() const { return M; }
|
||||
Method *getCalledMethod() { return M; }
|
||||
|
||||
// Implement all of the functionality required by Instruction...
|
||||
//
|
||||
virtual void dropAllReferences();
|
||||
virtual const Value *getOperand(unsigned i) const {
|
||||
return i == 0 ? M : ((i <= Params.size()) ? Params[i-1] : 0);
|
||||
const Method *getCalledMethod() const {
|
||||
return Operands[0]->castMethodAsserting();
|
||||
}
|
||||
inline Value *getOperand(unsigned i) {
|
||||
return (Value*)((const CallInst*)this)->getOperand(i);
|
||||
Method *getCalledMethod() {
|
||||
return Operands[0]->castMethodAsserting();
|
||||
}
|
||||
virtual unsigned getNumOperands() const { return Params.size()+1; }
|
||||
|
||||
virtual bool setOperand(unsigned i, Value *Val);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -24,26 +24,32 @@
|
||||
// not continue in this method any longer.
|
||||
//
|
||||
class ReturnInst : public TerminatorInst {
|
||||
Use Val; // Will be null if returning void...
|
||||
ReturnInst(const ReturnInst &RI);
|
||||
ReturnInst(const ReturnInst &RI) : TerminatorInst(Instruction::Ret) {
|
||||
if (RI.Operands.size()) {
|
||||
assert(RI.Operands.size() == 1 && "Return insn can only have 1 operand!");
|
||||
Operands.reserve(1);
|
||||
Operands.push_back(Use(RI.Operands[0], this));
|
||||
}
|
||||
}
|
||||
public:
|
||||
ReturnInst(Value *value = 0);
|
||||
ReturnInst(Value *RetVal = 0) : TerminatorInst(Instruction::Ret) {
|
||||
if (RetVal) {
|
||||
Operands.reserve(1);
|
||||
Operands.push_back(Use(RetVal, this));
|
||||
}
|
||||
}
|
||||
inline ~ReturnInst() { dropAllReferences(); }
|
||||
|
||||
virtual Instruction *clone() const { return new ReturnInst(*this); }
|
||||
|
||||
virtual string getOpcode() const { return "ret"; }
|
||||
|
||||
inline const Value *getReturnValue() const { return Val; }
|
||||
inline Value *getReturnValue() { return Val; }
|
||||
|
||||
virtual void dropAllReferences();
|
||||
virtual const Value *getOperand(unsigned i) const {
|
||||
return (i == 0) ? Val : 0;
|
||||
inline const Value *getReturnValue() const {
|
||||
return Operands.size() ? Operands[0] : 0;
|
||||
}
|
||||
inline Value *getReturnValue() {
|
||||
return Operands.size() ? Operands[0] : 0;
|
||||
}
|
||||
inline Value *getOperand(unsigned i) { return (i == 0) ? Val : 0; }
|
||||
virtual bool setOperand(unsigned i, Value *Val);
|
||||
virtual unsigned getNumOperands() const { return Val != 0; }
|
||||
|
||||
// Additionally, they must provide a method to get at the successors of this
|
||||
// terminator instruction. If 'idx' is out of range, a null pointer shall be
|
||||
@ -58,9 +64,6 @@ public:
|
||||
// BranchInst - Conditional or Unconditional Branch instruction.
|
||||
//
|
||||
class BranchInst : public TerminatorInst {
|
||||
BasicBlockUse TrueDest, FalseDest;
|
||||
Use Condition;
|
||||
|
||||
BranchInst(const BranchInst &BI);
|
||||
public:
|
||||
// If cond = null, then is an unconditional br...
|
||||
@ -69,32 +72,40 @@ public:
|
||||
|
||||
virtual Instruction *clone() const { return new BranchInst(*this); }
|
||||
|
||||
virtual void dropAllReferences();
|
||||
|
||||
inline const Value *getCondition() const { return Condition; }
|
||||
inline Value *getCondition() { return Condition; }
|
||||
|
||||
inline bool isUnconditional() const {
|
||||
return Condition == 0 || !FalseDest;
|
||||
return Operands.size() == 1;
|
||||
}
|
||||
|
||||
inline const Value *getCondition() const {
|
||||
return isUnconditional() ? 0 : Operands[2];
|
||||
}
|
||||
inline Value *getCondition() {
|
||||
return isUnconditional() ? 0 : Operands[2];
|
||||
}
|
||||
|
||||
virtual string getOpcode() const { return "br"; }
|
||||
|
||||
inline Value *getOperand(unsigned i) {
|
||||
return (Value*)((const BranchInst *)this)->getOperand(i);
|
||||
// setUnconditionalDest - Change the current branch to an unconditional branch
|
||||
// targeting the specified block.
|
||||
//
|
||||
void setUnconditionalDest(BasicBlock *Dest) {
|
||||
if (Operands.size() == 3)
|
||||
Operands.erase(Operands.begin()+1, Operands.end());
|
||||
Operands[0] = Dest;
|
||||
}
|
||||
|
||||
// Additionally, they must provide a method to get at the successors of this
|
||||
// terminator instruction.
|
||||
//
|
||||
virtual const BasicBlock *getSuccessor(unsigned i) const {
|
||||
return (i == 0) ? Operands[0]->castBasicBlockAsserting() :
|
||||
((i == 1 && Operands.size() > 1)
|
||||
? Operands[1]->castBasicBlockAsserting() : 0);
|
||||
}
|
||||
virtual const Value *getOperand(unsigned i) const;
|
||||
virtual bool setOperand(unsigned i, Value *Val);
|
||||
virtual unsigned getNumOperands() const { return isUnconditional() ? 1 : 3; }
|
||||
inline BasicBlock *getSuccessor(unsigned idx) {
|
||||
return (BasicBlock*)((const BranchInst *)this)->getSuccessor(idx);
|
||||
}
|
||||
|
||||
// Additionally, they must provide a method to get at the successors of this
|
||||
// terminator instruction. If 'idx' is out of range, a null pointer shall be
|
||||
// returned.
|
||||
//
|
||||
virtual const BasicBlock *getSuccessor(unsigned idx) const;
|
||||
virtual unsigned getNumSuccessors() const { return 1+!isUnconditional(); }
|
||||
};
|
||||
|
||||
@ -103,17 +114,12 @@ public:
|
||||
// SwitchInst - Multiway switch
|
||||
//
|
||||
class SwitchInst : public TerminatorInst {
|
||||
public:
|
||||
typedef pair<ConstPoolUse, BasicBlockUse> dest_value;
|
||||
private:
|
||||
BasicBlockUse DefaultDest;
|
||||
Use Val;
|
||||
vector<dest_value> Destinations;
|
||||
|
||||
// Operand[0] = Value to switch on
|
||||
// Operand[1] = Default basic block destination
|
||||
SwitchInst(const SwitchInst &RI);
|
||||
public:
|
||||
typedef vector<dest_value>::iterator dest_iterator;
|
||||
typedef vector<dest_value>::const_iterator dest_const_iterator;
|
||||
//typedef vector<dest_value>::iterator dest_iterator;
|
||||
//typedef vector<dest_value>::const_iterator dest_const_iterator;
|
||||
|
||||
SwitchInst(Value *Value, BasicBlock *Default);
|
||||
inline ~SwitchInst() { dropAllReferences(); }
|
||||
@ -122,36 +128,50 @@ public:
|
||||
|
||||
// Accessor Methods for Switch stmt
|
||||
//
|
||||
/*
|
||||
inline dest_iterator dest_begin() { return Destinations.begin(); }
|
||||
inline dest_iterator dest_end () { return Destinations.end(); }
|
||||
inline dest_const_iterator dest_begin() const { return Destinations.begin(); }
|
||||
inline dest_const_iterator dest_end () const { return Destinations.end(); }
|
||||
*/
|
||||
|
||||
inline const Value *getCondition() const { return Val; }
|
||||
inline Value *getCondition() { return Val; }
|
||||
inline const BasicBlock *getDefaultDest() const { return DefaultDest; }
|
||||
inline BasicBlock *getDefaultDest() { return DefaultDest; }
|
||||
inline const Value *getCondition() const { return Operands[0]; }
|
||||
inline Value *getCondition() { return Operands[0]; }
|
||||
inline const BasicBlock *getDefaultDest() const {
|
||||
return Operands[1]->castBasicBlockAsserting();
|
||||
}
|
||||
inline BasicBlock *getDefaultDest() {
|
||||
return Operands[1]->castBasicBlockAsserting();
|
||||
}
|
||||
|
||||
void dest_push_back(ConstPoolVal *OnVal, BasicBlock *Dest);
|
||||
|
||||
virtual string getOpcode() const { return "switch"; }
|
||||
inline Value *getOperand(unsigned i) {
|
||||
return (Value*)((const SwitchInst*)this)->getOperand(i);
|
||||
}
|
||||
virtual const Value *getOperand(unsigned i) const;
|
||||
virtual bool setOperand(unsigned i, Value *Val);
|
||||
virtual unsigned getNumOperands() const;
|
||||
virtual void dropAllReferences();
|
||||
|
||||
// Additionally, they must provide a method to get at the successors of this
|
||||
// terminator instruction. If 'idx' is out of range, a null pointer shall be
|
||||
// returned.
|
||||
//
|
||||
virtual const BasicBlock *getSuccessor(unsigned idx) const;
|
||||
virtual unsigned getNumSuccessors() const { return 1+Destinations.size(); }
|
||||
inline BasicBlock *getSuccessor(unsigned idx) {
|
||||
return (BasicBlock*)((const SwitchInst *)this)->getSuccessor(idx);
|
||||
virtual const BasicBlock *getSuccessor(unsigned idx) const {
|
||||
if (idx >= Operands.size()/2) return 0;
|
||||
return Operands[idx*2+1]->castBasicBlockAsserting();
|
||||
}
|
||||
inline BasicBlock *getSuccessor(unsigned idx) {
|
||||
if (idx >= Operands.size()/2) return 0;
|
||||
return Operands[idx*2+1]->castBasicBlockAsserting();
|
||||
}
|
||||
|
||||
// getSuccessorValue - Return the value associated with the specified successor
|
||||
// WARNING: This does not gracefully accept idx's out of range!
|
||||
inline const ConstPoolVal *getSuccessorValue(unsigned idx) const {
|
||||
assert(idx < getNumSuccessors() && "Successor # out of range!");
|
||||
return Operands[idx*2]->castConstantAsserting();
|
||||
}
|
||||
inline ConstPoolVal *getSuccessorValue(unsigned idx) {
|
||||
assert(idx < getNumSuccessors() && "Successor # out of range!");
|
||||
return Operands[idx*2]->castConstantAsserting();
|
||||
}
|
||||
virtual unsigned getNumSuccessors() const { return Operands.size()/2; }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -80,8 +80,11 @@ bool BytecodeParser::ParseRawInst(const uchar *&Buf, const uchar *EndBuf,
|
||||
break;
|
||||
}
|
||||
|
||||
//cerr << "NO: " << Result.NumOperands << " opcode: " << Result.Opcode
|
||||
// << " Ty: " << Result.Ty->getName() << " arg1: " << Result.Arg1 << endl;
|
||||
#if 0
|
||||
cerr << "NO: " << Result.NumOperands << " opcode: " << Result.Opcode
|
||||
<< " Ty: " << Result.Ty->getName() << " arg1: " << Result.Arg1
|
||||
<< " arg2: " << Result.Arg2 << " arg3: " << Result.Arg3 << endl;
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -198,13 +201,13 @@ bool BytecodeParser::ParseInstruction(const uchar *&Buf, const uchar *EndBuf,
|
||||
return false;
|
||||
} else if (Raw.Opcode == Instruction::Malloc) {
|
||||
if (Raw.NumOperands > 2) return true;
|
||||
Value *Sz = (Raw.NumOperands == 2) ? getValue(Type::UIntTy, Raw.Arg2) : 0;
|
||||
Res = new MallocInst((ConstPoolType*)getValue(Type::TypeTy, Raw.Arg1), Sz);
|
||||
Value *Sz = Raw.NumOperands ? getValue(Type::UIntTy, Raw.Arg1) : 0;
|
||||
Res = new MallocInst(Raw.Ty, Sz);
|
||||
return false;
|
||||
} else if (Raw.Opcode == Instruction::Alloca) {
|
||||
if (Raw.NumOperands > 2) return true;
|
||||
Value *Sz = (Raw.NumOperands == 2) ? getValue(Type::UIntTy, Raw.Arg2) : 0;
|
||||
Res = new AllocaInst((ConstPoolType*)getValue(Type::TypeTy, Raw.Arg1), Sz);
|
||||
Value *Sz = Raw.NumOperands ? getValue(Type::UIntTy, Raw.Arg1) : 0;
|
||||
Res = new AllocaInst(Raw.Ty, Sz);
|
||||
return false;
|
||||
} else if (Raw.Opcode == Instruction::Free) {
|
||||
Value *Val = getValue(Raw.Ty, Raw.Arg1);
|
||||
@ -213,6 +216,7 @@ bool BytecodeParser::ParseInstruction(const uchar *&Buf, const uchar *EndBuf,
|
||||
return false;
|
||||
}
|
||||
|
||||
cerr << "Unrecognized instruction! " << Raw.Opcode << endl;
|
||||
cerr << "Unrecognized instruction! " << Raw.Opcode
|
||||
<< " ADDR = 0x" << (void*)Buf << endl;
|
||||
return true;
|
||||
}
|
||||
|
@ -94,16 +94,9 @@ public:
|
||||
|
||||
struct InstPlaceHolderHelper : public Instruction {
|
||||
InstPlaceHolderHelper(const Type *Ty) : Instruction(Ty, UserOp1, "") {}
|
||||
inline virtual void dropAllReferences() {}
|
||||
virtual string getOpcode() const { return "placeholder"; }
|
||||
|
||||
virtual Instruction *clone() const { abort(); return 0; }
|
||||
|
||||
// No "operands"...
|
||||
virtual Value *getOperand(unsigned i) { return 0; }
|
||||
virtual const Value *getOperand(unsigned i) const { return 0; }
|
||||
virtual bool setOperand(unsigned i, Value *Val) { return false; }
|
||||
virtual unsigned getNumOperands() const { return 0; }
|
||||
};
|
||||
|
||||
struct BBPlaceHolderHelper : public BasicBlock {
|
||||
|
@ -128,7 +128,7 @@ bool BytecodeWriter::outputConstant(const ConstPoolVal *CPV) {
|
||||
|
||||
case Type::StructTyID: {
|
||||
const ConstPoolStruct *CPS = (const ConstPoolStruct*)CPV;
|
||||
const vector<ConstPoolUse> &Vals = CPS->getValues();
|
||||
const vector<Use> &Vals = CPS->getValues();
|
||||
|
||||
for (unsigned i = 0; i < Vals.size(); ++i) {
|
||||
int Slot = Table.getValSlot(Vals[i]);
|
||||
|
@ -32,14 +32,13 @@ static void outputInstructionFormat0(const Instruction *I,
|
||||
output_vbr(I->getInstType(), Out); // Instruction Opcode ID
|
||||
output_vbr(Type, Out); // Result type
|
||||
|
||||
unsigned NumArgs; // Count the number of arguments to the instruction
|
||||
for (NumArgs = 0; I->getOperand(NumArgs); NumArgs++) /*empty*/;
|
||||
unsigned NumArgs = I->getNumOperands();
|
||||
output_vbr(NumArgs, Out);
|
||||
|
||||
for (unsigned i = 0; const Value *N = I->getOperand(i); i++) {
|
||||
assert(i < NumArgs && "Count of arguments failed!");
|
||||
|
||||
for (unsigned i = 0; i < NumArgs; ++i) {
|
||||
const Value *N = I->getOperand(i);
|
||||
int Slot = Table.getValSlot(N);
|
||||
assert(Slot >= 0 && "No slot number for value!?!?");
|
||||
output_vbr((unsigned)Slot, Out);
|
||||
}
|
||||
align32(Out); // We must maintain correct alignment!
|
||||
@ -110,25 +109,24 @@ static void outputInstructionFormat3(const Instruction *I,
|
||||
//
|
||||
unsigned Opcode = (3 << 30) | (IType << 24) | (Type << 18) |
|
||||
(Slots[0] << 12) | (Slots[1] << 6) | (Slots[2] << 0);
|
||||
// cerr << "3 " << IType << " " << Type << " " << Slots[0] << " "
|
||||
// << Slots[1] << " " << Slots[2] << endl;
|
||||
//cerr << "3 " << IType << " " << Type << " " << Slots[0] << " "
|
||||
// << Slots[1] << " " << Slots[2] << endl;
|
||||
output(Opcode, Out);
|
||||
}
|
||||
|
||||
bool BytecodeWriter::processInstruction(const Instruction *I) {
|
||||
assert(I->getInstType() < 64 && "Opcode too big???");
|
||||
|
||||
unsigned NumOperands = 0;
|
||||
unsigned NumOperands = I->getNumOperands();
|
||||
int MaxOpSlot = 0;
|
||||
int Slots[3]; Slots[0] = (1 << 12)-1;
|
||||
int Slots[3]; Slots[0] = (1 << 12)-1; // Marker to signify 0 operands
|
||||
|
||||
const Value *Def;
|
||||
while ((Def = I->getOperand(NumOperands))) {
|
||||
for (unsigned i = 0; i < NumOperands; ++i) {
|
||||
const Value *Def = I->getOperand(i);
|
||||
int slot = Table.getValSlot(Def);
|
||||
assert(slot != -1 && "Broken bytecode!");
|
||||
if (slot > MaxOpSlot) MaxOpSlot = slot;
|
||||
if (NumOperands < 3) Slots[NumOperands] = slot;
|
||||
NumOperands++;
|
||||
if (i < 3) Slots[i] = slot;
|
||||
}
|
||||
|
||||
// Figure out which type to encode with the instruction. Typically we want
|
||||
@ -137,12 +135,10 @@ bool BytecodeWriter::processInstruction(const Instruction *I) {
|
||||
// the first param is actually interesting). But if we have no arguments
|
||||
// we take the type of the instruction itself.
|
||||
//
|
||||
|
||||
const Type *Ty;
|
||||
if (NumOperands)
|
||||
Ty = I->getOperand(0)->getType();
|
||||
else
|
||||
Ty = I->getType();
|
||||
const Type *Ty = NumOperands ? I->getOperand(0)->getType() : I->getType();
|
||||
if (I->getInstType() == Instruction::Malloc ||
|
||||
I->getInstType() == Instruction::Alloca)
|
||||
Ty = I->getType(); // Malloc & Alloca ALWAYS want to encode the return type
|
||||
|
||||
unsigned Type;
|
||||
int Slot = Table.getValSlot(Ty);
|
||||
@ -179,6 +175,8 @@ bool BytecodeWriter::processInstruction(const Instruction *I) {
|
||||
break;
|
||||
}
|
||||
|
||||
// If we weren't handled before here, we either have a large number of operands
|
||||
// or a large operand index that we are refering to.
|
||||
outputInstructionFormat0(I, Table, Type, Out);
|
||||
return false;
|
||||
}
|
||||
|
@ -37,7 +37,8 @@ using namespace opt;
|
||||
static inline void RemapInstruction(Instruction *I,
|
||||
map<const Value *, Value*> &ValueMap) {
|
||||
|
||||
for (unsigned op = 0; const Value *Op = I->getOperand(op); ++op) {
|
||||
for (unsigned op = 0, E = I->getNumOperands(); op != E; ++op) {
|
||||
const Value *Op = I->getOperand(op);
|
||||
Value *V = ValueMap[Op];
|
||||
if (!V && Op->isMethod())
|
||||
continue; // Methods don't get relocated
|
||||
@ -115,11 +116,9 @@ bool opt::InlineMethod(BasicBlock::iterator CIIt) {
|
||||
//
|
||||
Method::ArgumentListType::const_iterator PTI =
|
||||
CalledMeth->getArgumentList().begin();
|
||||
for (unsigned a = 1; Value *Operand = CI->getOperand(a); ++a, ++PTI) {
|
||||
ValueMap[*PTI] = Operand;
|
||||
}
|
||||
for (unsigned a = 1, E = CI->getNumOperands(); a != E; ++a, ++PTI)
|
||||
ValueMap[*PTI] = CI->getOperand(a);
|
||||
|
||||
|
||||
ValueMap[NewBB] = NewBB; // Returns get converted to reference NewBB
|
||||
|
||||
// Loop over all of the basic blocks in the method, inlining them as
|
||||
|
@ -132,9 +132,9 @@ bool opt::ConstantFoldTerminator(TerminatorInst *T) {
|
||||
BasicBlock *Dest1 = BI->getOperand(0)->castBasicBlockAsserting();
|
||||
BasicBlock *Dest2 = BI->getOperand(1)->castBasicBlockAsserting();
|
||||
|
||||
if (BI->getOperand(2)->isConstant()) { // Are we branching on constant?
|
||||
if (BI->getCondition()->isConstant()) { // Are we branching on constant?
|
||||
// YES. Change to unconditional branch...
|
||||
ConstPoolBool *Cond = (ConstPoolBool*)BI->getOperand(2);
|
||||
ConstPoolBool *Cond = (ConstPoolBool*)BI->getCondition();
|
||||
BasicBlock *Destination = Cond->getValue() ? Dest1 : Dest2;
|
||||
BasicBlock *OldDest = Cond->getValue() ? Dest2 : Dest1;
|
||||
|
||||
@ -147,9 +147,9 @@ bool opt::ConstantFoldTerminator(TerminatorInst *T) {
|
||||
assert(BI->getParent() && "Terminator not inserted in block!");
|
||||
OldDest->removePredecessor(BI->getParent());
|
||||
|
||||
BI->setOperand(0, Destination); // Set the unconditional destination
|
||||
BI->setOperand(1, 0); // Clear the conditional destination
|
||||
BI->setOperand(2, 0); // Clear the condition...
|
||||
// Set the unconditional destination, and change the insn to be an
|
||||
// unconditional branch.
|
||||
BI->setUnconditionalDest(Destination);
|
||||
return true;
|
||||
} else if (Dest2 == Dest1) { // Conditional branch to same location?
|
||||
// This branch matches something like this:
|
||||
@ -160,9 +160,8 @@ bool opt::ConstantFoldTerminator(TerminatorInst *T) {
|
||||
assert(BI->getParent() && "Terminator not inserted in block!");
|
||||
Dest1->removePredecessor(BI->getParent());
|
||||
|
||||
// Nuke the second destination, and the use of the condition variable
|
||||
BI->setOperand(1, 0); // Clear the conditional destination
|
||||
BI->setOperand(2, 0); // Clear the condition...
|
||||
// Change a conditional branch to unconditional.
|
||||
BI->setUnconditionalDest(Dest1);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -192,7 +191,7 @@ ConstantFoldInstruction(Method *M, Method::inst_iterator &II) {
|
||||
PHINode *PN = (PHINode*)Inst; // If it's a PHI node and only has one operand
|
||||
// Then replace it directly with that operand.
|
||||
assert(PN->getOperand(0) && "PHI Node must have at least one operand!");
|
||||
if (PN->getOperand(1) == 0) { // If the PHI Node has exactly 1 operand
|
||||
if (PN->getNumOperands() == 1) { // If the PHI Node has exactly 1 operand
|
||||
Value *V = PN->getOperand(0);
|
||||
PN->replaceAllUsesWith(V); // Replace all uses of this PHI
|
||||
// Unlink from basic block
|
||||
|
@ -91,7 +91,7 @@ static bool RemoveSingularPHIs(BasicBlock *BB) {
|
||||
|
||||
do {
|
||||
PHINode *PN = (PHINode*)I;
|
||||
assert(PN->getOperand(2) == 0 && "PHI node should only have one value!");
|
||||
assert(PN->getNumOperands() == 2 && "PHI node should only have one value!");
|
||||
Value *V = PN->getOperand(0);
|
||||
|
||||
PN->replaceAllUsesWith(V); // Replace PHI node with its single value.
|
||||
|
@ -408,10 +408,10 @@ void SCCP::UpdateInstruction(Instruction *I) {
|
||||
markExecutable(Succ);
|
||||
} else if (SCValue.isConstant()) {
|
||||
ConstPoolVal *CPV = SCValue.getConstant();
|
||||
for (SwitchInst::dest_iterator I = SI->dest_begin(), E = SI->dest_end();
|
||||
I != E; ++I) {
|
||||
if (I->first->equals(CPV)) { // Found the right branch...
|
||||
markExecutable(I->second);
|
||||
// Make sure to skip the "default value" which isn't a value
|
||||
for (unsigned i = 1, E = SI->getNumSuccessors(); i != E; ++i) {
|
||||
if (SI->getSuccessorValue(i)->equals(CPV)) {// Found the right branch...
|
||||
markExecutable(SI->getSuccessor(i));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -157,10 +157,10 @@ bool AssemblyWriter::processInstruction(const Instruction *I) {
|
||||
Out << I->getOpcode();
|
||||
|
||||
// Print out the type of the operands...
|
||||
const Value *Operand = I->getOperand(0);
|
||||
const Value *Operand = I->getNumOperands() ? I->getOperand(0) : 0;
|
||||
|
||||
// Special case conditional branches to swizzle the condition out to the front
|
||||
if (I->getInstType() == Instruction::Br && I->getOperand(1)) {
|
||||
if (I->getInstType() == Instruction::Br && I->getNumOperands() > 1) {
|
||||
writeOperand(I->getOperand(2), true);
|
||||
Out << ",";
|
||||
writeOperand(Operand, true);
|
||||
@ -172,9 +172,9 @@ bool AssemblyWriter::processInstruction(const Instruction *I) {
|
||||
writeOperand(Operand , true); Out << ",";
|
||||
writeOperand(I->getOperand(1), true); Out << " [";
|
||||
|
||||
for (unsigned op = 2; (Operand = I->getOperand(op)); op += 2) {
|
||||
for (unsigned op = 2, Eop = I->getNumOperands(); op < Eop; op += 2) {
|
||||
Out << "\n\t\t";
|
||||
writeOperand(Operand, true); Out << ",";
|
||||
writeOperand(I->getOperand(op ), true); Out << ",";
|
||||
writeOperand(I->getOperand(op+1), true);
|
||||
}
|
||||
Out << "\n\t]";
|
||||
@ -183,8 +183,9 @@ bool AssemblyWriter::processInstruction(const Instruction *I) {
|
||||
|
||||
Out << " ["; writeOperand(Operand, false); Out << ",";
|
||||
writeOperand(I->getOperand(1), false); Out << " ]";
|
||||
for (unsigned op = 2; (Operand = I->getOperand(op)); op += 2) {
|
||||
Out << ", ["; writeOperand(Operand, false); Out << ",";
|
||||
for (unsigned op = 2, Eop = I->getNumOperands(); op < Eop; op += 2) {
|
||||
Out << ", [";
|
||||
writeOperand(I->getOperand(op ), false); Out << ",";
|
||||
writeOperand(I->getOperand(op+1), false); Out << " ]";
|
||||
}
|
||||
} else if (I->getInstType() == Instruction::Ret && !Operand) {
|
||||
@ -192,20 +193,19 @@ bool AssemblyWriter::processInstruction(const Instruction *I) {
|
||||
} else if (I->getInstType() == Instruction::Call) {
|
||||
writeOperand(Operand, true);
|
||||
Out << "(";
|
||||
Operand = I->getOperand(1);
|
||||
if (Operand) writeOperand(Operand, true);
|
||||
for (unsigned op = 2; (Operand = I->getOperand(op)); ++op) {
|
||||
if (I->getNumOperands() > 1) writeOperand(I->getOperand(1), true);
|
||||
for (unsigned op = 2, Eop = I->getNumOperands(); op < Eop; ++op) {
|
||||
Out << ",";
|
||||
writeOperand(Operand, true);
|
||||
writeOperand(I->getOperand(op), true);
|
||||
}
|
||||
|
||||
Out << " )";
|
||||
} else if (I->getInstType() == Instruction::Malloc ||
|
||||
I->getInstType() == Instruction::Alloca) {
|
||||
Out << " " << ((const PointerType*)((ConstPoolType*)Operand)
|
||||
->getValue())->getValueType();
|
||||
if ((Operand = I->getOperand(1))) {
|
||||
Out << ","; writeOperand(Operand, true);
|
||||
Out << " " << ((const PointerType*)I->getType())->getValueType();
|
||||
if (I->getNumOperands()) {
|
||||
Out << ",";
|
||||
writeOperand(I->getOperand(0), true);
|
||||
}
|
||||
|
||||
} else if (Operand) { // Print the normal way...
|
||||
@ -215,9 +215,9 @@ bool AssemblyWriter::processInstruction(const Instruction *I) {
|
||||
// different type operands (for example br), then they are all printed.
|
||||
bool PrintAllTypes = false;
|
||||
const Type *TheType = Operand->getType();
|
||||
unsigned i;
|
||||
|
||||
for (i = 1; (Operand = I->getOperand(i)); i++) {
|
||||
for (unsigned i = 1, E = I->getNumOperands(); i != E; ++i) {
|
||||
Operand = I->getOperand(i);
|
||||
if (Operand->getType() != TheType) {
|
||||
PrintAllTypes = true; // We have differing types! Print them all!
|
||||
break;
|
||||
@ -227,9 +227,9 @@ bool AssemblyWriter::processInstruction(const Instruction *I) {
|
||||
if (!PrintAllTypes)
|
||||
Out << " " << I->getOperand(0)->getType();
|
||||
|
||||
for (unsigned i = 0; (Operand = I->getOperand(i)); i++) {
|
||||
for (unsigned i = 0, E = I->getNumOperands(); i != E; ++i) {
|
||||
if (i) Out << ",";
|
||||
writeOperand(Operand, PrintAllTypes);
|
||||
writeOperand(I->getOperand(i), PrintAllTypes);
|
||||
}
|
||||
}
|
||||
|
||||
@ -262,8 +262,8 @@ void AssemblyWriter::writeOperand(const Value *Operand, bool PrintType,
|
||||
} else {
|
||||
int Slot = Table.getValSlot(Operand);
|
||||
|
||||
if (Operand->isConstant()) {
|
||||
Out << " " << ((ConstPoolVal*)Operand)->getStrValue();
|
||||
if (const ConstPoolVal *CPV = Operand->castConstant()) {
|
||||
Out << " " << CPV->getStrValue();
|
||||
} else {
|
||||
if (Slot >= 0) Out << " %" << Slot;
|
||||
else if (PrintName)
|
||||
|
@ -219,7 +219,7 @@ ConstPoolArray::ConstPoolArray(const ArrayType *T,
|
||||
: ConstPoolVal(T, Name) {
|
||||
for (unsigned i = 0; i < V.size(); i++) {
|
||||
assert(V[i]->getType() == T->getElementType());
|
||||
Val.push_back(ConstPoolUse(V[i], this));
|
||||
Operands.push_back(Use(V[i], this));
|
||||
}
|
||||
}
|
||||
|
||||
@ -231,7 +231,7 @@ ConstPoolStruct::ConstPoolStruct(const StructType *T,
|
||||
|
||||
for (unsigned i = 0; i < V.size(); i++) {
|
||||
assert(V[i]->getType() == ETypes[i]);
|
||||
Val.push_back(ConstPoolUse(V[i], this));
|
||||
Operands.push_back(Use(V[i], this));
|
||||
}
|
||||
}
|
||||
|
||||
@ -265,14 +265,14 @@ ConstPoolType::ConstPoolType(const ConstPoolType &CPT)
|
||||
|
||||
ConstPoolArray::ConstPoolArray(const ConstPoolArray &CPA)
|
||||
: ConstPoolVal(CPA.getType()) {
|
||||
for (unsigned i = 0; i < CPA.Val.size(); i++)
|
||||
Val.push_back(ConstPoolUse((ConstPoolVal*)CPA.Val[i], this));
|
||||
for (unsigned i = 0; i < CPA.Operands.size(); i++)
|
||||
Operands.push_back(Use(CPA.Operands[i], this));
|
||||
}
|
||||
|
||||
ConstPoolStruct::ConstPoolStruct(const ConstPoolStruct &CPS)
|
||||
: ConstPoolVal(CPS.getType()) {
|
||||
for (unsigned i = 0; i < CPS.Val.size(); i++)
|
||||
Val.push_back(ConstPoolUse((ConstPoolVal*)CPS.Val[i], this));
|
||||
for (unsigned i = 0; i < CPS.Operands.size(); i++)
|
||||
Operands.push_back(Use(CPS.Operands[i], this));
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
@ -301,12 +301,12 @@ string ConstPoolType::getStrValue() const {
|
||||
|
||||
string ConstPoolArray::getStrValue() const {
|
||||
string Result = "[";
|
||||
if (Val.size()) {
|
||||
Result += " " + Val[0]->getType()->getName() +
|
||||
" " + Val[0]->getStrValue();
|
||||
for (unsigned i = 1; i < Val.size(); i++)
|
||||
Result += ", " + Val[i]->getType()->getName() +
|
||||
" " + Val[i]->getStrValue();
|
||||
if (Operands.size()) {
|
||||
Result += " " + Operands[0]->getType()->getName() +
|
||||
" " + Operands[0]->castConstantAsserting()->getStrValue();
|
||||
for (unsigned i = 1; i < Operands.size(); i++)
|
||||
Result += ", " + Operands[i]->getType()->getName() +
|
||||
" " + Operands[i]->castConstantAsserting()->getStrValue();
|
||||
}
|
||||
|
||||
return Result + " ]";
|
||||
@ -314,12 +314,12 @@ string ConstPoolArray::getStrValue() const {
|
||||
|
||||
string ConstPoolStruct::getStrValue() const {
|
||||
string Result = "{";
|
||||
if (Val.size()) {
|
||||
Result += " " + Val[0]->getType()->getName() +
|
||||
" " + Val[0]->getStrValue();
|
||||
for (unsigned i = 1; i < Val.size(); i++)
|
||||
Result += ", " + Val[i]->getType()->getName() +
|
||||
" " + Val[i]->getStrValue();
|
||||
if (Operands.size()) {
|
||||
Result += " " + Operands[0]->getType()->getName() +
|
||||
" " + Operands[0]->castConstantAsserting()->getStrValue();
|
||||
for (unsigned i = 1; i < Operands.size(); i++)
|
||||
Result += ", " + Operands[i]->getType()->getName() +
|
||||
" " + Operands[i]->castConstantAsserting()->getStrValue();
|
||||
}
|
||||
|
||||
return Result + " }";
|
||||
@ -356,9 +356,11 @@ bool ConstPoolType::equals(const ConstPoolVal *V) const {
|
||||
bool ConstPoolArray::equals(const ConstPoolVal *V) const {
|
||||
assert(getType() == V->getType());
|
||||
ConstPoolArray *AV = (ConstPoolArray*)V;
|
||||
if (Val.size() != AV->Val.size()) return false;
|
||||
for (unsigned i = 0; i < Val.size(); i++)
|
||||
if (!Val[i]->equals(AV->Val[i])) return false;
|
||||
if (Operands.size() != AV->Operands.size()) return false;
|
||||
for (unsigned i = 0; i < Operands.size(); i++)
|
||||
if (!Operands[i]->castConstantAsserting()->equals(
|
||||
AV->Operands[i]->castConstantAsserting()))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -366,9 +368,11 @@ bool ConstPoolArray::equals(const ConstPoolVal *V) const {
|
||||
bool ConstPoolStruct::equals(const ConstPoolVal *V) const {
|
||||
assert(getType() == V->getType());
|
||||
ConstPoolStruct *SV = (ConstPoolStruct*)V;
|
||||
if (Val.size() != SV->Val.size()) return false;
|
||||
for (unsigned i = 0; i < Val.size(); i++)
|
||||
if (!Val[i]->equals(SV->Val[i])) return false;
|
||||
if (Operands.size() != SV->Operands.size()) return false;
|
||||
for (unsigned i = 0; i < Operands.size(); i++)
|
||||
if (!Operands[i]->castConstantAsserting()->equals(
|
||||
SV->Operands[i]->castConstantAsserting()))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -9,7 +9,7 @@
|
||||
#include "llvm/Method.h"
|
||||
#include "llvm/SymbolTable.h"
|
||||
#include "llvm/Type.h"
|
||||
#include <algorithm>
|
||||
#include <algorithm> // find
|
||||
|
||||
// TODO: Move to getUnaryOperator iUnary.cpp when and if it exists!
|
||||
UnaryOperator *UnaryOperator::create(unsigned Op, Value *Source) {
|
||||
@ -52,49 +52,25 @@ PHINode::PHINode(const Type *Ty, const string &name)
|
||||
|
||||
PHINode::PHINode(const PHINode &PN)
|
||||
: Instruction(PN.getType(), Instruction::PHINode) {
|
||||
|
||||
for (unsigned i = 0; i < PN.IncomingValues.size(); i++)
|
||||
IncomingValues.push_back(
|
||||
make_pair(Use(PN.IncomingValues[i].first, this),
|
||||
BasicBlockUse(PN.IncomingValues[i].second, this)));
|
||||
}
|
||||
|
||||
void PHINode::dropAllReferences() {
|
||||
IncomingValues.clear();
|
||||
}
|
||||
|
||||
bool PHINode::setOperand(unsigned i, Value *Val) {
|
||||
assert(Val && "PHI node must only reference nonnull definitions!");
|
||||
if (i >= IncomingValues.size()*2) return false;
|
||||
|
||||
if (i & 1) {
|
||||
IncomingValues[i/2].second = Val->castBasicBlockAsserting();
|
||||
} else {
|
||||
IncomingValues[i/2].first = Val;
|
||||
Operands.reserve(PN.Operands.size());
|
||||
for (unsigned i = 0; i < PN.Operands.size(); i+=2) {
|
||||
Operands.push_back(Use(PN.Operands[i], this));
|
||||
Operands.push_back(Use(PN.Operands[i+1], this));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void PHINode::addIncoming(Value *D, BasicBlock *BB) {
|
||||
IncomingValues.push_back(make_pair(Use(D, this), BasicBlockUse(BB, this)));
|
||||
Operands.push_back(Use(D, this));
|
||||
Operands.push_back(Use(BB, this));
|
||||
}
|
||||
|
||||
struct FindBBEntry {
|
||||
const BasicBlock *BB;
|
||||
inline FindBBEntry(const BasicBlock *bb) : BB(bb) {}
|
||||
inline bool operator()(const pair<Use,BasicBlockUse> &Entry) {
|
||||
return Entry.second == BB;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// removeIncomingValue - Remove an incoming value. This is useful if a
|
||||
// predecessor basic block is deleted.
|
||||
Value *PHINode::removeIncomingValue(const BasicBlock *BB) {
|
||||
vector<PairTy>::iterator Idx = find_if(IncomingValues.begin(),
|
||||
IncomingValues.end(), FindBBEntry(BB));
|
||||
assert(Idx != IncomingValues.end() && "BB not in PHI node!");
|
||||
Value *Removed = Idx->first;
|
||||
IncomingValues.erase(Idx);
|
||||
op_iterator Idx = find(Operands.begin(), Operands.end(), (const Value*)BB);
|
||||
assert(Idx != Operands.end() && "BB not in PHI node!");
|
||||
--Idx; // Back up to value prior to Basic block
|
||||
Value *Removed = *Idx;
|
||||
Operands.erase(Idx, Idx+2); // Erase Value and BasicBlock
|
||||
return Removed;
|
||||
}
|
||||
|
@ -89,14 +89,13 @@ User::User(const Type *Ty, ValueTy vty, const string &name)
|
||||
void User::replaceUsesOfWith(Value *From, Value *To) {
|
||||
if (From == To) return; // Duh what?
|
||||
|
||||
for (unsigned OpNum = 0; Value *D = getOperand(OpNum); ++OpNum) {
|
||||
if (D == From) { // Okay, this operand is pointing to our fake def.
|
||||
for (unsigned i = 0, E = getNumOperands(); i != E; ++i)
|
||||
if (getOperand(i) == From) { // Is This operand is pointing to oldval?
|
||||
// The side effects of this setOperand call include linking to
|
||||
// "To", adding "this" to the uses list of To, and
|
||||
// most importantly, removing "this" from the use list of "From".
|
||||
setOperand(OpNum, To); // Fix it now...
|
||||
setOperand(i, To); // Fix it now...
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -13,9 +13,17 @@
|
||||
#endif
|
||||
|
||||
BranchInst::BranchInst(BasicBlock *True, BasicBlock *False, Value *Cond)
|
||||
: TerminatorInst(Instruction::Br), TrueDest(True, this),
|
||||
FalseDest(False, this), Condition(Cond, this) {
|
||||
: TerminatorInst(Instruction::Br) {
|
||||
assert(True != 0 && "True branch destination may not be null!!!");
|
||||
Operands.reserve(False ? 3 : 1);
|
||||
Operands.push_back(Use(True, this));
|
||||
if (False) {
|
||||
Operands.push_back(Use(False, this));
|
||||
Operands.push_back(Use(Cond, this));
|
||||
}
|
||||
|
||||
assert(!!False == !!Cond &&
|
||||
"Either both cond and false or neither can be specified!");
|
||||
|
||||
#ifndef NDEBUG
|
||||
if (Cond != 0 && Cond->getType() != Type::BoolTy)
|
||||
@ -25,45 +33,12 @@ BranchInst::BranchInst(BasicBlock *True, BasicBlock *False, Value *Cond)
|
||||
"May only branch on boolean predicates!!!!");
|
||||
}
|
||||
|
||||
BranchInst::BranchInst(const BranchInst &BI)
|
||||
: TerminatorInst(Instruction::Br), TrueDest(BI.TrueDest, this),
|
||||
FalseDest(BI.FalseDest, this), Condition(BI.Condition, this) {
|
||||
}
|
||||
|
||||
|
||||
void BranchInst::dropAllReferences() {
|
||||
Condition = 0;
|
||||
TrueDest = FalseDest = 0;
|
||||
}
|
||||
|
||||
const Value *BranchInst::getOperand(unsigned i) const {
|
||||
return (i == 0) ? (Value*)TrueDest :
|
||||
((i == 1) ? (Value*)FalseDest :
|
||||
((i == 2) ? (Value*)Condition : 0));
|
||||
}
|
||||
|
||||
const BasicBlock *BranchInst::getSuccessor(unsigned i) const {
|
||||
return (i == 0) ? (const BasicBlock*)TrueDest :
|
||||
((i == 1) ? (const BasicBlock*)FalseDest : 0);
|
||||
}
|
||||
|
||||
bool BranchInst::setOperand(unsigned i, Value *Val) {
|
||||
switch (i) {
|
||||
case 0:
|
||||
assert(Val && "Can't change primary direction to 0!");
|
||||
assert(Val->getType() == Type::LabelTy);
|
||||
TrueDest = (BasicBlock*)Val;
|
||||
return true;
|
||||
case 1:
|
||||
assert(Val == 0 || Val->getType() == Type::LabelTy);
|
||||
FalseDest = (BasicBlock*)Val;
|
||||
return true;
|
||||
case 2:
|
||||
Condition = Val;
|
||||
assert(!Condition || Condition->getType() == Type::BoolTy &&
|
||||
"Condition expr must be a boolean expression!");
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
//===-- iCall.cpp - Implement the Call & Invoke instructions -----*- C++ -*--=//
|
||||
//===-- iCall.cpp - Implement the call & icall instructions ------*- C++ -*--=//
|
||||
//
|
||||
// This file implements the call and invoke instructions.
|
||||
// This file implements the call and icall instructions.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
@ -8,9 +8,12 @@
|
||||
#include "llvm/DerivedTypes.h"
|
||||
#include "llvm/Method.h"
|
||||
|
||||
CallInst::CallInst(Method *m, vector<Value*> ¶ms,
|
||||
CallInst::CallInst(Method *M, vector<Value*> ¶ms,
|
||||
const string &Name)
|
||||
: Instruction(m->getReturnType(), Instruction::Call, Name), M(m, this) {
|
||||
: Instruction(M->getReturnType(), Instruction::Call, Name) {
|
||||
|
||||
Operands.reserve(1+params.size());
|
||||
Operands.push_back(Use(M, this));
|
||||
|
||||
const MethodType* MT = M->getMethodType();
|
||||
const MethodType::ParamTypes &PL = MT->getParamTypes();
|
||||
@ -19,29 +22,15 @@ CallInst::CallInst(Method *m, vector<Value*> ¶ms,
|
||||
MethodType::ParamTypes::const_iterator It = PL.begin();
|
||||
#endif
|
||||
for (unsigned i = 0; i < params.size(); i++) {
|
||||
assert(*It++ == params[i]->getType());
|
||||
Params.push_back(Use(params[i], this));
|
||||
assert(*It++ == params[i]->getType() && "Call Operands not correct type!");
|
||||
Operands.push_back(Use(params[i], this));
|
||||
}
|
||||
}
|
||||
|
||||
CallInst::CallInst(const CallInst &CI)
|
||||
: Instruction(CI.getType(), Instruction::Call), M(CI.M, this) {
|
||||
for (unsigned i = 0; i < CI.Params.size(); i++)
|
||||
Params.push_back(Use(CI.Params[i], this));
|
||||
: 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));
|
||||
}
|
||||
|
||||
void CallInst::dropAllReferences() {
|
||||
M = 0;
|
||||
Params.clear();
|
||||
}
|
||||
|
||||
bool CallInst::setOperand(unsigned i, Value *Val) {
|
||||
if (i > Params.size()) return false;
|
||||
if (i == 0) {
|
||||
M = Val->castMethodAsserting();
|
||||
} else {
|
||||
// TODO: assert = method arg type
|
||||
Params[i-1] = Val;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -1,25 +1,3 @@
|
||||
//===-- iReturn.cpp - Implement the Return instruction -----------*- C++ -*--=//
|
||||
//
|
||||
// This file implements the Return instruction...
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/iTerminators.h"
|
||||
|
||||
ReturnInst::ReturnInst(Value *V)
|
||||
: TerminatorInst(Instruction::Ret), Val(V, this) {
|
||||
}
|
||||
|
||||
ReturnInst::ReturnInst(const ReturnInst &RI)
|
||||
: TerminatorInst(Instruction::Ret), Val(RI.Val, this) {
|
||||
}
|
||||
|
||||
void ReturnInst::dropAllReferences() {
|
||||
Val = 0;
|
||||
}
|
||||
|
||||
bool ReturnInst::setOperand(unsigned i, Value *V) {
|
||||
if (i) return false;
|
||||
Val = V;
|
||||
return true;
|
||||
}
|
||||
|
@ -10,72 +10,24 @@
|
||||
#include "llvm/Type.h"
|
||||
#endif
|
||||
|
||||
SwitchInst::SwitchInst(Value *V, BasicBlock *DefV)
|
||||
: TerminatorInst(Instruction::Switch),
|
||||
DefaultDest(DefV, this), Val(V, this) {
|
||||
assert(Val && DefV);
|
||||
SwitchInst::SwitchInst(Value *V, BasicBlock *DefDest)
|
||||
: TerminatorInst(Instruction::Switch) {
|
||||
assert(V && DefDest);
|
||||
Operands.push_back(Use(V, this));
|
||||
Operands.push_back(Use(DefDest, this));
|
||||
}
|
||||
|
||||
SwitchInst::SwitchInst(const SwitchInst &SI)
|
||||
: TerminatorInst(Instruction::Switch), DefaultDest(SI.DefaultDest),
|
||||
Val(SI.Val) {
|
||||
: TerminatorInst(Instruction::Switch) {
|
||||
Operands.reserve(SI.Operands.size());
|
||||
|
||||
for (dest_const_iterator I = SI.Destinations.begin(),
|
||||
end = SI.Destinations.end(); I != end; ++I)
|
||||
Destinations.push_back(dest_value(ConstPoolUse(I->first, this),
|
||||
BasicBlockUse(I->second, this)));
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SwitchInst::dest_push_back(ConstPoolVal *OnVal, BasicBlock *Dest) {
|
||||
Destinations.push_back(dest_value(ConstPoolUse(OnVal, this),
|
||||
BasicBlockUse(Dest, this)));
|
||||
}
|
||||
|
||||
void SwitchInst::dropAllReferences() {
|
||||
Val = 0;
|
||||
DefaultDest = 0;
|
||||
Destinations.clear();
|
||||
}
|
||||
|
||||
const BasicBlock *SwitchInst::getSuccessor(unsigned idx) const {
|
||||
if (idx == 0) return DefaultDest;
|
||||
if (idx > Destinations.size()) return 0;
|
||||
return Destinations[idx-1].second;
|
||||
}
|
||||
|
||||
unsigned SwitchInst::getNumOperands() const {
|
||||
return 2+Destinations.size();
|
||||
}
|
||||
|
||||
const Value *SwitchInst::getOperand(unsigned i) const {
|
||||
if (i == 0) return Val;
|
||||
else if (i == 1) return DefaultDest;
|
||||
|
||||
unsigned slot = (i-2) >> 1;
|
||||
if (slot >= Destinations.size()) return 0;
|
||||
|
||||
if (i & 1) return Destinations[slot].second;
|
||||
return Destinations[slot].first;
|
||||
}
|
||||
|
||||
bool SwitchInst::setOperand(unsigned i, Value *V) {
|
||||
if (i == 0) { Val = V; return true; }
|
||||
else if (i == 1) {
|
||||
assert(V->getType() == Type::LabelTy);
|
||||
DefaultDest = (BasicBlock*)V;
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned slot = (i-2) >> 1;
|
||||
if (slot >= Destinations.size()) return 0;
|
||||
|
||||
if (i & 1) {
|
||||
assert(V->getType() == Type::LabelTy);
|
||||
Destinations[slot].second = (BasicBlock*)V;
|
||||
} else {
|
||||
// TODO: assert constant
|
||||
Destinations[slot].first = (ConstPoolVal*)V;
|
||||
}
|
||||
return true;
|
||||
Operands.push_back(Use(OnVal, this));
|
||||
Operands.push_back(Use(Dest, this));
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user