1 //===-- X86InstrBuilder.h - Functions to aid building x86 insts -*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file exposes functions that may be used with BuildMI from the
11 // MachineInstrBuilder.h file to handle X86'isms in a clean way.
13 // The BuildMem function may be used with the BuildMI function to add entire
14 // memory references in a single, typed, function call. X86 memory references
15 // can be very complex expressions (described in the README), so wrapping them
16 // up behind an easier to use interface makes sense. Descriptions of the
17 // functions are included below.
19 // For reference, the order of operands for memory references is:
20 // (Operand), Base, Scale, Index, Displacement.
22 //===----------------------------------------------------------------------===//
24 #ifndef X86INSTRBUILDER_H
25 #define X86INSTRBUILDER_H
27 #include "llvm/CodeGen/MachineFrameInfo.h"
28 #include "llvm/CodeGen/MachineInstrBuilder.h"
29 #include "llvm/CodeGen/MachineMemOperand.h"
30 #include "llvm/CodeGen/PseudoSourceValue.h"
34 /// X86AddressMode - This struct holds a generalized full x86 address mode.
35 /// The base register can be a frame index, which will eventually be replaced
36 /// with BP or SP and Disp being offsetted accordingly. The displacement may
37 /// also include the offset of a global value.
38 struct X86AddressMode
{
52 const GlobalValue
*GV
;
56 : BaseType(RegBase
), Scale(1), IndexReg(0), Disp(0), GV(0), GVOpFlags(0) {
61 void getFullAddress(SmallVectorImpl
<MachineOperand
> &MO
) {
62 assert(Scale
== 1 || Scale
== 2 || Scale
== 4 || Scale
== 8);
64 if (BaseType
== X86AddressMode::RegBase
)
65 MO
.push_back(MachineOperand::CreateReg(Base
.Reg
, false, false,
66 false, false, false, 0, false));
68 assert(BaseType
== X86AddressMode::FrameIndexBase
);
69 MO
.push_back(MachineOperand::CreateFI(Base
.FrameIndex
));
72 MO
.push_back(MachineOperand::CreateImm(Scale
));
73 MO
.push_back(MachineOperand::CreateReg(IndexReg
, false, false,
74 false, false, false, 0, false));
77 MO
.push_back(MachineOperand::CreateGA(GV
, Disp
, GVOpFlags
));
79 MO
.push_back(MachineOperand::CreateImm(Disp
));
81 MO
.push_back(MachineOperand::CreateReg(0, false, false,
82 false, false, false, 0, false));
86 /// addDirectMem - This function is used to add a direct memory reference to the
87 /// current instruction -- that is, a dereference of an address in a register,
88 /// with no scale, index or displacement. An example is: DWORD PTR [EAX].
90 static inline const MachineInstrBuilder
&
91 addDirectMem(const MachineInstrBuilder
&MIB
, unsigned Reg
) {
92 // Because memory references are always represented with five
93 // values, this adds: Reg, 1, NoReg, 0, NoReg to the instruction.
94 return MIB
.addReg(Reg
).addImm(1).addReg(0).addImm(0).addReg(0);
98 static inline const MachineInstrBuilder
&
99 addOffset(const MachineInstrBuilder
&MIB
, int Offset
) {
100 return MIB
.addImm(1).addReg(0).addImm(Offset
).addReg(0);
103 /// addRegOffset - This function is used to add a memory reference of the form
104 /// [Reg + Offset], i.e., one with no scale or index, but with a
105 /// displacement. An example is: DWORD PTR [EAX + 4].
107 static inline const MachineInstrBuilder
&
108 addRegOffset(const MachineInstrBuilder
&MIB
,
109 unsigned Reg
, bool isKill
, int Offset
) {
110 return addOffset(MIB
.addReg(Reg
, getKillRegState(isKill
)), Offset
);
113 /// addRegReg - This function is used to add a memory reference of the form:
115 static inline const MachineInstrBuilder
&addRegReg(const MachineInstrBuilder
&MIB
,
116 unsigned Reg1
, bool isKill1
,
117 unsigned Reg2
, bool isKill2
) {
118 return MIB
.addReg(Reg1
, getKillRegState(isKill1
)).addImm(1)
119 .addReg(Reg2
, getKillRegState(isKill2
)).addImm(0).addReg(0);
122 static inline const MachineInstrBuilder
&
123 addFullAddress(const MachineInstrBuilder
&MIB
,
124 const X86AddressMode
&AM
) {
125 assert(AM
.Scale
== 1 || AM
.Scale
== 2 || AM
.Scale
== 4 || AM
.Scale
== 8);
127 if (AM
.BaseType
== X86AddressMode::RegBase
)
128 MIB
.addReg(AM
.Base
.Reg
);
130 assert(AM
.BaseType
== X86AddressMode::FrameIndexBase
);
131 MIB
.addFrameIndex(AM
.Base
.FrameIndex
);
134 MIB
.addImm(AM
.Scale
).addReg(AM
.IndexReg
);
136 MIB
.addGlobalAddress(AM
.GV
, AM
.Disp
, AM
.GVOpFlags
);
140 return MIB
.addReg(0);
143 /// addFrameReference - This function is used to add a reference to the base of
144 /// an abstract object on the stack frame of the current function. This
145 /// reference has base register as the FrameIndex offset until it is resolved.
146 /// This allows a constant offset to be specified as well...
148 static inline const MachineInstrBuilder
&
149 addFrameReference(const MachineInstrBuilder
&MIB
, int FI
, int Offset
= 0) {
150 MachineInstr
*MI
= MIB
;
151 MachineFunction
&MF
= *MI
->getParent()->getParent();
152 MachineFrameInfo
&MFI
= *MF
.getFrameInfo();
153 const TargetInstrDesc
&TID
= MI
->getDesc();
156 Flags
|= MachineMemOperand::MOLoad
;
158 Flags
|= MachineMemOperand::MOStore
;
159 MachineMemOperand
*MMO
=
160 MF
.getMachineMemOperand(MachinePointerInfo::getFixedStack(FI
, Offset
),
161 Flags
, MFI
.getObjectSize(FI
),
162 MFI
.getObjectAlignment(FI
));
163 return addOffset(MIB
.addFrameIndex(FI
), Offset
)
167 /// addConstantPoolReference - This function is used to add a reference to the
168 /// base of a constant value spilled to the per-function constant pool. The
169 /// reference uses the abstract ConstantPoolIndex which is retained until
170 /// either machine code emission or assembly output. In PIC mode on x86-32,
171 /// the GlobalBaseReg parameter can be used to make this a
172 /// GlobalBaseReg-relative reference.
174 static inline const MachineInstrBuilder
&
175 addConstantPoolReference(const MachineInstrBuilder
&MIB
, unsigned CPI
,
176 unsigned GlobalBaseReg
, unsigned char OpFlags
) {
178 return MIB
.addReg(GlobalBaseReg
).addImm(1).addReg(0)
179 .addConstantPoolIndex(CPI
, 0, OpFlags
).addReg(0);
182 } // End llvm namespace