ARM backend contribution from Apple.
[oota-llvm.git] / lib / Target / ARM / ARMAsmPrinter.cpp
1 //===-- ARMAsmPrinter.cpp - ARM LLVM assembly writer ----------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file was developed by the "Instituto Nokia de Tecnologia" and
6 // is distributed under the University of Illinois Open Source
7 // License. See LICENSE.TXT for details.
8 //
9 //===----------------------------------------------------------------------===//
10 //
11 // This file contains a printer that converts from our internal representation
12 // of machine-dependent LLVM code to GAS-format ARM assembly language.
13 //
14 //===----------------------------------------------------------------------===//
15
16 #define DEBUG_TYPE "asm-printer"
17 #include "ARM.h"
18 #include "ARMTargetMachine.h"
19 #include "ARMAddressingModes.h"
20 #include "ARMConstantPoolValue.h"
21 #include "ARMMachineFunctionInfo.h"
22 #include "llvm/Constants.h"
23 #include "llvm/Module.h"
24 #include "llvm/CodeGen/AsmPrinter.h"
25 #include "llvm/CodeGen/DwarfWriter.h"
26 #include "llvm/CodeGen/MachineDebugInfo.h"
27 #include "llvm/CodeGen/MachineFunctionPass.h"
28 #include "llvm/CodeGen/MachineJumpTableInfo.h"
29 #include "llvm/Target/TargetAsmInfo.h"
30 #include "llvm/Target/TargetData.h"
31 #include "llvm/Target/TargetMachine.h"
32 #include "llvm/ADT/Statistic.h"
33 #include "llvm/ADT/StringExtras.h"
34 #include "llvm/Support/Compiler.h"
35 #include "llvm/Support/Mangler.h"
36 #include "llvm/Support/MathExtras.h"
37 #include <cctype>
38 #include <iostream>
39 #include <set>
40 using namespace llvm;
41
42 STATISTIC(EmittedInsts, "Number of machine instrs printed");
43
44 namespace {
45   struct VISIBILITY_HIDDEN ARMAsmPrinter : public AsmPrinter {
46     ARMAsmPrinter(std::ostream &O, TargetMachine &TM, const TargetAsmInfo *T)
47       : AsmPrinter(O, TM, T), DW(O, this, T), AFI(NULL), InCPMode(false) {
48       Subtarget = &TM.getSubtarget<ARMSubtarget>();
49     }
50
51     DwarfWriter DW;
52
53     /// Subtarget - Keep a pointer to the ARMSubtarget around so that we can
54     /// make the right decision when printing asm code for different targets.
55     const ARMSubtarget *Subtarget;
56
57     /// AFI - Keep a pointer to ARMFunctionInfo for the current
58     /// MachineFunction
59     ARMFunctionInfo *AFI;
60
61     /// We name each basic block in a Function with a unique number, so
62     /// that we can consistently refer to them later. This is cleared
63     /// at the beginning of each call to runOnMachineFunction().
64     ///
65     typedef std::map<const Value *, unsigned> ValueMapTy;
66     ValueMapTy NumberForBB;
67
68     /// Keeps the set of GlobalValues that require non-lazy-pointers for
69     /// indirect access.
70     std::set<std::string> GVNonLazyPtrs;
71
72     /// Keeps the set of external function GlobalAddresses that the asm
73     /// printer should generate stubs for.
74     std::set<std::string> FnStubs;
75
76     /// True if asm printer is printing a series of CONSTPOOL_ENTRY.
77     bool InCPMode;
78     
79     virtual const char *getPassName() const {
80       return "ARM Assembly Printer";
81     }
82
83     void printOperand(const MachineInstr *MI, int opNum,
84                       const char *Modifier = 0);
85     void printSOImmOperand(const MachineInstr *MI, int opNum);
86     void printSORegOperand(const MachineInstr *MI, int opNum);
87     void printAddrMode2Operand(const MachineInstr *MI, int OpNo);
88     void printAddrMode2OffsetOperand(const MachineInstr *MI, int OpNo);
89     void printAddrMode3Operand(const MachineInstr *MI, int OpNo);
90     void printAddrMode3OffsetOperand(const MachineInstr *MI, int OpNo);
91     void printAddrMode4Operand(const MachineInstr *MI, int OpNo,
92                                const char *Modifier = 0);
93     void printAddrMode5Operand(const MachineInstr *MI, int OpNo,
94                                const char *Modifier = 0);
95     void printAddrModePCOperand(const MachineInstr *MI, int OpNo,
96                                 const char *Modifier = 0);
97     void printThumbAddrModeRROperand(const MachineInstr *MI, int OpNo);
98     void printThumbAddrModeRI5Operand(const MachineInstr *MI, int OpNo,
99                                       unsigned Scale);
100     void printThumbAddrModeRI5_1Operand(const MachineInstr *MI, int OpNo);
101     void printThumbAddrModeRI5_2Operand(const MachineInstr *MI, int OpNo);
102     void printThumbAddrModeRI5_4Operand(const MachineInstr *MI, int OpNo);
103     void printThumbAddrModeSPOperand(const MachineInstr *MI, int OpNo);
104     void printCCOperand(const MachineInstr *MI, int opNum);
105     void printPCLabel(const MachineInstr *MI, int opNum);
106     void printRegisterList(const MachineInstr *MI, int opNum);
107     void printCPInstOperand(const MachineInstr *MI, int opNum,
108                             const char *Modifier);
109     void printJTBlockOperand(const MachineInstr *MI, int opNum);
110
111     virtual bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
112                                  unsigned AsmVariant, const char *ExtraCode);
113
114     bool printInstruction(const MachineInstr *MI);  // autogenerated.
115     void printMachineInstruction(const MachineInstr *MI);
116     bool runOnMachineFunction(MachineFunction &F);
117     bool doInitialization(Module &M);
118     bool doFinalization(Module &M);
119
120     virtual void EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) {
121       printDataDirective(MCPV->getType());
122
123       ARMConstantPoolValue *ACPV = (ARMConstantPoolValue*)MCPV;
124       std::string Name = Mang->getValueName(ACPV->getGV());
125       if (ACPV->isNonLazyPointer()) {
126         GVNonLazyPtrs.insert(Name);
127         O << TAI->getPrivateGlobalPrefix() << Name << "$non_lazy_ptr";
128       } else
129         O << Name;
130       if (ACPV->getPCAdjustment() != 0)
131         O << "-(" << TAI->getPrivateGlobalPrefix() << "PC"
132           << utostr(ACPV->getLabelId())
133           << "+" << (unsigned)ACPV->getPCAdjustment() << ")";
134       O << "\n";
135     }
136     
137     void getAnalysisUsage(AnalysisUsage &AU) const {
138       AU.setPreservesAll();
139       AU.addRequired<MachineDebugInfo>();
140     }
141   };
142 } // end of anonymous namespace
143
144 #include "ARMGenAsmWriter.inc"
145
146 /// createARMCodePrinterPass - Returns a pass that prints the ARM
147 /// assembly code for a MachineFunction to the given output stream,
148 /// using the given target machine description.  This should work
149 /// regardless of whether the function is in SSA form.
150 ///
151 FunctionPass *llvm::createARMCodePrinterPass(std::ostream &o,
152                                              ARMTargetMachine &tm) {
153   return new ARMAsmPrinter(o, tm, tm.getTargetAsmInfo());
154 }
155
156 /// runOnMachineFunction - This uses the printInstruction()
157 /// method to print assembly for each instruction.
158 ///
159 bool ARMAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
160   AFI = MF.getInfo<ARMFunctionInfo>();
161
162   if (Subtarget->isDarwin()) {
163     DW.SetDebugInfo(&getAnalysis<MachineDebugInfo>());
164   }
165
166   SetupMachineFunction(MF);
167   O << "\n";
168
169   // NOTE: we don't print out constant pools here, they are handled as
170   // instructions.
171
172   O << "\n";
173   // Print out labels for the function.
174   const Function *F = MF.getFunction();
175   switch (F->getLinkage()) {
176   default: assert(0 && "Unknown linkage type!");
177   case Function::InternalLinkage:
178     SwitchToTextSection("\t.text", F);
179     break;
180   case Function::ExternalLinkage:
181     SwitchToTextSection("\t.text", F);
182     O << "\t.globl\t" << CurrentFnName << "\n";
183     break;
184   case Function::WeakLinkage:
185   case Function::LinkOnceLinkage:
186     if (Subtarget->isDarwin()) {
187       SwitchToTextSection(
188                 ".section __TEXT,__textcoal_nt,coalesced,pure_instructions", F);
189       O << "\t.globl\t" << CurrentFnName << "\n";
190       O << "\t.weak_definition\t" << CurrentFnName << "\n";
191     } else {
192       O << TAI->getWeakRefDirective() << CurrentFnName << "\n";
193     }
194     break;
195   }
196
197   if (AFI->isThumbFunction()) {
198     EmitAlignment(1, F);
199     O << "\t.code\t16\n";
200     O << "\t.thumb_func\t" << CurrentFnName << "\n";
201     InCPMode = false;
202   } else
203     EmitAlignment(2, F);
204
205   O << CurrentFnName << ":\n";
206   if (Subtarget->isDarwin()) {
207     // Emit pre-function debug information.
208     DW.BeginFunction(&MF);
209   }
210
211   // Print out code for the function.
212   for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
213        I != E; ++I) {
214     // Print a label for the basic block.
215     if (I != MF.begin()) {
216       printBasicBlockLabel(I, true);
217       O << '\n';
218     }
219     for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
220          II != E; ++II) {
221       // Print the assembly for the instruction.
222       printMachineInstruction(II);
223     }
224   }
225
226   if (TAI->hasDotTypeDotSizeDirective())
227     O << "\t.size " << CurrentFnName << ", .-" << CurrentFnName << "\n";
228
229   if (Subtarget->isDarwin()) {
230     // Emit post-function debug information.
231     DW.EndFunction();
232   }
233
234   return false;
235 }
236
237 void ARMAsmPrinter::printOperand(const MachineInstr *MI, int opNum,
238                                  const char *Modifier) {
239   const MachineOperand &MO = MI->getOperand(opNum);
240   switch (MO.getType()) {
241   case MachineOperand::MO_Register:
242     if (MRegisterInfo::isPhysicalRegister(MO.getReg()))
243       O << TM.getRegisterInfo()->get(MO.getReg()).Name;
244     else
245       assert(0 && "not implemented");
246     break;
247   case MachineOperand::MO_Immediate: {
248     if (!Modifier || strcmp(Modifier, "no_hash") != 0)
249       O << "#";
250
251     O << (int)MO.getImmedValue();
252     break;
253   }
254   case MachineOperand::MO_MachineBasicBlock:
255     printBasicBlockLabel(MO.getMachineBasicBlock());
256     return;
257   case MachineOperand::MO_GlobalAddress: {
258     bool isCallOp = Modifier && !strcmp(Modifier, "call");
259     GlobalValue *GV = MO.getGlobal();
260     std::string Name = Mang->getValueName(GV);
261     bool isExt = (GV->isExternal() || GV->hasWeakLinkage() ||
262                   GV->hasLinkOnceLinkage());
263     if (isExt && isCallOp && Subtarget->isDarwin() &&
264         TM.getRelocationModel() != Reloc::Static) {
265       O << TAI->getPrivateGlobalPrefix() << Name << "$stub";
266       FnStubs.insert(Name);
267     } else
268       O << Name;
269
270     if (GV->hasExternalWeakLinkage())
271       ExtWeakSymbols.insert(GV);
272     break;
273   }
274   case MachineOperand::MO_ExternalSymbol: {
275     bool isCallOp = Modifier && !strcmp(Modifier, "call");
276     std::string Name(TAI->getGlobalPrefix());
277     Name += MO.getSymbolName();
278     if (isCallOp && Subtarget->isDarwin() &&
279         TM.getRelocationModel() != Reloc::Static) {
280       O << TAI->getPrivateGlobalPrefix() << Name << "$stub";
281       FnStubs.insert(Name);
282     } else
283       O << Name;
284     break;
285   }
286   case MachineOperand::MO_ConstantPoolIndex:
287     O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber()
288       << '_' << MO.getConstantPoolIndex();
289     break;
290   case MachineOperand::MO_JumpTableIndex:
291     O << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
292       << '_' << MO.getJumpTableIndex();
293     break;
294   default:
295     O << "<unknown operand type>"; abort (); break;
296   }
297 }
298
299 /// printSOImmOperand - SOImm is 4-bit rotate amount in bits 8-11 with 8-bit
300 /// immediate in bits 0-7.
301 void ARMAsmPrinter::printSOImmOperand(const MachineInstr *MI, int OpNum) {
302   const MachineOperand &MO = MI->getOperand(OpNum);
303   assert(MO.isImmediate() && (MO.getImmedValue() < (1 << 12)) &&
304          "Not a valid so_imm value!");
305   unsigned Imm = ARM_AM::getSOImmValImm(MO.getImmedValue());
306   unsigned Rot = ARM_AM::getSOImmValRot(MO.getImmedValue());
307   
308   // Print low-level immediate formation info, per
309   // A5.1.3: "Data-processing operands - Immediate".
310   if (Rot) {
311     O << "#" << Imm << ", " << Rot;
312     // Pretty printed version.
313     O << ' ' << TAI->getCommentString() << ' ' << (int)ARM_AM::rotr32(Imm, Rot);
314   } else {
315     O << "#" << Imm;
316   }
317 }
318
319 // so_reg is a 4-operand unit corresponding to register forms of the A5.1
320 // "Addressing Mode 1 - Data-processing operands" forms.  This includes:
321 //    REG 0   0    - e.g. R5
322 //    REG REG 0,SH_OPC     - e.g. R5, ROR R3
323 //    REG 0   IMM,SH_OPC  - e.g. R5, LSL #3
324 void ARMAsmPrinter::printSORegOperand(const MachineInstr *MI, int Op) {
325   const MachineOperand &MO1 = MI->getOperand(Op);
326   const MachineOperand &MO2 = MI->getOperand(Op+1);
327   const MachineOperand &MO3 = MI->getOperand(Op+2);
328
329   assert(MRegisterInfo::isPhysicalRegister(MO1.getReg()));
330   O << TM.getRegisterInfo()->get(MO1.getReg()).Name;
331
332   // Print the shift opc.
333   O << ", "
334     << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(MO3.getImmedValue()))
335     << " ";
336
337   if (MO2.getReg()) {
338     assert(MRegisterInfo::isPhysicalRegister(MO2.getReg()));
339     O << TM.getRegisterInfo()->get(MO2.getReg()).Name;
340     assert(ARM_AM::getSORegOffset(MO3.getImm()) == 0);
341   } else {
342     O << "#" << ARM_AM::getSORegOffset(MO3.getImm());
343   }
344 }
345
346 void ARMAsmPrinter::printAddrMode2Operand(const MachineInstr *MI, int Op) {
347   const MachineOperand &MO1 = MI->getOperand(Op);
348   const MachineOperand &MO2 = MI->getOperand(Op+1);
349   const MachineOperand &MO3 = MI->getOperand(Op+2);
350
351   if (!MO1.isRegister()) {   // FIXME: This is for CP entries, but isn't right.
352     printOperand(MI, Op);
353     return;
354   }
355
356   O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).Name;
357
358   if (!MO2.getReg()) {
359     if (ARM_AM::getAM2Offset(MO3.getImm()))  // Don't print +0.
360       O << ", #"
361         << (char)ARM_AM::getAM2Op(MO3.getImm())
362         << ARM_AM::getAM2Offset(MO3.getImm());
363     O << "]";
364     return;
365   }
366
367   O << ", "
368     << (char)ARM_AM::getAM2Op(MO3.getImm())
369     << TM.getRegisterInfo()->get(MO2.getReg()).Name;
370   
371   if (unsigned ShImm = ARM_AM::getAM2Offset(MO3.getImm()))
372     O << ", "
373       << ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO3.getImmedValue()))
374       << " #" << ShImm;
375   O << "]";
376 }
377
378 void ARMAsmPrinter::printAddrMode2OffsetOperand(const MachineInstr *MI, int Op){
379   const MachineOperand &MO1 = MI->getOperand(Op);
380   const MachineOperand &MO2 = MI->getOperand(Op+1);
381
382   if (!MO1.getReg()) {
383     if (ARM_AM::getAM2Offset(MO2.getImm()))  // Don't print +0.
384       O << "#"
385         << (char)ARM_AM::getAM2Op(MO2.getImm())
386         << ARM_AM::getAM2Offset(MO2.getImm());
387     return;
388   }
389
390   O << (char)ARM_AM::getAM2Op(MO2.getImm())
391     << TM.getRegisterInfo()->get(MO1.getReg()).Name;
392   
393   if (unsigned ShImm = ARM_AM::getAM2Offset(MO2.getImm()))
394     O << ", "
395       << ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO2.getImmedValue()))
396       << " #" << ShImm;
397 }
398
399 void ARMAsmPrinter::printAddrMode3Operand(const MachineInstr *MI, int Op) {
400   const MachineOperand &MO1 = MI->getOperand(Op);
401   const MachineOperand &MO2 = MI->getOperand(Op+1);
402   const MachineOperand &MO3 = MI->getOperand(Op+2);
403   
404   assert(MRegisterInfo::isPhysicalRegister(MO1.getReg()));
405   O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).Name;
406
407   if (MO2.getReg()) {
408     O << ", "
409       << (char)ARM_AM::getAM3Op(MO3.getImm())
410       << TM.getRegisterInfo()->get(MO2.getReg()).Name
411       << "]";
412     return;
413   }
414   
415   if (unsigned ImmOffs = ARM_AM::getAM3Offset(MO3.getImm()))
416     O << ", #"
417       << (char)ARM_AM::getAM3Op(MO3.getImm())
418       << ImmOffs;
419   O << "]";
420 }
421
422 void ARMAsmPrinter::printAddrMode3OffsetOperand(const MachineInstr *MI, int Op){
423   const MachineOperand &MO1 = MI->getOperand(Op);
424   const MachineOperand &MO2 = MI->getOperand(Op+1);
425
426   if (MO1.getReg()) {
427     O << (char)ARM_AM::getAM3Op(MO2.getImm())
428       << TM.getRegisterInfo()->get(MO1.getReg()).Name;
429     return;
430   }
431
432   unsigned ImmOffs = ARM_AM::getAM3Offset(MO2.getImm());
433   O << "#"
434   << (char)ARM_AM::getAM3Op(MO2.getImm())
435     << ImmOffs;
436 }
437   
438 void ARMAsmPrinter::printAddrMode4Operand(const MachineInstr *MI, int Op,
439                                           const char *Modifier) {
440   const MachineOperand &MO1 = MI->getOperand(Op);
441   const MachineOperand &MO2 = MI->getOperand(Op+1);
442   ARM_AM::AMSubMode Mode = ARM_AM::getAM4SubMode(MO2.getImm());
443   if (Modifier && strcmp(Modifier, "submode") == 0) {
444     if (MO1.getReg() == ARM::SP) {
445       bool isLDM = (MI->getOpcode() == ARM::LDM ||
446                     MI->getOpcode() == ARM::LDM_RET);
447       O << ARM_AM::getAMSubModeAltStr(Mode, isLDM);
448     } else
449       O << ARM_AM::getAMSubModeStr(Mode);
450   } else {
451     printOperand(MI, Op);
452     if (ARM_AM::getAM4WBFlag(MO2.getImm()))
453       O << "!";
454   }
455 }
456
457 void ARMAsmPrinter::printAddrMode5Operand(const MachineInstr *MI, int Op,
458                                           const char *Modifier) {
459   const MachineOperand &MO1 = MI->getOperand(Op);
460   const MachineOperand &MO2 = MI->getOperand(Op+1);
461
462   if (!MO1.isRegister()) {   // FIXME: This is for CP entries, but isn't right.
463     printOperand(MI, Op);
464     return;
465   }
466   
467   assert(MRegisterInfo::isPhysicalRegister(MO1.getReg()));
468
469   if (Modifier && strcmp(Modifier, "submode") == 0) {
470     ARM_AM::AMSubMode Mode = ARM_AM::getAM5SubMode(MO2.getImm());
471     if (MO1.getReg() == ARM::SP) {
472       bool isFLDM = (MI->getOpcode() == ARM::FLDMD ||
473                      MI->getOpcode() == ARM::FLDMS);
474       O << ARM_AM::getAMSubModeAltStr(Mode, isFLDM);
475     } else
476       O << ARM_AM::getAMSubModeStr(Mode);
477     return;
478   } else if (Modifier && strcmp(Modifier, "base") == 0) {
479     // Used for FSTM{D|S} and LSTM{D|S} operations.
480     O << TM.getRegisterInfo()->get(MO1.getReg()).Name;
481     if (ARM_AM::getAM5WBFlag(MO2.getImm()))
482       O << "!";
483     return;
484   }
485   
486   O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).Name;
487   
488   if (unsigned ImmOffs = ARM_AM::getAM5Offset(MO2.getImm())) {
489     O << ", #"
490       << (char)ARM_AM::getAM5Op(MO2.getImm())
491       << ImmOffs*4;
492   }
493   O << "]";
494 }
495
496 void ARMAsmPrinter::printAddrModePCOperand(const MachineInstr *MI, int Op,
497                                            const char *Modifier) {
498   if (Modifier && strcmp(Modifier, "label") == 0) {
499     printPCLabel(MI, Op+1);
500     return;
501   }
502
503   const MachineOperand &MO1 = MI->getOperand(Op);
504   assert(MRegisterInfo::isPhysicalRegister(MO1.getReg()));
505   O << "[pc, +" << TM.getRegisterInfo()->get(MO1.getReg()).Name << "]";
506 }
507
508 void
509 ARMAsmPrinter::printThumbAddrModeRROperand(const MachineInstr *MI, int Op) {
510   const MachineOperand &MO1 = MI->getOperand(Op);
511   const MachineOperand &MO2 = MI->getOperand(Op+1);
512   O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).Name;
513   O << ", " << TM.getRegisterInfo()->get(MO2.getReg()).Name << "]";
514 }
515
516 void
517 ARMAsmPrinter::printThumbAddrModeRI5Operand(const MachineInstr *MI, int Op,
518                                             unsigned Scale) {
519   const MachineOperand &MO1 = MI->getOperand(Op);
520   const MachineOperand &MO2 = MI->getOperand(Op+1);
521
522   if (!MO1.isRegister()) {   // FIXME: This is for CP entries, but isn't right.
523     printOperand(MI, Op);
524     return;
525   }
526
527   O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).Name;
528   if (unsigned ImmOffs = MO2.getImm()) {
529     O << ", #" << ImmOffs;
530     if (Scale > 1)
531       O << " * " << Scale;
532   }
533   O << "]";
534 }
535
536 void
537 ARMAsmPrinter::printThumbAddrModeRI5_1Operand(const MachineInstr *MI, int Op) {
538   printThumbAddrModeRI5Operand(MI, Op, 1);
539 }
540 void
541 ARMAsmPrinter::printThumbAddrModeRI5_2Operand(const MachineInstr *MI, int Op) {
542   printThumbAddrModeRI5Operand(MI, Op, 2);
543 }
544 void
545 ARMAsmPrinter::printThumbAddrModeRI5_4Operand(const MachineInstr *MI, int Op) {
546   printThumbAddrModeRI5Operand(MI, Op, 4);
547 }
548
549 void ARMAsmPrinter::printThumbAddrModeSPOperand(const MachineInstr *MI,int Op) {
550   const MachineOperand &MO1 = MI->getOperand(Op);
551   const MachineOperand &MO2 = MI->getOperand(Op+1);
552   O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).Name;
553   if (unsigned ImmOffs = MO2.getImm())
554     O << ", #" << ImmOffs << " * 4";
555   O << "]";
556 }
557
558 void ARMAsmPrinter::printCCOperand(const MachineInstr *MI, int opNum) {
559   int CC = (int)MI->getOperand(opNum).getImmedValue();
560   O << ARMCondCodeToString((ARMCC::CondCodes)CC);
561 }
562
563 void ARMAsmPrinter::printPCLabel(const MachineInstr *MI, int opNum) {
564   int Id = (int)MI->getOperand(opNum).getImmedValue();
565   O << TAI->getPrivateGlobalPrefix() << "PC" << Id;
566 }
567
568 void ARMAsmPrinter::printRegisterList(const MachineInstr *MI, int opNum) {
569   O << "{";
570   for (unsigned i = opNum, e = MI->getNumOperands(); i != e; ++i) {
571     printOperand(MI, i);
572     if (i != e-1) O << ", ";
573   }
574   O << "}";
575 }
576
577 void ARMAsmPrinter::printCPInstOperand(const MachineInstr *MI, int OpNo,
578                                        const char *Modifier) {
579   assert(Modifier && "This operand only works with a modifier!");
580   // There are two aspects to a CONSTANTPOOL_ENTRY operand, the label and the
581   // data itself.
582   if (!strcmp(Modifier, "label")) {
583     unsigned ID = MI->getOperand(OpNo).getImm();
584     O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber()
585       << '_' << ID << ":\n";
586   } else {
587     assert(!strcmp(Modifier, "cpentry") && "Unknown modifier for CPE");
588     unsigned CPI = MI->getOperand(OpNo).getConstantPoolIndex();
589
590     const MachineConstantPoolEntry &MCPE =  // Chasing pointers is fun?
591       MI->getParent()->getParent()->getConstantPool()->getConstants()[CPI];
592     
593     if (MCPE.isMachineConstantPoolEntry())
594       EmitMachineConstantPoolValue(MCPE.Val.MachineCPVal);
595     else
596       EmitGlobalConstant(MCPE.Val.ConstVal);
597   }
598 }
599
600 void ARMAsmPrinter::printJTBlockOperand(const MachineInstr *MI, int OpNo) {
601   const MachineOperand &MO1 = MI->getOperand(OpNo);
602   const MachineOperand &MO2 = MI->getOperand(OpNo+1); // Unique Id
603   unsigned JTI = MO1.getJumpTableIndex();
604   O << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
605     << '_' << JTI << '_' << MO2.getImmedValue() << ":\n";
606
607   const char *JTEntryDirective = TAI->getJumpTableDirective();
608   if (!JTEntryDirective)
609     JTEntryDirective = TAI->getData32bitsDirective();
610
611   const MachineFunction *MF = MI->getParent()->getParent();
612   MachineJumpTableInfo *MJTI = MF->getJumpTableInfo();
613   const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables();
614   const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs;
615   bool UseSet= TAI->getSetDirective() && TM.getRelocationModel() == Reloc::PIC_;
616   std::set<MachineBasicBlock*> JTSets;
617   for (unsigned i = 0, e = JTBBs.size(); i != e; ++i) {
618     MachineBasicBlock *MBB = JTBBs[i];
619     if (UseSet && JTSets.insert(MBB).second)
620       printSetLabel(JTI, MO2.getImmedValue(), MBB);
621
622     O << JTEntryDirective << ' ';
623     if (UseSet)
624       O << TAI->getPrivateGlobalPrefix() << getFunctionNumber()
625         << '_' << JTI << '_' << MO2.getImmedValue()
626         << "_set_" << MBB->getNumber();
627     else if (TM.getRelocationModel() == Reloc::PIC_) {
628       printBasicBlockLabel(MBB, false, false);
629       // If the arch uses custom Jump Table directives, don't calc relative to JT
630       if (!TAI->getJumpTableDirective()) 
631         O << '-' << TAI->getPrivateGlobalPrefix() << "JTI"
632           << getFunctionNumber() << '_' << JTI << '_' << MO2.getImmedValue();
633     } else
634       printBasicBlockLabel(MBB, false, false);
635     O << '\n';
636   }
637 }
638
639
640 bool ARMAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
641                                     unsigned AsmVariant, const char *ExtraCode){
642   // Does this asm operand have a single letter operand modifier?
643   if (ExtraCode && ExtraCode[0]) {
644     if (ExtraCode[1] != 0) return true; // Unknown modifier.
645     
646     switch (ExtraCode[0]) {
647     default: return true;  // Unknown modifier.
648     case 'Q':
649       if (TM.getTargetData()->isLittleEndian())
650         break;
651       // Fallthrough
652     case 'R':
653       if (TM.getTargetData()->isBigEndian())
654         break;
655       // Fallthrough
656     case 'H': // Write second word of DI / DF reference.  
657       // Verify that this operand has two consecutive registers.
658       if (!MI->getOperand(OpNo).isRegister() ||
659           OpNo+1 == MI->getNumOperands() ||
660           !MI->getOperand(OpNo+1).isRegister())
661         return true;
662       ++OpNo;   // Return the high-part.
663     }
664   }
665   
666   printOperand(MI, OpNo);
667   return false;
668 }
669
670 void ARMAsmPrinter::printMachineInstruction(const MachineInstr *MI) {
671   ++EmittedInsts;
672
673   if (MI->getOpcode() == ARM::CONSTPOOL_ENTRY) {
674     if (!InCPMode && AFI->isThumbFunction()) {
675       EmitAlignment(2);
676       InCPMode = true;
677     }
678   } else {
679     if (InCPMode && AFI->isThumbFunction()) {
680       EmitAlignment(1);
681       InCPMode = false;
682     }
683     O << "\t";
684   }
685
686   // Call the autogenerated instruction printer routines.
687   printInstruction(MI);
688 }
689
690 bool ARMAsmPrinter::doInitialization(Module &M) {
691   if (Subtarget->isDarwin()) {
692     // Emit initial debug information.
693     DW.BeginModule(&M);
694   }
695   
696   return AsmPrinter::doInitialization(M);
697 }
698
699 bool ARMAsmPrinter::doFinalization(Module &M) {
700   const TargetData *TD = TM.getTargetData();
701
702   for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
703        I != E; ++I) {
704     if (!I->hasInitializer())   // External global require no code
705       continue;
706
707     if (EmitSpecialLLVMGlobal(I))
708       continue;
709
710     std::string name = Mang->getValueName(I);
711     Constant *C = I->getInitializer();
712     unsigned Size = TD->getTypeSize(C->getType());
713     unsigned Align = TD->getPreferredAlignmentLog(I);
714
715     if (C->isNullValue() &&
716         !I->hasSection() &&
717         (I->hasInternalLinkage() || I->hasWeakLinkage() ||
718          I->hasLinkOnceLinkage() ||
719          (Subtarget->isDarwin() &&  I->hasExternalLinkage()))) {
720       if (Size == 0) Size = 1;   // .comm Foo, 0 is undefined, avoid it.
721       if (I->hasExternalLinkage()) {
722           O << "\t.globl\t" << name << "\n";
723           O << "\t.zerofill __DATA__, __common, " << name << ", "
724             << Size << ", " << Align;
725       } else {
726         SwitchToDataSection(TAI->getDataSection(), I);
727         if (TAI->getLCOMMDirective() != NULL) {
728           if (I->hasInternalLinkage()) {
729             O << TAI->getLCOMMDirective() << name << "," << Size;
730             if (Subtarget->isDarwin())
731               O << "," << Align;
732           } else
733             O << TAI->getCOMMDirective()  << name << "," << Size;
734         } else {
735           if (I->hasInternalLinkage())
736             O << "\t.local\t" << name << "\n";
737           O << TAI->getCOMMDirective()  << name << "," << Size;
738           if (TAI->getCOMMDirectiveTakesAlignment())
739             O << "," << (TAI->getAlignmentIsInBytes() ? (1 << Align) : Align);
740         }
741       }
742       O << "\t\t" << TAI->getCommentString() << " " << I->getName() << "\n";
743       continue;
744     } else {
745       switch (I->getLinkage()) {
746       default:
747         assert(0 && "Unknown linkage type!");
748         break;
749       case GlobalValue::LinkOnceLinkage:
750       case GlobalValue::WeakLinkage:
751         if (Subtarget->isDarwin()) {
752           O << "\t.globl " << name << "\n"
753             << "\t.weak_definition " << name << "\n";
754           SwitchToDataSection("\t.section __DATA,__const_coal,coalesced", I);
755         } else {
756           O << "\t.section\t.llvm.linkonce.d." << name << ",\"aw\",@progbits\n"
757             << "\t.weak " << name << "\n";
758         }
759         break;
760       case GlobalValue::ExternalLinkage:
761         O << "\t.globl " << name << "\n";
762         // FALL THROUGH
763       case GlobalValue::InternalLinkage:
764         if (I->isConstant()) {
765           const ConstantArray *CVA = dyn_cast<ConstantArray>(C);
766           if (TAI->getCStringSection() && CVA && CVA->isCString()) {
767             SwitchToDataSection(TAI->getCStringSection(), I);
768             break;
769           }
770         }
771
772         if (I->hasSection() &&
773             (I->getSection() == ".ctors" ||
774              I->getSection() == ".dtors")) {
775           assert(!Subtarget->isDarwin());
776           std::string SectionName = ".section " + I->getSection();
777           SectionName += ",\"aw\",@progbits";
778           SwitchToDataSection(SectionName.c_str());
779         } else {
780           SwitchToDataSection(TAI->getDataSection(), I);
781         }
782
783         break;
784       }
785     }
786
787     EmitAlignment(Align, I);
788     if (TAI->hasDotTypeDotSizeDirective()) {
789       O << "\t.type " << name << ", %object\n";
790       O << "\t.size " << name << ", " << Size << "\n";
791     }
792     O << name << ":\n";
793     
794     // If the initializer is a extern weak symbol, remember to emit the weak
795     // reference!
796     if (const GlobalValue *GV = dyn_cast<GlobalValue>(C))
797       if (GV->hasExternalWeakLinkage())
798       ExtWeakSymbols.insert(GV);
799
800     EmitGlobalConstant(C);
801     O << '\n';
802   }
803
804   if (Subtarget->isDarwin()) {
805     // Output stubs for dynamically-linked functions
806     unsigned j = 1;
807     for (std::set<std::string>::iterator i = FnStubs.begin(), e = FnStubs.end();
808          i != e; ++i, ++j) {
809       if (TM.getRelocationModel() == Reloc::PIC_)
810         SwitchToTextSection(".section __TEXT,__picsymbolstub4,symbol_stubs,"
811                             "none,16", 0);
812       else
813         SwitchToTextSection(".section __TEXT,__symbol_stub4,symbol_stubs,"
814                             "none,12", 0);
815
816       EmitAlignment(2);
817       O << "\t.code\t32\n";
818
819       O << "L" << *i << "$stub:\n";
820       O << "\t.indirect_symbol " << *i << "\n";
821       O << "\tldr ip, L" << *i << "$slp\n";
822       if (TM.getRelocationModel() == Reloc::PIC_) {
823         O << "L" << *i << "$scv:\n";
824         O << "\tadd ip, pc, ip\n";
825       }
826       O << "\tldr pc, [ip, #0]\n";
827       O << "L" << *i << "$slp:\n";
828       if (TM.getRelocationModel() == Reloc::PIC_)
829         O << "\t.long\tL" << *i << "$lazy_ptr-(L" << *i << "$scv+8)\n";
830       else
831         O << "\t.long\tL" << *i << "$lazy_ptr\n";
832       SwitchToDataSection(".lazy_symbol_pointer", 0);
833       O << "L" << *i << "$lazy_ptr:\n";
834       O << "\t.indirect_symbol " << *i << "\n";
835       O << "\t.long\tdyld_stub_binding_helper\n";
836     }
837     O << "\n";
838
839     // Output non-lazy-pointers for external and common global variables.
840     if (GVNonLazyPtrs.begin() != GVNonLazyPtrs.end())
841       SwitchToDataSection(".non_lazy_symbol_pointer", 0);
842     for (std::set<std::string>::iterator i = GVNonLazyPtrs.begin(),
843            e = GVNonLazyPtrs.end(); i != e; ++i) {
844       O << "L" << *i << "$non_lazy_ptr:\n";
845       O << "\t.indirect_symbol " << *i << "\n";
846       O << "\t.long\t0\n";
847     }
848
849     // Emit initial debug information.
850     DW.EndModule();
851
852     // Funny Darwin hack: This flag tells the linker that no global symbols
853     // contain code that falls through to other global symbols (e.g. the obvious
854     // implementation of multiple entry points).  If this doesn't occur, the
855     // linker can safely perform dead code stripping.  Since LLVM never
856     // generates code that does this, it is always safe to set.
857     O << "\t.subsections_via_symbols\n";
858   }
859
860   AsmPrinter::doFinalization(M);
861   return false; // success
862 }