blob: dcce7b9951f266d3d7443bb92b353bb67f809b05 [file] [log] [blame]
Chris Lattnerc682b4a2002-11-17 21:03:35 +00001//===-- X86InstrBuilder.h - Functions to aid building x86 insts -*- C++ -*-===//
Misha Brukmanc88330a2005-04-21 23:38:14 +00002//
John Criswell29265fe2003-10-21 15:17:13 +00003// The LLVM Compiler Infrastructure
4//
Chris Lattnerf3ebc3f2007-12-29 20:36:04 +00005// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
Misha Brukmanc88330a2005-04-21 23:38:14 +00007//
John Criswell29265fe2003-10-21 15:17:13 +00008//===----------------------------------------------------------------------===//
Chris Lattnerc682b4a2002-11-17 21:03:35 +00009//
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//
Brian Gaekeeaeacc52002-12-13 09:28:50 +000019// For reference, the order of operands for memory references is:
20// (Operand), Base, Scale, Index, Displacement.
21//
Chris Lattnerc682b4a2002-11-17 21:03:35 +000022//===----------------------------------------------------------------------===//
23
Benjamin Kramera7c40ef2014-08-13 16:26:38 +000024#ifndef LLVM_LIB_TARGET_X86_X86INSTRBUILDER_H
25#define LLVM_LIB_TARGET_X86_X86INSTRBUILDER_H
Chris Lattnerc682b4a2002-11-17 21:03:35 +000026
Eugene Zelenko61a72d82016-08-18 17:56:27 +000027#include "llvm/ADT/SmallVector.h"
Dan Gohman78407ac2008-12-03 18:11:40 +000028#include "llvm/CodeGen/MachineFrameInfo.h"
Eugene Zelenko61a72d82016-08-18 17:56:27 +000029#include "llvm/CodeGen/MachineFunction.h"
30#include "llvm/CodeGen/MachineInstr.h"
Chris Lattnerc682b4a2002-11-17 21:03:35 +000031#include "llvm/CodeGen/MachineInstrBuilder.h"
Dan Gohman48b185d2009-09-25 20:36:54 +000032#include "llvm/CodeGen/MachineMemOperand.h"
Eugene Zelenko61a72d82016-08-18 17:56:27 +000033#include "llvm/CodeGen/MachineOperand.h"
34#include "llvm/MC/MCInstrDesc.h"
35#include <cassert>
Chris Lattnerc682b4a2002-11-17 21:03:35 +000036
Brian Gaeke960707c2003-11-11 22:41:34 +000037namespace llvm {
38
Reid Spencer8aca0b42004-08-30 00:13:26 +000039/// X86AddressMode - This struct holds a generalized full x86 address mode.
40/// The base register can be a frame index, which will eventually be replaced
Chris Lattnerdf7b9842004-10-15 04:43:20 +000041/// with BP or SP and Disp being offsetted accordingly. The displacement may
42/// also include the offset of a global value.
Reid Spencer8aca0b42004-08-30 00:13:26 +000043struct X86AddressMode {
Chris Lattnerb93409f2005-01-17 23:25:45 +000044 enum {
45 RegBase,
Chris Lattneraa2372562006-05-24 17:04:05 +000046 FrameIndexBase
Chris Lattnerb93409f2005-01-17 23:25:45 +000047 } BaseType;
Misha Brukmanc88330a2005-04-21 23:38:14 +000048
Chris Lattnerb93409f2005-01-17 23:25:45 +000049 union {
50 unsigned Reg;
51 int FrameIndex;
52 } Base;
Misha Brukmanc88330a2005-04-21 23:38:14 +000053
Chris Lattnerb93409f2005-01-17 23:25:45 +000054 unsigned Scale;
55 unsigned IndexReg;
Chris Lattnerdb4916a2009-09-15 18:27:02 +000056 int Disp;
Dan Gohmanbcaf6812010-04-15 01:51:59 +000057 const GlobalValue *GV;
Chris Lattnerf95fa1b2009-07-01 03:27:19 +000058 unsigned GVOpFlags;
Misha Brukmanc88330a2005-04-21 23:38:14 +000059
Chris Lattnerf95fa1b2009-07-01 03:27:19 +000060 X86AddressMode()
Craig Toppere73658d2014-04-28 04:05:08 +000061 : BaseType(RegBase), Scale(1), IndexReg(0), Disp(0), GV(nullptr),
62 GVOpFlags(0) {
Chris Lattnerb93409f2005-01-17 23:25:45 +000063 Base.Reg = 0;
64 }
Chad Rosierf5cdea32012-06-22 22:07:19 +000065
Chris Lattnereeba0c72010-09-05 02:18:34 +000066 void getFullAddress(SmallVectorImpl<MachineOperand> &MO) {
67 assert(Scale == 1 || Scale == 2 || Scale == 4 || Scale == 8);
Chad Rosierf5cdea32012-06-22 22:07:19 +000068
Chris Lattnereeba0c72010-09-05 02:18:34 +000069 if (BaseType == X86AddressMode::RegBase)
Eugene Zelenko61a72d82016-08-18 17:56:27 +000070 MO.push_back(MachineOperand::CreateReg(Base.Reg, false, false, false,
Chris Lattnereeba0c72010-09-05 02:18:34 +000071 false, false, false, 0, false));
72 else {
73 assert(BaseType == X86AddressMode::FrameIndexBase);
74 MO.push_back(MachineOperand::CreateFI(Base.FrameIndex));
75 }
Chad Rosierf5cdea32012-06-22 22:07:19 +000076
Chris Lattnereeba0c72010-09-05 02:18:34 +000077 MO.push_back(MachineOperand::CreateImm(Scale));
Eugene Zelenko61a72d82016-08-18 17:56:27 +000078 MO.push_back(MachineOperand::CreateReg(IndexReg, false, false, false, false,
79 false, false, 0, false));
Chad Rosierf5cdea32012-06-22 22:07:19 +000080
Chris Lattnereeba0c72010-09-05 02:18:34 +000081 if (GV)
82 MO.push_back(MachineOperand::CreateGA(GV, Disp, GVOpFlags));
83 else
84 MO.push_back(MachineOperand::CreateImm(Disp));
Chad Rosierf5cdea32012-06-22 22:07:19 +000085
Eugene Zelenko61a72d82016-08-18 17:56:27 +000086 MO.push_back(MachineOperand::CreateReg(0, false, false, false, false, false,
87 false, 0, false));
Chris Lattnereeba0c72010-09-05 02:18:34 +000088 }
Reid Spencer8aca0b42004-08-30 00:13:26 +000089};
90
Chandler Carruth81c3dde2016-03-30 03:10:24 +000091/// Compute the addressing mode from an machine instruction starting with the
92/// given operand.
Nikolai Bozhenova2dabed2016-11-24 13:05:43 +000093static inline X86AddressMode getAddressFromInstr(const MachineInstr *MI,
Chandler Carruth81c3dde2016-03-30 03:10:24 +000094 unsigned Operand) {
95 X86AddressMode AM;
Nikolai Bozhenova2dabed2016-11-24 13:05:43 +000096 const MachineOperand &Op0 = MI->getOperand(Operand);
97 if (Op0.isReg()) {
Chandler Carruth81c3dde2016-03-30 03:10:24 +000098 AM.BaseType = X86AddressMode::RegBase;
Nikolai Bozhenova2dabed2016-11-24 13:05:43 +000099 AM.Base.Reg = Op0.getReg();
Chandler Carruth81c3dde2016-03-30 03:10:24 +0000100 } else {
101 AM.BaseType = X86AddressMode::FrameIndexBase;
Nikolai Bozhenova2dabed2016-11-24 13:05:43 +0000102 AM.Base.FrameIndex = Op0.getIndex();
Chandler Carruth81c3dde2016-03-30 03:10:24 +0000103 }
Nikolai Bozhenova2dabed2016-11-24 13:05:43 +0000104
105 const MachineOperand &Op1 = MI->getOperand(Operand + 1);
106 AM.Scale = Op1.getImm();
107
108 const MachineOperand &Op2 = MI->getOperand(Operand + 2);
109 AM.IndexReg = Op2.getReg();
110
111 const MachineOperand &Op3 = MI->getOperand(Operand + 3);
112 if (Op3.isGlobal())
113 AM.GV = Op3.getGlobal();
114 else
115 AM.Disp = Op3.getImm();
116
Chandler Carruth81c3dde2016-03-30 03:10:24 +0000117 return AM;
118}
119
Chris Lattnerc682b4a2002-11-17 21:03:35 +0000120/// addDirectMem - This function is used to add a direct memory reference to the
Chris Lattneref5a8f92002-12-28 20:26:58 +0000121/// current instruction -- that is, a dereference of an address in a register,
122/// with no scale, index or displacement. An example is: DWORD PTR [EAX].
123///
Anton Korobeynikov12b4b7c2009-07-16 14:03:08 +0000124static inline const MachineInstrBuilder &
125addDirectMem(const MachineInstrBuilder &MIB, unsigned Reg) {
Chris Lattnerf4693072010-07-08 23:46:44 +0000126 // Because memory references are always represented with five
127 // values, this adds: Reg, 1, NoReg, 0, NoReg to the instruction.
128 return MIB.addReg(Reg).addImm(1).addReg(0).addImm(0).addReg(0);
Chris Lattnerc682b4a2002-11-17 21:03:35 +0000129}
130
Nikolai Bozhenov3a8d1082016-11-24 13:23:35 +0000131/// Replace the address used in the instruction with the direct memory
132/// reference.
133static inline void setDirectAddressInInstr(MachineInstr *MI, unsigned Operand,
134 unsigned Reg) {
135 // Direct memory address is in a form of: Reg, 1 (Scale), NoReg, 0, NoReg.
136 MI->getOperand(Operand).setReg(Reg);
137 MI->getOperand(Operand + 1).setImm(1);
138 MI->getOperand(Operand + 2).setReg(0);
139 MI->getOperand(Operand + 3).setImm(0);
140 MI->getOperand(Operand + 4).setReg(0);
141}
Rafael Espindola3b2df102009-04-08 21:14:34 +0000142
Anton Korobeynikov12b4b7c2009-07-16 14:03:08 +0000143static inline const MachineInstrBuilder &
144addOffset(const MachineInstrBuilder &MIB, int Offset) {
Chris Lattnerf4693072010-07-08 23:46:44 +0000145 return MIB.addImm(1).addReg(0).addImm(Offset).addReg(0);
Rafael Espindola3b2df102009-04-08 21:14:34 +0000146}
Misha Brukman4ea94a42002-11-22 22:42:12 +0000147
Michael Kuperstein18092cf2016-12-07 19:29:18 +0000148static inline const MachineInstrBuilder &
149addOffset(const MachineInstrBuilder &MIB, const MachineOperand& Offset) {
Diana Picus116bbab2017-01-13 09:58:52 +0000150 return MIB.addImm(1).addReg(0).add(Offset).addReg(0);
Michael Kuperstein18092cf2016-12-07 19:29:18 +0000151}
152
Chris Lattneref5a8f92002-12-28 20:26:58 +0000153/// addRegOffset - This function is used to add a memory reference of the form
154/// [Reg + Offset], i.e., one with no scale or index, but with a
155/// displacement. An example is: DWORD PTR [EAX + 4].
156///
Anton Korobeynikov12b4b7c2009-07-16 14:03:08 +0000157static inline const MachineInstrBuilder &
158addRegOffset(const MachineInstrBuilder &MIB,
159 unsigned Reg, bool isKill, int Offset) {
Bill Wendlingf7b83c72009-05-13 21:33:08 +0000160 return addOffset(MIB.addReg(Reg, getKillRegState(isKill)), Offset);
Rafael Espindola3b2df102009-04-08 21:14:34 +0000161}
162
Chris Lattnere7228732005-01-02 02:38:18 +0000163/// addRegReg - This function is used to add a memory reference of the form:
164/// [Reg + Reg].
Anton Korobeynikov12b4b7c2009-07-16 14:03:08 +0000165static inline const MachineInstrBuilder &addRegReg(const MachineInstrBuilder &MIB,
Evan Cheng7d98a482008-07-03 09:09:37 +0000166 unsigned Reg1, bool isKill1,
167 unsigned Reg2, bool isKill2) {
Bill Wendlingf7b83c72009-05-13 21:33:08 +0000168 return MIB.addReg(Reg1, getKillRegState(isKill1)).addImm(1)
Chris Lattnerf4693072010-07-08 23:46:44 +0000169 .addReg(Reg2, getKillRegState(isKill2)).addImm(0).addReg(0);
Chris Lattnere7228732005-01-02 02:38:18 +0000170}
171
Anton Korobeynikov12b4b7c2009-07-16 14:03:08 +0000172static inline const MachineInstrBuilder &
Chris Lattnerf4693072010-07-08 23:46:44 +0000173addFullAddress(const MachineInstrBuilder &MIB,
174 const X86AddressMode &AM) {
175 assert(AM.Scale == 1 || AM.Scale == 2 || AM.Scale == 4 || AM.Scale == 8);
Chad Rosierf5cdea32012-06-22 22:07:19 +0000176
Reid Spencer8aca0b42004-08-30 00:13:26 +0000177 if (AM.BaseType == X86AddressMode::RegBase)
178 MIB.addReg(AM.Base.Reg);
Chris Lattnereeba0c72010-09-05 02:18:34 +0000179 else {
180 assert(AM.BaseType == X86AddressMode::FrameIndexBase);
Reid Spencer8aca0b42004-08-30 00:13:26 +0000181 MIB.addFrameIndex(AM.Base.FrameIndex);
Chris Lattnereeba0c72010-09-05 02:18:34 +0000182 }
183
Chris Lattner469647b2006-05-04 18:16:01 +0000184 MIB.addImm(AM.Scale).addReg(AM.IndexReg);
Chris Lattnerdf7b9842004-10-15 04:43:20 +0000185 if (AM.GV)
Chris Lattnerf4693072010-07-08 23:46:44 +0000186 MIB.addGlobalAddress(AM.GV, AM.Disp, AM.GVOpFlags);
Chris Lattnerdf7b9842004-10-15 04:43:20 +0000187 else
Chris Lattnerf4693072010-07-08 23:46:44 +0000188 MIB.addImm(AM.Disp);
Chad Rosierf5cdea32012-06-22 22:07:19 +0000189
Chris Lattnerf4693072010-07-08 23:46:44 +0000190 return MIB.addReg(0);
Rafael Espindola3b2df102009-04-08 21:14:34 +0000191}
192
Chris Lattneref5a8f92002-12-28 20:26:58 +0000193/// addFrameReference - This function is used to add a reference to the base of
194/// an abstract object on the stack frame of the current function. This
Chris Lattner78785632003-01-13 00:45:53 +0000195/// reference has base register as the FrameIndex offset until it is resolved.
196/// This allows a constant offset to be specified as well...
Chris Lattneref5a8f92002-12-28 20:26:58 +0000197///
Anton Korobeynikov12b4b7c2009-07-16 14:03:08 +0000198static inline const MachineInstrBuilder &
Chris Lattner78785632003-01-13 00:45:53 +0000199addFrameReference(const MachineInstrBuilder &MIB, int FI, int Offset = 0) {
Dan Gohman78407ac2008-12-03 18:11:40 +0000200 MachineInstr *MI = MIB;
201 MachineFunction &MF = *MI->getParent()->getParent();
Matthias Braun941a7052016-07-28 18:40:00 +0000202 MachineFrameInfo &MFI = MF.getFrameInfo();
Evan Cheng6cc775f2011-06-28 19:10:37 +0000203 const MCInstrDesc &MCID = MI->getDesc();
Justin Lebar0af80cd2016-07-15 18:26:59 +0000204 auto Flags = MachineMemOperand::MONone;
Evan Cheng6cc775f2011-06-28 19:10:37 +0000205 if (MCID.mayLoad())
Dan Gohman78407ac2008-12-03 18:11:40 +0000206 Flags |= MachineMemOperand::MOLoad;
Evan Cheng6cc775f2011-06-28 19:10:37 +0000207 if (MCID.mayStore())
Dan Gohman78407ac2008-12-03 18:11:40 +0000208 Flags |= MachineMemOperand::MOStore;
Alex Lorenze40c8a22015-08-11 23:09:45 +0000209 MachineMemOperand *MMO = MF.getMachineMemOperand(
210 MachinePointerInfo::getFixedStack(MF, FI, Offset), Flags,
211 MFI.getObjectSize(FI), MFI.getObjectAlignment(FI));
Rafael Espindola3b2df102009-04-08 21:14:34 +0000212 return addOffset(MIB.addFrameIndex(FI), Offset)
Dan Gohman78407ac2008-12-03 18:11:40 +0000213 .addMemOperand(MMO);
Chris Lattner78785632003-01-13 00:45:53 +0000214}
215
216/// addConstantPoolReference - This function is used to add a reference to the
217/// base of a constant value spilled to the per-function constant pool. The
Dan Gohman8392f0c2008-09-30 01:21:32 +0000218/// reference uses the abstract ConstantPoolIndex which is retained until
219/// either machine code emission or assembly output. In PIC mode on x86-32,
220/// the GlobalBaseReg parameter can be used to make this a
221/// GlobalBaseReg-relative reference.
Chris Lattner78785632003-01-13 00:45:53 +0000222///
Anton Korobeynikov12b4b7c2009-07-16 14:03:08 +0000223static inline const MachineInstrBuilder &
Dan Gohman8392f0c2008-09-30 01:21:32 +0000224addConstantPoolReference(const MachineInstrBuilder &MIB, unsigned CPI,
Chris Lattnera3260c02009-06-27 01:31:51 +0000225 unsigned GlobalBaseReg, unsigned char OpFlags) {
Rafael Espindola3b2df102009-04-08 21:14:34 +0000226 //FIXME: factor this
227 return MIB.addReg(GlobalBaseReg).addImm(1).addReg(0)
Chris Lattnera3260c02009-06-27 01:31:51 +0000228 .addConstantPoolIndex(CPI, 0, OpFlags).addReg(0);
Chris Lattneref5a8f92002-12-28 20:26:58 +0000229}
230
Eugene Zelenko61a72d82016-08-18 17:56:27 +0000231} // end namespace llvm
Brian Gaeke960707c2003-11-11 22:41:34 +0000232
Eugene Zelenko61a72d82016-08-18 17:56:27 +0000233#endif // LLVM_LIB_TARGET_X86_X86INSTRBUILDER_H