1 //===-- ARMAsmPrinter.cpp - Print machine code to an ARM .s file ----------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file contains a printer that converts from our internal representation
11 // of machine-dependent LLVM code to GAS-format ARM assembly language.
13 //===----------------------------------------------------------------------===//
15 #define DEBUG_TYPE "asm-printer"
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"
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 {
75 virtual void MaybeSwitchVendor(StringRef Vendor) = 0;
76 virtual void EmitAttribute(unsigned Attribute, unsigned Value) = 0;
77 virtual void Finish() = 0;
78 virtual ~AttributeEmitter() {}
81 class AsmAttributeEmitter : public AttributeEmitter {
85 AsmAttributeEmitter(MCStreamer &Streamer_) : Streamer(Streamer_) {}
86 void MaybeSwitchVendor(StringRef Vendor) { }
88 void EmitAttribute(unsigned Attribute, unsigned Value) {
89 Streamer.EmitRawText("\t.eabi_attribute " +
90 Twine(Attribute) + ", " + Twine(Value));
96 class ObjectAttributeEmitter : public AttributeEmitter {
97 MCObjectStreamer &Streamer;
98 StringRef CurrentVendor;
99 SmallString<64> Contents;
102 ObjectAttributeEmitter(MCObjectStreamer &Streamer_) :
103 Streamer(Streamer_), CurrentVendor("") { }
105 void MaybeSwitchVendor(StringRef Vendor) {
106 assert(!Vendor.empty() && "Vendor cannot be empty.");
108 if (CurrentVendor.empty())
109 CurrentVendor = Vendor;
110 else if (CurrentVendor == Vendor)
115 CurrentVendor = Vendor;
117 assert(Contents.size() == 0);
120 void EmitAttribute(unsigned Attribute, unsigned Value) {
121 // FIXME: should be ULEB
122 Contents += Attribute;
127 const size_t ContentsSize = Contents.size();
129 // Vendor size + Vendor name + '\0'
130 const size_t VendorHeaderSize = 4 + CurrentVendor.size() + 1;
133 const size_t TagHeaderSize = 1 + 4;
135 Streamer.EmitIntValue(VendorHeaderSize + TagHeaderSize + ContentsSize, 4);
136 Streamer.EmitBytes(CurrentVendor, 0);
137 Streamer.EmitIntValue(0, 1); // '\0'
139 Streamer.EmitIntValue(ARMBuildAttrs::File, 1);
140 Streamer.EmitIntValue(TagHeaderSize + ContentsSize, 4);
142 Streamer.EmitBytes(Contents, 0);
148 class ARMAsmPrinter : public AsmPrinter {
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;
154 /// AFI - Keep a pointer to ARMFunctionInfo for the current
156 ARMFunctionInfo *AFI;
158 /// MCP - Keep a pointer to constantpool entries of the current
160 const MachineConstantPool *MCP;
163 explicit ARMAsmPrinter(TargetMachine &TM, MCStreamer &Streamer)
164 : AsmPrinter(TM, Streamer), AFI(NULL), MCP(NULL) {
165 Subtarget = &TM.getSubtarget<ARMSubtarget>();
168 virtual const char *getPassName() const {
169 return "ARM Assembly Printer";
172 void printOperand(const MachineInstr *MI, int OpNum, raw_ostream &O,
173 const char *Modifier = 0);
175 virtual bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNum,
176 unsigned AsmVariant, const char *ExtraCode,
178 virtual bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNum,
180 const char *ExtraCode, raw_ostream &O);
182 void EmitJumpTable(const MachineInstr *MI);
183 void EmitJump2Table(const MachineInstr *MI);
184 virtual void EmitInstruction(const MachineInstr *MI);
185 bool runOnMachineFunction(MachineFunction &F);
187 virtual void EmitConstantPool() {} // we emit constant pools customly!
188 virtual void EmitFunctionEntryLabel();
189 void EmitStartOfAsmFile(Module &M);
190 void EmitEndOfAsmFile(Module &M);
193 // Helpers for EmitStartOfAsmFile() and EmitEndOfAsmFile()
194 void emitAttributes();
196 // Helper for ELF .o only
197 void emitARMAttributeSection();
200 void PrintDebugValueComment(const MachineInstr *MI, raw_ostream &OS);
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());
209 DEBUG(dbgs() << "DBG_VALUE instruction ignored! " << *MI << "\n");
214 virtual unsigned getISAEncoding() {
215 // ARM/Darwin adds ISA to the DWARF info for each function.
216 if (!Subtarget->isTargetDarwin())
218 return Subtarget->isThumb() ?
219 llvm::ARM::DW_ISA_ARM_thumb : llvm::ARM::DW_ISA_ARM_arm;
222 MCSymbol *GetARMSetPICJumpTableLabel2(unsigned uid, unsigned uid2,
223 const MachineBasicBlock *MBB) const;
224 MCSymbol *GetARMJTIPICJumpTableLabel2(unsigned uid, unsigned uid2) const;
226 MCSymbol *GetARMSJLJEHLabel(void) const;
228 /// EmitMachineConstantPoolValue - Print a machine constantpool value to
230 virtual void EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) {
231 int Size = TM.getTargetData()->getTypeAllocSize(MCPV->getType());
233 ARMConstantPoolValue *ACPV = static_cast<ARMConstantPoolValue*>(MCPV);
234 SmallString<128> Str;
235 raw_svector_ostream OS(Str);
237 if (ACPV->isLSDA()) {
238 OS << MAI->getPrivateGlobalPrefix() << "_LSDA_" << getFunctionNumber();
239 } else if (ACPV->isBlockAddress()) {
240 OS << *GetBlockAddressSymbol(ACPV->getBlockAddress());
241 } else if (ACPV->isGlobalValue()) {
242 const GlobalValue *GV = ACPV->getGV();
243 bool isIndirect = Subtarget->isTargetDarwin() &&
244 Subtarget->GVIsIndirectSymbol(GV, TM.getRelocationModel());
246 OS << *Mang->getSymbol(GV);
248 // FIXME: Remove this when Darwin transition to @GOT like syntax.
249 MCSymbol *Sym = GetSymbolWithGlobalValueBase(GV, "$non_lazy_ptr");
252 MachineModuleInfoMachO &MMIMachO =
253 MMI->getObjFileInfo<MachineModuleInfoMachO>();
254 MachineModuleInfoImpl::StubValueTy &StubSym =
255 GV->hasHiddenVisibility() ? MMIMachO.getHiddenGVStubEntry(Sym) :
256 MMIMachO.getGVStubEntry(Sym);
257 if (StubSym.getPointer() == 0)
258 StubSym = MachineModuleInfoImpl::
259 StubValueTy(Mang->getSymbol(GV), !GV->hasInternalLinkage());
262 assert(ACPV->isExtSymbol() && "unrecognized constant pool value");
263 OS << *GetExternalSymbolSymbol(ACPV->getSymbol());
266 // Create an MCSymbol for the reference.
267 MCSymbol *MCSym = OutContext.GetOrCreateSymbol(OS.str());
268 const MCExpr *Expr = MCSymbolRefExpr::Create(MCSym, OutContext);
270 // FIXME: Model the whole expression an an MCExpr and we can get rid
271 // of this hasRawTextSupport() clause and just do an EmitValue().
272 if (OutStreamer.hasRawTextSupport()) {
273 if (ACPV->hasModifier()) OS << "(" << ACPV->getModifier() << ")";
274 if (ACPV->getPCAdjustment() != 0) {
275 OS << "-(" << MAI->getPrivateGlobalPrefix() << "PC"
276 << getFunctionNumber() << "_" << ACPV->getLabelId()
277 << "+" << (unsigned)ACPV->getPCAdjustment();
278 if (ACPV->mustAddCurrentAddress())
282 const char *DataDirective = 0;
284 case 1: DataDirective = MAI->getData8bitsDirective(0); break;
285 case 2: DataDirective = MAI->getData16bitsDirective(0); break;
286 case 4: DataDirective = MAI->getData32bitsDirective(0); break;
287 default: assert(0 && "Unknown CPV size");
289 Twine Text(DataDirective, OS.str());
290 OutStreamer.EmitRawText(Text);
292 assert(!ACPV->hasModifier() && ACPV->getPCAdjustment() == 0 &&
293 "ARM binary streamer of non-trivial constant pool value!");
294 OutStreamer.EmitValue(Expr, Size);
298 } // end of anonymous namespace
300 void ARMAsmPrinter::EmitFunctionEntryLabel() {
301 if (AFI->isThumbFunction()) {
302 OutStreamer.EmitRawText(StringRef("\t.code\t16"));
303 if (!Subtarget->isTargetDarwin())
304 OutStreamer.EmitRawText(StringRef("\t.thumb_func"));
306 // This needs to emit to a temporary string to get properly quoted
307 // MCSymbols when they have spaces in them.
308 SmallString<128> Tmp;
309 raw_svector_ostream OS(Tmp);
310 OS << "\t.thumb_func\t" << *CurrentFnSym;
311 OutStreamer.EmitRawText(OS.str());
315 OutStreamer.EmitLabel(CurrentFnSym);
318 /// runOnMachineFunction - This uses the EmitInstruction()
319 /// method to print assembly for each instruction.
321 bool ARMAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
322 AFI = MF.getInfo<ARMFunctionInfo>();
323 MCP = MF.getConstantPool();
325 return AsmPrinter::runOnMachineFunction(MF);
328 void ARMAsmPrinter::printOperand(const MachineInstr *MI, int OpNum,
329 raw_ostream &O, const char *Modifier) {
330 const MachineOperand &MO = MI->getOperand(OpNum);
331 unsigned TF = MO.getTargetFlags();
333 switch (MO.getType()) {
335 assert(0 && "<unknown operand type>");
336 case MachineOperand::MO_Register: {
337 unsigned Reg = MO.getReg();
338 assert(TargetRegisterInfo::isPhysicalRegister(Reg));
339 assert(!MO.getSubReg() && "Subregs should be eliminated!");
340 O << ARMInstPrinter::getRegisterName(Reg);
343 case MachineOperand::MO_Immediate: {
344 int64_t Imm = MO.getImm();
346 if ((Modifier && strcmp(Modifier, "lo16") == 0) ||
347 (TF == ARMII::MO_LO16))
349 else if ((Modifier && strcmp(Modifier, "hi16") == 0) ||
350 (TF == ARMII::MO_HI16))
355 case MachineOperand::MO_MachineBasicBlock:
356 O << *MO.getMBB()->getSymbol();
358 case MachineOperand::MO_GlobalAddress: {
359 const GlobalValue *GV = MO.getGlobal();
360 if ((Modifier && strcmp(Modifier, "lo16") == 0) ||
361 (TF & ARMII::MO_LO16))
363 else if ((Modifier && strcmp(Modifier, "hi16") == 0) ||
364 (TF & ARMII::MO_HI16))
366 O << *Mang->getSymbol(GV);
368 printOffset(MO.getOffset(), O);
369 if (TF == ARMII::MO_PLT)
373 case MachineOperand::MO_ExternalSymbol: {
374 O << *GetExternalSymbolSymbol(MO.getSymbolName());
375 if (TF == ARMII::MO_PLT)
379 case MachineOperand::MO_ConstantPoolIndex:
380 O << *GetCPISymbol(MO.getIndex());
382 case MachineOperand::MO_JumpTableIndex:
383 O << *GetJTISymbol(MO.getIndex());
388 //===--------------------------------------------------------------------===//
390 MCSymbol *ARMAsmPrinter::
391 GetARMSetPICJumpTableLabel2(unsigned uid, unsigned uid2,
392 const MachineBasicBlock *MBB) const {
393 SmallString<60> Name;
394 raw_svector_ostream(Name) << MAI->getPrivateGlobalPrefix()
395 << getFunctionNumber() << '_' << uid << '_' << uid2
396 << "_set_" << MBB->getNumber();
397 return OutContext.GetOrCreateSymbol(Name.str());
400 MCSymbol *ARMAsmPrinter::
401 GetARMJTIPICJumpTableLabel2(unsigned uid, unsigned uid2) const {
402 SmallString<60> Name;
403 raw_svector_ostream(Name) << MAI->getPrivateGlobalPrefix() << "JTI"
404 << getFunctionNumber() << '_' << uid << '_' << uid2;
405 return OutContext.GetOrCreateSymbol(Name.str());
409 MCSymbol *ARMAsmPrinter::GetARMSJLJEHLabel(void) const {
410 SmallString<60> Name;
411 raw_svector_ostream(Name) << MAI->getPrivateGlobalPrefix() << "SJLJEH"
412 << getFunctionNumber();
413 return OutContext.GetOrCreateSymbol(Name.str());
416 bool ARMAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNum,
417 unsigned AsmVariant, const char *ExtraCode,
419 // Does this asm operand have a single letter operand modifier?
420 if (ExtraCode && ExtraCode[0]) {
421 if (ExtraCode[1] != 0) return true; // Unknown modifier.
423 switch (ExtraCode[0]) {
424 default: return true; // Unknown modifier.
425 case 'a': // Print as a memory address.
426 if (MI->getOperand(OpNum).isReg()) {
428 << ARMInstPrinter::getRegisterName(MI->getOperand(OpNum).getReg())
433 case 'c': // Don't print "#" before an immediate operand.
434 if (!MI->getOperand(OpNum).isImm())
436 O << MI->getOperand(OpNum).getImm();
438 case 'P': // Print a VFP double precision register.
439 case 'q': // Print a NEON quad precision register.
440 printOperand(MI, OpNum, O);
445 report_fatal_error("llvm does not support 'Q', 'R', and 'H' modifiers!");
450 printOperand(MI, OpNum, O);
454 bool ARMAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
455 unsigned OpNum, unsigned AsmVariant,
456 const char *ExtraCode,
458 if (ExtraCode && ExtraCode[0])
459 return true; // Unknown modifier.
461 const MachineOperand &MO = MI->getOperand(OpNum);
462 assert(MO.isReg() && "unexpected inline asm memory operand");
463 O << "[" << ARMInstPrinter::getRegisterName(MO.getReg()) << "]";
467 void ARMAsmPrinter::EmitStartOfAsmFile(Module &M) {
468 if (Subtarget->isTargetDarwin()) {
469 Reloc::Model RelocM = TM.getRelocationModel();
470 if (RelocM == Reloc::PIC_ || RelocM == Reloc::DynamicNoPIC) {
471 // Declare all the text sections up front (before the DWARF sections
472 // emitted by AsmPrinter::doInitialization) so the assembler will keep
473 // them together at the beginning of the object file. This helps
474 // avoid out-of-range branches that are due a fundamental limitation of
475 // the way symbol offsets are encoded with the current Darwin ARM
477 const TargetLoweringObjectFileMachO &TLOFMacho =
478 static_cast<const TargetLoweringObjectFileMachO &>(
479 getObjFileLowering());
480 OutStreamer.SwitchSection(TLOFMacho.getTextSection());
481 OutStreamer.SwitchSection(TLOFMacho.getTextCoalSection());
482 OutStreamer.SwitchSection(TLOFMacho.getConstTextCoalSection());
483 if (RelocM == Reloc::DynamicNoPIC) {
484 const MCSection *sect =
485 OutContext.getMachOSection("__TEXT", "__symbol_stub4",
486 MCSectionMachO::S_SYMBOL_STUBS,
487 12, SectionKind::getText());
488 OutStreamer.SwitchSection(sect);
490 const MCSection *sect =
491 OutContext.getMachOSection("__TEXT", "__picsymbolstub4",
492 MCSectionMachO::S_SYMBOL_STUBS,
493 16, SectionKind::getText());
494 OutStreamer.SwitchSection(sect);
496 const MCSection *StaticInitSect =
497 OutContext.getMachOSection("__TEXT", "__StaticInit",
498 MCSectionMachO::S_REGULAR |
499 MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS,
500 SectionKind::getText());
501 OutStreamer.SwitchSection(StaticInitSect);
505 // Use unified assembler syntax.
506 OutStreamer.EmitAssemblerFlag(MCAF_SyntaxUnified);
508 // Emit ARM Build Attributes
509 if (Subtarget->isTargetELF()) {
516 void ARMAsmPrinter::EmitEndOfAsmFile(Module &M) {
517 if (Subtarget->isTargetDarwin()) {
518 // All darwin targets use mach-o.
519 const TargetLoweringObjectFileMachO &TLOFMacho =
520 static_cast<const TargetLoweringObjectFileMachO &>(getObjFileLowering());
521 MachineModuleInfoMachO &MMIMacho =
522 MMI->getObjFileInfo<MachineModuleInfoMachO>();
524 // Output non-lazy-pointers for external and common global variables.
525 MachineModuleInfoMachO::SymbolListTy Stubs = MMIMacho.GetGVStubList();
527 if (!Stubs.empty()) {
528 // Switch with ".non_lazy_symbol_pointer" directive.
529 OutStreamer.SwitchSection(TLOFMacho.getNonLazySymbolPointerSection());
531 for (unsigned i = 0, e = Stubs.size(); i != e; ++i) {
533 OutStreamer.EmitLabel(Stubs[i].first);
534 // .indirect_symbol _foo
535 MachineModuleInfoImpl::StubValueTy &MCSym = Stubs[i].second;
536 OutStreamer.EmitSymbolAttribute(MCSym.getPointer(),MCSA_IndirectSymbol);
539 // External to current translation unit.
540 OutStreamer.EmitIntValue(0, 4/*size*/, 0/*addrspace*/);
542 // Internal to current translation unit.
544 // When we place the LSDA into the TEXT section, the type info
545 // pointers need to be indirect and pc-rel. We accomplish this by
546 // using NLPs; however, sometimes the types are local to the file.
547 // We need to fill in the value for the NLP in those cases.
548 OutStreamer.EmitValue(MCSymbolRefExpr::Create(MCSym.getPointer(),
550 4/*size*/, 0/*addrspace*/);
554 OutStreamer.AddBlankLine();
557 Stubs = MMIMacho.GetHiddenGVStubList();
558 if (!Stubs.empty()) {
559 OutStreamer.SwitchSection(getObjFileLowering().getDataSection());
561 for (unsigned i = 0, e = Stubs.size(); i != e; ++i) {
563 OutStreamer.EmitLabel(Stubs[i].first);
565 OutStreamer.EmitValue(MCSymbolRefExpr::
566 Create(Stubs[i].second.getPointer(),
568 4/*size*/, 0/*addrspace*/);
572 OutStreamer.AddBlankLine();
575 // Funny Darwin hack: This flag tells the linker that no global symbols
576 // contain code that falls through to other global symbols (e.g. the obvious
577 // implementation of multiple entry points). If this doesn't occur, the
578 // linker can safely perform dead code stripping. Since LLVM never
579 // generates code that does this, it is always safe to set.
580 OutStreamer.EmitAssemblerFlag(MCAF_SubsectionsViaSymbols);
584 //===----------------------------------------------------------------------===//
585 // Helper routines for EmitStartOfAsmFile() and EmitEndOfAsmFile()
587 // The following seem like one-off assembler flags, but they actually need
588 // to appear in the .ARM.attributes section in ELF.
589 // Instead of subclassing the MCELFStreamer, we do the work here.
591 void ARMAsmPrinter::emitAttributes() {
593 emitARMAttributeSection();
595 AttributeEmitter *AttrEmitter;
596 if (OutStreamer.hasRawTextSupport())
597 AttrEmitter = new AsmAttributeEmitter(OutStreamer);
599 MCObjectStreamer &O = static_cast<MCObjectStreamer&>(OutStreamer);
600 AttrEmitter = new ObjectAttributeEmitter(O);
603 AttrEmitter->MaybeSwitchVendor("aeabi");
605 std::string CPUString = Subtarget->getCPUString();
606 if (OutStreamer.hasRawTextSupport()) {
607 if (CPUString != "generic")
608 OutStreamer.EmitRawText(StringRef("\t.cpu ") + CPUString);
610 assert(CPUString == "generic" && "Unsupported .cpu attribute for ELF/.o");
611 // FIXME: Why these defaults?
612 AttrEmitter->EmitAttribute(ARMBuildAttrs::CPU_arch, ARMBuildAttrs::v4T);
613 AttrEmitter->EmitAttribute(ARMBuildAttrs::ARM_ISA_use, 1);
614 AttrEmitter->EmitAttribute(ARMBuildAttrs::THUMB_ISA_use, 1);
617 // FIXME: Emit FPU type
618 if (Subtarget->hasVFP2())
619 AttrEmitter->EmitAttribute(ARMBuildAttrs::VFP_arch, 2);
621 // Signal various FP modes.
623 AttrEmitter->EmitAttribute(ARMBuildAttrs::ABI_FP_denormal, 1);
624 AttrEmitter->EmitAttribute(ARMBuildAttrs::ABI_FP_exceptions, 1);
627 if (NoInfsFPMath && NoNaNsFPMath)
628 AttrEmitter->EmitAttribute(ARMBuildAttrs::ABI_FP_number_model, 1);
630 AttrEmitter->EmitAttribute(ARMBuildAttrs::ABI_FP_number_model, 3);
632 // 8-bytes alignment stuff.
633 AttrEmitter->EmitAttribute(ARMBuildAttrs::ABI_align8_needed, 1);
634 AttrEmitter->EmitAttribute(ARMBuildAttrs::ABI_align8_preserved, 1);
636 // Hard float. Use both S and D registers and conform to AAPCS-VFP.
637 if (Subtarget->isAAPCS_ABI() && FloatABIType == FloatABI::Hard) {
638 AttrEmitter->EmitAttribute(ARMBuildAttrs::ABI_HardFP_use, 3);
639 AttrEmitter->EmitAttribute(ARMBuildAttrs::ABI_VFP_args, 1);
641 // FIXME: Should we signal R9 usage?
643 AttrEmitter->EmitAttribute(ARMBuildAttrs::DIV_use, 1);
645 AttrEmitter->Finish();
649 void ARMAsmPrinter::emitARMAttributeSection() {
651 // [ <section-length> "vendor-name"
652 // [ <file-tag> <size> <attribute>*
653 // | <section-tag> <size> <section-number>* 0 <attribute>*
654 // | <symbol-tag> <size> <symbol-number>* 0 <attribute>*
658 if (OutStreamer.hasRawTextSupport())
661 const ARMElfTargetObjectFile &TLOFELF =
662 static_cast<const ARMElfTargetObjectFile &>
663 (getObjFileLowering());
665 OutStreamer.SwitchSection(TLOFELF.getAttributesSection());
668 OutStreamer.EmitIntValue(0x41, 1);
671 //===----------------------------------------------------------------------===//
673 static MCSymbol *getPICLabel(const char *Prefix, unsigned FunctionNumber,
674 unsigned LabelId, MCContext &Ctx) {
676 MCSymbol *Label = Ctx.GetOrCreateSymbol(Twine(Prefix)
677 + "PC" + Twine(FunctionNumber) + "_" + Twine(LabelId));
681 void ARMAsmPrinter::EmitJumpTable(const MachineInstr *MI) {
682 unsigned Opcode = MI->getOpcode();
684 if (Opcode == ARM::BR_JTadd)
686 else if (Opcode == ARM::BR_JTm)
689 const MachineOperand &MO1 = MI->getOperand(OpNum);
690 const MachineOperand &MO2 = MI->getOperand(OpNum+1); // Unique Id
691 unsigned JTI = MO1.getIndex();
693 // Emit a label for the jump table.
694 MCSymbol *JTISymbol = GetARMJTIPICJumpTableLabel2(JTI, MO2.getImm());
695 OutStreamer.EmitLabel(JTISymbol);
697 // Emit each entry of the table.
698 const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo();
699 const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables();
700 const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs;
702 for (unsigned i = 0, e = JTBBs.size(); i != e; ++i) {
703 MachineBasicBlock *MBB = JTBBs[i];
704 // Construct an MCExpr for the entry. We want a value of the form:
705 // (BasicBlockAddr - TableBeginAddr)
707 // For example, a table with entries jumping to basic blocks BB0 and BB1
710 // .word (LBB0 - LJTI_0_0)
711 // .word (LBB1 - LJTI_0_0)
712 const MCExpr *Expr = MCSymbolRefExpr::Create(MBB->getSymbol(), OutContext);
714 if (TM.getRelocationModel() == Reloc::PIC_)
715 Expr = MCBinaryExpr::CreateSub(Expr, MCSymbolRefExpr::Create(JTISymbol,
718 OutStreamer.EmitValue(Expr, 4);
722 void ARMAsmPrinter::EmitJump2Table(const MachineInstr *MI) {
723 unsigned Opcode = MI->getOpcode();
724 int OpNum = (Opcode == ARM::t2BR_JT) ? 2 : 1;
725 const MachineOperand &MO1 = MI->getOperand(OpNum);
726 const MachineOperand &MO2 = MI->getOperand(OpNum+1); // Unique Id
727 unsigned JTI = MO1.getIndex();
729 // Emit a label for the jump table.
730 MCSymbol *JTISymbol = GetARMJTIPICJumpTableLabel2(JTI, MO2.getImm());
731 OutStreamer.EmitLabel(JTISymbol);
733 // Emit each entry of the table.
734 const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo();
735 const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables();
736 const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs;
737 unsigned OffsetWidth = 4;
738 if (MI->getOpcode() == ARM::t2TBB)
740 else if (MI->getOpcode() == ARM::t2TBH)
743 for (unsigned i = 0, e = JTBBs.size(); i != e; ++i) {
744 MachineBasicBlock *MBB = JTBBs[i];
745 const MCExpr *MBBSymbolExpr = MCSymbolRefExpr::Create(MBB->getSymbol(),
747 // If this isn't a TBB or TBH, the entries are direct branch instructions.
748 if (OffsetWidth == 4) {
750 BrInst.setOpcode(ARM::t2B);
751 BrInst.addOperand(MCOperand::CreateExpr(MBBSymbolExpr));
752 OutStreamer.EmitInstruction(BrInst);
755 // Otherwise it's an offset from the dispatch instruction. Construct an
756 // MCExpr for the entry. We want a value of the form:
757 // (BasicBlockAddr - TableBeginAddr) / 2
759 // For example, a TBB table with entries jumping to basic blocks BB0 and BB1
762 // .byte (LBB0 - LJTI_0_0) / 2
763 // .byte (LBB1 - LJTI_0_0) / 2
765 MCBinaryExpr::CreateSub(MBBSymbolExpr,
766 MCSymbolRefExpr::Create(JTISymbol, OutContext),
768 Expr = MCBinaryExpr::CreateDiv(Expr, MCConstantExpr::Create(2, OutContext),
770 OutStreamer.EmitValue(Expr, OffsetWidth);
773 // Make sure the instruction that follows TBB is 2-byte aligned.
774 // FIXME: Constant island pass should insert an "ALIGN" instruction instead.
775 if (MI->getOpcode() == ARM::t2TBB)
779 void ARMAsmPrinter::PrintDebugValueComment(const MachineInstr *MI,
781 unsigned NOps = MI->getNumOperands();
783 OS << '\t' << MAI->getCommentString() << "DEBUG_VALUE: ";
784 // cast away const; DIetc do not take const operands for some reason.
785 DIVariable V(const_cast<MDNode *>(MI->getOperand(NOps-1).getMetadata()));
788 // Frame address. Currently handles register +- offset only.
789 assert(MI->getOperand(0).isReg() && MI->getOperand(1).isImm());
790 OS << '['; printOperand(MI, 0, OS); OS << '+'; printOperand(MI, 1, OS);
793 printOperand(MI, NOps-2, OS);
796 void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) {
797 ARMMCInstLower MCInstLowering(OutContext, *Mang, *this);
798 switch (MI->getOpcode()) {
799 case ARM::t2MOVi32imm:
800 assert(0 && "Should be lowered by thumb2it pass");
802 case ARM::DBG_VALUE: {
803 if (isVerbose() && OutStreamer.hasRawTextSupport()) {
804 SmallString<128> TmpStr;
805 raw_svector_ostream OS(TmpStr);
806 PrintDebugValueComment(MI, OS);
807 OutStreamer.EmitRawText(StringRef(OS.str()));
812 // This is a pseudo op for a label + instruction sequence, which looks like:
815 // This adds the address of LPC0 to r0.
818 OutStreamer.EmitLabel(getPICLabel(MAI->getPrivateGlobalPrefix(),
819 getFunctionNumber(), MI->getOperand(2).getImm(),
822 // Form and emit the add.
824 AddInst.setOpcode(ARM::tADDhirr);
825 AddInst.addOperand(MCOperand::CreateReg(MI->getOperand(0).getReg()));
826 AddInst.addOperand(MCOperand::CreateReg(MI->getOperand(0).getReg()));
827 AddInst.addOperand(MCOperand::CreateReg(ARM::PC));
828 // Add predicate operands.
829 AddInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
830 AddInst.addOperand(MCOperand::CreateReg(0));
831 OutStreamer.EmitInstruction(AddInst);
835 // This is a pseudo op for a label + instruction sequence, which looks like:
838 // This adds the address of LPC0 to r0.
841 OutStreamer.EmitLabel(getPICLabel(MAI->getPrivateGlobalPrefix(),
842 getFunctionNumber(), MI->getOperand(2).getImm(),
845 // Form and emit the add.
847 AddInst.setOpcode(ARM::ADDrr);
848 AddInst.addOperand(MCOperand::CreateReg(MI->getOperand(0).getReg()));
849 AddInst.addOperand(MCOperand::CreateReg(ARM::PC));
850 AddInst.addOperand(MCOperand::CreateReg(MI->getOperand(1).getReg()));
851 // Add predicate operands.
852 AddInst.addOperand(MCOperand::CreateImm(MI->getOperand(3).getImm()));
853 AddInst.addOperand(MCOperand::CreateReg(MI->getOperand(4).getReg()));
854 // Add 's' bit operand (always reg0 for this)
855 AddInst.addOperand(MCOperand::CreateReg(0));
856 OutStreamer.EmitInstruction(AddInst);
866 case ARM::PICLDRSH: {
867 // This is a pseudo op for a label + instruction sequence, which looks like:
870 // The LCP0 label is referenced by a constant pool entry in order to get
871 // a PC-relative address at the ldr instruction.
874 OutStreamer.EmitLabel(getPICLabel(MAI->getPrivateGlobalPrefix(),
875 getFunctionNumber(), MI->getOperand(2).getImm(),
878 // Form and emit the load
880 switch (MI->getOpcode()) {
882 llvm_unreachable("Unexpected opcode!");
883 case ARM::PICSTR: Opcode = ARM::STRrs; break;
884 case ARM::PICSTRB: Opcode = ARM::STRBrs; break;
885 case ARM::PICSTRH: Opcode = ARM::STRH; break;
886 case ARM::PICLDR: Opcode = ARM::LDRrs; break;
887 case ARM::PICLDRB: Opcode = ARM::LDRBrs; break;
888 case ARM::PICLDRH: Opcode = ARM::LDRH; break;
889 case ARM::PICLDRSB: Opcode = ARM::LDRSB; break;
890 case ARM::PICLDRSH: Opcode = ARM::LDRSH; break;
893 LdStInst.setOpcode(Opcode);
894 LdStInst.addOperand(MCOperand::CreateReg(MI->getOperand(0).getReg()));
895 LdStInst.addOperand(MCOperand::CreateReg(ARM::PC));
896 LdStInst.addOperand(MCOperand::CreateReg(MI->getOperand(1).getReg()));
897 LdStInst.addOperand(MCOperand::CreateImm(0));
898 // Add predicate operands.
899 LdStInst.addOperand(MCOperand::CreateImm(MI->getOperand(3).getImm()));
900 LdStInst.addOperand(MCOperand::CreateReg(MI->getOperand(4).getReg()));
901 OutStreamer.EmitInstruction(LdStInst);
905 case ARM::CONSTPOOL_ENTRY: {
906 /// CONSTPOOL_ENTRY - This instruction represents a floating constant pool
907 /// in the function. The first operand is the ID# for this instruction, the
908 /// second is the index into the MachineConstantPool that this is, the third
909 /// is the size in bytes of this constant pool entry.
910 unsigned LabelId = (unsigned)MI->getOperand(0).getImm();
911 unsigned CPIdx = (unsigned)MI->getOperand(1).getIndex();
914 OutStreamer.EmitLabel(GetCPISymbol(LabelId));
916 const MachineConstantPoolEntry &MCPE = MCP->getConstants()[CPIdx];
917 if (MCPE.isMachineConstantPoolEntry())
918 EmitMachineConstantPoolValue(MCPE.Val.MachineCPVal);
920 EmitGlobalConstant(MCPE.Val.ConstVal);
927 // Lower and emit the instruction itself, then the jump table following it.
929 MCInstLowering.Lower(MI, TmpInst);
930 OutStreamer.EmitInstruction(TmpInst);
937 case ARM::BR_JTadd: {
938 // Lower and emit the instruction itself, then the jump table following it.
940 MCInstLowering.Lower(MI, TmpInst);
941 OutStreamer.EmitInstruction(TmpInst);
946 // Non-Darwin binutils don't yet support the "trap" mnemonic.
947 // FIXME: Remove this special case when they do.
948 if (!Subtarget->isTargetDarwin()) {
949 //.long 0xe7ffdefe @ trap
950 uint32_t Val = 0xe7ffdefeUL;
951 OutStreamer.AddComment("trap");
952 OutStreamer.EmitIntValue(Val, 4);
958 // Non-Darwin binutils don't yet support the "trap" mnemonic.
959 // FIXME: Remove this special case when they do.
960 if (!Subtarget->isTargetDarwin()) {
961 //.short 57086 @ trap
962 uint16_t Val = 0xdefe;
963 OutStreamer.AddComment("trap");
964 OutStreamer.EmitIntValue(Val, 2);
969 case ARM::t2Int_eh_sjlj_setjmp:
970 case ARM::t2Int_eh_sjlj_setjmp_nofp:
971 case ARM::tInt_eh_sjlj_setjmp: {
972 // Two incoming args: GPR:$src, GPR:$val
975 // str $val, [$src, #4]
980 unsigned SrcReg = MI->getOperand(0).getReg();
981 unsigned ValReg = MI->getOperand(1).getReg();
982 MCSymbol *Label = GetARMSJLJEHLabel();
985 TmpInst.setOpcode(ARM::tMOVgpr2tgpr);
986 TmpInst.addOperand(MCOperand::CreateReg(ValReg));
987 TmpInst.addOperand(MCOperand::CreateReg(ARM::PC));
989 TmpInst.addOperand(MCOperand::CreateReg(ARM::CPSR));
990 OutStreamer.AddComment("eh_setjmp begin");
991 OutStreamer.EmitInstruction(TmpInst);
995 TmpInst.setOpcode(ARM::tADDi3);
996 TmpInst.addOperand(MCOperand::CreateReg(ValReg));
998 TmpInst.addOperand(MCOperand::CreateReg(ARM::CPSR));
999 TmpInst.addOperand(MCOperand::CreateReg(ValReg));
1000 TmpInst.addOperand(MCOperand::CreateImm(7));
1002 TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
1003 TmpInst.addOperand(MCOperand::CreateReg(0));
1004 OutStreamer.EmitInstruction(TmpInst);
1008 TmpInst.setOpcode(ARM::tSTR);
1009 TmpInst.addOperand(MCOperand::CreateReg(ValReg));
1010 TmpInst.addOperand(MCOperand::CreateReg(SrcReg));
1011 // The offset immediate is #4. The operand value is scaled by 4 for the
1012 // tSTR instruction.
1013 TmpInst.addOperand(MCOperand::CreateImm(1));
1014 TmpInst.addOperand(MCOperand::CreateReg(0));
1016 TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
1017 TmpInst.addOperand(MCOperand::CreateReg(0));
1018 OutStreamer.EmitInstruction(TmpInst);
1022 TmpInst.setOpcode(ARM::tMOVi8);
1023 TmpInst.addOperand(MCOperand::CreateReg(ARM::R0));
1024 TmpInst.addOperand(MCOperand::CreateReg(ARM::CPSR));
1025 TmpInst.addOperand(MCOperand::CreateImm(0));
1027 TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
1028 TmpInst.addOperand(MCOperand::CreateReg(0));
1029 OutStreamer.EmitInstruction(TmpInst);
1032 const MCExpr *SymbolExpr = MCSymbolRefExpr::Create(Label, OutContext);
1034 TmpInst.setOpcode(ARM::tB);
1035 TmpInst.addOperand(MCOperand::CreateExpr(SymbolExpr));
1036 OutStreamer.EmitInstruction(TmpInst);
1040 TmpInst.setOpcode(ARM::tMOVi8);
1041 TmpInst.addOperand(MCOperand::CreateReg(ARM::R0));
1042 TmpInst.addOperand(MCOperand::CreateReg(ARM::CPSR));
1043 TmpInst.addOperand(MCOperand::CreateImm(1));
1045 TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
1046 TmpInst.addOperand(MCOperand::CreateReg(0));
1047 OutStreamer.AddComment("eh_setjmp end");
1048 OutStreamer.EmitInstruction(TmpInst);
1050 OutStreamer.EmitLabel(Label);
1054 case ARM::Int_eh_sjlj_setjmp_nofp:
1055 case ARM::Int_eh_sjlj_setjmp: {
1056 // Two incoming args: GPR:$src, GPR:$val
1058 // str $val, [$src, #+4]
1062 unsigned SrcReg = MI->getOperand(0).getReg();
1063 unsigned ValReg = MI->getOperand(1).getReg();
1067 TmpInst.setOpcode(ARM::ADDri);
1068 TmpInst.addOperand(MCOperand::CreateReg(ValReg));
1069 TmpInst.addOperand(MCOperand::CreateReg(ARM::PC));
1070 TmpInst.addOperand(MCOperand::CreateImm(8));
1072 TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
1073 TmpInst.addOperand(MCOperand::CreateReg(0));
1074 // 's' bit operand (always reg0 for this).
1075 TmpInst.addOperand(MCOperand::CreateReg(0));
1076 OutStreamer.AddComment("eh_setjmp begin");
1077 OutStreamer.EmitInstruction(TmpInst);
1081 TmpInst.setOpcode(ARM::STRi12);
1082 TmpInst.addOperand(MCOperand::CreateReg(ValReg));
1083 TmpInst.addOperand(MCOperand::CreateReg(SrcReg));
1084 TmpInst.addOperand(MCOperand::CreateImm(4));
1086 TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
1087 TmpInst.addOperand(MCOperand::CreateReg(0));
1088 OutStreamer.EmitInstruction(TmpInst);
1092 TmpInst.setOpcode(ARM::MOVi);
1093 TmpInst.addOperand(MCOperand::CreateReg(ARM::R0));
1094 TmpInst.addOperand(MCOperand::CreateImm(0));
1096 TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
1097 TmpInst.addOperand(MCOperand::CreateReg(0));
1098 // 's' bit operand (always reg0 for this).
1099 TmpInst.addOperand(MCOperand::CreateReg(0));
1100 OutStreamer.EmitInstruction(TmpInst);
1104 TmpInst.setOpcode(ARM::ADDri);
1105 TmpInst.addOperand(MCOperand::CreateReg(ARM::PC));
1106 TmpInst.addOperand(MCOperand::CreateReg(ARM::PC));
1107 TmpInst.addOperand(MCOperand::CreateImm(0));
1109 TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
1110 TmpInst.addOperand(MCOperand::CreateReg(0));
1111 // 's' bit operand (always reg0 for this).
1112 TmpInst.addOperand(MCOperand::CreateReg(0));
1113 OutStreamer.EmitInstruction(TmpInst);
1117 TmpInst.setOpcode(ARM::MOVi);
1118 TmpInst.addOperand(MCOperand::CreateReg(ARM::R0));
1119 TmpInst.addOperand(MCOperand::CreateImm(1));
1121 TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
1122 TmpInst.addOperand(MCOperand::CreateReg(0));
1123 // 's' bit operand (always reg0 for this).
1124 TmpInst.addOperand(MCOperand::CreateReg(0));
1125 OutStreamer.AddComment("eh_setjmp end");
1126 OutStreamer.EmitInstruction(TmpInst);
1130 case ARM::Int_eh_sjlj_longjmp: {
1131 // ldr sp, [$src, #8]
1132 // ldr $scratch, [$src, #4]
1135 unsigned SrcReg = MI->getOperand(0).getReg();
1136 unsigned ScratchReg = MI->getOperand(1).getReg();
1139 TmpInst.setOpcode(ARM::LDRi12);
1140 TmpInst.addOperand(MCOperand::CreateReg(ARM::SP));
1141 TmpInst.addOperand(MCOperand::CreateReg(SrcReg));
1142 TmpInst.addOperand(MCOperand::CreateImm(8));
1144 TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
1145 TmpInst.addOperand(MCOperand::CreateReg(0));
1146 OutStreamer.EmitInstruction(TmpInst);
1150 TmpInst.setOpcode(ARM::LDRi12);
1151 TmpInst.addOperand(MCOperand::CreateReg(ScratchReg));
1152 TmpInst.addOperand(MCOperand::CreateReg(SrcReg));
1153 TmpInst.addOperand(MCOperand::CreateImm(4));
1155 TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
1156 TmpInst.addOperand(MCOperand::CreateReg(0));
1157 OutStreamer.EmitInstruction(TmpInst);
1161 TmpInst.setOpcode(ARM::LDRi12);
1162 TmpInst.addOperand(MCOperand::CreateReg(ARM::R7));
1163 TmpInst.addOperand(MCOperand::CreateReg(SrcReg));
1164 TmpInst.addOperand(MCOperand::CreateImm(0));
1166 TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
1167 TmpInst.addOperand(MCOperand::CreateReg(0));
1168 OutStreamer.EmitInstruction(TmpInst);
1172 TmpInst.setOpcode(ARM::BRIND);
1173 TmpInst.addOperand(MCOperand::CreateReg(ScratchReg));
1175 TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
1176 TmpInst.addOperand(MCOperand::CreateReg(0));
1177 OutStreamer.EmitInstruction(TmpInst);
1181 case ARM::tInt_eh_sjlj_longjmp: {
1182 // ldr $scratch, [$src, #8]
1184 // ldr $scratch, [$src, #4]
1187 unsigned SrcReg = MI->getOperand(0).getReg();
1188 unsigned ScratchReg = MI->getOperand(1).getReg();
1191 TmpInst.setOpcode(ARM::tLDR);
1192 TmpInst.addOperand(MCOperand::CreateReg(ScratchReg));
1193 TmpInst.addOperand(MCOperand::CreateReg(SrcReg));
1194 // The offset immediate is #8. The operand value is scaled by 4 for the
1195 // tSTR instruction.
1196 TmpInst.addOperand(MCOperand::CreateImm(2));
1197 TmpInst.addOperand(MCOperand::CreateReg(0));
1199 TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
1200 TmpInst.addOperand(MCOperand::CreateReg(0));
1201 OutStreamer.EmitInstruction(TmpInst);
1205 TmpInst.setOpcode(ARM::tMOVtgpr2gpr);
1206 TmpInst.addOperand(MCOperand::CreateReg(ARM::SP));
1207 TmpInst.addOperand(MCOperand::CreateReg(ScratchReg));
1209 TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
1210 TmpInst.addOperand(MCOperand::CreateReg(0));
1211 OutStreamer.EmitInstruction(TmpInst);
1215 TmpInst.setOpcode(ARM::tLDR);
1216 TmpInst.addOperand(MCOperand::CreateReg(ScratchReg));
1217 TmpInst.addOperand(MCOperand::CreateReg(SrcReg));
1218 TmpInst.addOperand(MCOperand::CreateImm(1));
1219 TmpInst.addOperand(MCOperand::CreateReg(0));
1221 TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
1222 TmpInst.addOperand(MCOperand::CreateReg(0));
1223 OutStreamer.EmitInstruction(TmpInst);
1227 TmpInst.setOpcode(ARM::tLDR);
1228 TmpInst.addOperand(MCOperand::CreateReg(ARM::R7));
1229 TmpInst.addOperand(MCOperand::CreateReg(SrcReg));
1230 TmpInst.addOperand(MCOperand::CreateImm(0));
1231 TmpInst.addOperand(MCOperand::CreateReg(0));
1233 TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
1234 TmpInst.addOperand(MCOperand::CreateReg(0));
1235 OutStreamer.EmitInstruction(TmpInst);
1239 TmpInst.setOpcode(ARM::tBX_RET_vararg);
1240 TmpInst.addOperand(MCOperand::CreateReg(ScratchReg));
1242 TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
1243 TmpInst.addOperand(MCOperand::CreateReg(0));
1244 OutStreamer.EmitInstruction(TmpInst);
1251 MCInstLowering.Lower(MI, TmpInst);
1252 OutStreamer.EmitInstruction(TmpInst);
1255 //===----------------------------------------------------------------------===//
1256 // Target Registry Stuff
1257 //===----------------------------------------------------------------------===//
1259 static MCInstPrinter *createARMMCInstPrinter(const Target &T,
1260 unsigned SyntaxVariant,
1261 const MCAsmInfo &MAI) {
1262 if (SyntaxVariant == 0)
1263 return new ARMInstPrinter(MAI);
1267 // Force static initialization.
1268 extern "C" void LLVMInitializeARMAsmPrinter() {
1269 RegisterAsmPrinter<ARMAsmPrinter> X(TheARMTarget);
1270 RegisterAsmPrinter<ARMAsmPrinter> Y(TheThumbTarget);
1272 TargetRegistry::RegisterMCInstPrinter(TheARMTarget, createARMMCInstPrinter);
1273 TargetRegistry::RegisterMCInstPrinter(TheThumbTarget, createARMMCInstPrinter);