X86InstrBuilder.h 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. //===-- X86InstrBuilder.h - Functions to aid building x86 insts -*- C++ -*-===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. // This file exposes functions that may be used with BuildMI from the
  10. // MachineInstrBuilder.h file to handle X86'isms in a clean way.
  11. //
  12. // The BuildMem function may be used with the BuildMI function to add entire
  13. // memory references in a single, typed, function call. X86 memory references
  14. // can be very complex expressions (described in the README), so wrapping them
  15. // up behind an easier to use interface makes sense. Descriptions of the
  16. // functions are included below.
  17. //
  18. // For reference, the order of operands for memory references is:
  19. // (Operand), Base, Scale, Index, Displacement.
  20. //
  21. //===----------------------------------------------------------------------===//
  22. #ifndef LLVM_LIB_TARGET_X86_X86INSTRBUILDER_H
  23. #define LLVM_LIB_TARGET_X86_X86INSTRBUILDER_H
  24. #include "llvm/ADT/SmallVector.h"
  25. #include "llvm/CodeGen/MachineFrameInfo.h"
  26. #include "llvm/CodeGen/MachineFunction.h"
  27. #include "llvm/CodeGen/MachineInstr.h"
  28. #include "llvm/CodeGen/MachineInstrBuilder.h"
  29. #include "llvm/CodeGen/MachineMemOperand.h"
  30. #include "llvm/CodeGen/MachineOperand.h"
  31. #include "llvm/MC/MCInstrDesc.h"
  32. #include <cassert>
  33. namespace llvm {
  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 {
  39. enum {
  40. RegBase,
  41. FrameIndexBase
  42. } BaseType;
  43. union {
  44. unsigned Reg;
  45. int FrameIndex;
  46. } Base;
  47. unsigned Scale;
  48. unsigned IndexReg;
  49. int Disp;
  50. const GlobalValue *GV;
  51. unsigned GVOpFlags;
  52. X86AddressMode()
  53. : BaseType(RegBase), Scale(1), IndexReg(0), Disp(0), GV(nullptr),
  54. GVOpFlags(0) {
  55. Base.Reg = 0;
  56. }
  57. void getFullAddress(SmallVectorImpl<MachineOperand> &MO) {
  58. assert(Scale == 1 || Scale == 2 || Scale == 4 || Scale == 8);
  59. if (BaseType == X86AddressMode::RegBase)
  60. MO.push_back(MachineOperand::CreateReg(Base.Reg, false, false, false,
  61. false, false, false, 0, false));
  62. else {
  63. assert(BaseType == X86AddressMode::FrameIndexBase);
  64. MO.push_back(MachineOperand::CreateFI(Base.FrameIndex));
  65. }
  66. MO.push_back(MachineOperand::CreateImm(Scale));
  67. MO.push_back(MachineOperand::CreateReg(IndexReg, false, false, false, false,
  68. false, false, 0, false));
  69. if (GV)
  70. MO.push_back(MachineOperand::CreateGA(GV, Disp, GVOpFlags));
  71. else
  72. MO.push_back(MachineOperand::CreateImm(Disp));
  73. MO.push_back(MachineOperand::CreateReg(0, false, false, false, false, false,
  74. false, 0, false));
  75. }
  76. };
  77. /// Compute the addressing mode from an machine instruction starting with the
  78. /// given operand.
  79. static inline X86AddressMode getAddressFromInstr(const MachineInstr *MI,
  80. unsigned Operand) {
  81. X86AddressMode AM;
  82. const MachineOperand &Op0 = MI->getOperand(Operand);
  83. if (Op0.isReg()) {
  84. AM.BaseType = X86AddressMode::RegBase;
  85. AM.Base.Reg = Op0.getReg();
  86. } else {
  87. AM.BaseType = X86AddressMode::FrameIndexBase;
  88. AM.Base.FrameIndex = Op0.getIndex();
  89. }
  90. const MachineOperand &Op1 = MI->getOperand(Operand + 1);
  91. AM.Scale = Op1.getImm();
  92. const MachineOperand &Op2 = MI->getOperand(Operand + 2);
  93. AM.IndexReg = Op2.getReg();
  94. const MachineOperand &Op3 = MI->getOperand(Operand + 3);
  95. if (Op3.isGlobal())
  96. AM.GV = Op3.getGlobal();
  97. else
  98. AM.Disp = Op3.getImm();
  99. return AM;
  100. }
  101. /// addDirectMem - This function is used to add a direct memory reference to the
  102. /// current instruction -- that is, a dereference of an address in a register,
  103. /// with no scale, index or displacement. An example is: DWORD PTR [EAX].
  104. ///
  105. static inline const MachineInstrBuilder &
  106. addDirectMem(const MachineInstrBuilder &MIB, unsigned Reg) {
  107. // Because memory references are always represented with five
  108. // values, this adds: Reg, 1, NoReg, 0, NoReg to the instruction.
  109. return MIB.addReg(Reg).addImm(1).addReg(0).addImm(0).addReg(0);
  110. }
  111. /// Replace the address used in the instruction with the direct memory
  112. /// reference.
  113. static inline void setDirectAddressInInstr(MachineInstr *MI, unsigned Operand,
  114. unsigned Reg) {
  115. // Direct memory address is in a form of: Reg/FI, 1 (Scale), NoReg, 0, NoReg.
  116. MI->getOperand(Operand).ChangeToRegister(Reg, /*isDef=*/false);
  117. MI->getOperand(Operand + 1).setImm(1);
  118. MI->getOperand(Operand + 2).setReg(0);
  119. MI->getOperand(Operand + 3).ChangeToImmediate(0);
  120. MI->getOperand(Operand + 4).setReg(0);
  121. }
  122. static inline const MachineInstrBuilder &
  123. addOffset(const MachineInstrBuilder &MIB, int Offset) {
  124. return MIB.addImm(1).addReg(0).addImm(Offset).addReg(0);
  125. }
  126. static inline const MachineInstrBuilder &
  127. addOffset(const MachineInstrBuilder &MIB, const MachineOperand& Offset) {
  128. return MIB.addImm(1).addReg(0).add(Offset).addReg(0);
  129. }
  130. /// addRegOffset - This function is used to add a memory reference of the form
  131. /// [Reg + Offset], i.e., one with no scale or index, but with a
  132. /// displacement. An example is: DWORD PTR [EAX + 4].
  133. ///
  134. static inline const MachineInstrBuilder &
  135. addRegOffset(const MachineInstrBuilder &MIB,
  136. unsigned Reg, bool isKill, int Offset) {
  137. return addOffset(MIB.addReg(Reg, getKillRegState(isKill)), Offset);
  138. }
  139. /// addRegReg - This function is used to add a memory reference of the form:
  140. /// [Reg + Reg].
  141. static inline const MachineInstrBuilder &addRegReg(const MachineInstrBuilder &MIB,
  142. unsigned Reg1, bool isKill1,
  143. unsigned Reg2, bool isKill2) {
  144. return MIB.addReg(Reg1, getKillRegState(isKill1)).addImm(1)
  145. .addReg(Reg2, getKillRegState(isKill2)).addImm(0).addReg(0);
  146. }
  147. static inline const MachineInstrBuilder &
  148. addFullAddress(const MachineInstrBuilder &MIB,
  149. const X86AddressMode &AM) {
  150. assert(AM.Scale == 1 || AM.Scale == 2 || AM.Scale == 4 || AM.Scale == 8);
  151. if (AM.BaseType == X86AddressMode::RegBase)
  152. MIB.addReg(AM.Base.Reg);
  153. else {
  154. assert(AM.BaseType == X86AddressMode::FrameIndexBase);
  155. MIB.addFrameIndex(AM.Base.FrameIndex);
  156. }
  157. MIB.addImm(AM.Scale).addReg(AM.IndexReg);
  158. if (AM.GV)
  159. MIB.addGlobalAddress(AM.GV, AM.Disp, AM.GVOpFlags);
  160. else
  161. MIB.addImm(AM.Disp);
  162. return MIB.addReg(0);
  163. }
  164. /// addFrameReference - This function is used to add a reference to the base of
  165. /// an abstract object on the stack frame of the current function. This
  166. /// reference has base register as the FrameIndex offset until it is resolved.
  167. /// This allows a constant offset to be specified as well...
  168. ///
  169. static inline const MachineInstrBuilder &
  170. addFrameReference(const MachineInstrBuilder &MIB, int FI, int Offset = 0) {
  171. MachineInstr *MI = MIB;
  172. MachineFunction &MF = *MI->getParent()->getParent();
  173. MachineFrameInfo &MFI = MF.getFrameInfo();
  174. const MCInstrDesc &MCID = MI->getDesc();
  175. auto Flags = MachineMemOperand::MONone;
  176. if (MCID.mayLoad())
  177. Flags |= MachineMemOperand::MOLoad;
  178. if (MCID.mayStore())
  179. Flags |= MachineMemOperand::MOStore;
  180. MachineMemOperand *MMO = MF.getMachineMemOperand(
  181. MachinePointerInfo::getFixedStack(MF, FI, Offset), Flags,
  182. MFI.getObjectSize(FI), MFI.getObjectAlign(FI));
  183. return addOffset(MIB.addFrameIndex(FI), Offset)
  184. .addMemOperand(MMO);
  185. }
  186. /// addConstantPoolReference - This function is used to add a reference to the
  187. /// base of a constant value spilled to the per-function constant pool. The
  188. /// reference uses the abstract ConstantPoolIndex which is retained until
  189. /// either machine code emission or assembly output. In PIC mode on x86-32,
  190. /// the GlobalBaseReg parameter can be used to make this a
  191. /// GlobalBaseReg-relative reference.
  192. ///
  193. static inline const MachineInstrBuilder &
  194. addConstantPoolReference(const MachineInstrBuilder &MIB, unsigned CPI,
  195. unsigned GlobalBaseReg, unsigned char OpFlags) {
  196. //FIXME: factor this
  197. return MIB.addReg(GlobalBaseReg).addImm(1).addReg(0)
  198. .addConstantPoolIndex(CPI, 0, OpFlags).addReg(0);
  199. }
  200. } // end namespace llvm
  201. #endif // LLVM_LIB_TARGET_X86_X86INSTRBUILDER_H