Add support for ARM's Advanced SIMD (NEON) instruction set.
[oota-llvm.git] / lib / Target / ARM / AsmPrinter / ARMAsmPrinter.cpp
1 //===-- ARMAsmPrinter.cpp - ARM LLVM assembly writer ----------------------===//
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 ARM assembly language.
12 //
13 //===----------------------------------------------------------------------===//
14
15 #define DEBUG_TYPE "asm-printer"
16 #include "ARM.h"
17 #include "ARMBuildAttrs.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/MachineModuleInfo.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/Target/TargetOptions.h"
33 #include "llvm/ADT/Statistic.h"
34 #include "llvm/ADT/StringExtras.h"
35 #include "llvm/ADT/StringSet.h"
36 #include "llvm/Support/Compiler.h"
37 #include "llvm/Support/Mangler.h"
38 #include "llvm/Support/MathExtras.h"
39 #include "llvm/Support/raw_ostream.h"
40 #include <cctype>
41 using namespace llvm;
42
43 STATISTIC(EmittedInsts, "Number of machine instrs printed");
44
45 namespace {
46   class VISIBILITY_HIDDEN ARMAsmPrinter : public AsmPrinter {
47     DwarfWriter *DW;
48
49     /// Subtarget - Keep a pointer to the ARMSubtarget around so that we can
50     /// make the right decision when printing asm code for different targets.
51     const ARMSubtarget *Subtarget;
52
53     /// AFI - Keep a pointer to ARMFunctionInfo for the current
54     /// MachineFunction.
55     ARMFunctionInfo *AFI;
56
57     /// MCP - Keep a pointer to constantpool entries of the current
58     /// MachineFunction.
59     const MachineConstantPool *MCP;
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     /// GVNonLazyPtrs - Keeps the set of GlobalValues that require
69     /// non-lazy-pointers for indirect access.
70     StringSet<> GVNonLazyPtrs;
71
72     /// HiddenGVNonLazyPtrs - Keeps the set of GlobalValues with hidden
73     /// visibility that require non-lazy-pointers for indirect access.
74     StringSet<> HiddenGVNonLazyPtrs;
75
76     /// FnStubs - Keeps the set of external function GlobalAddresses that the
77     /// asm printer should generate stubs for.
78     StringSet<> FnStubs;
79
80     /// True if asm printer is printing a series of CONSTPOOL_ENTRY.
81     bool InCPMode;
82   public:
83     explicit ARMAsmPrinter(raw_ostream &O, TargetMachine &TM,
84                            const TargetAsmInfo *T, CodeGenOpt::Level OL,
85                            bool V)
86       : AsmPrinter(O, TM, T, OL, V), DW(0), AFI(NULL), MCP(NULL),
87         InCPMode(false) {
88       Subtarget = &TM.getSubtarget<ARMSubtarget>();
89     }
90
91     virtual const char *getPassName() const {
92       return "ARM Assembly Printer";
93     }
94
95     void printOperand(const MachineInstr *MI, int opNum,
96                       const char *Modifier = 0);
97     void printSOImmOperand(const MachineInstr *MI, int opNum);
98     void printSOImm2PartOperand(const MachineInstr *MI, int opNum);
99     void printSOOperand(const MachineInstr *MI, int OpNum);
100     void printSORegOperand(const MachineInstr *MI, int opNum);
101     void printAddrMode2Operand(const MachineInstr *MI, int OpNo);
102     void printAddrMode2OffsetOperand(const MachineInstr *MI, int OpNo);
103     void printAddrMode3Operand(const MachineInstr *MI, int OpNo);
104     void printAddrMode3OffsetOperand(const MachineInstr *MI, int OpNo);
105     void printAddrMode4Operand(const MachineInstr *MI, int OpNo,
106                                const char *Modifier = 0);
107     void printAddrMode5Operand(const MachineInstr *MI, int OpNo,
108                                const char *Modifier = 0);
109     void printAddrModePCOperand(const MachineInstr *MI, int OpNo,
110                                 const char *Modifier = 0);
111     void printThumbAddrModeRROperand(const MachineInstr *MI, int OpNo);
112     void printThumbAddrModeRI5Operand(const MachineInstr *MI, int OpNo,
113                                       unsigned Scale);
114     void printThumbAddrModeS1Operand(const MachineInstr *MI, int OpNo);
115     void printThumbAddrModeS2Operand(const MachineInstr *MI, int OpNo);
116     void printThumbAddrModeS4Operand(const MachineInstr *MI, int OpNo);
117     void printThumbAddrModeSPOperand(const MachineInstr *MI, int OpNo);
118     void printPredicateOperand(const MachineInstr *MI, int opNum);
119     void printSBitModifierOperand(const MachineInstr *MI, int opNum);
120     void printPCLabel(const MachineInstr *MI, int opNum);
121     void printRegisterList(const MachineInstr *MI, int opNum);
122     void printCPInstOperand(const MachineInstr *MI, int opNum,
123                             const char *Modifier);
124     void printJTBlockOperand(const MachineInstr *MI, int opNum);
125
126     virtual bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
127                                  unsigned AsmVariant, const char *ExtraCode);
128     virtual bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
129                                        unsigned AsmVariant,
130                                        const char *ExtraCode);
131
132     void printModuleLevelGV(const GlobalVariable* GVar);
133     bool printInstruction(const MachineInstr *MI);  // autogenerated.
134     void printMachineInstruction(const MachineInstr *MI);
135     bool runOnMachineFunction(MachineFunction &F);
136     bool doInitialization(Module &M);
137     bool doFinalization(Module &M);
138
139     /// EmitMachineConstantPoolValue - Print a machine constantpool value to
140     /// the .s file.
141     virtual void EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) {
142       printDataDirective(MCPV->getType());
143
144       ARMConstantPoolValue *ACPV = static_cast<ARMConstantPoolValue*>(MCPV);
145       GlobalValue *GV = ACPV->getGV();
146       std::string Name = GV ? Mang->getValueName(GV) : TAI->getGlobalPrefix();
147       if (!GV)
148         Name += ACPV->getSymbol();
149       if (ACPV->isNonLazyPointer()) {
150         if (GV->hasHiddenVisibility())
151           HiddenGVNonLazyPtrs.insert(Name);
152         else
153           GVNonLazyPtrs.insert(Name);
154         printSuffixedName(Name, "$non_lazy_ptr");
155       } else if (ACPV->isStub()) {
156         FnStubs.insert(Name);
157         printSuffixedName(Name, "$stub");
158       } else
159         O << Name;
160       if (ACPV->hasModifier()) O << "(" << ACPV->getModifier() << ")";
161       if (ACPV->getPCAdjustment() != 0) {
162         O << "-(" << TAI->getPrivateGlobalPrefix() << "PC"
163           << utostr(ACPV->getLabelId())
164           << "+" << (unsigned)ACPV->getPCAdjustment();
165          if (ACPV->mustAddCurrentAddress())
166            O << "-.";
167          O << ")";
168       }
169       O << "\n";
170
171       // If the constant pool value is a extern weak symbol, remember to emit
172       // the weak reference.
173       if (GV && GV->hasExternalWeakLinkage())
174         ExtWeakSymbols.insert(GV);
175     }
176     
177     void getAnalysisUsage(AnalysisUsage &AU) const {
178       AsmPrinter::getAnalysisUsage(AU);
179       AU.setPreservesAll();
180       AU.addRequired<MachineModuleInfo>();
181       AU.addRequired<DwarfWriter>();
182     }
183   };
184 } // end of anonymous namespace
185
186 #include "ARMGenAsmWriter.inc"
187
188 /// runOnMachineFunction - This uses the printInstruction()
189 /// method to print assembly for each instruction.
190 ///
191 bool ARMAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
192   this->MF = &MF;
193
194   AFI = MF.getInfo<ARMFunctionInfo>();
195   MCP = MF.getConstantPool();
196
197   SetupMachineFunction(MF);
198   O << "\n";
199
200   // NOTE: we don't print out constant pools here, they are handled as
201   // instructions.
202
203   O << "\n";
204   // Print out labels for the function.
205   const Function *F = MF.getFunction();
206   switch (F->getLinkage()) {
207   default: assert(0 && "Unknown linkage type!");
208   case Function::PrivateLinkage:
209   case Function::InternalLinkage:
210     SwitchToTextSection("\t.text", F);
211     break;
212   case Function::ExternalLinkage:
213     SwitchToTextSection("\t.text", F);
214     O << "\t.globl\t" << CurrentFnName << "\n";
215     break;
216   case Function::WeakAnyLinkage:
217   case Function::WeakODRLinkage:
218   case Function::LinkOnceAnyLinkage:
219   case Function::LinkOnceODRLinkage:
220     if (Subtarget->isTargetDarwin()) {
221       SwitchToTextSection(
222                 ".section __TEXT,__textcoal_nt,coalesced,pure_instructions", F);
223       O << "\t.globl\t" << CurrentFnName << "\n";
224       O << "\t.weak_definition\t" << CurrentFnName << "\n";
225     } else {
226       O << TAI->getWeakRefDirective() << CurrentFnName << "\n";
227     }
228     break;
229   }
230
231   printVisibility(CurrentFnName, F->getVisibility());
232
233   if (AFI->isThumbFunction()) {
234     EmitAlignment(1, F, AFI->getAlign());
235     O << "\t.code\t16\n";
236     O << "\t.thumb_func";
237     if (Subtarget->isTargetDarwin())
238       O << "\t" << CurrentFnName;
239     O << "\n";
240     InCPMode = false;
241   } else
242     EmitAlignment(2, F);
243
244   O << CurrentFnName << ":\n";
245   // Emit pre-function debug information.
246   DW->BeginFunction(&MF);
247
248   if (Subtarget->isTargetDarwin()) {
249     // If the function is empty, then we need to emit *something*. Otherwise,
250     // the function's label might be associated with something that it wasn't
251     // meant to be associated with. We emit a noop in this situation.
252     MachineFunction::iterator I = MF.begin();
253
254     if (++I == MF.end() && MF.front().empty())
255       O << "\tnop\n";
256   }
257
258   // Print out code for the function.
259   for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
260        I != E; ++I) {
261     // Print a label for the basic block.
262     if (I != MF.begin()) {
263       printBasicBlockLabel(I, true, true, VerboseAsm);
264       O << '\n';
265     }
266     for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
267          II != E; ++II) {
268       // Print the assembly for the instruction.
269       printMachineInstruction(II);
270     }
271   }
272
273   if (TAI->hasDotTypeDotSizeDirective())
274     O << "\t.size " << CurrentFnName << ", .-" << CurrentFnName << "\n";
275
276   // Emit post-function debug information.
277   DW->EndFunction(&MF);
278
279   O.flush();
280
281   return false;
282 }
283
284 void ARMAsmPrinter::printOperand(const MachineInstr *MI, int opNum,
285                                  const char *Modifier) {
286   const MachineOperand &MO = MI->getOperand(opNum);
287   switch (MO.getType()) {
288   case MachineOperand::MO_Register: {
289     unsigned Reg = MO.getReg();
290     if (TargetRegisterInfo::isPhysicalRegister(Reg)) {
291       if (Modifier && strcmp(Modifier, "dregpair") == 0) {
292         unsigned DRegLo = TRI->getSubReg(Reg, 5); // arm_dsubreg_0
293         unsigned DRegHi = TRI->getSubReg(Reg, 6); // arm_dsubreg_1
294         O << '{'
295           << TRI->getAsmName(DRegLo) << "-" << TRI->getAsmName(DRegHi)
296           << '}';
297       } else {
298         O << TRI->getAsmName(Reg);
299       }
300     } else
301       assert(0 && "not implemented");
302     break;
303   }
304   case MachineOperand::MO_Immediate: {
305     if (!Modifier || strcmp(Modifier, "no_hash") != 0)
306       O << "#";
307
308     O << MO.getImm();
309     break;
310   }
311   case MachineOperand::MO_MachineBasicBlock:
312     printBasicBlockLabel(MO.getMBB());
313     return;
314   case MachineOperand::MO_GlobalAddress: {
315     bool isCallOp = Modifier && !strcmp(Modifier, "call");
316     GlobalValue *GV = MO.getGlobal();
317     std::string Name = Mang->getValueName(GV);
318     bool isExt = (GV->isDeclaration() || GV->hasWeakLinkage() ||
319                   GV->hasLinkOnceLinkage());
320     if (isExt && isCallOp && Subtarget->isTargetDarwin() &&
321         TM.getRelocationModel() != Reloc::Static) {
322       printSuffixedName(Name, "$stub");
323       FnStubs.insert(Name);
324     } else
325       O << Name;
326
327     printOffset(MO.getOffset());
328
329     if (isCallOp && Subtarget->isTargetELF() &&
330         TM.getRelocationModel() == Reloc::PIC_)
331       O << "(PLT)";
332     if (GV->hasExternalWeakLinkage())
333       ExtWeakSymbols.insert(GV);
334     break;
335   }
336   case MachineOperand::MO_ExternalSymbol: {
337     bool isCallOp = Modifier && !strcmp(Modifier, "call");
338     std::string Name(TAI->getGlobalPrefix());
339     Name += MO.getSymbolName();
340     if (isCallOp && Subtarget->isTargetDarwin() &&
341         TM.getRelocationModel() != Reloc::Static) {
342       printSuffixedName(Name, "$stub");
343       FnStubs.insert(Name);
344     } else
345       O << Name;
346     if (isCallOp && Subtarget->isTargetELF() &&
347         TM.getRelocationModel() == Reloc::PIC_)
348       O << "(PLT)";
349     break;
350   }
351   case MachineOperand::MO_ConstantPoolIndex:
352     O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber()
353       << '_' << MO.getIndex();
354     break;
355   case MachineOperand::MO_JumpTableIndex:
356     O << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
357       << '_' << MO.getIndex();
358     break;
359   default:
360     O << "<unknown operand type>"; abort (); break;
361   }
362 }
363
364 static void printSOImm(raw_ostream &O, int64_t V, bool VerboseAsm,
365                        const TargetAsmInfo *TAI) {
366   assert(V < (1 << 12) && "Not a valid so_imm value!");
367   unsigned Imm = ARM_AM::getSOImmValImm(V);
368   unsigned Rot = ARM_AM::getSOImmValRot(V);
369
370   // Print low-level immediate formation info, per
371   // A5.1.3: "Data-processing operands - Immediate".
372   if (Rot) {
373     O << "#" << Imm << ", " << Rot;
374     // Pretty printed version.
375     if (VerboseAsm)
376       O << ' ' << TAI->getCommentString()
377         << ' ' << (int)ARM_AM::rotr32(Imm, Rot);
378   } else {
379     O << "#" << Imm;
380   }
381 }
382
383 /// printSOImmOperand - SOImm is 4-bit rotate amount in bits 8-11 with 8-bit
384 /// immediate in bits 0-7.
385 void ARMAsmPrinter::printSOImmOperand(const MachineInstr *MI, int OpNum) {
386   const MachineOperand &MO = MI->getOperand(OpNum);
387   assert(MO.isImm() && "Not a valid so_imm value!");
388   printSOImm(O, MO.getImm(), VerboseAsm, TAI);
389 }
390
391 /// printSOImm2PartOperand - SOImm is broken into two pieces using a 'mov'
392 /// followed by an 'orr' to materialize.
393 void ARMAsmPrinter::printSOImm2PartOperand(const MachineInstr *MI, int OpNum) {
394   const MachineOperand &MO = MI->getOperand(OpNum);
395   assert(MO.isImm() && "Not a valid so_imm value!");
396   unsigned V1 = ARM_AM::getSOImmTwoPartFirst(MO.getImm());
397   unsigned V2 = ARM_AM::getSOImmTwoPartSecond(MO.getImm());
398   printSOImm(O, ARM_AM::getSOImmVal(V1), VerboseAsm, TAI);
399   O << "\n\torr";
400   printPredicateOperand(MI, 2);
401   O << " ";
402   printOperand(MI, 0); 
403   O << ", ";
404   printOperand(MI, 0); 
405   O << ", ";
406   printSOImm(O, ARM_AM::getSOImmVal(V2), VerboseAsm, TAI);
407 }
408
409 // Constant shifts so_reg is a 3-operand unit corresponding to register forms of
410 // the A5.1 "Addressing Mode 1 - Data-processing operands" forms.  This
411 // includes:
412 // REG 0 - e.g. R5
413 // REG IMM, SH_OPC - e.g. R5, LSL #3
414 void ARMAsmPrinter::printSOOperand(const MachineInstr *MI, int OpNum) {
415   const MachineOperand &MO1 = MI->getOperand(OpNum);
416   const MachineOperand &MO2 = MI->getOperand(OpNum+1);
417
418   unsigned Reg = MO1.getReg();
419   assert(TargetRegisterInfo::isPhysicalRegister(Reg));
420   O << TM.getRegisterInfo()->getAsmName(Reg);
421
422   // Print the shift opc.
423   O << ", "
424     << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(MO2.getImm()))
425     << " ";
426
427   assert(MO2.isImm() && "Not a valid t2_so_reg value!");
428   O << "#" << ARM_AM::getSORegOffset(MO2.getImm());
429 }
430
431 // so_reg is a 4-operand unit corresponding to register forms of the A5.1
432 // "Addressing Mode 1 - Data-processing operands" forms.  This includes:
433 //    REG 0   0    - e.g. R5
434 //    REG REG 0,SH_OPC     - e.g. R5, ROR R3
435 //    REG 0   IMM,SH_OPC  - e.g. R5, LSL #3
436 void ARMAsmPrinter::printSORegOperand(const MachineInstr *MI, int Op) {
437   const MachineOperand &MO1 = MI->getOperand(Op);
438   const MachineOperand &MO2 = MI->getOperand(Op+1);
439   const MachineOperand &MO3 = MI->getOperand(Op+2);
440
441   assert(TargetRegisterInfo::isPhysicalRegister(MO1.getReg()));
442   O << TM.getRegisterInfo()->get(MO1.getReg()).AsmName;
443
444   // Print the shift opc.
445   O << ", "
446     << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(MO3.getImm()))
447     << " ";
448
449   if (MO2.getReg()) {
450     assert(TargetRegisterInfo::isPhysicalRegister(MO2.getReg()));
451     O << TM.getRegisterInfo()->get(MO2.getReg()).AsmName;
452     assert(ARM_AM::getSORegOffset(MO3.getImm()) == 0);
453   } else {
454     O << "#" << ARM_AM::getSORegOffset(MO3.getImm());
455   }
456 }
457
458 void ARMAsmPrinter::printAddrMode2Operand(const MachineInstr *MI, int Op) {
459   const MachineOperand &MO1 = MI->getOperand(Op);
460   const MachineOperand &MO2 = MI->getOperand(Op+1);
461   const MachineOperand &MO3 = MI->getOperand(Op+2);
462
463   if (!MO1.isReg()) {   // FIXME: This is for CP entries, but isn't right.
464     printOperand(MI, Op);
465     return;
466   }
467
468   O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).AsmName;
469
470   if (!MO2.getReg()) {
471     if (ARM_AM::getAM2Offset(MO3.getImm()))  // Don't print +0.
472       O << ", #"
473         << (char)ARM_AM::getAM2Op(MO3.getImm())
474         << ARM_AM::getAM2Offset(MO3.getImm());
475     O << "]";
476     return;
477   }
478
479   O << ", "
480     << (char)ARM_AM::getAM2Op(MO3.getImm())
481     << TM.getRegisterInfo()->get(MO2.getReg()).AsmName;
482   
483   if (unsigned ShImm = ARM_AM::getAM2Offset(MO3.getImm()))
484     O << ", "
485       << ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO3.getImm()))
486       << " #" << ShImm;
487   O << "]";
488 }
489
490 void ARMAsmPrinter::printAddrMode2OffsetOperand(const MachineInstr *MI, int Op){
491   const MachineOperand &MO1 = MI->getOperand(Op);
492   const MachineOperand &MO2 = MI->getOperand(Op+1);
493
494   if (!MO1.getReg()) {
495     unsigned ImmOffs = ARM_AM::getAM2Offset(MO2.getImm());
496     assert(ImmOffs && "Malformed indexed load / store!");
497     O << "#"
498       << (char)ARM_AM::getAM2Op(MO2.getImm())
499       << ImmOffs;
500     return;
501   }
502
503   O << (char)ARM_AM::getAM2Op(MO2.getImm())
504     << TM.getRegisterInfo()->get(MO1.getReg()).AsmName;
505   
506   if (unsigned ShImm = ARM_AM::getAM2Offset(MO2.getImm()))
507     O << ", "
508       << ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO2.getImm()))
509       << " #" << ShImm;
510 }
511
512 void ARMAsmPrinter::printAddrMode3Operand(const MachineInstr *MI, int Op) {
513   const MachineOperand &MO1 = MI->getOperand(Op);
514   const MachineOperand &MO2 = MI->getOperand(Op+1);
515   const MachineOperand &MO3 = MI->getOperand(Op+2);
516   
517   assert(TargetRegisterInfo::isPhysicalRegister(MO1.getReg()));
518   O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).AsmName;
519
520   if (MO2.getReg()) {
521     O << ", "
522       << (char)ARM_AM::getAM3Op(MO3.getImm())
523       << TM.getRegisterInfo()->get(MO2.getReg()).AsmName
524       << "]";
525     return;
526   }
527   
528   if (unsigned ImmOffs = ARM_AM::getAM3Offset(MO3.getImm()))
529     O << ", #"
530       << (char)ARM_AM::getAM3Op(MO3.getImm())
531       << ImmOffs;
532   O << "]";
533 }
534
535 void ARMAsmPrinter::printAddrMode3OffsetOperand(const MachineInstr *MI, int Op){
536   const MachineOperand &MO1 = MI->getOperand(Op);
537   const MachineOperand &MO2 = MI->getOperand(Op+1);
538
539   if (MO1.getReg()) {
540     O << (char)ARM_AM::getAM3Op(MO2.getImm())
541       << TM.getRegisterInfo()->get(MO1.getReg()).AsmName;
542     return;
543   }
544
545   unsigned ImmOffs = ARM_AM::getAM3Offset(MO2.getImm());
546   assert(ImmOffs && "Malformed indexed load / store!");
547   O << "#"
548     << (char)ARM_AM::getAM3Op(MO2.getImm())
549     << ImmOffs;
550 }
551   
552 void ARMAsmPrinter::printAddrMode4Operand(const MachineInstr *MI, int Op,
553                                           const char *Modifier) {
554   const MachineOperand &MO1 = MI->getOperand(Op);
555   const MachineOperand &MO2 = MI->getOperand(Op+1);
556   ARM_AM::AMSubMode Mode = ARM_AM::getAM4SubMode(MO2.getImm());
557   if (Modifier && strcmp(Modifier, "submode") == 0) {
558     if (MO1.getReg() == ARM::SP) {
559       bool isLDM = (MI->getOpcode() == ARM::LDM ||
560                     MI->getOpcode() == ARM::LDM_RET);
561       O << ARM_AM::getAMSubModeAltStr(Mode, isLDM);
562     } else
563       O << ARM_AM::getAMSubModeStr(Mode);
564   } else {
565     printOperand(MI, Op);
566     if (ARM_AM::getAM4WBFlag(MO2.getImm()))
567       O << "!";
568   }
569 }
570
571 void ARMAsmPrinter::printAddrMode5Operand(const MachineInstr *MI, int Op,
572                                           const char *Modifier) {
573   const MachineOperand &MO1 = MI->getOperand(Op);
574   const MachineOperand &MO2 = MI->getOperand(Op+1);
575
576   if (!MO1.isReg()) {   // FIXME: This is for CP entries, but isn't right.
577     printOperand(MI, Op);
578     return;
579   }
580   
581   assert(TargetRegisterInfo::isPhysicalRegister(MO1.getReg()));
582
583   if (Modifier && strcmp(Modifier, "submode") == 0) {
584     ARM_AM::AMSubMode Mode = ARM_AM::getAM5SubMode(MO2.getImm());
585     if (MO1.getReg() == ARM::SP) {
586       bool isFLDM = (MI->getOpcode() == ARM::FLDMD ||
587                      MI->getOpcode() == ARM::FLDMS);
588       O << ARM_AM::getAMSubModeAltStr(Mode, isFLDM);
589     } else
590       O << ARM_AM::getAMSubModeStr(Mode);
591     return;
592   } else if (Modifier && strcmp(Modifier, "base") == 0) {
593     // Used for FSTM{D|S} and LSTM{D|S} operations.
594     O << TM.getRegisterInfo()->get(MO1.getReg()).AsmName;
595     if (ARM_AM::getAM5WBFlag(MO2.getImm()))
596       O << "!";
597     return;
598   }
599   
600   O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).AsmName;
601   
602   if (unsigned ImmOffs = ARM_AM::getAM5Offset(MO2.getImm())) {
603     O << ", #"
604       << (char)ARM_AM::getAM5Op(MO2.getImm())
605       << ImmOffs*4;
606   }
607   O << "]";
608 }
609
610 void ARMAsmPrinter::printAddrModePCOperand(const MachineInstr *MI, int Op,
611                                            const char *Modifier) {
612   if (Modifier && strcmp(Modifier, "label") == 0) {
613     printPCLabel(MI, Op+1);
614     return;
615   }
616
617   const MachineOperand &MO1 = MI->getOperand(Op);
618   assert(TargetRegisterInfo::isPhysicalRegister(MO1.getReg()));
619   O << "[pc, +" << TM.getRegisterInfo()->get(MO1.getReg()).AsmName << "]";
620 }
621
622 void
623 ARMAsmPrinter::printThumbAddrModeRROperand(const MachineInstr *MI, int Op) {
624   const MachineOperand &MO1 = MI->getOperand(Op);
625   const MachineOperand &MO2 = MI->getOperand(Op+1);
626   O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).AsmName;
627   O << ", " << TM.getRegisterInfo()->get(MO2.getReg()).AsmName << "]";
628 }
629
630 void
631 ARMAsmPrinter::printThumbAddrModeRI5Operand(const MachineInstr *MI, int Op,
632                                             unsigned Scale) {
633   const MachineOperand &MO1 = MI->getOperand(Op);
634   const MachineOperand &MO2 = MI->getOperand(Op+1);
635   const MachineOperand &MO3 = MI->getOperand(Op+2);
636
637   if (!MO1.isReg()) {   // FIXME: This is for CP entries, but isn't right.
638     printOperand(MI, Op);
639     return;
640   }
641
642   O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).AsmName;
643   if (MO3.getReg())
644     O << ", " << TM.getRegisterInfo()->get(MO3.getReg()).AsmName;
645   else if (unsigned ImmOffs = MO2.getImm()) {
646     O << ", #" << ImmOffs;
647     if (Scale > 1)
648       O << " * " << Scale;
649   }
650   O << "]";
651 }
652
653 void
654 ARMAsmPrinter::printThumbAddrModeS1Operand(const MachineInstr *MI, int Op) {
655   printThumbAddrModeRI5Operand(MI, Op, 1);
656 }
657 void
658 ARMAsmPrinter::printThumbAddrModeS2Operand(const MachineInstr *MI, int Op) {
659   printThumbAddrModeRI5Operand(MI, Op, 2);
660 }
661 void
662 ARMAsmPrinter::printThumbAddrModeS4Operand(const MachineInstr *MI, int Op) {
663   printThumbAddrModeRI5Operand(MI, Op, 4);
664 }
665
666 void ARMAsmPrinter::printThumbAddrModeSPOperand(const MachineInstr *MI,int Op) {
667   const MachineOperand &MO1 = MI->getOperand(Op);
668   const MachineOperand &MO2 = MI->getOperand(Op+1);
669   O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).AsmName;
670   if (unsigned ImmOffs = MO2.getImm())
671     O << ", #" << ImmOffs << " * 4";
672   O << "]";
673 }
674
675 void ARMAsmPrinter::printPredicateOperand(const MachineInstr *MI, int opNum) {
676   ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(opNum).getImm();
677   if (CC != ARMCC::AL)
678     O << ARMCondCodeToString(CC);
679 }
680
681 void ARMAsmPrinter::printSBitModifierOperand(const MachineInstr *MI, int opNum){
682   unsigned Reg = MI->getOperand(opNum).getReg();
683   if (Reg) {
684     assert(Reg == ARM::CPSR && "Expect ARM CPSR register!");
685     O << 's';
686   }
687 }
688
689 void ARMAsmPrinter::printPCLabel(const MachineInstr *MI, int opNum) {
690   int Id = (int)MI->getOperand(opNum).getImm();
691   O << TAI->getPrivateGlobalPrefix() << "PC" << Id;
692 }
693
694 void ARMAsmPrinter::printRegisterList(const MachineInstr *MI, int opNum) {
695   O << "{";
696   for (unsigned i = opNum, e = MI->getNumOperands(); i != e; ++i) {
697     printOperand(MI, i);
698     if (i != e-1) O << ", ";
699   }
700   O << "}";
701 }
702
703 void ARMAsmPrinter::printCPInstOperand(const MachineInstr *MI, int OpNo,
704                                        const char *Modifier) {
705   assert(Modifier && "This operand only works with a modifier!");
706   // There are two aspects to a CONSTANTPOOL_ENTRY operand, the label and the
707   // data itself.
708   if (!strcmp(Modifier, "label")) {
709     unsigned ID = MI->getOperand(OpNo).getImm();
710     O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber()
711       << '_' << ID << ":\n";
712   } else {
713     assert(!strcmp(Modifier, "cpentry") && "Unknown modifier for CPE");
714     unsigned CPI = MI->getOperand(OpNo).getIndex();
715
716     const MachineConstantPoolEntry &MCPE = MCP->getConstants()[CPI];
717     
718     if (MCPE.isMachineConstantPoolEntry()) {
719       EmitMachineConstantPoolValue(MCPE.Val.MachineCPVal);
720     } else {
721       EmitGlobalConstant(MCPE.Val.ConstVal);
722       // remember to emit the weak reference
723       if (const GlobalValue *GV = dyn_cast<GlobalValue>(MCPE.Val.ConstVal))
724         if (GV->hasExternalWeakLinkage())
725           ExtWeakSymbols.insert(GV);
726     }
727   }
728 }
729
730 void ARMAsmPrinter::printJTBlockOperand(const MachineInstr *MI, int OpNo) {
731   const MachineOperand &MO1 = MI->getOperand(OpNo);
732   const MachineOperand &MO2 = MI->getOperand(OpNo+1); // Unique Id
733   unsigned JTI = MO1.getIndex();
734   O << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
735     << '_' << JTI << '_' << MO2.getImm() << ":\n";
736
737   const char *JTEntryDirective = TAI->getJumpTableDirective();
738   if (!JTEntryDirective)
739     JTEntryDirective = TAI->getData32bitsDirective();
740
741   const MachineFunction *MF = MI->getParent()->getParent();
742   const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo();
743   const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables();
744   const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs;
745   bool UseSet= TAI->getSetDirective() && TM.getRelocationModel() == Reloc::PIC_;
746   std::set<MachineBasicBlock*> JTSets;
747   for (unsigned i = 0, e = JTBBs.size(); i != e; ++i) {
748     MachineBasicBlock *MBB = JTBBs[i];
749     if (UseSet && JTSets.insert(MBB).second)
750       printPICJumpTableSetLabel(JTI, MO2.getImm(), MBB);
751
752     O << JTEntryDirective << ' ';
753     if (UseSet)
754       O << TAI->getPrivateGlobalPrefix() << getFunctionNumber()
755         << '_' << JTI << '_' << MO2.getImm()
756         << "_set_" << MBB->getNumber();
757     else if (TM.getRelocationModel() == Reloc::PIC_) {
758       printBasicBlockLabel(MBB, false, false, false);
759       // If the arch uses custom Jump Table directives, don't calc relative to JT
760       if (!TAI->getJumpTableDirective()) 
761         O << '-' << TAI->getPrivateGlobalPrefix() << "JTI"
762           << getFunctionNumber() << '_' << JTI << '_' << MO2.getImm();
763     } else
764       printBasicBlockLabel(MBB, false, false, false);
765     if (i != e-1)
766       O << '\n';
767   }
768 }
769
770
771 bool ARMAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
772                                     unsigned AsmVariant, const char *ExtraCode){
773   // Does this asm operand have a single letter operand modifier?
774   if (ExtraCode && ExtraCode[0]) {
775     if (ExtraCode[1] != 0) return true; // Unknown modifier.
776     
777     switch (ExtraCode[0]) {
778     default: return true;  // Unknown modifier.
779     case 'a': // Don't print "#" before a global var name or constant.
780     case 'c': // Don't print "$" before a global var name or constant.
781       printOperand(MI, OpNo, "no_hash");
782       return false;
783     case 'P': // Print a VFP double precision register.
784       printOperand(MI, OpNo);
785       return false;
786     case 'Q':
787       if (TM.getTargetData()->isLittleEndian())
788         break;
789       // Fallthrough
790     case 'R':
791       if (TM.getTargetData()->isBigEndian())
792         break;
793       // Fallthrough
794     case 'H': // Write second word of DI / DF reference.  
795       // Verify that this operand has two consecutive registers.
796       if (!MI->getOperand(OpNo).isReg() ||
797           OpNo+1 == MI->getNumOperands() ||
798           !MI->getOperand(OpNo+1).isReg())
799         return true;
800       ++OpNo;   // Return the high-part.
801     }
802   }
803   
804   printOperand(MI, OpNo);
805   return false;
806 }
807
808 bool ARMAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
809                                           unsigned OpNo, unsigned AsmVariant,
810                                           const char *ExtraCode) {
811   if (ExtraCode && ExtraCode[0])
812     return true; // Unknown modifier.
813   printAddrMode2Operand(MI, OpNo);
814   return false;
815 }
816
817 void ARMAsmPrinter::printMachineInstruction(const MachineInstr *MI) {
818   ++EmittedInsts;
819
820   int Opc = MI->getOpcode();
821   switch (Opc) {
822   case ARM::CONSTPOOL_ENTRY:
823     if (!InCPMode && AFI->isThumbFunction()) {
824       EmitAlignment(2);
825       InCPMode = true;
826     }
827     break;
828   default: {
829     if (InCPMode && AFI->isThumbFunction())
830       InCPMode = false;
831   }}
832
833   // Call the autogenerated instruction printer routines.
834   printInstruction(MI);
835 }
836
837 bool ARMAsmPrinter::doInitialization(Module &M) {
838
839   bool Result = AsmPrinter::doInitialization(M);
840   DW = getAnalysisIfAvailable<DwarfWriter>();
841
842   // Thumb-2 instructions are supported only in unified assembler syntax mode.
843   if (Subtarget->hasThumb2())
844     O << "\t.syntax unified\n";
845
846   // Emit ARM Build Attributes
847   if (Subtarget->isTargetELF()) {
848     // CPU Type
849     std::string CPUString = Subtarget->getCPUString();
850     if (CPUString != "generic")
851       O << "\t.cpu " << CPUString << '\n';
852
853     // FIXME: Emit FPU type
854     if (Subtarget->hasVFP2())
855       O << "\t.eabi_attribute " << ARMBuildAttrs::VFP_arch << ", 2\n";
856
857     // Signal various FP modes.
858     if (!UnsafeFPMath)
859       O << "\t.eabi_attribute " << ARMBuildAttrs::ABI_FP_denormal << ", 1\n"
860         << "\t.eabi_attribute " << ARMBuildAttrs::ABI_FP_exceptions << ", 1\n";
861
862     if (FiniteOnlyFPMath())
863       O << "\t.eabi_attribute " << ARMBuildAttrs::ABI_FP_number_model << ", 1\n";
864     else
865       O << "\t.eabi_attribute " << ARMBuildAttrs::ABI_FP_number_model << ", 3\n";
866
867     // 8-bytes alignment stuff.
868     O << "\t.eabi_attribute " << ARMBuildAttrs::ABI_align8_needed << ", 1\n"
869       << "\t.eabi_attribute " << ARMBuildAttrs::ABI_align8_preserved << ", 1\n";
870
871     // FIXME: Should we signal R9 usage?
872   }
873
874   return Result;
875 }
876
877 /// PrintUnmangledNameSafely - Print out the printable characters in the name.
878 /// Don't print things like \\n or \\0.
879 static void PrintUnmangledNameSafely(const Value *V, raw_ostream &OS) {
880   for (const char *Name = V->getNameStart(), *E = Name+V->getNameLen();
881        Name != E; ++Name)
882     if (isprint(*Name))
883       OS << *Name;
884 }
885
886 void ARMAsmPrinter::printModuleLevelGV(const GlobalVariable* GVar) {
887   const TargetData *TD = TM.getTargetData();
888
889   if (!GVar->hasInitializer())   // External global require no code
890     return;
891
892   // Check to see if this is a special global used by LLVM, if so, emit it.
893
894   if (EmitSpecialLLVMGlobal(GVar)) {
895     if (Subtarget->isTargetDarwin() &&
896         TM.getRelocationModel() == Reloc::Static) {
897       if (GVar->getName() == "llvm.global_ctors")
898         O << ".reference .constructors_used\n";
899       else if (GVar->getName() == "llvm.global_dtors")
900         O << ".reference .destructors_used\n";
901     }
902     return;
903   }
904
905   std::string name = Mang->getValueName(GVar);
906   Constant *C = GVar->getInitializer();
907   const Type *Type = C->getType();
908   unsigned Size = TD->getTypeAllocSize(Type);
909   unsigned Align = TD->getPreferredAlignmentLog(GVar);
910   bool isDarwin = Subtarget->isTargetDarwin();
911
912   printVisibility(name, GVar->getVisibility());
913
914   if (Subtarget->isTargetELF())
915     O << "\t.type " << name << ",%object\n";
916
917   if (C->isNullValue() && !GVar->hasSection() && !GVar->isThreadLocal() &&
918       !(isDarwin &&
919         TAI->SectionKindForGlobal(GVar) == SectionKind::RODataMergeStr)) {
920     // FIXME: This seems to be pretty darwin-specific
921
922     if (GVar->hasExternalLinkage()) {
923       SwitchToSection(TAI->SectionForGlobal(GVar));
924       if (const char *Directive = TAI->getZeroFillDirective()) {
925         O << "\t.globl\t" << name << "\n";
926         O << Directive << "__DATA, __common, " << name << ", "
927           << Size << ", " << Align << "\n";
928         return;
929       }
930     }
931
932     if (GVar->hasLocalLinkage() || GVar->isWeakForLinker()) {
933       if (Size == 0) Size = 1;   // .comm Foo, 0 is undefined, avoid it.
934
935       if (isDarwin) {
936         if (GVar->hasLocalLinkage()) {
937           O << TAI->getLCOMMDirective()  << name << "," << Size
938             << ',' << Align;
939         } else if (GVar->hasCommonLinkage()) {
940           O << TAI->getCOMMDirective()  << name << "," << Size
941             << ',' << Align;
942         } else {
943           SwitchToSection(TAI->SectionForGlobal(GVar));
944           O << "\t.globl " << name << '\n'
945             << TAI->getWeakDefDirective() << name << '\n';
946           EmitAlignment(Align, GVar);
947           O << name << ":";
948           if (VerboseAsm) {
949             O << "\t\t\t\t" << TAI->getCommentString() << ' ';
950             PrintUnmangledNameSafely(GVar, O);
951           }
952           O << '\n';
953           EmitGlobalConstant(C);
954           return;
955         }
956       } else if (TAI->getLCOMMDirective() != NULL) {
957         if (GVar->hasLocalLinkage()) {
958           O << TAI->getLCOMMDirective() << name << "," << Size;
959         } else {
960           O << TAI->getCOMMDirective()  << name << "," << Size;
961           if (TAI->getCOMMDirectiveTakesAlignment())
962             O << ',' << (TAI->getAlignmentIsInBytes() ? (1 << Align) : Align);
963         }
964       } else {
965         SwitchToSection(TAI->SectionForGlobal(GVar));
966         if (GVar->hasLocalLinkage())
967           O << "\t.local\t" << name << "\n";
968         O << TAI->getCOMMDirective()  << name << "," << Size;
969         if (TAI->getCOMMDirectiveTakesAlignment())
970           O << "," << (TAI->getAlignmentIsInBytes() ? (1 << Align) : Align);
971       }
972       if (VerboseAsm) {
973         O << "\t\t" << TAI->getCommentString() << " ";
974         PrintUnmangledNameSafely(GVar, O);
975       }
976       O << "\n";
977       return;
978     }
979   }
980
981   SwitchToSection(TAI->SectionForGlobal(GVar));
982   switch (GVar->getLinkage()) {
983    case GlobalValue::CommonLinkage:
984    case GlobalValue::LinkOnceAnyLinkage:
985    case GlobalValue::LinkOnceODRLinkage:
986    case GlobalValue::WeakAnyLinkage:
987    case GlobalValue::WeakODRLinkage:
988     if (isDarwin) {
989       O << "\t.globl " << name << "\n"
990         << "\t.weak_definition " << name << "\n";
991     } else {
992       O << "\t.weak " << name << "\n";
993     }
994     break;
995    case GlobalValue::AppendingLinkage:
996     // FIXME: appending linkage variables should go into a section of
997     // their name or something.  For now, just emit them as external.
998    case GlobalValue::ExternalLinkage:
999     O << "\t.globl " << name << "\n";
1000     // FALL THROUGH
1001    case GlobalValue::PrivateLinkage:
1002    case GlobalValue::InternalLinkage:
1003     break;
1004    default:
1005     assert(0 && "Unknown linkage type!");
1006     break;
1007   }
1008
1009   EmitAlignment(Align, GVar);
1010   O << name << ":";
1011   if (VerboseAsm) {
1012     O << "\t\t\t\t" << TAI->getCommentString() << " ";
1013     PrintUnmangledNameSafely(GVar, O);
1014   }
1015   O << "\n";
1016   if (TAI->hasDotTypeDotSizeDirective())
1017     O << "\t.size " << name << ", " << Size << "\n";
1018
1019   // If the initializer is a extern weak symbol, remember to emit the weak
1020   // reference!
1021   if (const GlobalValue *GV = dyn_cast<GlobalValue>(C))
1022     if (GV->hasExternalWeakLinkage())
1023       ExtWeakSymbols.insert(GV);
1024
1025   EmitGlobalConstant(C);
1026   O << '\n';
1027 }
1028
1029
1030 bool ARMAsmPrinter::doFinalization(Module &M) {
1031   for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
1032        I != E; ++I)
1033     printModuleLevelGV(I);
1034
1035   if (Subtarget->isTargetDarwin()) {
1036     SwitchToDataSection("");
1037
1038     // Output stubs for dynamically-linked functions
1039     for (StringSet<>::iterator i = FnStubs.begin(), e = FnStubs.end();
1040          i != e; ++i) {
1041       if (TM.getRelocationModel() == Reloc::PIC_)
1042         SwitchToTextSection(".section __TEXT,__picsymbolstub4,symbol_stubs,"
1043                             "none,16", 0);
1044       else
1045         SwitchToTextSection(".section __TEXT,__symbol_stub4,symbol_stubs,"
1046                             "none,12", 0);
1047
1048       EmitAlignment(2);
1049       O << "\t.code\t32\n";
1050
1051       const char *p = i->getKeyData();
1052       printSuffixedName(p, "$stub");
1053       O << ":\n";
1054       O << "\t.indirect_symbol " << p << "\n";
1055       O << "\tldr ip, ";
1056       printSuffixedName(p, "$slp");
1057       O << "\n";
1058       if (TM.getRelocationModel() == Reloc::PIC_) {
1059         printSuffixedName(p, "$scv");
1060         O << ":\n";
1061         O << "\tadd ip, pc, ip\n";
1062       }
1063       O << "\tldr pc, [ip, #0]\n";
1064       printSuffixedName(p, "$slp");
1065       O << ":\n";
1066       O << "\t.long\t";
1067       printSuffixedName(p, "$lazy_ptr");
1068       if (TM.getRelocationModel() == Reloc::PIC_) {
1069         O << "-(";
1070         printSuffixedName(p, "$scv");
1071         O << "+8)\n";
1072       } else
1073         O << "\n";
1074       SwitchToDataSection(".lazy_symbol_pointer", 0);
1075       printSuffixedName(p, "$lazy_ptr");
1076       O << ":\n";
1077       O << "\t.indirect_symbol " << p << "\n";
1078       O << "\t.long\tdyld_stub_binding_helper\n";
1079     }
1080     O << "\n";
1081
1082     // Output non-lazy-pointers for external and common global variables.
1083     if (!GVNonLazyPtrs.empty()) {
1084       SwitchToDataSection("\t.non_lazy_symbol_pointer", 0);
1085       for (StringSet<>::iterator i =  GVNonLazyPtrs.begin(),
1086              e = GVNonLazyPtrs.end(); i != e; ++i) {
1087         const char *p = i->getKeyData();
1088         printSuffixedName(p, "$non_lazy_ptr");
1089         O << ":\n";
1090         O << "\t.indirect_symbol " << p << "\n";
1091         O << "\t.long\t0\n";
1092       }
1093     }
1094
1095     if (!HiddenGVNonLazyPtrs.empty()) {
1096       SwitchToSection(TAI->getDataSection());
1097       for (StringSet<>::iterator i = HiddenGVNonLazyPtrs.begin(),
1098              e = HiddenGVNonLazyPtrs.end(); i != e; ++i) {
1099         const char *p = i->getKeyData();
1100         EmitAlignment(2);
1101         printSuffixedName(p, "$non_lazy_ptr");
1102         O << ":\n";
1103         O << "\t.long " << p << "\n";
1104       }
1105     }
1106
1107
1108     // Emit initial debug information.
1109     DW->EndModule();
1110
1111     // Funny Darwin hack: This flag tells the linker that no global symbols
1112     // contain code that falls through to other global symbols (e.g. the obvious
1113     // implementation of multiple entry points).  If this doesn't occur, the
1114     // linker can safely perform dead code stripping.  Since LLVM never
1115     // generates code that does this, it is always safe to set.
1116     O << "\t.subsections_via_symbols\n";
1117   } else {
1118     // Emit final debug information for ELF.
1119     DW->EndModule();
1120   }
1121
1122   return AsmPrinter::doFinalization(M);
1123 }
1124
1125 /// createARMCodePrinterPass - Returns a pass that prints the ARM
1126 /// assembly code for a MachineFunction to the given output stream,
1127 /// using the given target machine description.  This should work
1128 /// regardless of whether the function is in SSA form.
1129 ///
1130 FunctionPass *llvm::createARMCodePrinterPass(raw_ostream &o,
1131                                              ARMTargetMachine &tm,
1132                                              CodeGenOpt::Level OptLevel,
1133                                              bool verbose) {
1134   return new ARMAsmPrinter(o, tm, tm.getTargetAsmInfo(), OptLevel, verbose);
1135 }
1136
1137 namespace {
1138   static struct Register {
1139     Register() {
1140       ARMTargetMachine::registerAsmPrinter(createARMCodePrinterPass);
1141     }
1142   } Registrator;
1143 }
1144
1145 // Force static initialization when called from
1146 // llvm/InitializeAllAsmPrinters.h
1147 namespace llvm {
1148   void InitializeARMAsmPrinter() { }
1149 }