Add AArch64 as an experimental target.
[oota-llvm.git] / lib / Target / AArch64 / AArch64AsmPrinter.cpp
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"
17 #include "InstPrinter/AArch64InstPrinter.h"
18 #include "llvm/DebugInfo.h"
19 #include "llvm/ADT/SmallString.h"
20 #include "llvm/CodeGen/MachineConstantPool.h"
21 #include "llvm/CodeGen/MachineModuleInfoImpls.h"
22 #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
23 #include "llvm/MC/MCAsmInfo.h"
24 #include "llvm/MC/MCInst.h"
25 #include "llvm/MC/MCSymbol.h"
26 #include "llvm/Support/TargetRegistry.h"
27 #include "llvm/Target/Mangler.h"
28
29 using namespace llvm;
30
31 MachineLocation
32 AArch64AsmPrinter::getDebugValueLocation(const MachineInstr *MI) const {
33   // See emitFrameIndexDebugValue in InstrInfo for where this instruction is
34   // expected to be created.
35   assert(MI->getNumOperands() == 4 && MI->getOperand(0).isReg()
36          && MI->getOperand(1).isImm() && "unexpected custom DBG_VALUE");
37   return MachineLocation(MI->getOperand(0).getReg(), MI->getOperand(1).getImm());
38 }
39
40 /// Try to print a floating-point register as if it belonged to a specified
41 /// register-class. For example the inline asm operand modifier "b" requires its
42 /// argument to be printed as "bN".
43 static bool printModifiedFPRAsmOperand(const MachineOperand &MO,
44                                        const TargetRegisterInfo *TRI,
45                                        const TargetRegisterClass &RegClass,
46                                        raw_ostream &O) {
47   if (!MO.isReg())
48     return true;
49
50   for (MCRegAliasIterator AR(MO.getReg(), TRI, true); AR.isValid(); ++AR) {
51     if (RegClass.contains(*AR)) {
52       O << AArch64InstPrinter::getRegisterName(*AR);
53       return false;
54     }
55   }
56   return true;
57 }
58
59 /// Implements the 'w' and 'x' inline asm operand modifiers, which print a GPR
60 /// with the obvious type and an immediate 0 as either wzr or xzr.
61 static bool printModifiedGPRAsmOperand(const MachineOperand &MO,
62                                        const TargetRegisterInfo *TRI,
63                                        const TargetRegisterClass &RegClass,
64                                        raw_ostream &O) {
65   char Prefix = &RegClass == &AArch64::GPR32RegClass ? 'w' : 'x';
66
67   if (MO.isImm() && MO.getImm() == 0) {
68     O << Prefix << "zr";
69     return false;
70   } else if (MO.isReg()) {
71     if (MO.getReg() == AArch64::XSP || MO.getReg() == AArch64::WSP) {
72       O << (Prefix == 'x' ? "sp" : "wsp");
73       return false;
74     }
75
76     for (MCRegAliasIterator AR(MO.getReg(), TRI, true); AR.isValid(); ++AR) {
77       if (RegClass.contains(*AR)) {
78         O << AArch64InstPrinter::getRegisterName(*AR);
79         return false;
80       }
81     }
82   }
83
84   return true;
85 }
86
87 bool AArch64AsmPrinter::printSymbolicAddress(const MachineOperand &MO,
88                                              bool PrintImmediatePrefix,
89                                              StringRef Suffix, raw_ostream &O) {
90   StringRef Name;
91   StringRef Modifier;
92   switch (MO.getType()) {
93   default: llvm_unreachable("Unexpected operand for symbolic address constraint");
94   case MachineOperand::MO_GlobalAddress:
95     Name = Mang->getSymbol(MO.getGlobal())->getName();
96
97     // Global variables may be accessed either via a GOT or in various fun and
98     // interesting TLS-model specific ways. Set the prefix modifier as
99     // appropriate here.
100     if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(MO.getGlobal())) {
101       Reloc::Model RelocM = TM.getRelocationModel();
102       if (GV->isThreadLocal()) {
103         switch (TM.getTLSModel(GV)) {
104         case TLSModel::GeneralDynamic:
105           Modifier = "tlsdesc";
106           break;
107         case TLSModel::LocalDynamic:
108           Modifier = "dtprel";
109           break;
110         case TLSModel::InitialExec:
111           Modifier = "gottprel";
112           break;
113         case TLSModel::LocalExec:
114           Modifier = "tprel";
115           break;
116         }
117       } else if (Subtarget->GVIsIndirectSymbol(GV, RelocM)) {
118         Modifier = "got";
119       }
120     }
121     break;
122   case MachineOperand::MO_BlockAddress:
123     Name = GetBlockAddressSymbol(MO.getBlockAddress())->getName();
124     break;
125   case MachineOperand::MO_ExternalSymbol:
126     Name = MO.getSymbolName();
127     break;
128   case MachineOperand::MO_ConstantPoolIndex:
129     Name = GetCPISymbol(MO.getIndex())->getName();
130     break;
131   }
132
133   // Some instructions (notably ADRP) don't take the # prefix for
134   // immediates. Only print it if asked to.
135   if (PrintImmediatePrefix)
136     O << '#';
137
138   // Only need the joining "_" if both the prefix and the suffix are
139   // non-null. This little block simply takes care of the four possibly
140   // combinations involved there.
141   if (Modifier == "" && Suffix == "")
142     O << Name;
143   else if (Modifier == "" && Suffix != "")
144     O << ":" << Suffix << ':' << Name;
145   else if (Modifier != "" && Suffix == "")
146     O << ":" << Modifier << ':' << Name;
147   else
148     O << ":" << Modifier << '_' << Suffix << ':' << Name;
149
150   return false;
151 }
152
153 bool AArch64AsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNum,
154                                         unsigned AsmVariant,
155                                         const char *ExtraCode, raw_ostream &O) {
156   const TargetRegisterInfo *TRI = MF->getTarget().getRegisterInfo();
157   if (!ExtraCode || !ExtraCode[0]) {
158     // There's actually no operand modifier, which leads to a slightly eclectic
159     // set of behaviour which we have to handle here.
160     const MachineOperand &MO = MI->getOperand(OpNum);
161     switch (MO.getType()) {
162     default:
163       llvm_unreachable("Unexpected operand for inline assembly");
164     case MachineOperand::MO_Register:
165       // GCC prints the unmodified operand of a 'w' constraint as the vector
166       // register. Technically, we could allocate the argument as a VPR128, but
167       // that leads to extremely dodgy copies being generated to get the data
168       // there.
169       if (printModifiedFPRAsmOperand(MO, TRI, AArch64::VPR128RegClass, O))
170         O << AArch64InstPrinter::getRegisterName(MO.getReg());
171       break;
172     case MachineOperand::MO_Immediate:
173       O << '#' << MO.getImm();
174       break;
175     case MachineOperand::MO_FPImmediate:
176       assert(MO.getFPImm()->isExactlyValue(0.0) && "Only FP 0.0 expected");
177       O << "#0.0";
178       break;
179     case MachineOperand::MO_BlockAddress:
180     case MachineOperand::MO_ConstantPoolIndex:
181     case MachineOperand::MO_GlobalAddress:
182     case MachineOperand::MO_ExternalSymbol:
183       return printSymbolicAddress(MO, false, "", O);
184     }
185     return false;
186   }
187
188   // We have a real modifier to handle.
189   switch(ExtraCode[0]) {
190   default:
191     // See if this is a generic operand
192     return AsmPrinter::PrintAsmOperand(MI, OpNum, AsmVariant, ExtraCode, O);
193   case 'c': // Don't print "#" before an immediate operand.
194     if (!MI->getOperand(OpNum).isImm())
195       return true;
196     O << MI->getOperand(OpNum).getImm();
197     return false;
198   case 'w':
199     // Output 32-bit general register operand, constant zero as wzr, or stack
200     // pointer as wsp. Ignored when used with other operand types.
201     return printModifiedGPRAsmOperand(MI->getOperand(OpNum), TRI,
202                                       AArch64::GPR32RegClass, O);
203   case 'x':
204     // Output 64-bit general register operand, constant zero as xzr, or stack
205     // pointer as sp. Ignored when used with other operand types.
206     return printModifiedGPRAsmOperand(MI->getOperand(OpNum), TRI,
207                                       AArch64::GPR64RegClass, O);
208   case 'H':
209     // Output higher numbered of a 64-bit general register pair
210   case 'Q':
211     // Output least significant register of a 64-bit general register pair
212   case 'R':
213     // Output most significant register of a 64-bit general register pair
214
215     // FIXME note: these three operand modifiers will require, to some extent,
216     // adding a paired GPR64 register class. Initial investigation suggests that
217     // assertions are hit unless it has a type and is made legal for that type
218     // in ISelLowering. After that step is made, the number of modifications
219     // needed explodes (operation legality, calling conventions, stores, reg
220     // copies ...).
221     llvm_unreachable("FIXME: Unimplemented register pairs");
222   case 'b':
223     // Output 8-bit FP/SIMD scalar register operand, prefixed with b.
224     return printModifiedFPRAsmOperand(MI->getOperand(OpNum), TRI,
225                                       AArch64::FPR8RegClass, O);
226   case 'h':
227     // Output 16-bit FP/SIMD scalar register operand, prefixed with h.
228     return printModifiedFPRAsmOperand(MI->getOperand(OpNum), TRI,
229                                       AArch64::FPR16RegClass, O);
230   case 's':
231     // Output 32-bit FP/SIMD scalar register operand, prefixed with s.
232     return printModifiedFPRAsmOperand(MI->getOperand(OpNum), TRI,
233                                       AArch64::FPR32RegClass, O);
234   case 'd':
235     // Output 64-bit FP/SIMD scalar register operand, prefixed with d.
236     return printModifiedFPRAsmOperand(MI->getOperand(OpNum), TRI,
237                                       AArch64::FPR64RegClass, O);
238   case 'q':
239     // Output 128-bit FP/SIMD scalar register operand, prefixed with q.
240     return printModifiedFPRAsmOperand(MI->getOperand(OpNum), TRI,
241                                       AArch64::FPR128RegClass, O);
242   case 'A':
243     // Output symbolic address with appropriate relocation modifier (also
244     // suitable for ADRP).
245     return printSymbolicAddress(MI->getOperand(OpNum), false, "", O);
246   case 'L':
247     // Output bits 11:0 of symbolic address with appropriate :lo12: relocation
248     // modifier.
249     return printSymbolicAddress(MI->getOperand(OpNum), true, "lo12", O);
250   case 'G':
251     // Output bits 23:12 of symbolic address with appropriate :hi12: relocation
252     // modifier (currently only for TLS local exec).
253     return printSymbolicAddress(MI->getOperand(OpNum), true, "hi12", O);
254   }
255
256
257 }
258
259 bool AArch64AsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
260                                               unsigned OpNum,
261                                               unsigned AsmVariant,
262                                               const char *ExtraCode,
263                                               raw_ostream &O) {
264   // Currently both the memory constraints (m and Q) behave the same and amount
265   // to the address as a single register. In future, we may allow "m" to provide
266   // both a base and an offset.
267   const MachineOperand &MO = MI->getOperand(OpNum);
268   assert(MO.isReg() && "unexpected inline assembly memory operand");
269   O << '[' << AArch64InstPrinter::getRegisterName(MO.getReg()) << ']';
270   return false;
271 }
272
273 void AArch64AsmPrinter::PrintDebugValueComment(const MachineInstr *MI,
274                                                raw_ostream &OS) {
275   unsigned NOps = MI->getNumOperands();
276   assert(NOps==4);
277   OS << '\t' << MAI->getCommentString() << "DEBUG_VALUE: ";
278   // cast away const; DIetc do not take const operands for some reason.
279   DIVariable V(const_cast<MDNode *>(MI->getOperand(NOps-1).getMetadata()));
280   OS << V.getName();
281   OS << " <- ";
282   // Frame address.  Currently handles register +- offset only.
283   assert(MI->getOperand(0).isReg() && MI->getOperand(1).isImm());
284   OS << '[' << AArch64InstPrinter::getRegisterName(MI->getOperand(0).getReg());
285   OS << '+' << MI->getOperand(1).getImm();
286   OS << ']';
287   OS << "+" << MI->getOperand(NOps - 2).getImm();
288 }
289
290
291 #include "AArch64GenMCPseudoLowering.inc"
292
293 void AArch64AsmPrinter::EmitInstruction(const MachineInstr *MI) {
294   // Do any auto-generated pseudo lowerings.
295   if (emitPseudoExpansionLowering(OutStreamer, MI))
296     return;
297
298   switch (MI->getOpcode()) {
299   case AArch64::CONSTPOOL_ENTRY: {
300     unsigned LabelId = (unsigned)MI->getOperand(0).getImm();
301     unsigned CPIdx = (unsigned)MI->getOperand(1).getIndex();
302
303     OutStreamer.EmitLabel(GetCPISymbol(LabelId));
304
305     const MachineConstantPoolEntry &MCPE = MCP->getConstants()[CPIdx];
306     if (MCPE.isMachineConstantPoolEntry())
307       EmitMachineConstantPoolValue(MCPE.Val.MachineCPVal);
308     else
309       EmitGlobalConstant(MCPE.Val.ConstVal);
310
311     return;
312   }
313   case AArch64::DBG_VALUE: {
314     if (isVerbose() && OutStreamer.hasRawTextSupport()) {
315       SmallString<128> TmpStr;
316       raw_svector_ostream OS(TmpStr);
317       PrintDebugValueComment(MI, OS);
318       OutStreamer.EmitRawText(StringRef(OS.str()));
319     }
320     return;
321   }
322   }
323
324   MCInst TmpInst;
325   LowerAArch64MachineInstrToMCInst(MI, TmpInst, *this);
326   OutStreamer.EmitInstruction(TmpInst);
327 }
328
329 void AArch64AsmPrinter::EmitEndOfAsmFile(Module &M) {
330   if (Subtarget->isTargetELF()) {
331     const TargetLoweringObjectFileELF &TLOFELF =
332       static_cast<const TargetLoweringObjectFileELF &>(getObjFileLowering());
333
334     MachineModuleInfoELF &MMIELF = MMI->getObjFileInfo<MachineModuleInfoELF>();
335
336     // Output stubs for external and common global variables.
337     MachineModuleInfoELF::SymbolListTy Stubs = MMIELF.GetGVStubList();
338     if (!Stubs.empty()) {
339       OutStreamer.SwitchSection(TLOFELF.getDataRelSection());
340       const DataLayout *TD = TM.getDataLayout();
341
342       for (unsigned i = 0, e = Stubs.size(); i != e; ++i) {
343         OutStreamer.EmitLabel(Stubs[i].first);
344         OutStreamer.EmitSymbolValue(Stubs[i].second.getPointer(),
345                                     TD->getPointerSize(0), 0);
346       }
347       Stubs.clear();
348     }
349   }
350 }
351
352 bool AArch64AsmPrinter::runOnMachineFunction(MachineFunction &MF) {
353   MCP = MF.getConstantPool();
354   return AsmPrinter::runOnMachineFunction(MF);
355 }
356
357 // Force static initialization.
358 extern "C" void LLVMInitializeAArch64AsmPrinter() {
359     RegisterAsmPrinter<AArch64AsmPrinter> X(TheAArch64Target);
360 }
361