LLVM  8.0.1
AArch64MCInstLower.cpp
Go to the documentation of this file.
1 //==-- AArch64MCInstLower.cpp - Convert AArch64 MachineInstr to an MCInst --==//
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 contains code to lower AArch64 MachineInstrs to their corresponding
11 // MCInst records.
12 //
13 //===----------------------------------------------------------------------===//
14 
15 #include "AArch64MCInstLower.h"
17 #include "Utils/AArch64BaseInfo.h"
22 #include "llvm/IR/Mangler.h"
23 #include "llvm/MC/MCContext.h"
24 #include "llvm/MC/MCExpr.h"
25 #include "llvm/MC/MCInst.h"
26 #include "llvm/Support/CodeGen.h"
30 using namespace llvm;
31 
33 
35  : Ctx(ctx), Printer(printer) {}
36 
37 MCSymbol *
39  const GlobalValue *GV = MO.getGlobal();
40  unsigned TargetFlags = MO.getTargetFlags();
41  const Triple &TheTriple = Printer.TM.getTargetTriple();
42  if (!TheTriple.isOSBinFormatCOFF())
43  return Printer.getSymbol(GV);
44 
45  assert(TheTriple.isOSWindows() &&
46  "Windows is the only supported COFF target");
47 
48  bool IsIndirect = (TargetFlags & (AArch64II::MO_DLLIMPORT | AArch64II::MO_COFFSTUB));
49  if (!IsIndirect)
50  return Printer.getSymbol(GV);
51 
53  if (TargetFlags & AArch64II::MO_DLLIMPORT)
54  Name = "__imp_";
55  else if (TargetFlags & AArch64II::MO_COFFSTUB)
56  Name = ".refptr.";
57  Printer.TM.getNameWithPrefix(Name, GV,
58  Printer.getObjFileLowering().getMangler());
59 
60  MCSymbol *MCSym = Ctx.getOrCreateSymbol(Name);
61 
62  if (TargetFlags & AArch64II::MO_COFFSTUB) {
63  MachineModuleInfoCOFF &MMICOFF =
66  MMICOFF.getGVStubEntry(MCSym);
67 
68  if (!StubSym.getPointer())
69  StubSym = MachineModuleInfoImpl::StubValueTy(Printer.getSymbol(GV), true);
70  }
71 
72  return MCSym;
73 }
74 
75 MCSymbol *
77  return Printer.GetExternalSymbolSymbol(MO.getSymbolName());
78 }
79 
81  MCSymbol *Sym) const {
82  // FIXME: We would like an efficient form for this, so we don't have to do a
83  // lot of extra uniquing.
85  if ((MO.getTargetFlags() & AArch64II::MO_GOT) != 0) {
88  else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) ==
91  else
92  llvm_unreachable("Unexpected target flags with MO_GOT on GV operand");
93  } else if ((MO.getTargetFlags() & AArch64II::MO_TLS) != 0) {
96  else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) ==
99  else
100  llvm_unreachable("Unexpected target flags with MO_TLS on GV operand");
101  } else {
103  RefKind = MCSymbolRefExpr::VK_PAGE;
104  else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) ==
106  RefKind = MCSymbolRefExpr::VK_PAGEOFF;
107  }
108  const MCExpr *Expr = MCSymbolRefExpr::create(Sym, RefKind, Ctx);
109  if (!MO.isJTI() && MO.getOffset())
111  Expr, MCConstantExpr::create(MO.getOffset(), Ctx), Ctx);
112  return MCOperand::createExpr(Expr);
113 }
114 
116  MCSymbol *Sym) const {
117  uint32_t RefFlags = 0;
118 
120  RefFlags |= AArch64MCExpr::VK_GOT;
121  else if (MO.getTargetFlags() & AArch64II::MO_TLS) {
123  if (MO.isGlobal()) {
124  const GlobalValue *GV = MO.getGlobal();
125  Model = Printer.TM.getTLSModel(GV);
126  if (!EnableAArch64ELFLocalDynamicTLSGeneration &&
127  Model == TLSModel::LocalDynamic)
128  Model = TLSModel::GeneralDynamic;
129 
130  } else {
131  assert(MO.isSymbol() &&
132  StringRef(MO.getSymbolName()) == "_TLS_MODULE_BASE_" &&
133  "unexpected external TLS symbol");
134  // The general dynamic access sequence is used to get the
135  // address of _TLS_MODULE_BASE_.
136  Model = TLSModel::GeneralDynamic;
137  }
138  switch (Model) {
140  RefFlags |= AArch64MCExpr::VK_GOTTPREL;
141  break;
142  case TLSModel::LocalExec:
143  RefFlags |= AArch64MCExpr::VK_TPREL;
144  break;
146  RefFlags |= AArch64MCExpr::VK_DTPREL;
147  break;
149  RefFlags |= AArch64MCExpr::VK_TLSDESC;
150  break;
151  }
152  } else {
153  // No modifier means this is a generic reference, classified as absolute for
154  // the cases where it matters (:abs_g0: etc).
155  RefFlags |= AArch64MCExpr::VK_ABS;
156  }
157 
159  RefFlags |= AArch64MCExpr::VK_PAGE;
160  else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) ==
162  RefFlags |= AArch64MCExpr::VK_PAGEOFF;
164  RefFlags |= AArch64MCExpr::VK_G3;
166  RefFlags |= AArch64MCExpr::VK_G2;
168  RefFlags |= AArch64MCExpr::VK_G1;
170  RefFlags |= AArch64MCExpr::VK_G0;
172  RefFlags |= AArch64MCExpr::VK_HI12;
173 
174  if (MO.getTargetFlags() & AArch64II::MO_NC)
175  RefFlags |= AArch64MCExpr::VK_NC;
176 
177  const MCExpr *Expr =
179  if (!MO.isJTI() && MO.getOffset())
181  Expr, MCConstantExpr::create(MO.getOffset(), Ctx), Ctx);
182 
184  RefKind = static_cast<AArch64MCExpr::VariantKind>(RefFlags);
185  Expr = AArch64MCExpr::create(Expr, RefKind, Ctx);
186 
187  return MCOperand::createExpr(Expr);
188 }
189 
191  MCSymbol *Sym) const {
192  uint32_t RefFlags = 0;
193 
194  if (MO.getTargetFlags() & AArch64II::MO_TLS) {
196  RefFlags |= AArch64MCExpr::VK_SECREL_LO12;
197  else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) ==
199  RefFlags |= AArch64MCExpr::VK_SECREL_HI12;
200 
201  } else if (MO.getTargetFlags() & AArch64II::MO_S) {
202  RefFlags |= AArch64MCExpr::VK_SABS;
203  } else {
204  RefFlags |= AArch64MCExpr::VK_ABS;
205  }
206 
208  RefFlags |= AArch64MCExpr::VK_G3;
210  RefFlags |= AArch64MCExpr::VK_G2;
212  RefFlags |= AArch64MCExpr::VK_G1;
214  RefFlags |= AArch64MCExpr::VK_G0;
215 
216  // FIXME: Currently we only set VK_NC for MO_G3/MO_G2/MO_G1/MO_G0. This is
217  // because setting VK_NC for others would mean setting their respective
218  // RefFlags correctly. We should do this in a separate patch.
219  if (MO.getTargetFlags() & AArch64II::MO_NC) {
220  auto MOFrag = (MO.getTargetFlags() & AArch64II::MO_FRAGMENT);
221  if (MOFrag == AArch64II::MO_G3 || MOFrag == AArch64II::MO_G2 ||
222  MOFrag == AArch64II::MO_G1 || MOFrag == AArch64II::MO_G0)
223  RefFlags |= AArch64MCExpr::VK_NC;
224  }
225 
226  const MCExpr *Expr =
228  if (!MO.isJTI() && MO.getOffset())
230  Expr, MCConstantExpr::create(MO.getOffset(), Ctx), Ctx);
231 
232  auto RefKind = static_cast<AArch64MCExpr::VariantKind>(RefFlags);
233  assert(RefKind != AArch64MCExpr::VK_INVALID &&
234  "Invalid relocation requested");
235  Expr = AArch64MCExpr::create(Expr, RefKind, Ctx);
236 
237  return MCOperand::createExpr(Expr);
238 }
239 
241  MCSymbol *Sym) const {
242  if (Printer.TM.getTargetTriple().isOSDarwin())
243  return lowerSymbolOperandDarwin(MO, Sym);
244  if (Printer.TM.getTargetTriple().isOSBinFormatCOFF())
245  return lowerSymbolOperandCOFF(MO, Sym);
246 
247  assert(Printer.TM.getTargetTriple().isOSBinFormatELF() && "Invalid target");
248  return lowerSymbolOperandELF(MO, Sym);
249 }
250 
252  MCOperand &MCOp) const {
253  switch (MO.getType()) {
254  default:
255  llvm_unreachable("unknown operand type");
257  // Ignore all implicit register operands.
258  if (MO.isImplicit())
259  return false;
260  MCOp = MCOperand::createReg(MO.getReg());
261  break;
263  // Regmasks are like implicit defs.
264  return false;
266  MCOp = MCOperand::createImm(MO.getImm());
267  break;
269  MCOp = MCOperand::createExpr(
271  break;
274  break;
277  break;
279  MCOp = LowerSymbolOperand(MO, MO.getMCSymbol());
280  break;
282  MCOp = LowerSymbolOperand(MO, Printer.GetJTISymbol(MO.getIndex()));
283  break;
285  MCOp = LowerSymbolOperand(MO, Printer.GetCPISymbol(MO.getIndex()));
286  break;
288  MCOp = LowerSymbolOperand(
289  MO, Printer.GetBlockAddressSymbol(MO.getBlockAddress()));
290  break;
291  }
292  return true;
293 }
294 
295 void AArch64MCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const {
296  OutMI.setOpcode(MI->getOpcode());
297 
298  for (const MachineOperand &MO : MI->operands()) {
299  MCOperand MCOp;
300  if (lowerOperand(MO, MCOp))
301  OutMI.addOperand(MCOp);
302  }
303 
304  switch (OutMI.getOpcode()) {
305  case AArch64::CATCHRET:
306  OutMI = MCInst();
307  OutMI.setOpcode(AArch64::RET);
308  OutMI.addOperand(MCOperand::createReg(AArch64::LR));
309  break;
310  case AArch64::CLEANUPRET:
311  OutMI = MCInst();
312  OutMI.setOpcode(AArch64::RET);
313  OutMI.addOperand(MCOperand::createReg(AArch64::LR));
314  break;
315  }
316 }
unsigned getTargetFlags() const
bool isOSDarwin() const
isOSDarwin - Is this a "Darwin" OS (OS X, iOS, or watchOS).
Definition: Triple.h:475
const TargetLoweringObjectFile & getObjFileLowering() const
Return information about object file lowering.
Definition: AsmPrinter.cpp:212
MO_G3 - A symbol operand with this flag (granule 3) represents the high 16-bits of a 64-bit address...
MachineBasicBlock * getMBB() const
MCSymbol * GetExternalSymbolSymbol(StringRef Sym) const
Return the MCSymbol for the specified ExternalSymbol.
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx)
Definition: MCExpr.h:323
This class represents lattice values for constants.
Definition: AllocatorList.h:24
MO_PAGE - A symbol operand with this flag represents the pc-relative offset of the 4K page containing...
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition: MCSymbol.h:42
static const AArch64MCExpr * create(const MCExpr *Expr, VariantKind Kind, MCContext &Ctx)
bool isOSBinFormatELF() const
Tests whether the OS uses the ELF binary format.
Definition: Triple.h:604
static MCOperand createExpr(const MCExpr *Val)
Definition: MCInst.h:137
unsigned getReg() const
getReg - Returns the register number.
Address of indexed Jump Table for switch.
MCOperand lowerSymbolOperandCOFF(const MachineOperand &MO, MCSymbol *Sym) const
MachineBasicBlock reference.
MO_G0 - A symbol operand with this flag (granule 0) represents the bits 0-15 of a 64-bit address...
iterator_range< mop_iterator > operands()
Definition: MachineInstr.h:459
print alias Alias Set Printer
Mask of preserved registers.
MO_G2 - A symbol operand with this flag (granule 2) represents the bits 32-47 of a 64-bit address...
CLEANUPRET - Represents a return from a cleanup block funclet.
Definition: ISDOpcodes.h:690
amdgpu Simplify well known AMD library false Value Value const Twine & Name
static MCOperand createReg(unsigned Reg)
Definition: MCInst.h:116
MachineModuleInfoCOFF - This is a MachineModuleInfoImpl implementation for COFF targets.
Base class for the full range of assembler expressions which are needed for parsing.
Definition: MCExpr.h:36
Name of external global symbol.
void getNameWithPrefix(SmallVectorImpl< char > &Name, const GlobalValue *GV, Mangler &Mang, bool MayAlwaysUsePrivate=false) const
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
Definition: MachineInstr.h:409
const char * getSymbolName() const
Context object for machine code objects.
Definition: MCContext.h:63
MCOperand LowerSymbolOperand(const MachineOperand &MO, MCSymbol *Sym) const
MO_GOT - This flag indicates that a symbol operand represents the address of the GOT entry for the sy...
TLSModel::Model getTLSModel(const GlobalValue *GV) const
Returns the TLS model which should be used for the given global variable.
static const MCBinaryExpr * createAdd(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Definition: MCExpr.h:461
MachineModuleInfo * MMI
This is a pointer to the current MachineModuleInfo.
Definition: AsmPrinter.h:100
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:161
MCSymbol * GetGlobalAddressSymbol(const MachineOperand &MO) const
bool isOSWindows() const
Tests whether the OS is Windows.
Definition: Triple.h:567
Address of a global value.
MO_G1 - A symbol operand with this flag (granule 1) represents the bits 16-31 of a 64-bit address...
PointerIntPair - This class implements a pair of a pointer and small integer.
bool isOSBinFormatCOFF() const
Tests whether the OS uses the COFF binary format.
Definition: Triple.h:609
const GlobalValue * getGlobal() const
TargetMachine & TM
Target machine description.
Definition: AsmPrinter.h:82
This class is intended to be used as a driving class for all asm writers.
Definition: AsmPrinter.h:79
Address of a basic block.
const Triple & getTargetTriple() const
Ty & getObjFileInfo()
Keep track of various per-function pieces of information for backends that would like to do so...
MO_HI12 - This flag indicates that a symbol operand represents the bits 13-24 of a 64-bit address...
virtual MCSymbol * GetCPISymbol(unsigned CPID) const
Return the symbol for the specified constant pool entry.
MO_TLS - Indicates that the operand being accessed is some kind of thread-local symbol.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Triple - Helper class for working with autoconf configuration names.
Definition: Triple.h:44
MCSymbol * GetExternalSymbolSymbol(const MachineOperand &MO) const
void setOpcode(unsigned Op)
Definition: MCInst.h:173
MCSymbol * GetBlockAddressSymbol(const BlockAddress *BA) const
Return the MCSymbol used to satisfy BlockAddress uses of the specified basic block.
bool isJTI() const
isJTI - Tests if this is a MO_JumpTableIndex operand.
bool isGlobal() const
isGlobal - Tests if this is a MO_GlobalAddress operand.
MCSymbol * getSymbol(const GlobalValue *GV) const
Definition: AsmPrinter.cpp:430
MachineOperand class - Representation of each machine instruction operand.
int64_t getImm() const
bool lowerOperand(const MachineOperand &MO, MCOperand &MCOp) const
MCSymbol reference (for debug/eh info)
MCOperand lowerSymbolOperandELF(const MachineOperand &MO, MCSymbol *Sym) const
StubValueTy & getGVStubEntry(MCSymbol *Sym)
AArch64MCInstLower(MCContext &ctx, AsmPrinter &printer)
void Lower(const MachineInstr *MI, MCInst &OutMI) const
MO_S - Indicates that the bits of the symbol operand represented by MO_G0 etc are signed...
CATCHRET - Represents a return from a catch block funclet.
Definition: ISDOpcodes.h:686
Representation of each machine instruction.
Definition: MachineInstr.h:64
MCOperand lowerSymbolOperandDarwin(const MachineOperand &MO, MCSymbol *Sym) const
MCSymbol * GetJTISymbol(unsigned JTID, bool isLinkerPrivate=false) const
Return the symbol for the specified jump table entry.
MCSymbol * getOrCreateSymbol(const Twine &Name)
Lookup the symbol inside with the specified Name.
Definition: MCContext.cpp:123
MO_COFFSTUB - On a symbol operand "FOO", this indicates that the reference is actually to the "...
MO_DLLIMPORT - On a symbol operand, this represents that the reference to the symbol is for an import...
int64_t getOffset() const
Return the offset from the symbol in this operand.
const BlockAddress * getBlockAddress() const
MCSymbol * getSymbol() const
Return the MCSymbol for this basic block.
MO_PAGEOFF - A symbol operand with this flag represents the offset of that symbol within a 4K page...
bool isSymbol() const
isSymbol - Tests if this is a MO_ExternalSymbol operand.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
MCSymbol * getMCSymbol() const
IRTranslator LLVM IR MI
void addOperand(const MCOperand &Op)
Definition: MCInst.h:186
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:49
MO_NC - Indicates whether the linker is expected to check the symbol reference for overflow...
Address of indexed Constant in Constant Pool.
unsigned getOpcode() const
Definition: MCInst.h:174
Instances of this class represent operands of the MCInst class.
Definition: MCInst.h:35
cl::opt< bool > EnableAArch64ELFLocalDynamicTLSGeneration
MachineOperandType getType() const
getType - Returns the MachineOperandType for this operand.
static MCOperand createImm(int64_t Val)
Definition: MCInst.h:123
static const MCConstantExpr * create(int64_t Value, MCContext &Ctx)
Definition: MCExpr.cpp:164
bool isImplicit() const