#ifndef LLVM_CODEGEN_MACHINEOPERAND_H
#define LLVM_CODEGEN_MACHINEOPERAND_H
#include "llvm/System/DataTypes.h"
#include <cassert>
namespace llvm {
class BlockAddress;
class ConstantFP;
class GlobalValue;
class MachineBasicBlock;
class MachineInstr;
class MachineRegisterInfo;
class MDNode;
class TargetMachine;
class TargetRegisterInfo;
class raw_ostream;
class MCSymbol;
class MachineOperand {
public:
enum MachineOperandType {
MO_Register, MO_Immediate, MO_FPImmediate, MO_MachineBasicBlock, MO_FrameIndex, MO_ConstantPoolIndex, MO_JumpTableIndex, MO_ExternalSymbol, MO_GlobalAddress, MO_BlockAddress, MO_Metadata, MO_MCSymbol };
private:
unsigned char OpKind;
unsigned char SubReg;
unsigned char TargetFlags;
bool IsDef : 1;
bool IsImp : 1;
bool IsKill : 1;
bool IsDead : 1;
bool IsUndef : 1;
bool IsEarlyClobber : 1;
bool IsDebug : 1;
union {
unsigned RegNo; unsigned OffsetLo; } SmallContents;
MachineInstr *ParentMI;
union {
MachineBasicBlock *MBB; const ConstantFP *CFP; int64_t ImmVal; const MDNode *MD; MCSymbol *Sym;
struct { MachineOperand **Prev; MachineOperand *Next;
} Reg;
struct {
union {
int Index; const char *SymbolName; const GlobalValue *GV; const BlockAddress *BA; } Val;
int OffsetHi; } OffsetedInfo;
} Contents;
explicit MachineOperand(MachineOperandType K) : OpKind(K), ParentMI(0) {
TargetFlags = 0;
}
public:
MachineOperandType getType() const { return (MachineOperandType)OpKind; }
unsigned char getTargetFlags() const { return TargetFlags; }
void setTargetFlags(unsigned char F) { TargetFlags = F; }
void addTargetFlag(unsigned char F) { TargetFlags |= F; }
MachineInstr *getParent() { return ParentMI; }
const MachineInstr *getParent() const { return ParentMI; }
void print(raw_ostream &os, const TargetMachine *TM = 0) const;
bool isReg() const { return OpKind == MO_Register; }
bool isImm() const { return OpKind == MO_Immediate; }
bool isFPImm() const { return OpKind == MO_FPImmediate; }
bool isMBB() const { return OpKind == MO_MachineBasicBlock; }
bool isFI() const { return OpKind == MO_FrameIndex; }
bool isCPI() const { return OpKind == MO_ConstantPoolIndex; }
bool isJTI() const { return OpKind == MO_JumpTableIndex; }
bool isGlobal() const { return OpKind == MO_GlobalAddress; }
bool isSymbol() const { return OpKind == MO_ExternalSymbol; }
bool isBlockAddress() const { return OpKind == MO_BlockAddress; }
bool isMetadata() const { return OpKind == MO_Metadata; }
bool isMCSymbol() const { return OpKind == MO_MCSymbol; }
unsigned getReg() const {
assert(isReg() && "This is not a register operand!");
return SmallContents.RegNo;
}
unsigned getSubReg() const {
assert(isReg() && "Wrong MachineOperand accessor");
return (unsigned)SubReg;
}
bool isUse() const {
assert(isReg() && "Wrong MachineOperand accessor");
return !IsDef;
}
bool isDef() const {
assert(isReg() && "Wrong MachineOperand accessor");
return IsDef;
}
bool isImplicit() const {
assert(isReg() && "Wrong MachineOperand accessor");
return IsImp;
}
bool isDead() const {
assert(isReg() && "Wrong MachineOperand accessor");
return IsDead;
}
bool isKill() const {
assert(isReg() && "Wrong MachineOperand accessor");
return IsKill;
}
bool isUndef() const {
assert(isReg() && "Wrong MachineOperand accessor");
return IsUndef;
}
bool isEarlyClobber() const {
assert(isReg() && "Wrong MachineOperand accessor");
return IsEarlyClobber;
}
bool isDebug() const {
assert(isReg() && "Wrong MachineOperand accessor");
return IsDebug;
}
MachineOperand *getNextOperandForReg() const {
assert(isReg() && "This is not a register operand!");
return Contents.Reg.Next;
}
void setReg(unsigned Reg);
void setSubReg(unsigned subReg) {
assert(isReg() && "Wrong MachineOperand accessor");
SubReg = (unsigned char)subReg;
}
void substVirtReg(unsigned Reg, unsigned SubIdx, const TargetRegisterInfo&);
void substPhysReg(unsigned Reg, const TargetRegisterInfo&);
void setIsUse(bool Val = true) {
assert(isReg() && "Wrong MachineOperand accessor");
assert((Val || !isDebug()) && "Marking a debug operation as def");
IsDef = !Val;
}
void setIsDef(bool Val = true) {
assert(isReg() && "Wrong MachineOperand accessor");
assert((!Val || !isDebug()) && "Marking a debug operation as def");
IsDef = Val;
}
void setImplicit(bool Val = true) {
assert(isReg() && "Wrong MachineOperand accessor");
IsImp = Val;
}
void setIsKill(bool Val = true) {
assert(isReg() && !IsDef && "Wrong MachineOperand accessor");
assert((!Val || !isDebug()) && "Marking a debug operation as kill");
IsKill = Val;
}
void setIsDead(bool Val = true) {
assert(isReg() && IsDef && "Wrong MachineOperand accessor");
IsDead = Val;
}
void setIsUndef(bool Val = true) {
assert(isReg() && "Wrong MachineOperand accessor");
IsUndef = Val;
}
void setIsEarlyClobber(bool Val = true) {
assert(isReg() && IsDef && "Wrong MachineOperand accessor");
IsEarlyClobber = Val;
}
void setIsDebug(bool Val = true) {
assert(isReg() && IsDef && "Wrong MachineOperand accessor");
IsDebug = Val;
}
int64_t getImm() const {
assert(isImm() && "Wrong MachineOperand accessor");
return Contents.ImmVal;
}
const ConstantFP *getFPImm() const {
assert(isFPImm() && "Wrong MachineOperand accessor");
return Contents.CFP;
}
MachineBasicBlock *getMBB() const {
assert(isMBB() && "Wrong MachineOperand accessor");
return Contents.MBB;
}
int getIndex() const {
assert((isFI() || isCPI() || isJTI()) &&
"Wrong MachineOperand accessor");
return Contents.OffsetedInfo.Val.Index;
}
const GlobalValue *getGlobal() const {
assert(isGlobal() && "Wrong MachineOperand accessor");
return Contents.OffsetedInfo.Val.GV;
}
const BlockAddress *getBlockAddress() const {
assert(isBlockAddress() && "Wrong MachineOperand accessor");
return Contents.OffsetedInfo.Val.BA;
}
MCSymbol *getMCSymbol() const {
assert(isMCSymbol() && "Wrong MachineOperand accessor");
return Contents.Sym;
}
int64_t getOffset() const {
assert((isGlobal() || isSymbol() || isCPI() || isBlockAddress()) &&
"Wrong MachineOperand accessor");
return (int64_t(Contents.OffsetedInfo.OffsetHi) << 32) |
SmallContents.OffsetLo;
}
const char *getSymbolName() const {
assert(isSymbol() && "Wrong MachineOperand accessor");
return Contents.OffsetedInfo.Val.SymbolName;
}
const MDNode *getMetadata() const {
assert(isMetadata() && "Wrong MachineOperand accessor");
return Contents.MD;
}
void setImm(int64_t immVal) {
assert(isImm() && "Wrong MachineOperand mutator");
Contents.ImmVal = immVal;
}
void setOffset(int64_t Offset) {
assert((isGlobal() || isSymbol() || isCPI() || isBlockAddress()) &&
"Wrong MachineOperand accessor");
SmallContents.OffsetLo = unsigned(Offset);
Contents.OffsetedInfo.OffsetHi = int(Offset >> 32);
}
void setIndex(int Idx) {
assert((isFI() || isCPI() || isJTI()) &&
"Wrong MachineOperand accessor");
Contents.OffsetedInfo.Val.Index = Idx;
}
void setMBB(MachineBasicBlock *MBB) {
assert(isMBB() && "Wrong MachineOperand accessor");
Contents.MBB = MBB;
}
bool isIdenticalTo(const MachineOperand &Other) const;
void ChangeToImmediate(int64_t ImmVal);
void ChangeToRegister(unsigned Reg, bool isDef, bool isImp = false,
bool isKill = false, bool isDead = false,
bool isUndef = false, bool isDebug = false);
static MachineOperand CreateImm(int64_t Val) {
MachineOperand Op(MachineOperand::MO_Immediate);
Op.setImm(Val);
return Op;
}
static MachineOperand CreateFPImm(const ConstantFP *CFP) {
MachineOperand Op(MachineOperand::MO_FPImmediate);
Op.Contents.CFP = CFP;
return Op;
}
static MachineOperand CreateReg(unsigned Reg, bool isDef, bool isImp = false,
bool isKill = false, bool isDead = false,
bool isUndef = false,
bool isEarlyClobber = false,
unsigned SubReg = 0,
bool isDebug = false) {
MachineOperand Op(MachineOperand::MO_Register);
Op.IsDef = isDef;
Op.IsImp = isImp;
Op.IsKill = isKill;
Op.IsDead = isDead;
Op.IsUndef = isUndef;
Op.IsEarlyClobber = isEarlyClobber;
Op.IsDebug = isDebug;
Op.SmallContents.RegNo = Reg;
Op.Contents.Reg.Prev = 0;
Op.Contents.Reg.Next = 0;
Op.SubReg = SubReg;
return Op;
}
static MachineOperand CreateMBB(MachineBasicBlock *MBB,
unsigned char TargetFlags = 0) {
MachineOperand Op(MachineOperand::MO_MachineBasicBlock);
Op.setMBB(MBB);
Op.setTargetFlags(TargetFlags);
return Op;
}
static MachineOperand CreateFI(unsigned Idx) {
MachineOperand Op(MachineOperand::MO_FrameIndex);
Op.setIndex(Idx);
return Op;
}
static MachineOperand CreateCPI(unsigned Idx, int Offset,
unsigned char TargetFlags = 0) {
MachineOperand Op(MachineOperand::MO_ConstantPoolIndex);
Op.setIndex(Idx);
Op.setOffset(Offset);
Op.setTargetFlags(TargetFlags);
return Op;
}
static MachineOperand CreateJTI(unsigned Idx,
unsigned char TargetFlags = 0) {
MachineOperand Op(MachineOperand::MO_JumpTableIndex);
Op.setIndex(Idx);
Op.setTargetFlags(TargetFlags);
return Op;
}
static MachineOperand CreateGA(const GlobalValue *GV, int64_t Offset,
unsigned char TargetFlags = 0) {
MachineOperand Op(MachineOperand::MO_GlobalAddress);
Op.Contents.OffsetedInfo.Val.GV = GV;
Op.setOffset(Offset);
Op.setTargetFlags(TargetFlags);
return Op;
}
static MachineOperand CreateES(const char *SymName,
unsigned char TargetFlags = 0) {
MachineOperand Op(MachineOperand::MO_ExternalSymbol);
Op.Contents.OffsetedInfo.Val.SymbolName = SymName;
Op.setOffset(0); Op.setTargetFlags(TargetFlags);
return Op;
}
static MachineOperand CreateBA(const BlockAddress *BA,
unsigned char TargetFlags = 0) {
MachineOperand Op(MachineOperand::MO_BlockAddress);
Op.Contents.OffsetedInfo.Val.BA = BA;
Op.setOffset(0); Op.setTargetFlags(TargetFlags);
return Op;
}
static MachineOperand CreateMetadata(const MDNode *Meta) {
MachineOperand Op(MachineOperand::MO_Metadata);
Op.Contents.MD = Meta;
return Op;
}
static MachineOperand CreateMCSymbol(MCSymbol *Sym) {
MachineOperand Op(MachineOperand::MO_MCSymbol);
Op.Contents.Sym = Sym;
return Op;
}
friend class MachineInstr;
friend class MachineRegisterInfo;
private:
bool isOnRegUseList() const {
assert(isReg() && "Can only add reg operand to use lists");
return Contents.Reg.Prev != 0;
}
void AddRegOperandToRegInfo(MachineRegisterInfo *RegInfo);
void RemoveRegOperandFromRegInfo();
};
inline raw_ostream &operator<<(raw_ostream &OS, const MachineOperand& MO) {
MO.print(OS, 0);
return OS;
}
}
#endif