]>
Commit | Line | Data |
---|---|---|
223e47cc LB |
1 | //===-- X86InstrBuilder.h - Functions to aid building x86 insts -*- C++ -*-===// |
2 | // | |
3 | // The LLVM Compiler Infrastructure | |
4 | // | |
5 | // This file is distributed under the University of Illinois Open Source | |
6 | // License. See LICENSE.TXT for details. | |
7 | // | |
8 | //===----------------------------------------------------------------------===// | |
9 | // | |
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. | |
12 | // | |
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. | |
18 | // | |
19 | // For reference, the order of operands for memory references is: | |
20 | // (Operand), Base, Scale, Index, Displacement. | |
21 | // | |
22 | //===----------------------------------------------------------------------===// | |
23 | ||
1a4d82fc JJ |
24 | #ifndef LLVM_LIB_TARGET_X86_X86INSTRBUILDER_H |
25 | #define LLVM_LIB_TARGET_X86_X86INSTRBUILDER_H | |
223e47cc LB |
26 | |
27 | #include "llvm/CodeGen/MachineFrameInfo.h" | |
28 | #include "llvm/CodeGen/MachineInstrBuilder.h" | |
29 | #include "llvm/CodeGen/MachineMemOperand.h" | |
30 | ||
31 | namespace llvm { | |
32 | ||
33 | /// X86AddressMode - This struct holds a generalized full x86 address mode. | |
34 | /// The base register can be a frame index, which will eventually be replaced | |
35 | /// with BP or SP and Disp being offsetted accordingly. The displacement may | |
36 | /// also include the offset of a global value. | |
37 | struct X86AddressMode { | |
38 | enum { | |
39 | RegBase, | |
40 | FrameIndexBase | |
41 | } BaseType; | |
42 | ||
43 | union { | |
44 | unsigned Reg; | |
45 | int FrameIndex; | |
46 | } Base; | |
47 | ||
48 | unsigned Scale; | |
49 | unsigned IndexReg; | |
50 | int Disp; | |
51 | const GlobalValue *GV; | |
52 | unsigned GVOpFlags; | |
53 | ||
54 | X86AddressMode() | |
1a4d82fc JJ |
55 | : BaseType(RegBase), Scale(1), IndexReg(0), Disp(0), GV(nullptr), |
56 | GVOpFlags(0) { | |
223e47cc LB |
57 | Base.Reg = 0; |
58 | } | |
59 | ||
60 | ||
61 | void getFullAddress(SmallVectorImpl<MachineOperand> &MO) { | |
62 | assert(Scale == 1 || Scale == 2 || Scale == 4 || Scale == 8); | |
63 | ||
64 | if (BaseType == X86AddressMode::RegBase) | |
65 | MO.push_back(MachineOperand::CreateReg(Base.Reg, false, false, | |
66 | false, false, false, 0, false)); | |
67 | else { | |
68 | assert(BaseType == X86AddressMode::FrameIndexBase); | |
69 | MO.push_back(MachineOperand::CreateFI(Base.FrameIndex)); | |
70 | } | |
71 | ||
72 | MO.push_back(MachineOperand::CreateImm(Scale)); | |
73 | MO.push_back(MachineOperand::CreateReg(IndexReg, false, false, | |
74 | false, false, false, 0, false)); | |
75 | ||
76 | if (GV) | |
77 | MO.push_back(MachineOperand::CreateGA(GV, Disp, GVOpFlags)); | |
78 | else | |
79 | MO.push_back(MachineOperand::CreateImm(Disp)); | |
80 | ||
81 | MO.push_back(MachineOperand::CreateReg(0, false, false, | |
82 | false, false, false, 0, false)); | |
83 | } | |
84 | }; | |
85 | ||
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]. | |
89 | /// | |
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); | |
95 | } | |
96 | ||
97 | ||
98 | static inline const MachineInstrBuilder & | |
99 | addOffset(const MachineInstrBuilder &MIB, int Offset) { | |
100 | return MIB.addImm(1).addReg(0).addImm(Offset).addReg(0); | |
101 | } | |
102 | ||
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]. | |
106 | /// | |
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); | |
111 | } | |
112 | ||
113 | /// addRegReg - This function is used to add a memory reference of the form: | |
114 | /// [Reg + Reg]. | |
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); | |
120 | } | |
121 | ||
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); | |
126 | ||
127 | if (AM.BaseType == X86AddressMode::RegBase) | |
128 | MIB.addReg(AM.Base.Reg); | |
129 | else { | |
130 | assert(AM.BaseType == X86AddressMode::FrameIndexBase); | |
131 | MIB.addFrameIndex(AM.Base.FrameIndex); | |
132 | } | |
133 | ||
134 | MIB.addImm(AM.Scale).addReg(AM.IndexReg); | |
135 | if (AM.GV) | |
136 | MIB.addGlobalAddress(AM.GV, AM.Disp, AM.GVOpFlags); | |
137 | else | |
138 | MIB.addImm(AM.Disp); | |
139 | ||
140 | return MIB.addReg(0); | |
141 | } | |
142 | ||
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... | |
147 | /// | |
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 MCInstrDesc &MCID = MI->getDesc(); | |
154 | unsigned Flags = 0; | |
155 | if (MCID.mayLoad()) | |
156 | Flags |= MachineMemOperand::MOLoad; | |
157 | if (MCID.mayStore()) | |
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) | |
164 | .addMemOperand(MMO); | |
165 | } | |
166 | ||
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. | |
173 | /// | |
174 | static inline const MachineInstrBuilder & | |
175 | addConstantPoolReference(const MachineInstrBuilder &MIB, unsigned CPI, | |
176 | unsigned GlobalBaseReg, unsigned char OpFlags) { | |
177 | //FIXME: factor this | |
178 | return MIB.addReg(GlobalBaseReg).addImm(1).addReg(0) | |
179 | .addConstantPoolIndex(CPI, 0, OpFlags).addReg(0); | |
180 | } | |
181 | ||
182 | } // End llvm namespace | |
183 | ||
184 | #endif |