1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
|
//===-- llvm/CodeGen/MInstruction.h - Machine Instruction -------*- C++ -*-===//
//
// This class represents a single machine instruction for the LLVM backend.
// This instruction is represented in a completely generic way to allow all
// backends to share a common representation. MInstructions are embedded into
// MBasicBlocks, and are maintained as a doubly linked list.
//
// Because there are a lot of machine instruction that may be in use at a time
// (being manipulated), we are sure to keep a very compact representation that
// is extremely light-weight.
//
// This class is used to represent an instruction when it is in SSA form as well
// as when it has been register allocated to use physical registers.
//
// FIXME: This should eventually be merged with the MachineInstr class.
//
//===----------------------------------------------------------------------===//
#ifndef CODEGEN_MINSTRUCTION_H
#define CODEGEN_MINSTRUCTION_H
#include <vector>
template<typename NodeTy> struct ilist_traits;
class MBasicBlock;
/// MOperand - This class represents a single operand in an instruction.
/// Interpretation of this operand is not really possible without information
/// from the machine instruction that it is embedded into.
///
class MOperand {
union {
unsigned uVal;
int iVal;
};
public:
MOperand(unsigned Value) : uVal(Value) {}
MOperand(int Value) : iVal(Value) {}
/// Interpretation - This enum is used by the MInstruction class to interpret
/// the untyped value field of the operand.
enum Interpretation {
Register, // This is some register number
SignExtImmediate, // This is a sign extended immediate
ZeroExtImmediate, // This is a zero extended immediate
PCRelativeDisp // This is a displacement relative to the PC
// FIXME: We need a symbolic value here, like global variable address
};
unsigned getUnsignedValue() const { return uVal; }
unsigned getSignedValue() const { return iVal; }
};
/// MInstruction - Represent a single machine instruction in the code generator.
/// This is meant to be a light weight representation that is completely
/// independant of the target machine being code generated for.
///
class MInstruction {
MInstruction *Prev, *Next; // Doubly linked list of instructions...
unsigned Opcode; // Opcode of the instruction
unsigned Dest; // Destination register written (or 0 if none)
std::vector<MOperand> Operands; // Operands of the instruction...
/// OperandInterpretation - This array specifies how the operands of the
/// instruction are to be interpreted (is it a register?, an immediate
/// constant?, a PC relative displacement?, etc...). Only four values are
/// allowed, so any instruction with more than four operands (should be
/// exceedingly rare, perhaps only PHI nodes) are assumed to have register
/// operands beyond the fourth.
///
unsigned char OperandInterpretation[4];
public:
/// MInstruction ctor - Create a new machine instruction, with the specified
/// opcode and destination register. Operands are then added with the
/// addOperand method.
///
MInstruction(unsigned O = 0, unsigned D = 0) : Opcode(O), Dest(D) {}
/// MInstruction ctor - Create a new instruction, and append it to the
/// specified basic block.
///
MInstruction(MBasicBlock *BB, unsigned Opcode = 0, unsigned Dest = 0);
/// getOpcode - Return the opcode for this machine instruction. The value of
/// the opcode defines how to interpret the operands of the instruction.
///
unsigned getOpcode() const { return Opcode; }
/// getDestinationReg - This method returns the register written to by this
/// instruction. If this returns zero, the instruction does not produce a
/// value, because register #0 is always the garbage marker.
///
unsigned getDestinationReg() const { return Dest; }
/// setDestinationReg - This method changes the register written to by this
/// instruction. Note that if SSA form is currently active then the SSA table
/// needs to be updated to match this, thus this method shouldn't be used
/// directly.
///
void setDestinationReg(unsigned R) { Dest = R; }
/// getNumOperands - Return the number of operands the instruction currently
/// has.
///
unsigned getNumOperands() const { return Operands.size(); }
/// getOperandInterpretation - Return the interpretation of operand #Op
///
MOperand::Interpretation getOperandInterpretation(unsigned Op) const {
if (Op < 4) return (MOperand::Interpretation)OperandInterpretation[Op];
return MOperand::Register; // Operands >= 4 are all registers
}
unsigned getRegisterOperand(unsigned Op) const {
assert(getOperandInterpretation(Op) == MOperand::Register &&
"Operand isn't a register!");
return Operands[Op].getUnsignedValue();
}
int getSignExtOperand(unsigned Op) const {
assert(getOperandInterpretation(Op) == MOperand::SignExtImmediate &&
"Operand isn't a sign extended immediate!");
return Operands[Op].getSignedValue();
}
unsigned getZeroExtOperand(unsigned Op) const {
assert(getOperandInterpretation(Op) == MOperand::ZeroExtImmediate &&
"Operand isn't a zero extended immediate!");
return Operands[Op].getUnsignedValue();
}
int getPCRelativeOperand(unsigned Op) const {
assert(getOperandInterpretation(Op) == MOperand::PCRelativeDisp &&
"Operand isn't a PC relative displacement!");
return Operands[Op].getSignedValue();
}
/// addOperand - Add a new operand to the instruction with the specified value
/// and interpretation.
///
void addOperand(unsigned Value, MOperand::Interpretation Ty);
private: // Methods used to maintain doubly linked list of instructions...
friend class ilist_traits<MInstruction>;
MInstruction *getPrev() const { return Prev; }
MInstruction *getNext() const { return Next; }
void setPrev(MInstruction *P) { Prev = P; }
void setNext(MInstruction *N) { Next = N; }
};
#endif
|