LLVM API Documentation

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
AArch64AsmPrinter.cpp
Go to the documentation of this file.
1 //===-- AArch64AsmPrinter.cpp - Print machine code to an AArch64 .s file --===//
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 a printer that converts from our internal representation
11 // of machine-dependent LLVM code to GAS-format AArch64 assembly language.
12 //
13 //===----------------------------------------------------------------------===//
14 
15 #define DEBUG_TYPE "asm-printer"
16 #include "AArch64AsmPrinter.h"
18 #include "llvm/DebugInfo.h"
19 #include "llvm/ADT/SmallString.h"
22 #include "llvm/MC/MCAsmInfo.h"
23 #include "llvm/MC/MCInst.h"
24 #include "llvm/MC/MCSymbol.h"
26 #include "llvm/Target/Mangler.h"
27 
28 using namespace llvm;
29 
30 /// Try to print a floating-point register as if it belonged to a specified
31 /// register-class. For example the inline asm operand modifier "b" requires its
32 /// argument to be printed as "bN".
34  const TargetRegisterInfo *TRI,
35  char RegType, raw_ostream &O) {
36  if (!MO.isReg())
37  return true;
38 
39  for (MCRegAliasIterator AR(MO.getReg(), TRI, true); AR.isValid(); ++AR) {
40  if (AArch64::FPR8RegClass.contains(*AR)) {
41  O << RegType << TRI->getEncodingValue(MO.getReg());
42  return false;
43  }
44  }
45 
46  // The register doesn't correspond to anything floating-point like.
47  return true;
48 }
49 
50 /// Implements the 'w' and 'x' inline asm operand modifiers, which print a GPR
51 /// with the obvious type and an immediate 0 as either wzr or xzr.
53  const TargetRegisterInfo *TRI,
54  const TargetRegisterClass &RegClass,
55  raw_ostream &O) {
56  char Prefix = &RegClass == &AArch64::GPR32RegClass ? 'w' : 'x';
57 
58  if (MO.isImm() && MO.getImm() == 0) {
59  O << Prefix << "zr";
60  return false;
61  } else if (MO.isReg()) {
62  if (MO.getReg() == AArch64::XSP || MO.getReg() == AArch64::WSP) {
63  O << (Prefix == 'x' ? "sp" : "wsp");
64  return false;
65  }
66 
67  for (MCRegAliasIterator AR(MO.getReg(), TRI, true); AR.isValid(); ++AR) {
68  if (RegClass.contains(*AR)) {
70  return false;
71  }
72  }
73  }
74 
75  return true;
76 }
77 
79  bool PrintImmediatePrefix,
80  StringRef Suffix, raw_ostream &O) {
82  StringRef Modifier;
83  switch (MO.getType()) {
84  default:
85  return true;
87  Name = getSymbol(MO.getGlobal())->getName();
88 
89  // Global variables may be accessed either via a GOT or in various fun and
90  // interesting TLS-model specific ways. Set the prefix modifier as
91  // appropriate here.
92  if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(MO.getGlobal())) {
94  if (GV->isThreadLocal()) {
95  switch (TM.getTLSModel(GV)) {
97  Modifier = "tlsdesc";
98  break;
100  Modifier = "dtprel";
101  break;
103  Modifier = "gottprel";
104  break;
105  case TLSModel::LocalExec:
106  Modifier = "tprel";
107  break;
108  }
109  } else if (Subtarget->GVIsIndirectSymbol(GV, RelocM)) {
110  Modifier = "got";
111  }
112  }
113  break;
116  break;
118  Name = MO.getSymbolName();
119  break;
121  Name = GetCPISymbol(MO.getIndex())->getName();
122  break;
123  }
124 
125  // Some instructions (notably ADRP) don't take the # prefix for
126  // immediates. Only print it if asked to.
127  if (PrintImmediatePrefix)
128  O << '#';
129 
130  // Only need the joining "_" if both the prefix and the suffix are
131  // non-null. This little block simply takes care of the four possibly
132  // combinations involved there.
133  if (Modifier == "" && Suffix == "")
134  O << Name;
135  else if (Modifier == "" && Suffix != "")
136  O << ":" << Suffix << ':' << Name;
137  else if (Modifier != "" && Suffix == "")
138  O << ":" << Modifier << ':' << Name;
139  else
140  O << ":" << Modifier << '_' << Suffix << ':' << Name;
141 
142  return false;
143 }
144 
146  unsigned AsmVariant,
147  const char *ExtraCode, raw_ostream &O) {
149 
150  if (!ExtraCode)
151  ExtraCode = "";
152 
153  switch(ExtraCode[0]) {
154  default:
155  if (!AsmPrinter::PrintAsmOperand(MI, OpNum, AsmVariant, ExtraCode, O))
156  return false;
157  break;
158  case 'w':
159  // Output 32-bit general register operand, constant zero as wzr, or stack
160  // pointer as wsp. Ignored when used with other operand types.
161  if (!printModifiedGPRAsmOperand(MI->getOperand(OpNum), TRI,
162  AArch64::GPR32RegClass, O))
163  return false;
164  break;
165  case 'x':
166  // Output 64-bit general register operand, constant zero as xzr, or stack
167  // pointer as sp. Ignored when used with other operand types.
168  if (!printModifiedGPRAsmOperand(MI->getOperand(OpNum), TRI,
169  AArch64::GPR64RegClass, O))
170  return false;
171  break;
172  case 'H':
173  // Output higher numbered of a 64-bit general register pair
174  case 'Q':
175  // Output least significant register of a 64-bit general register pair
176  case 'R':
177  // Output most significant register of a 64-bit general register pair
178 
179  // FIXME note: these three operand modifiers will require, to some extent,
180  // adding a paired GPR64 register class. Initial investigation suggests that
181  // assertions are hit unless it has a type and is made legal for that type
182  // in ISelLowering. After that step is made, the number of modifications
183  // needed explodes (operation legality, calling conventions, stores, reg
184  // copies ...).
185  llvm_unreachable("FIXME: Unimplemented register pairs");
186  case 'b':
187  case 'h':
188  case 's':
189  case 'd':
190  case 'q':
191  if (!printModifiedFPRAsmOperand(MI->getOperand(OpNum), TRI,
192  ExtraCode[0], O))
193  return false;
194  break;
195  case 'A':
196  // Output symbolic address with appropriate relocation modifier (also
197  // suitable for ADRP).
198  if (!printSymbolicAddress(MI->getOperand(OpNum), false, "", O))
199  return false;
200  break;
201  case 'L':
202  // Output bits 11:0 of symbolic address with appropriate :lo12: relocation
203  // modifier.
204  if (!printSymbolicAddress(MI->getOperand(OpNum), true, "lo12", O))
205  return false;
206  break;
207  case 'G':
208  // Output bits 23:12 of symbolic address with appropriate :hi12: relocation
209  // modifier (currently only for TLS local exec).
210  if (!printSymbolicAddress(MI->getOperand(OpNum), true, "hi12", O))
211  return false;
212  break;
213  case 'a':
214  return PrintAsmMemoryOperand(MI, OpNum, AsmVariant, ExtraCode, O);
215  }
216 
217  // There's actually no operand modifier, which leads to a slightly eclectic
218  // set of behaviour which we have to handle here.
219  const MachineOperand &MO = MI->getOperand(OpNum);
220  switch (MO.getType()) {
221  default:
222  llvm_unreachable("Unexpected operand for inline assembly");
224  // GCC prints the unmodified operand of a 'w' constraint as the vector
225  // register. Technically, we could allocate the argument as a VPR128, but
226  // that leads to extremely dodgy copies being generated to get the data
227  // there.
228  if (printModifiedFPRAsmOperand(MO, TRI, 'v', O))
230  break;
232  O << '#' << MO.getImm();
233  break;
235  assert(MO.getFPImm()->isExactlyValue(0.0) && "Only FP 0.0 expected");
236  O << "#0.0";
237  break;
242  return printSymbolicAddress(MO, false, "", O);
243  }
244 
245  return false;
246 }
247 
249  unsigned OpNum,
250  unsigned AsmVariant,
251  const char *ExtraCode,
252  raw_ostream &O) {
253  // Currently both the memory constraints (m and Q) behave the same and amount
254  // to the address as a single register. In future, we may allow "m" to provide
255  // both a base and an offset.
256  const MachineOperand &MO = MI->getOperand(OpNum);
257  assert(MO.isReg() && "unexpected inline assembly memory operand");
258  O << '[' << AArch64InstPrinter::getRegisterName(MO.getReg()) << ']';
259  return false;
260 }
261 
262 #include "AArch64GenMCPseudoLowering.inc"
263 
265  // Do any auto-generated pseudo lowerings.
266  if (emitPseudoExpansionLowering(OutStreamer, MI))
267  return;
268 
269  MCInst TmpInst;
270  LowerAArch64MachineInstrToMCInst(MI, TmpInst, *this);
271  OutStreamer.EmitInstruction(TmpInst);
272 }
273 
275  if (Subtarget->isTargetELF()) {
276  const TargetLoweringObjectFileELF &TLOFELF =
277  static_cast<const TargetLoweringObjectFileELF &>(getObjFileLowering());
278 
280 
281  // Output stubs for external and common global variables.
283  if (!Stubs.empty()) {
285  const DataLayout *TD = TM.getDataLayout();
286 
287  for (unsigned i = 0, e = Stubs.size(); i != e; ++i) {
288  OutStreamer.EmitLabel(Stubs[i].first);
289  OutStreamer.EmitSymbolValue(Stubs[i].second.getPointer(),
290  TD->getPointerSize(0));
291  }
292  Stubs.clear();
293  }
294  }
295 }
296 
299 }
300 
301 // Force static initialization.
304 }
305 
const GlobalValue * getGlobal() const
MCSymbol * getSymbol(const GlobalValue *GV) const
Definition: AsmPrinter.cpp:277
Reloc::Model getRelocationModel() const
const ConstantFP * getFPImm() const
The main container class for the LLVM Intermediate Representation.
Definition: Module.h:112
void LowerAArch64MachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI, AArch64AsmPrinter &AP)
unsigned getPointerSize(unsigned AS=0) const
Definition: DataLayout.h:261
const MachineFunction * MF
The current machine function.
Definition: AsmPrinter.h:81
bool GVIsIndirectSymbol(const GlobalValue *GV, Reloc::Model RelocM) const
virtual void EmitInstruction(const MCInst &Inst)=0
const char * getSymbolName() const
std::vector< std::pair< MCSymbol *, StubValueTy > > SymbolListTy
bool printSymbolicAddress(const MachineOperand &MO, bool PrintImmediatePrefix, StringRef Suffix, raw_ostream &O)
static bool printModifiedGPRAsmOperand(const MachineOperand &MO, const TargetRegisterInfo *TRI, const TargetRegisterClass &RegClass, raw_ostream &O)
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
#define llvm_unreachable(msg)
void LLVMInitializeAArch64AsmPrinter()
bool isReg() const
isReg - Tests if this is a MO_Register operand.
virtual bool runOnMachineFunction(MachineFunction &MF)
void SwitchSection(const MCSection *Section, const MCExpr *Subsection=0)
Definition: MCStreamer.h:284
MCStreamer & OutStreamer
Definition: AsmPrinter.h:78
void EmitInstruction(const MachineInstr *MI)
EmitInstruction - Targets should implement this to emit instructions.
int64_t getImm() const
Address of indexed Constant in Constant Pool.
MachineModuleInfo * MMI
MMI - This is a pointer to the current MachineModuleInfo.
Definition: AsmPrinter.h:84
SymbolListTy GetGVStubList() const
Accessor methods to return the set of stubs in sorted order.
virtual bool runOnMachineFunction(MachineFunction &MF)
Definition: AsmPrinter.h:169
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:267
virtual bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, unsigned AsmVariant, const char *ExtraCode, raw_ostream &OS)
TargetMachine & TM
Definition: AsmPrinter.h:62
bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNum, unsigned AsmVariant, const char *ExtraCode, raw_ostream &O)
static bool printModifiedFPRAsmOperand(const MachineOperand &MO, const TargetRegisterInfo *TRI, char RegType, raw_ostream &O)
Floating-point immediate operand.
bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNum, unsigned AsmVariant, const char *ExtraCode, raw_ostream &O)
virtual void EmitLabel(MCSymbol *Symbol)
Definition: MCStreamer.cpp:212
static const char * getRegisterName(unsigned RegNo)
MachineOperandType getType() const
std::string getName(ID id, ArrayRef< Type * > Tys=None)
Definition: Function.cpp:400
virtual const DataLayout * getDataLayout() const
MCSymbol * GetBlockAddressSymbol(const BlockAddress *BA) const
const TargetMachine & getTarget() const
virtual const TargetRegisterInfo * getRegisterInfo() const
Target TheAArch64Target
MCSymbol * GetCPISymbol(unsigned CPID) const
GetCPISymbol - Return the symbol for the specified constant pool entry.
TLSModel::Model getTLSModel(const GlobalValue *GV) const
bool isExactlyValue(const APFloat &V) const
Definition: Constants.cpp:650
unsigned getReg() const
getReg - Returns the register number.
const TargetLoweringObjectFile & getObjFileLowering() const
getObjFileLowering - Return information about object file lowering.
Definition: AsmPrinter.cpp:129
uint16_t getEncodingValue(unsigned RegNo) const
Returns the encoding for RegNo.
Address of a basic block.
void EmitEndOfAsmFile(Module &M)
void EmitSymbolValue(const MCSymbol *Sym, unsigned Size)
Definition: MCStreamer.cpp:145
const BlockAddress * getBlockAddress() const
const MCSection * getDataRelSection() const
static RegisterPass< NVPTXAllocaHoisting > X("alloca-hoisting","Hoisting alloca instructions in non-entry ""blocks to the entry block")
INITIALIZE_PASS(GlobalMerge,"global-merge","Global Merge", false, false) bool GlobalMerge const DataLayout * TD
Address of a global value.
Name of external global symbol.
bool contains(unsigned Reg) const