X86InstrBuilder.h revision dffb6e5aee9607d78732824f00bf0f4a8a6fba9b
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 24#ifndef X86INSTRBUILDER_H 25#define X86INSTRBUILDER_H 26 27#include "llvm/CodeGen/MachineFrameInfo.h" 28#include "llvm/CodeGen/MachineInstrBuilder.h" 29#include "llvm/CodeGen/PseudoSourceValue.h" 30 31namespace 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. 37struct 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 GlobalValue *GV; 52 unsigned GVOpFlags; 53 54 X86AddressMode() 55 : BaseType(RegBase), Scale(1), IndexReg(0), Disp(0), GV(0), GVOpFlags(0) { 56 Base.Reg = 0; 57 } 58}; 59 60/// addDirectMem - This function is used to add a direct memory reference to the 61/// current instruction -- that is, a dereference of an address in a register, 62/// with no scale, index or displacement. An example is: DWORD PTR [EAX]. 63/// 64static inline const MachineInstrBuilder & 65addDirectMem(const MachineInstrBuilder &MIB, unsigned Reg) { 66 // Because memory references are always represented with four 67 // values, this adds: Reg, [1, NoReg, 0] to the instruction. 68 return MIB.addReg(Reg).addImm(1).addReg(0).addImm(0); 69} 70 71static inline const MachineInstrBuilder & 72addLeaOffset(const MachineInstrBuilder &MIB, int Offset) { 73 return MIB.addImm(1).addReg(0).addImm(Offset); 74} 75 76static inline const MachineInstrBuilder & 77addOffset(const MachineInstrBuilder &MIB, int Offset) { 78 return addLeaOffset(MIB, Offset).addReg(0); 79} 80 81/// addRegOffset - This function is used to add a memory reference of the form 82/// [Reg + Offset], i.e., one with no scale or index, but with a 83/// displacement. An example is: DWORD PTR [EAX + 4]. 84/// 85static inline const MachineInstrBuilder & 86addRegOffset(const MachineInstrBuilder &MIB, 87 unsigned Reg, bool isKill, int Offset) { 88 return addOffset(MIB.addReg(Reg, getKillRegState(isKill)), Offset); 89} 90 91static inline const MachineInstrBuilder & 92addLeaRegOffset(const MachineInstrBuilder &MIB, 93 unsigned Reg, bool isKill, int Offset) { 94 return addLeaOffset(MIB.addReg(Reg, getKillRegState(isKill)), Offset); 95} 96 97/// addRegReg - This function is used to add a memory reference of the form: 98/// [Reg + Reg]. 99static inline const MachineInstrBuilder &addRegReg(const MachineInstrBuilder &MIB, 100 unsigned Reg1, bool isKill1, 101 unsigned Reg2, bool isKill2) { 102 return MIB.addReg(Reg1, getKillRegState(isKill1)).addImm(1) 103 .addReg(Reg2, getKillRegState(isKill2)).addImm(0); 104} 105 106static inline const MachineInstrBuilder & 107addLeaAddress(const MachineInstrBuilder &MIB, const X86AddressMode &AM) { 108 assert (AM.Scale == 1 || AM.Scale == 2 || AM.Scale == 4 || AM.Scale == 8); 109 110 if (AM.BaseType == X86AddressMode::RegBase) 111 MIB.addReg(AM.Base.Reg); 112 else if (AM.BaseType == X86AddressMode::FrameIndexBase) 113 MIB.addFrameIndex(AM.Base.FrameIndex); 114 else 115 assert (0); 116 MIB.addImm(AM.Scale).addReg(AM.IndexReg); 117 if (AM.GV) 118 return MIB.addGlobalAddress(AM.GV, AM.Disp, AM.GVOpFlags); 119 else 120 return MIB.addImm(AM.Disp); 121} 122 123static inline const MachineInstrBuilder & 124addFullAddress(const MachineInstrBuilder &MIB, 125 const X86AddressMode &AM) { 126 return addLeaAddress(MIB, AM).addReg(0); 127} 128 129/// addFrameReference - This function is used to add a reference to the base of 130/// an abstract object on the stack frame of the current function. This 131/// reference has base register as the FrameIndex offset until it is resolved. 132/// This allows a constant offset to be specified as well... 133/// 134static inline const MachineInstrBuilder & 135addFrameReference(const MachineInstrBuilder &MIB, int FI, int Offset = 0) { 136 MachineInstr *MI = MIB; 137 MachineFunction &MF = *MI->getParent()->getParent(); 138 MachineFrameInfo &MFI = *MF.getFrameInfo(); 139 const TargetInstrDesc &TID = MI->getDesc(); 140 unsigned Flags = 0; 141 if (TID.mayLoad()) 142 Flags |= MachineMemOperand::MOLoad; 143 if (TID.mayStore()) 144 Flags |= MachineMemOperand::MOStore; 145 MachineMemOperand MMO(PseudoSourceValue::getFixedStack(FI), 146 Flags, 147 MFI.getObjectOffset(FI) + Offset, 148 MFI.getObjectSize(FI), 149 MFI.getObjectAlignment(FI)); 150 return addOffset(MIB.addFrameIndex(FI), Offset) 151 .addMemOperand(MMO); 152} 153 154/// addConstantPoolReference - This function is used to add a reference to the 155/// base of a constant value spilled to the per-function constant pool. The 156/// reference uses the abstract ConstantPoolIndex which is retained until 157/// either machine code emission or assembly output. In PIC mode on x86-32, 158/// the GlobalBaseReg parameter can be used to make this a 159/// GlobalBaseReg-relative reference. 160/// 161static inline const MachineInstrBuilder & 162addConstantPoolReference(const MachineInstrBuilder &MIB, unsigned CPI, 163 unsigned GlobalBaseReg, unsigned char OpFlags) { 164 //FIXME: factor this 165 return MIB.addReg(GlobalBaseReg).addImm(1).addReg(0) 166 .addConstantPoolIndex(CPI, 0, OpFlags).addReg(0); 167} 168 169} // End llvm namespace 170 171#endif 172