ARMAsmPrinter.cpp revision 3dcb461d1e721afdd2b90b24b8882f13da0dac2c
1//===-- ARMAsmPrinter.cpp - Print machine code to an ARM .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 ARM assembly language.
12//
13//===----------------------------------------------------------------------===//
14
15#define DEBUG_TYPE "asm-printer"
16#include "ARM.h"
17#include "ARMBuildAttrs.h"
18#include "ARMAddressingModes.h"
19#include "ARMConstantPoolValue.h"
20#include "InstPrinter/ARMInstPrinter.h"
21#include "ARMMachineFunctionInfo.h"
22#include "ARMMCInstLower.h"
23#include "ARMTargetMachine.h"
24#include "ARMTargetObjectFile.h"
25#include "llvm/Analysis/DebugInfo.h"
26#include "llvm/Constants.h"
27#include "llvm/Module.h"
28#include "llvm/Type.h"
29#include "llvm/Assembly/Writer.h"
30#include "llvm/CodeGen/AsmPrinter.h"
31#include "llvm/CodeGen/MachineModuleInfoImpls.h"
32#include "llvm/CodeGen/MachineFunctionPass.h"
33#include "llvm/CodeGen/MachineJumpTableInfo.h"
34#include "llvm/MC/MCAsmInfo.h"
35#include "llvm/MC/MCAssembler.h"
36#include "llvm/MC/MCContext.h"
37#include "llvm/MC/MCExpr.h"
38#include "llvm/MC/MCInst.h"
39#include "llvm/MC/MCSectionMachO.h"
40#include "llvm/MC/MCObjectStreamer.h"
41#include "llvm/MC/MCStreamer.h"
42#include "llvm/MC/MCSymbol.h"
43#include "llvm/Target/Mangler.h"
44#include "llvm/Target/TargetData.h"
45#include "llvm/Target/TargetMachine.h"
46#include "llvm/Target/TargetOptions.h"
47#include "llvm/Target/TargetRegistry.h"
48#include "llvm/ADT/SmallPtrSet.h"
49#include "llvm/ADT/SmallString.h"
50#include "llvm/ADT/StringExtras.h"
51#include "llvm/Support/CommandLine.h"
52#include "llvm/Support/Debug.h"
53#include "llvm/Support/ErrorHandling.h"
54#include "llvm/Support/raw_ostream.h"
55#include <cctype>
56using namespace llvm;
57
58namespace llvm {
59  namespace ARM {
60    enum DW_ISA {
61      DW_ISA_ARM_thumb = 1,
62      DW_ISA_ARM_arm = 2
63    };
64  }
65}
66
67namespace {
68
69  // Per section and per symbol attributes are not supported.
70  // To implement them we would need the ability to delay this emission
71  // until the assembly file is fully parsed/generated as only then do we
72  // know the symbol and section numbers.
73  class AttributeEmitter {
74  public:
75    virtual void MaybeSwitchVendor(StringRef Vendor) = 0;
76    virtual void EmitAttribute(unsigned Attribute, unsigned Value) = 0;
77    virtual void Finish() = 0;
78    virtual ~AttributeEmitter() {}
79  };
80
81  class AsmAttributeEmitter : public AttributeEmitter {
82    MCStreamer &Streamer;
83
84  public:
85    AsmAttributeEmitter(MCStreamer &Streamer_) : Streamer(Streamer_) {}
86    void MaybeSwitchVendor(StringRef Vendor) { }
87
88    void EmitAttribute(unsigned Attribute, unsigned Value) {
89      Streamer.EmitRawText("\t.eabi_attribute " +
90                           Twine(Attribute) + ", " + Twine(Value));
91    }
92
93    void Finish() { }
94  };
95
96  class ObjectAttributeEmitter : public AttributeEmitter {
97    MCObjectStreamer &Streamer;
98    StringRef CurrentVendor;
99    SmallString<64> Contents;
100
101  public:
102    ObjectAttributeEmitter(MCObjectStreamer &Streamer_) :
103      Streamer(Streamer_), CurrentVendor("") { }
104
105    void MaybeSwitchVendor(StringRef Vendor) {
106      assert(!Vendor.empty() && "Vendor cannot be empty.");
107
108      if (CurrentVendor.empty())
109        CurrentVendor = Vendor;
110      else if (CurrentVendor == Vendor)
111        return;
112      else
113        Finish();
114
115      CurrentVendor = Vendor;
116
117      assert(Contents.size() == 0);
118    }
119
120    void EmitAttribute(unsigned Attribute, unsigned Value) {
121      // FIXME: should be ULEB
122      Contents += Attribute;
123      Contents += Value;
124    }
125
126    void Finish() {
127      const size_t ContentsSize = Contents.size();
128
129      // Vendor size + Vendor name + '\0'
130      const size_t VendorHeaderSize = 4 + CurrentVendor.size() + 1;
131
132      // Tag + Tag Size
133      const size_t TagHeaderSize = 1 + 4;
134
135      Streamer.EmitIntValue(VendorHeaderSize + TagHeaderSize + ContentsSize, 4);
136      Streamer.EmitBytes(CurrentVendor, 0);
137      Streamer.EmitIntValue(0, 1); // '\0'
138
139      Streamer.EmitIntValue(ARMBuildAttrs::File, 1);
140      Streamer.EmitIntValue(TagHeaderSize + ContentsSize, 4);
141
142      Streamer.EmitBytes(Contents, 0);
143
144      Contents.clear();
145    }
146  };
147
148  class ARMAsmPrinter : public AsmPrinter {
149
150    /// Subtarget - Keep a pointer to the ARMSubtarget around so that we can
151    /// make the right decision when printing asm code for different targets.
152    const ARMSubtarget *Subtarget;
153
154    /// AFI - Keep a pointer to ARMFunctionInfo for the current
155    /// MachineFunction.
156    ARMFunctionInfo *AFI;
157
158    /// MCP - Keep a pointer to constantpool entries of the current
159    /// MachineFunction.
160    const MachineConstantPool *MCP;
161
162  public:
163    explicit ARMAsmPrinter(TargetMachine &TM, MCStreamer &Streamer)
164      : AsmPrinter(TM, Streamer), AFI(NULL), MCP(NULL) {
165      Subtarget = &TM.getSubtarget<ARMSubtarget>();
166    }
167
168    virtual const char *getPassName() const {
169      return "ARM Assembly Printer";
170    }
171
172    void printOperand(const MachineInstr *MI, int OpNum, raw_ostream &O,
173                      const char *Modifier = 0);
174
175    virtual bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNum,
176                                 unsigned AsmVariant, const char *ExtraCode,
177                                 raw_ostream &O);
178    virtual bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNum,
179                                       unsigned AsmVariant,
180                                       const char *ExtraCode, raw_ostream &O);
181
182    void EmitJumpTable(const MachineInstr *MI);
183    void EmitJump2Table(const MachineInstr *MI);
184    virtual void EmitInstruction(const MachineInstr *MI);
185    bool runOnMachineFunction(MachineFunction &F);
186
187    virtual void EmitConstantPool() {} // we emit constant pools customly!
188    virtual void EmitFunctionEntryLabel();
189    void EmitStartOfAsmFile(Module &M);
190    void EmitEndOfAsmFile(Module &M);
191
192  private:
193    // Helpers for EmitStartOfAsmFile() and EmitEndOfAsmFile()
194    void emitAttributes();
195
196    // Helper for ELF .o only
197    void emitARMAttributeSection();
198
199  public:
200    void PrintDebugValueComment(const MachineInstr *MI, raw_ostream &OS);
201
202    MachineLocation getDebugValueLocation(const MachineInstr *MI) const {
203      MachineLocation Location;
204      assert (MI->getNumOperands() == 4 && "Invalid no. of machine operands!");
205      // Frame address.  Currently handles register +- offset only.
206      if (MI->getOperand(0).isReg() && MI->getOperand(1).isImm())
207        Location.set(MI->getOperand(0).getReg(), MI->getOperand(1).getImm());
208      else {
209        DEBUG(dbgs() << "DBG_VALUE instruction ignored! " << *MI << "\n");
210      }
211      return Location;
212    }
213
214    virtual unsigned getISAEncoding() {
215      // ARM/Darwin adds ISA to the DWARF info for each function.
216      if (!Subtarget->isTargetDarwin())
217        return 0;
218      return Subtarget->isThumb() ?
219        llvm::ARM::DW_ISA_ARM_thumb : llvm::ARM::DW_ISA_ARM_arm;
220    }
221
222    MCSymbol *GetARMSetPICJumpTableLabel2(unsigned uid, unsigned uid2,
223                                          const MachineBasicBlock *MBB) const;
224    MCSymbol *GetARMJTIPICJumpTableLabel2(unsigned uid, unsigned uid2) const;
225
226    MCSymbol *GetARMSJLJEHLabel(void) const;
227
228    /// EmitMachineConstantPoolValue - Print a machine constantpool value to
229    /// the .s file.
230    virtual void EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) {
231      SmallString<128> Str;
232      raw_svector_ostream OS(Str);
233      EmitMachineConstantPoolValue(MCPV, OS);
234      // FIXME: non-assembly streamer support.
235      OutStreamer.EmitRawText(OS.str());
236    }
237
238    void EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV,
239                                      raw_ostream &O) {
240      switch (TM.getTargetData()->getTypeAllocSize(MCPV->getType())) {
241      case 1: O << MAI->getData8bitsDirective(0); break;
242      case 2: O << MAI->getData16bitsDirective(0); break;
243      case 4: O << MAI->getData32bitsDirective(0); break;
244      default: assert(0 && "Unknown CPV size");
245      }
246
247      ARMConstantPoolValue *ACPV = static_cast<ARMConstantPoolValue*>(MCPV);
248
249      if (ACPV->isLSDA()) {
250        O << MAI->getPrivateGlobalPrefix() << "_LSDA_" << getFunctionNumber();
251      } else if (ACPV->isBlockAddress()) {
252        O << *GetBlockAddressSymbol(ACPV->getBlockAddress());
253      } else if (ACPV->isGlobalValue()) {
254        const GlobalValue *GV = ACPV->getGV();
255        bool isIndirect = Subtarget->isTargetDarwin() &&
256          Subtarget->GVIsIndirectSymbol(GV, TM.getRelocationModel());
257        if (!isIndirect)
258          O << *Mang->getSymbol(GV);
259        else {
260          // FIXME: Remove this when Darwin transition to @GOT like syntax.
261          MCSymbol *Sym = GetSymbolWithGlobalValueBase(GV, "$non_lazy_ptr");
262          O << *Sym;
263
264          MachineModuleInfoMachO &MMIMachO =
265            MMI->getObjFileInfo<MachineModuleInfoMachO>();
266          MachineModuleInfoImpl::StubValueTy &StubSym =
267            GV->hasHiddenVisibility() ? MMIMachO.getHiddenGVStubEntry(Sym) :
268                                        MMIMachO.getGVStubEntry(Sym);
269          if (StubSym.getPointer() == 0)
270            StubSym = MachineModuleInfoImpl::
271              StubValueTy(Mang->getSymbol(GV), !GV->hasInternalLinkage());
272        }
273      } else {
274        assert(ACPV->isExtSymbol() && "unrecognized constant pool value");
275        O << *GetExternalSymbolSymbol(ACPV->getSymbol());
276      }
277
278      if (ACPV->hasModifier()) O << "(" << ACPV->getModifier() << ")";
279      if (ACPV->getPCAdjustment() != 0) {
280        O << "-(" << MAI->getPrivateGlobalPrefix() << "PC"
281          << getFunctionNumber() << "_"  << ACPV->getLabelId()
282          << "+" << (unsigned)ACPV->getPCAdjustment();
283         if (ACPV->mustAddCurrentAddress())
284           O << "-.";
285         O << ')';
286      }
287    }
288  };
289} // end of anonymous namespace
290
291void ARMAsmPrinter::EmitFunctionEntryLabel() {
292  if (AFI->isThumbFunction()) {
293    OutStreamer.EmitRawText(StringRef("\t.code\t16"));
294    if (!Subtarget->isTargetDarwin())
295      OutStreamer.EmitRawText(StringRef("\t.thumb_func"));
296    else {
297      // This needs to emit to a temporary string to get properly quoted
298      // MCSymbols when they have spaces in them.
299      SmallString<128> Tmp;
300      raw_svector_ostream OS(Tmp);
301      OS << "\t.thumb_func\t" << *CurrentFnSym;
302      OutStreamer.EmitRawText(OS.str());
303    }
304  }
305
306  OutStreamer.EmitLabel(CurrentFnSym);
307}
308
309/// runOnMachineFunction - This uses the EmitInstruction()
310/// method to print assembly for each instruction.
311///
312bool ARMAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
313  AFI = MF.getInfo<ARMFunctionInfo>();
314  MCP = MF.getConstantPool();
315
316  return AsmPrinter::runOnMachineFunction(MF);
317}
318
319void ARMAsmPrinter::printOperand(const MachineInstr *MI, int OpNum,
320                                 raw_ostream &O, const char *Modifier) {
321  const MachineOperand &MO = MI->getOperand(OpNum);
322  unsigned TF = MO.getTargetFlags();
323
324  switch (MO.getType()) {
325  default:
326    assert(0 && "<unknown operand type>");
327  case MachineOperand::MO_Register: {
328    unsigned Reg = MO.getReg();
329    assert(TargetRegisterInfo::isPhysicalRegister(Reg));
330    assert(!MO.getSubReg() && "Subregs should be eliminated!");
331    O << ARMInstPrinter::getRegisterName(Reg);
332    break;
333  }
334  case MachineOperand::MO_Immediate: {
335    int64_t Imm = MO.getImm();
336    O << '#';
337    if ((Modifier && strcmp(Modifier, "lo16") == 0) ||
338        (TF == ARMII::MO_LO16))
339      O << ":lower16:";
340    else if ((Modifier && strcmp(Modifier, "hi16") == 0) ||
341             (TF == ARMII::MO_HI16))
342      O << ":upper16:";
343    O << Imm;
344    break;
345  }
346  case MachineOperand::MO_MachineBasicBlock:
347    O << *MO.getMBB()->getSymbol();
348    return;
349  case MachineOperand::MO_GlobalAddress: {
350    const GlobalValue *GV = MO.getGlobal();
351    if ((Modifier && strcmp(Modifier, "lo16") == 0) ||
352        (TF & ARMII::MO_LO16))
353      O << ":lower16:";
354    else if ((Modifier && strcmp(Modifier, "hi16") == 0) ||
355             (TF & ARMII::MO_HI16))
356      O << ":upper16:";
357    O << *Mang->getSymbol(GV);
358
359    printOffset(MO.getOffset(), O);
360    if (TF == ARMII::MO_PLT)
361      O << "(PLT)";
362    break;
363  }
364  case MachineOperand::MO_ExternalSymbol: {
365    O << *GetExternalSymbolSymbol(MO.getSymbolName());
366    if (TF == ARMII::MO_PLT)
367      O << "(PLT)";
368    break;
369  }
370  case MachineOperand::MO_ConstantPoolIndex:
371    O << *GetCPISymbol(MO.getIndex());
372    break;
373  case MachineOperand::MO_JumpTableIndex:
374    O << *GetJTISymbol(MO.getIndex());
375    break;
376  }
377}
378
379//===--------------------------------------------------------------------===//
380
381MCSymbol *ARMAsmPrinter::
382GetARMSetPICJumpTableLabel2(unsigned uid, unsigned uid2,
383                            const MachineBasicBlock *MBB) const {
384  SmallString<60> Name;
385  raw_svector_ostream(Name) << MAI->getPrivateGlobalPrefix()
386    << getFunctionNumber() << '_' << uid << '_' << uid2
387    << "_set_" << MBB->getNumber();
388  return OutContext.GetOrCreateSymbol(Name.str());
389}
390
391MCSymbol *ARMAsmPrinter::
392GetARMJTIPICJumpTableLabel2(unsigned uid, unsigned uid2) const {
393  SmallString<60> Name;
394  raw_svector_ostream(Name) << MAI->getPrivateGlobalPrefix() << "JTI"
395    << getFunctionNumber() << '_' << uid << '_' << uid2;
396  return OutContext.GetOrCreateSymbol(Name.str());
397}
398
399
400MCSymbol *ARMAsmPrinter::GetARMSJLJEHLabel(void) const {
401  SmallString<60> Name;
402  raw_svector_ostream(Name) << MAI->getPrivateGlobalPrefix() << "SJLJEH"
403    << getFunctionNumber();
404  return OutContext.GetOrCreateSymbol(Name.str());
405}
406
407bool ARMAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNum,
408                                    unsigned AsmVariant, const char *ExtraCode,
409                                    raw_ostream &O) {
410  // Does this asm operand have a single letter operand modifier?
411  if (ExtraCode && ExtraCode[0]) {
412    if (ExtraCode[1] != 0) return true; // Unknown modifier.
413
414    switch (ExtraCode[0]) {
415    default: return true;  // Unknown modifier.
416    case 'a': // Print as a memory address.
417      if (MI->getOperand(OpNum).isReg()) {
418        O << "["
419          << ARMInstPrinter::getRegisterName(MI->getOperand(OpNum).getReg())
420          << "]";
421        return false;
422      }
423      // Fallthrough
424    case 'c': // Don't print "#" before an immediate operand.
425      if (!MI->getOperand(OpNum).isImm())
426        return true;
427      O << MI->getOperand(OpNum).getImm();
428      return false;
429    case 'P': // Print a VFP double precision register.
430    case 'q': // Print a NEON quad precision register.
431      printOperand(MI, OpNum, O);
432      return false;
433    case 'Q':
434    case 'R':
435    case 'H':
436      report_fatal_error("llvm does not support 'Q', 'R', and 'H' modifiers!");
437      return true;
438    }
439  }
440
441  printOperand(MI, OpNum, O);
442  return false;
443}
444
445bool ARMAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
446                                          unsigned OpNum, unsigned AsmVariant,
447                                          const char *ExtraCode,
448                                          raw_ostream &O) {
449  if (ExtraCode && ExtraCode[0])
450    return true; // Unknown modifier.
451
452  const MachineOperand &MO = MI->getOperand(OpNum);
453  assert(MO.isReg() && "unexpected inline asm memory operand");
454  O << "[" << ARMInstPrinter::getRegisterName(MO.getReg()) << "]";
455  return false;
456}
457
458void ARMAsmPrinter::EmitStartOfAsmFile(Module &M) {
459  if (Subtarget->isTargetDarwin()) {
460    Reloc::Model RelocM = TM.getRelocationModel();
461    if (RelocM == Reloc::PIC_ || RelocM == Reloc::DynamicNoPIC) {
462      // Declare all the text sections up front (before the DWARF sections
463      // emitted by AsmPrinter::doInitialization) so the assembler will keep
464      // them together at the beginning of the object file.  This helps
465      // avoid out-of-range branches that are due a fundamental limitation of
466      // the way symbol offsets are encoded with the current Darwin ARM
467      // relocations.
468      const TargetLoweringObjectFileMachO &TLOFMacho =
469        static_cast<const TargetLoweringObjectFileMachO &>(
470          getObjFileLowering());
471      OutStreamer.SwitchSection(TLOFMacho.getTextSection());
472      OutStreamer.SwitchSection(TLOFMacho.getTextCoalSection());
473      OutStreamer.SwitchSection(TLOFMacho.getConstTextCoalSection());
474      if (RelocM == Reloc::DynamicNoPIC) {
475        const MCSection *sect =
476          OutContext.getMachOSection("__TEXT", "__symbol_stub4",
477                                     MCSectionMachO::S_SYMBOL_STUBS,
478                                     12, SectionKind::getText());
479        OutStreamer.SwitchSection(sect);
480      } else {
481        const MCSection *sect =
482          OutContext.getMachOSection("__TEXT", "__picsymbolstub4",
483                                     MCSectionMachO::S_SYMBOL_STUBS,
484                                     16, SectionKind::getText());
485        OutStreamer.SwitchSection(sect);
486      }
487      const MCSection *StaticInitSect =
488        OutContext.getMachOSection("__TEXT", "__StaticInit",
489                                   MCSectionMachO::S_REGULAR |
490                                   MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS,
491                                   SectionKind::getText());
492      OutStreamer.SwitchSection(StaticInitSect);
493    }
494  }
495
496  // Use unified assembler syntax.
497  OutStreamer.EmitAssemblerFlag(MCAF_SyntaxUnified);
498
499  // Emit ARM Build Attributes
500  if (Subtarget->isTargetELF()) {
501
502    emitAttributes();
503  }
504}
505
506
507void ARMAsmPrinter::EmitEndOfAsmFile(Module &M) {
508  if (Subtarget->isTargetDarwin()) {
509    // All darwin targets use mach-o.
510    const TargetLoweringObjectFileMachO &TLOFMacho =
511      static_cast<const TargetLoweringObjectFileMachO &>(getObjFileLowering());
512    MachineModuleInfoMachO &MMIMacho =
513      MMI->getObjFileInfo<MachineModuleInfoMachO>();
514
515    // Output non-lazy-pointers for external and common global variables.
516    MachineModuleInfoMachO::SymbolListTy Stubs = MMIMacho.GetGVStubList();
517
518    if (!Stubs.empty()) {
519      // Switch with ".non_lazy_symbol_pointer" directive.
520      OutStreamer.SwitchSection(TLOFMacho.getNonLazySymbolPointerSection());
521      EmitAlignment(2);
522      for (unsigned i = 0, e = Stubs.size(); i != e; ++i) {
523        // L_foo$stub:
524        OutStreamer.EmitLabel(Stubs[i].first);
525        //   .indirect_symbol _foo
526        MachineModuleInfoImpl::StubValueTy &MCSym = Stubs[i].second;
527        OutStreamer.EmitSymbolAttribute(MCSym.getPointer(),MCSA_IndirectSymbol);
528
529        if (MCSym.getInt())
530          // External to current translation unit.
531          OutStreamer.EmitIntValue(0, 4/*size*/, 0/*addrspace*/);
532        else
533          // Internal to current translation unit.
534          //
535          // When we place the LSDA into the TEXT section, the type info
536          // pointers need to be indirect and pc-rel. We accomplish this by
537          // using NLPs; however, sometimes the types are local to the file.
538          // We need to fill in the value for the NLP in those cases.
539          OutStreamer.EmitValue(MCSymbolRefExpr::Create(MCSym.getPointer(),
540                                                        OutContext),
541                                4/*size*/, 0/*addrspace*/);
542      }
543
544      Stubs.clear();
545      OutStreamer.AddBlankLine();
546    }
547
548    Stubs = MMIMacho.GetHiddenGVStubList();
549    if (!Stubs.empty()) {
550      OutStreamer.SwitchSection(getObjFileLowering().getDataSection());
551      EmitAlignment(2);
552      for (unsigned i = 0, e = Stubs.size(); i != e; ++i) {
553        // L_foo$stub:
554        OutStreamer.EmitLabel(Stubs[i].first);
555        //   .long _foo
556        OutStreamer.EmitValue(MCSymbolRefExpr::
557                              Create(Stubs[i].second.getPointer(),
558                                     OutContext),
559                              4/*size*/, 0/*addrspace*/);
560      }
561
562      Stubs.clear();
563      OutStreamer.AddBlankLine();
564    }
565
566    // Funny Darwin hack: This flag tells the linker that no global symbols
567    // contain code that falls through to other global symbols (e.g. the obvious
568    // implementation of multiple entry points).  If this doesn't occur, the
569    // linker can safely perform dead code stripping.  Since LLVM never
570    // generates code that does this, it is always safe to set.
571    OutStreamer.EmitAssemblerFlag(MCAF_SubsectionsViaSymbols);
572  }
573}
574
575//===----------------------------------------------------------------------===//
576// Helper routines for EmitStartOfAsmFile() and EmitEndOfAsmFile()
577// FIXME:
578// The following seem like one-off assembler flags, but they actually need
579// to appear in the .ARM.attributes section in ELF.
580// Instead of subclassing the MCELFStreamer, we do the work here.
581
582void ARMAsmPrinter::emitAttributes() {
583
584  emitARMAttributeSection();
585
586  AttributeEmitter *AttrEmitter;
587  if (OutStreamer.hasRawTextSupport())
588    AttrEmitter = new AsmAttributeEmitter(OutStreamer);
589  else {
590    MCObjectStreamer &O = static_cast<MCObjectStreamer&>(OutStreamer);
591    AttrEmitter = new ObjectAttributeEmitter(O);
592  }
593
594  AttrEmitter->MaybeSwitchVendor("aeabi");
595
596  std::string CPUString = Subtarget->getCPUString();
597  if (OutStreamer.hasRawTextSupport()) {
598    if (CPUString != "generic")
599      OutStreamer.EmitRawText(StringRef("\t.cpu ") + CPUString);
600  } else {
601    assert(CPUString == "generic" && "Unsupported .cpu attribute for ELF/.o");
602    // FIXME: Why these defaults?
603    AttrEmitter->EmitAttribute(ARMBuildAttrs::CPU_arch, ARMBuildAttrs::v4T);
604    AttrEmitter->EmitAttribute(ARMBuildAttrs::ARM_ISA_use, 1);
605    AttrEmitter->EmitAttribute(ARMBuildAttrs::THUMB_ISA_use, 1);
606  }
607
608  // FIXME: Emit FPU type
609  if (Subtarget->hasVFP2())
610    AttrEmitter->EmitAttribute(ARMBuildAttrs::VFP_arch, 2);
611
612  // Signal various FP modes.
613  if (!UnsafeFPMath) {
614    AttrEmitter->EmitAttribute(ARMBuildAttrs::ABI_FP_denormal, 1);
615    AttrEmitter->EmitAttribute(ARMBuildAttrs::ABI_FP_exceptions, 1);
616  }
617
618  if (NoInfsFPMath && NoNaNsFPMath)
619    AttrEmitter->EmitAttribute(ARMBuildAttrs::ABI_FP_number_model, 1);
620  else
621    AttrEmitter->EmitAttribute(ARMBuildAttrs::ABI_FP_number_model, 3);
622
623  // 8-bytes alignment stuff.
624  AttrEmitter->EmitAttribute(ARMBuildAttrs::ABI_align8_needed, 1);
625  AttrEmitter->EmitAttribute(ARMBuildAttrs::ABI_align8_preserved, 1);
626
627  // Hard float.  Use both S and D registers and conform to AAPCS-VFP.
628  if (Subtarget->isAAPCS_ABI() && FloatABIType == FloatABI::Hard) {
629    AttrEmitter->EmitAttribute(ARMBuildAttrs::ABI_HardFP_use, 3);
630    AttrEmitter->EmitAttribute(ARMBuildAttrs::ABI_VFP_args, 1);
631  }
632  // FIXME: Should we signal R9 usage?
633
634  AttrEmitter->EmitAttribute(ARMBuildAttrs::DIV_use, 1);
635
636  AttrEmitter->Finish();
637  delete AttrEmitter;
638}
639
640void ARMAsmPrinter::emitARMAttributeSection() {
641  // <format-version>
642  // [ <section-length> "vendor-name"
643  // [ <file-tag> <size> <attribute>*
644  //   | <section-tag> <size> <section-number>* 0 <attribute>*
645  //   | <symbol-tag> <size> <symbol-number>* 0 <attribute>*
646  //   ]+
647  // ]*
648
649  if (OutStreamer.hasRawTextSupport())
650    return;
651
652  const ARMElfTargetObjectFile &TLOFELF =
653    static_cast<const ARMElfTargetObjectFile &>
654    (getObjFileLowering());
655
656  OutStreamer.SwitchSection(TLOFELF.getAttributesSection());
657
658  // Format version
659  OutStreamer.EmitIntValue(0x41, 1);
660}
661
662//===----------------------------------------------------------------------===//
663
664static MCSymbol *getPICLabel(const char *Prefix, unsigned FunctionNumber,
665                             unsigned LabelId, MCContext &Ctx) {
666
667  MCSymbol *Label = Ctx.GetOrCreateSymbol(Twine(Prefix)
668                       + "PC" + Twine(FunctionNumber) + "_" + Twine(LabelId));
669  return Label;
670}
671
672void ARMAsmPrinter::EmitJumpTable(const MachineInstr *MI) {
673  unsigned Opcode = MI->getOpcode();
674  int OpNum = 1;
675  if (Opcode == ARM::BR_JTadd)
676    OpNum = 2;
677  else if (Opcode == ARM::BR_JTm)
678    OpNum = 3;
679
680  const MachineOperand &MO1 = MI->getOperand(OpNum);
681  const MachineOperand &MO2 = MI->getOperand(OpNum+1); // Unique Id
682  unsigned JTI = MO1.getIndex();
683
684  // Emit a label for the jump table.
685  MCSymbol *JTISymbol = GetARMJTIPICJumpTableLabel2(JTI, MO2.getImm());
686  OutStreamer.EmitLabel(JTISymbol);
687
688  // Emit each entry of the table.
689  const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo();
690  const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables();
691  const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs;
692
693  for (unsigned i = 0, e = JTBBs.size(); i != e; ++i) {
694    MachineBasicBlock *MBB = JTBBs[i];
695    // Construct an MCExpr for the entry. We want a value of the form:
696    // (BasicBlockAddr - TableBeginAddr)
697    //
698    // For example, a table with entries jumping to basic blocks BB0 and BB1
699    // would look like:
700    // LJTI_0_0:
701    //    .word (LBB0 - LJTI_0_0)
702    //    .word (LBB1 - LJTI_0_0)
703    const MCExpr *Expr = MCSymbolRefExpr::Create(MBB->getSymbol(), OutContext);
704
705    if (TM.getRelocationModel() == Reloc::PIC_)
706      Expr = MCBinaryExpr::CreateSub(Expr, MCSymbolRefExpr::Create(JTISymbol,
707                                                                   OutContext),
708                                     OutContext);
709    OutStreamer.EmitValue(Expr, 4);
710  }
711}
712
713void ARMAsmPrinter::EmitJump2Table(const MachineInstr *MI) {
714  unsigned Opcode = MI->getOpcode();
715  int OpNum = (Opcode == ARM::t2BR_JT) ? 2 : 1;
716  const MachineOperand &MO1 = MI->getOperand(OpNum);
717  const MachineOperand &MO2 = MI->getOperand(OpNum+1); // Unique Id
718  unsigned JTI = MO1.getIndex();
719
720  // Emit a label for the jump table.
721  MCSymbol *JTISymbol = GetARMJTIPICJumpTableLabel2(JTI, MO2.getImm());
722  OutStreamer.EmitLabel(JTISymbol);
723
724  // Emit each entry of the table.
725  const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo();
726  const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables();
727  const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs;
728  unsigned OffsetWidth = 4;
729  if (MI->getOpcode() == ARM::t2TBB)
730    OffsetWidth = 1;
731  else if (MI->getOpcode() == ARM::t2TBH)
732    OffsetWidth = 2;
733
734  for (unsigned i = 0, e = JTBBs.size(); i != e; ++i) {
735    MachineBasicBlock *MBB = JTBBs[i];
736    const MCExpr *MBBSymbolExpr = MCSymbolRefExpr::Create(MBB->getSymbol(),
737                                                      OutContext);
738    // If this isn't a TBB or TBH, the entries are direct branch instructions.
739    if (OffsetWidth == 4) {
740      MCInst BrInst;
741      BrInst.setOpcode(ARM::t2B);
742      BrInst.addOperand(MCOperand::CreateExpr(MBBSymbolExpr));
743      OutStreamer.EmitInstruction(BrInst);
744      continue;
745    }
746    // Otherwise it's an offset from the dispatch instruction. Construct an
747    // MCExpr for the entry. We want a value of the form:
748    // (BasicBlockAddr - TableBeginAddr) / 2
749    //
750    // For example, a TBB table with entries jumping to basic blocks BB0 and BB1
751    // would look like:
752    // LJTI_0_0:
753    //    .byte (LBB0 - LJTI_0_0) / 2
754    //    .byte (LBB1 - LJTI_0_0) / 2
755    const MCExpr *Expr =
756      MCBinaryExpr::CreateSub(MBBSymbolExpr,
757                              MCSymbolRefExpr::Create(JTISymbol, OutContext),
758                              OutContext);
759    Expr = MCBinaryExpr::CreateDiv(Expr, MCConstantExpr::Create(2, OutContext),
760                                   OutContext);
761    OutStreamer.EmitValue(Expr, OffsetWidth);
762  }
763
764  // Make sure the instruction that follows TBB is 2-byte aligned.
765  // FIXME: Constant island pass should insert an "ALIGN" instruction instead.
766  if (MI->getOpcode() == ARM::t2TBB)
767    EmitAlignment(1);
768}
769
770void ARMAsmPrinter::PrintDebugValueComment(const MachineInstr *MI,
771                                           raw_ostream &OS) {
772  unsigned NOps = MI->getNumOperands();
773  assert(NOps==4);
774  OS << '\t' << MAI->getCommentString() << "DEBUG_VALUE: ";
775  // cast away const; DIetc do not take const operands for some reason.
776  DIVariable V(const_cast<MDNode *>(MI->getOperand(NOps-1).getMetadata()));
777  OS << V.getName();
778  OS << " <- ";
779  // Frame address.  Currently handles register +- offset only.
780  assert(MI->getOperand(0).isReg() && MI->getOperand(1).isImm());
781  OS << '['; printOperand(MI, 0, OS); OS << '+'; printOperand(MI, 1, OS);
782  OS << ']';
783  OS << "+";
784  printOperand(MI, NOps-2, OS);
785}
786
787void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) {
788  ARMMCInstLower MCInstLowering(OutContext, *Mang, *this);
789  switch (MI->getOpcode()) {
790  case ARM::t2MOVi32imm:
791    assert(0 && "Should be lowered by thumb2it pass");
792  default: break;
793  case ARM::DBG_VALUE: {
794    if (isVerbose() && OutStreamer.hasRawTextSupport()) {
795      SmallString<128> TmpStr;
796      raw_svector_ostream OS(TmpStr);
797      PrintDebugValueComment(MI, OS);
798      OutStreamer.EmitRawText(StringRef(OS.str()));
799    }
800    return;
801  }
802  case ARM::tPICADD: {
803    // This is a pseudo op for a label + instruction sequence, which looks like:
804    // LPC0:
805    //     add r0, pc
806    // This adds the address of LPC0 to r0.
807
808    // Emit the label.
809    OutStreamer.EmitLabel(getPICLabel(MAI->getPrivateGlobalPrefix(),
810                          getFunctionNumber(), MI->getOperand(2).getImm(),
811                          OutContext));
812
813    // Form and emit the add.
814    MCInst AddInst;
815    AddInst.setOpcode(ARM::tADDhirr);
816    AddInst.addOperand(MCOperand::CreateReg(MI->getOperand(0).getReg()));
817    AddInst.addOperand(MCOperand::CreateReg(MI->getOperand(0).getReg()));
818    AddInst.addOperand(MCOperand::CreateReg(ARM::PC));
819    // Add predicate operands.
820    AddInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
821    AddInst.addOperand(MCOperand::CreateReg(0));
822    OutStreamer.EmitInstruction(AddInst);
823    return;
824  }
825  case ARM::PICADD: {
826    // This is a pseudo op for a label + instruction sequence, which looks like:
827    // LPC0:
828    //     add r0, pc, r0
829    // This adds the address of LPC0 to r0.
830
831    // Emit the label.
832    OutStreamer.EmitLabel(getPICLabel(MAI->getPrivateGlobalPrefix(),
833                          getFunctionNumber(), MI->getOperand(2).getImm(),
834                          OutContext));
835
836    // Form and emit the add.
837    MCInst AddInst;
838    AddInst.setOpcode(ARM::ADDrr);
839    AddInst.addOperand(MCOperand::CreateReg(MI->getOperand(0).getReg()));
840    AddInst.addOperand(MCOperand::CreateReg(ARM::PC));
841    AddInst.addOperand(MCOperand::CreateReg(MI->getOperand(1).getReg()));
842    // Add predicate operands.
843    AddInst.addOperand(MCOperand::CreateImm(MI->getOperand(3).getImm()));
844    AddInst.addOperand(MCOperand::CreateReg(MI->getOperand(4).getReg()));
845    // Add 's' bit operand (always reg0 for this)
846    AddInst.addOperand(MCOperand::CreateReg(0));
847    OutStreamer.EmitInstruction(AddInst);
848    return;
849  }
850  case ARM::PICSTR:
851  case ARM::PICSTRB:
852  case ARM::PICSTRH:
853  case ARM::PICLDR:
854  case ARM::PICLDRB:
855  case ARM::PICLDRH:
856  case ARM::PICLDRSB:
857  case ARM::PICLDRSH: {
858    // This is a pseudo op for a label + instruction sequence, which looks like:
859    // LPC0:
860    //     OP r0, [pc, r0]
861    // The LCP0 label is referenced by a constant pool entry in order to get
862    // a PC-relative address at the ldr instruction.
863
864    // Emit the label.
865    OutStreamer.EmitLabel(getPICLabel(MAI->getPrivateGlobalPrefix(),
866                          getFunctionNumber(), MI->getOperand(2).getImm(),
867                          OutContext));
868
869    // Form and emit the load
870    unsigned Opcode;
871    switch (MI->getOpcode()) {
872    default:
873      llvm_unreachable("Unexpected opcode!");
874    case ARM::PICSTR:   Opcode = ARM::STRrs; break;
875    case ARM::PICSTRB:  Opcode = ARM::STRBrs; break;
876    case ARM::PICSTRH:  Opcode = ARM::STRH; break;
877    case ARM::PICLDR:   Opcode = ARM::LDRrs; break;
878    case ARM::PICLDRB:  Opcode = ARM::LDRBrs; break;
879    case ARM::PICLDRH:  Opcode = ARM::LDRH; break;
880    case ARM::PICLDRSB: Opcode = ARM::LDRSB; break;
881    case ARM::PICLDRSH: Opcode = ARM::LDRSH; break;
882    }
883    MCInst LdStInst;
884    LdStInst.setOpcode(Opcode);
885    LdStInst.addOperand(MCOperand::CreateReg(MI->getOperand(0).getReg()));
886    LdStInst.addOperand(MCOperand::CreateReg(ARM::PC));
887    LdStInst.addOperand(MCOperand::CreateReg(MI->getOperand(1).getReg()));
888    LdStInst.addOperand(MCOperand::CreateImm(0));
889    // Add predicate operands.
890    LdStInst.addOperand(MCOperand::CreateImm(MI->getOperand(3).getImm()));
891    LdStInst.addOperand(MCOperand::CreateReg(MI->getOperand(4).getReg()));
892    OutStreamer.EmitInstruction(LdStInst);
893
894    return;
895  }
896  case ARM::CONSTPOOL_ENTRY: {
897    /// CONSTPOOL_ENTRY - This instruction represents a floating constant pool
898    /// in the function.  The first operand is the ID# for this instruction, the
899    /// second is the index into the MachineConstantPool that this is, the third
900    /// is the size in bytes of this constant pool entry.
901    unsigned LabelId = (unsigned)MI->getOperand(0).getImm();
902    unsigned CPIdx   = (unsigned)MI->getOperand(1).getIndex();
903
904    EmitAlignment(2);
905    OutStreamer.EmitLabel(GetCPISymbol(LabelId));
906
907    const MachineConstantPoolEntry &MCPE = MCP->getConstants()[CPIdx];
908    if (MCPE.isMachineConstantPoolEntry())
909      EmitMachineConstantPoolValue(MCPE.Val.MachineCPVal);
910    else
911      EmitGlobalConstant(MCPE.Val.ConstVal);
912
913    return;
914  }
915  case ARM::t2TBB:
916  case ARM::t2TBH:
917  case ARM::t2BR_JT: {
918    // Lower and emit the instruction itself, then the jump table following it.
919    MCInst TmpInst;
920    MCInstLowering.Lower(MI, TmpInst);
921    OutStreamer.EmitInstruction(TmpInst);
922    EmitJump2Table(MI);
923    return;
924  }
925  case ARM::tBR_JTr:
926  case ARM::BR_JTr:
927  case ARM::BR_JTm:
928  case ARM::BR_JTadd: {
929    // Lower and emit the instruction itself, then the jump table following it.
930    MCInst TmpInst;
931    MCInstLowering.Lower(MI, TmpInst);
932    OutStreamer.EmitInstruction(TmpInst);
933    EmitJumpTable(MI);
934    return;
935  }
936  case ARM::TRAP: {
937    // Non-Darwin binutils don't yet support the "trap" mnemonic.
938    // FIXME: Remove this special case when they do.
939    if (!Subtarget->isTargetDarwin()) {
940      //.long 0xe7ffdefe @ trap
941      uint32_t Val = 0xe7ffdefeUL;
942      OutStreamer.AddComment("trap");
943      OutStreamer.EmitIntValue(Val, 4);
944      return;
945    }
946    break;
947  }
948  case ARM::tTRAP: {
949    // Non-Darwin binutils don't yet support the "trap" mnemonic.
950    // FIXME: Remove this special case when they do.
951    if (!Subtarget->isTargetDarwin()) {
952      //.short 57086 @ trap
953      uint16_t Val = 0xdefe;
954      OutStreamer.AddComment("trap");
955      OutStreamer.EmitIntValue(Val, 2);
956      return;
957    }
958    break;
959  }
960  case ARM::t2Int_eh_sjlj_setjmp:
961  case ARM::t2Int_eh_sjlj_setjmp_nofp:
962  case ARM::tInt_eh_sjlj_setjmp: {
963    // Two incoming args: GPR:$src, GPR:$val
964    // mov $val, pc
965    // adds $val, #7
966    // str $val, [$src, #4]
967    // movs r0, #0
968    // b 1f
969    // movs r0, #1
970    // 1:
971    unsigned SrcReg = MI->getOperand(0).getReg();
972    unsigned ValReg = MI->getOperand(1).getReg();
973    MCSymbol *Label = GetARMSJLJEHLabel();
974    {
975      MCInst TmpInst;
976      TmpInst.setOpcode(ARM::tMOVgpr2tgpr);
977      TmpInst.addOperand(MCOperand::CreateReg(ValReg));
978      TmpInst.addOperand(MCOperand::CreateReg(ARM::PC));
979      // 's' bit operand
980      TmpInst.addOperand(MCOperand::CreateReg(ARM::CPSR));
981      OutStreamer.AddComment("eh_setjmp begin");
982      OutStreamer.EmitInstruction(TmpInst);
983    }
984    {
985      MCInst TmpInst;
986      TmpInst.setOpcode(ARM::tADDi3);
987      TmpInst.addOperand(MCOperand::CreateReg(ValReg));
988      // 's' bit operand
989      TmpInst.addOperand(MCOperand::CreateReg(ARM::CPSR));
990      TmpInst.addOperand(MCOperand::CreateReg(ValReg));
991      TmpInst.addOperand(MCOperand::CreateImm(7));
992      // Predicate.
993      TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
994      TmpInst.addOperand(MCOperand::CreateReg(0));
995      OutStreamer.EmitInstruction(TmpInst);
996    }
997    {
998      MCInst TmpInst;
999      TmpInst.setOpcode(ARM::tSTR);
1000      TmpInst.addOperand(MCOperand::CreateReg(ValReg));
1001      TmpInst.addOperand(MCOperand::CreateReg(SrcReg));
1002      // The offset immediate is #4. The operand value is scaled by 4 for the
1003      // tSTR instruction.
1004      TmpInst.addOperand(MCOperand::CreateImm(1));
1005      TmpInst.addOperand(MCOperand::CreateReg(0));
1006      // Predicate.
1007      TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
1008      TmpInst.addOperand(MCOperand::CreateReg(0));
1009      OutStreamer.EmitInstruction(TmpInst);
1010    }
1011    {
1012      MCInst TmpInst;
1013      TmpInst.setOpcode(ARM::tMOVi8);
1014      TmpInst.addOperand(MCOperand::CreateReg(ARM::R0));
1015      TmpInst.addOperand(MCOperand::CreateReg(ARM::CPSR));
1016      TmpInst.addOperand(MCOperand::CreateImm(0));
1017      // Predicate.
1018      TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
1019      TmpInst.addOperand(MCOperand::CreateReg(0));
1020      OutStreamer.EmitInstruction(TmpInst);
1021    }
1022    {
1023      const MCExpr *SymbolExpr = MCSymbolRefExpr::Create(Label, OutContext);
1024      MCInst TmpInst;
1025      TmpInst.setOpcode(ARM::tB);
1026      TmpInst.addOperand(MCOperand::CreateExpr(SymbolExpr));
1027      OutStreamer.EmitInstruction(TmpInst);
1028    }
1029    {
1030      MCInst TmpInst;
1031      TmpInst.setOpcode(ARM::tMOVi8);
1032      TmpInst.addOperand(MCOperand::CreateReg(ARM::R0));
1033      TmpInst.addOperand(MCOperand::CreateReg(ARM::CPSR));
1034      TmpInst.addOperand(MCOperand::CreateImm(1));
1035      // Predicate.
1036      TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
1037      TmpInst.addOperand(MCOperand::CreateReg(0));
1038      OutStreamer.AddComment("eh_setjmp end");
1039      OutStreamer.EmitInstruction(TmpInst);
1040    }
1041    OutStreamer.EmitLabel(Label);
1042    return;
1043  }
1044
1045  case ARM::Int_eh_sjlj_setjmp_nofp:
1046  case ARM::Int_eh_sjlj_setjmp: {
1047    // Two incoming args: GPR:$src, GPR:$val
1048    // add $val, pc, #8
1049    // str $val, [$src, #+4]
1050    // mov r0, #0
1051    // add pc, pc, #0
1052    // mov r0, #1
1053    unsigned SrcReg = MI->getOperand(0).getReg();
1054    unsigned ValReg = MI->getOperand(1).getReg();
1055
1056    {
1057      MCInst TmpInst;
1058      TmpInst.setOpcode(ARM::ADDri);
1059      TmpInst.addOperand(MCOperand::CreateReg(ValReg));
1060      TmpInst.addOperand(MCOperand::CreateReg(ARM::PC));
1061      TmpInst.addOperand(MCOperand::CreateImm(8));
1062      // Predicate.
1063      TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
1064      TmpInst.addOperand(MCOperand::CreateReg(0));
1065      // 's' bit operand (always reg0 for this).
1066      TmpInst.addOperand(MCOperand::CreateReg(0));
1067      OutStreamer.AddComment("eh_setjmp begin");
1068      OutStreamer.EmitInstruction(TmpInst);
1069    }
1070    {
1071      MCInst TmpInst;
1072      TmpInst.setOpcode(ARM::STRi12);
1073      TmpInst.addOperand(MCOperand::CreateReg(ValReg));
1074      TmpInst.addOperand(MCOperand::CreateReg(SrcReg));
1075      TmpInst.addOperand(MCOperand::CreateImm(4));
1076      // Predicate.
1077      TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
1078      TmpInst.addOperand(MCOperand::CreateReg(0));
1079      OutStreamer.EmitInstruction(TmpInst);
1080    }
1081    {
1082      MCInst TmpInst;
1083      TmpInst.setOpcode(ARM::MOVi);
1084      TmpInst.addOperand(MCOperand::CreateReg(ARM::R0));
1085      TmpInst.addOperand(MCOperand::CreateImm(0));
1086      // Predicate.
1087      TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
1088      TmpInst.addOperand(MCOperand::CreateReg(0));
1089      // 's' bit operand (always reg0 for this).
1090      TmpInst.addOperand(MCOperand::CreateReg(0));
1091      OutStreamer.EmitInstruction(TmpInst);
1092    }
1093    {
1094      MCInst TmpInst;
1095      TmpInst.setOpcode(ARM::ADDri);
1096      TmpInst.addOperand(MCOperand::CreateReg(ARM::PC));
1097      TmpInst.addOperand(MCOperand::CreateReg(ARM::PC));
1098      TmpInst.addOperand(MCOperand::CreateImm(0));
1099      // Predicate.
1100      TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
1101      TmpInst.addOperand(MCOperand::CreateReg(0));
1102      // 's' bit operand (always reg0 for this).
1103      TmpInst.addOperand(MCOperand::CreateReg(0));
1104      OutStreamer.EmitInstruction(TmpInst);
1105    }
1106    {
1107      MCInst TmpInst;
1108      TmpInst.setOpcode(ARM::MOVi);
1109      TmpInst.addOperand(MCOperand::CreateReg(ARM::R0));
1110      TmpInst.addOperand(MCOperand::CreateImm(1));
1111      // Predicate.
1112      TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
1113      TmpInst.addOperand(MCOperand::CreateReg(0));
1114      // 's' bit operand (always reg0 for this).
1115      TmpInst.addOperand(MCOperand::CreateReg(0));
1116      OutStreamer.AddComment("eh_setjmp end");
1117      OutStreamer.EmitInstruction(TmpInst);
1118    }
1119    return;
1120  }
1121  case ARM::Int_eh_sjlj_longjmp: {
1122    // ldr sp, [$src, #8]
1123    // ldr $scratch, [$src, #4]
1124    // ldr r7, [$src]
1125    // bx $scratch
1126    unsigned SrcReg = MI->getOperand(0).getReg();
1127    unsigned ScratchReg = MI->getOperand(1).getReg();
1128    {
1129      MCInst TmpInst;
1130      TmpInst.setOpcode(ARM::LDRi12);
1131      TmpInst.addOperand(MCOperand::CreateReg(ARM::SP));
1132      TmpInst.addOperand(MCOperand::CreateReg(SrcReg));
1133      TmpInst.addOperand(MCOperand::CreateImm(8));
1134      // Predicate.
1135      TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
1136      TmpInst.addOperand(MCOperand::CreateReg(0));
1137      OutStreamer.EmitInstruction(TmpInst);
1138    }
1139    {
1140      MCInst TmpInst;
1141      TmpInst.setOpcode(ARM::LDRi12);
1142      TmpInst.addOperand(MCOperand::CreateReg(ScratchReg));
1143      TmpInst.addOperand(MCOperand::CreateReg(SrcReg));
1144      TmpInst.addOperand(MCOperand::CreateImm(4));
1145      // Predicate.
1146      TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
1147      TmpInst.addOperand(MCOperand::CreateReg(0));
1148      OutStreamer.EmitInstruction(TmpInst);
1149    }
1150    {
1151      MCInst TmpInst;
1152      TmpInst.setOpcode(ARM::LDRi12);
1153      TmpInst.addOperand(MCOperand::CreateReg(ARM::R7));
1154      TmpInst.addOperand(MCOperand::CreateReg(SrcReg));
1155      TmpInst.addOperand(MCOperand::CreateImm(0));
1156      // Predicate.
1157      TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
1158      TmpInst.addOperand(MCOperand::CreateReg(0));
1159      OutStreamer.EmitInstruction(TmpInst);
1160    }
1161    {
1162      MCInst TmpInst;
1163      TmpInst.setOpcode(ARM::BRIND);
1164      TmpInst.addOperand(MCOperand::CreateReg(ScratchReg));
1165      // Predicate.
1166      TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
1167      TmpInst.addOperand(MCOperand::CreateReg(0));
1168      OutStreamer.EmitInstruction(TmpInst);
1169    }
1170    return;
1171  }
1172  case ARM::tInt_eh_sjlj_longjmp: {
1173    // ldr $scratch, [$src, #8]
1174    // mov sp, $scratch
1175    // ldr $scratch, [$src, #4]
1176    // ldr r7, [$src]
1177    // bx $scratch
1178    unsigned SrcReg = MI->getOperand(0).getReg();
1179    unsigned ScratchReg = MI->getOperand(1).getReg();
1180    {
1181      MCInst TmpInst;
1182      TmpInst.setOpcode(ARM::tLDR);
1183      TmpInst.addOperand(MCOperand::CreateReg(ScratchReg));
1184      TmpInst.addOperand(MCOperand::CreateReg(SrcReg));
1185      // The offset immediate is #8. The operand value is scaled by 4 for the
1186      // tSTR instruction.
1187      TmpInst.addOperand(MCOperand::CreateImm(2));
1188      TmpInst.addOperand(MCOperand::CreateReg(0));
1189      // Predicate.
1190      TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
1191      TmpInst.addOperand(MCOperand::CreateReg(0));
1192      OutStreamer.EmitInstruction(TmpInst);
1193    }
1194    {
1195      MCInst TmpInst;
1196      TmpInst.setOpcode(ARM::tMOVtgpr2gpr);
1197      TmpInst.addOperand(MCOperand::CreateReg(ARM::SP));
1198      TmpInst.addOperand(MCOperand::CreateReg(ScratchReg));
1199      // Predicate.
1200      TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
1201      TmpInst.addOperand(MCOperand::CreateReg(0));
1202      OutStreamer.EmitInstruction(TmpInst);
1203    }
1204    {
1205      MCInst TmpInst;
1206      TmpInst.setOpcode(ARM::tLDR);
1207      TmpInst.addOperand(MCOperand::CreateReg(ScratchReg));
1208      TmpInst.addOperand(MCOperand::CreateReg(SrcReg));
1209      TmpInst.addOperand(MCOperand::CreateImm(1));
1210      TmpInst.addOperand(MCOperand::CreateReg(0));
1211      // Predicate.
1212      TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
1213      TmpInst.addOperand(MCOperand::CreateReg(0));
1214      OutStreamer.EmitInstruction(TmpInst);
1215    }
1216    {
1217      MCInst TmpInst;
1218      TmpInst.setOpcode(ARM::tLDR);
1219      TmpInst.addOperand(MCOperand::CreateReg(ARM::R7));
1220      TmpInst.addOperand(MCOperand::CreateReg(SrcReg));
1221      TmpInst.addOperand(MCOperand::CreateImm(0));
1222      TmpInst.addOperand(MCOperand::CreateReg(0));
1223      // Predicate.
1224      TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
1225      TmpInst.addOperand(MCOperand::CreateReg(0));
1226      OutStreamer.EmitInstruction(TmpInst);
1227    }
1228    {
1229      MCInst TmpInst;
1230      TmpInst.setOpcode(ARM::tBX_RET_vararg);
1231      TmpInst.addOperand(MCOperand::CreateReg(ScratchReg));
1232      // Predicate.
1233      TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
1234      TmpInst.addOperand(MCOperand::CreateReg(0));
1235      OutStreamer.EmitInstruction(TmpInst);
1236    }
1237    return;
1238  }
1239  }
1240
1241  MCInst TmpInst;
1242  MCInstLowering.Lower(MI, TmpInst);
1243  OutStreamer.EmitInstruction(TmpInst);
1244}
1245
1246//===----------------------------------------------------------------------===//
1247// Target Registry Stuff
1248//===----------------------------------------------------------------------===//
1249
1250static MCInstPrinter *createARMMCInstPrinter(const Target &T,
1251                                             unsigned SyntaxVariant,
1252                                             const MCAsmInfo &MAI) {
1253  if (SyntaxVariant == 0)
1254    return new ARMInstPrinter(MAI);
1255  return 0;
1256}
1257
1258// Force static initialization.
1259extern "C" void LLVMInitializeARMAsmPrinter() {
1260  RegisterAsmPrinter<ARMAsmPrinter> X(TheARMTarget);
1261  RegisterAsmPrinter<ARMAsmPrinter> Y(TheThumbTarget);
1262
1263  TargetRegistry::RegisterMCInstPrinter(TheARMTarget, createARMMCInstPrinter);
1264  TargetRegistry::RegisterMCInstPrinter(TheThumbTarget, createARMMCInstPrinter);
1265}
1266
1267