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 "ARMTargetMachine.h"
23 #include "ARMTargetObjectFile.h"
24 #include "llvm/Analysis/DebugInfo.h"
25 #include "llvm/Constants.h"
26 #include "llvm/Module.h"
27 #include "llvm/Type.h"
28 #include "llvm/Assembly/Writer.h"
29 #include "llvm/CodeGen/AsmPrinter.h"
30 #include "llvm/CodeGen/MachineModuleInfoImpls.h"
31 #include "llvm/CodeGen/MachineFunctionPass.h"
32 #include "llvm/CodeGen/MachineJumpTableInfo.h"
33 #include "llvm/MC/MCAsmInfo.h"
34 #include "llvm/MC/MCAssembler.h"
35 #include "llvm/MC/MCContext.h"
36 #include "llvm/MC/MCExpr.h"
37 #include "llvm/MC/MCInst.h"
38 #include "llvm/MC/MCSectionMachO.h"
39 #include "llvm/MC/MCObjectStreamer.h"
40 #include "llvm/MC/MCStreamer.h"
41 #include "llvm/MC/MCSymbol.h"
42 #include "llvm/Target/Mangler.h"
43 #include "llvm/Target/TargetData.h"
44 #include "llvm/Target/TargetMachine.h"
45 #include "llvm/Target/TargetOptions.h"
46 #include "llvm/Target/TargetRegistry.h"
47 #include "llvm/ADT/SmallPtrSet.h"
48 #include "llvm/ADT/SmallString.h"
49 #include "llvm/ADT/StringExtras.h"
50 #include "llvm/Support/CommandLine.h"
51 #include "llvm/Support/Debug.h"
52 #include "llvm/Support/ErrorHandling.h"
53 #include "llvm/Support/raw_ostream.h"
68 // Per section and per symbol attributes are not supported.
69 // To implement them we would need the ability to delay this emission
70 // until the assembly file is fully parsed/generated as only then do we
71 // know the symbol and section numbers.
72 class AttributeEmitter {
74 virtual void MaybeSwitchVendor(StringRef Vendor) = 0;
75 virtual void EmitAttribute(unsigned Attribute, unsigned Value) = 0;
76 virtual void Finish() = 0;
77 virtual ~AttributeEmitter() {}
80 class AsmAttributeEmitter : public AttributeEmitter {
84 AsmAttributeEmitter(MCStreamer &Streamer_) : Streamer(Streamer_) {}
85 void MaybeSwitchVendor(StringRef Vendor) { }
87 void EmitAttribute(unsigned Attribute, unsigned Value) {
88 Streamer.EmitRawText("\t.eabi_attribute " +
89 Twine(Attribute) + ", " + Twine(Value));
95 class ObjectAttributeEmitter : public AttributeEmitter {
96 MCObjectStreamer &Streamer;
97 StringRef CurrentVendor;
98 SmallString<64> Contents;
101 ObjectAttributeEmitter(MCObjectStreamer &Streamer_) :
102 Streamer(Streamer_), CurrentVendor("") { }
104 void MaybeSwitchVendor(StringRef Vendor) {
105 assert(!Vendor.empty() && "Vendor cannot be empty.");
107 if (CurrentVendor.empty())
108 CurrentVendor = Vendor;
109 else if (CurrentVendor == Vendor)
114 CurrentVendor = Vendor;
116 assert(Contents.size() == 0);
119 void EmitAttribute(unsigned Attribute, unsigned Value) {
120 // FIXME: should be ULEB
121 Contents += Attribute;
126 const size_t ContentsSize = Contents.size();
128 // Vendor size + Vendor name + '\0'
129 const size_t VendorHeaderSize = 4 + CurrentVendor.size() + 1;
132 const size_t TagHeaderSize = 1 + 4;
134 Streamer.EmitIntValue(VendorHeaderSize + TagHeaderSize + ContentsSize, 4);
135 Streamer.EmitBytes(CurrentVendor, 0);
136 Streamer.EmitIntValue(0, 1); // '\0'
138 Streamer.EmitIntValue(ARMBuildAttrs::File, 1);
139 Streamer.EmitIntValue(TagHeaderSize + ContentsSize, 4);
141 Streamer.EmitBytes(Contents, 0);
147 class ARMAsmPrinter : public AsmPrinter {
149 /// Subtarget - Keep a pointer to the ARMSubtarget around so that we can
150 /// make the right decision when printing asm code for different targets.
151 const ARMSubtarget *Subtarget;
153 /// AFI - Keep a pointer to ARMFunctionInfo for the current
155 ARMFunctionInfo *AFI;
157 /// MCP - Keep a pointer to constantpool entries of the current
159 const MachineConstantPool *MCP;
162 explicit ARMAsmPrinter(TargetMachine &TM, MCStreamer &Streamer)
163 : AsmPrinter(TM, Streamer), AFI(NULL), MCP(NULL) {
164 Subtarget = &TM.getSubtarget<ARMSubtarget>();
167 virtual const char *getPassName() const {
168 return "ARM Assembly Printer";
171 void printOperand(const MachineInstr *MI, int OpNum, raw_ostream &O,
172 const char *Modifier = 0);
174 virtual bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNum,
175 unsigned AsmVariant, const char *ExtraCode,
177 virtual bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNum,
179 const char *ExtraCode, raw_ostream &O);
181 void EmitJumpTable(const MachineInstr *MI);
182 void EmitJump2Table(const MachineInstr *MI);
183 virtual void EmitInstruction(const MachineInstr *MI);
184 bool runOnMachineFunction(MachineFunction &F);
186 virtual void EmitConstantPool() {} // we emit constant pools customly!
187 virtual void EmitFunctionEntryLabel();
188 void EmitStartOfAsmFile(Module &M);
189 void EmitEndOfAsmFile(Module &M);
192 // Helpers for EmitStartOfAsmFile() and EmitEndOfAsmFile()
193 void emitAttributes();
195 // Helper for ELF .o only
196 void emitARMAttributeSection();
199 void PrintDebugValueComment(const MachineInstr *MI, raw_ostream &OS);
201 MachineLocation getDebugValueLocation(const MachineInstr *MI) const {
202 MachineLocation Location;
203 assert(MI->getNumOperands() == 4 && "Invalid no. of machine operands!");
204 // Frame address. Currently handles register +- offset only.
205 if (MI->getOperand(0).isReg() && MI->getOperand(1).isImm())
206 Location.set(MI->getOperand(0).getReg(), MI->getOperand(1).getImm());
208 DEBUG(dbgs() << "DBG_VALUE instruction ignored! " << *MI << "\n");
213 virtual unsigned getISAEncoding() {
214 // ARM/Darwin adds ISA to the DWARF info for each function.
215 if (!Subtarget->isTargetDarwin())
217 return Subtarget->isThumb() ?
218 llvm::ARM::DW_ISA_ARM_thumb : llvm::ARM::DW_ISA_ARM_arm;
221 MCSymbol *GetARMSetPICJumpTableLabel2(unsigned uid, unsigned uid2,
222 const MachineBasicBlock *MBB) const;
223 MCSymbol *GetARMJTIPICJumpTableLabel2(unsigned uid, unsigned uid2) const;
225 MCSymbol *GetARMSJLJEHLabel(void) const;
227 /// EmitMachineConstantPoolValue - Print a machine constantpool value to
229 virtual void EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV);
231 } // end of anonymous namespace
233 void ARMAsmPrinter::EmitFunctionEntryLabel() {
234 if (AFI->isThumbFunction()) {
235 OutStreamer.EmitAssemblerFlag(MCAF_Code16);
236 OutStreamer.EmitThumbFunc(Subtarget->isTargetDarwin()? CurrentFnSym : 0);
239 OutStreamer.EmitLabel(CurrentFnSym);
242 /// runOnMachineFunction - This uses the EmitInstruction()
243 /// method to print assembly for each instruction.
245 bool ARMAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
246 AFI = MF.getInfo<ARMFunctionInfo>();
247 MCP = MF.getConstantPool();
249 return AsmPrinter::runOnMachineFunction(MF);
252 void ARMAsmPrinter::printOperand(const MachineInstr *MI, int OpNum,
253 raw_ostream &O, const char *Modifier) {
254 const MachineOperand &MO = MI->getOperand(OpNum);
255 unsigned TF = MO.getTargetFlags();
257 switch (MO.getType()) {
259 assert(0 && "<unknown operand type>");
260 case MachineOperand::MO_Register: {
261 unsigned Reg = MO.getReg();
262 assert(TargetRegisterInfo::isPhysicalRegister(Reg));
263 assert(!MO.getSubReg() && "Subregs should be eliminated!");
264 O << ARMInstPrinter::getRegisterName(Reg);
267 case MachineOperand::MO_Immediate: {
268 int64_t Imm = MO.getImm();
270 if ((Modifier && strcmp(Modifier, "lo16") == 0) ||
271 (TF == ARMII::MO_LO16))
273 else if ((Modifier && strcmp(Modifier, "hi16") == 0) ||
274 (TF == ARMII::MO_HI16))
279 case MachineOperand::MO_MachineBasicBlock:
280 O << *MO.getMBB()->getSymbol();
282 case MachineOperand::MO_GlobalAddress: {
283 const GlobalValue *GV = MO.getGlobal();
284 if ((Modifier && strcmp(Modifier, "lo16") == 0) ||
285 (TF & ARMII::MO_LO16))
287 else if ((Modifier && strcmp(Modifier, "hi16") == 0) ||
288 (TF & ARMII::MO_HI16))
290 O << *Mang->getSymbol(GV);
292 printOffset(MO.getOffset(), O);
293 if (TF == ARMII::MO_PLT)
297 case MachineOperand::MO_ExternalSymbol: {
298 O << *GetExternalSymbolSymbol(MO.getSymbolName());
299 if (TF == ARMII::MO_PLT)
303 case MachineOperand::MO_ConstantPoolIndex:
304 O << *GetCPISymbol(MO.getIndex());
306 case MachineOperand::MO_JumpTableIndex:
307 O << *GetJTISymbol(MO.getIndex());
312 //===--------------------------------------------------------------------===//
314 MCSymbol *ARMAsmPrinter::
315 GetARMSetPICJumpTableLabel2(unsigned uid, unsigned uid2,
316 const MachineBasicBlock *MBB) const {
317 SmallString<60> Name;
318 raw_svector_ostream(Name) << MAI->getPrivateGlobalPrefix()
319 << getFunctionNumber() << '_' << uid << '_' << uid2
320 << "_set_" << MBB->getNumber();
321 return OutContext.GetOrCreateSymbol(Name.str());
324 MCSymbol *ARMAsmPrinter::
325 GetARMJTIPICJumpTableLabel2(unsigned uid, unsigned uid2) const {
326 SmallString<60> Name;
327 raw_svector_ostream(Name) << MAI->getPrivateGlobalPrefix() << "JTI"
328 << getFunctionNumber() << '_' << uid << '_' << uid2;
329 return OutContext.GetOrCreateSymbol(Name.str());
333 MCSymbol *ARMAsmPrinter::GetARMSJLJEHLabel(void) const {
334 SmallString<60> Name;
335 raw_svector_ostream(Name) << MAI->getPrivateGlobalPrefix() << "SJLJEH"
336 << getFunctionNumber();
337 return OutContext.GetOrCreateSymbol(Name.str());
340 bool ARMAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNum,
341 unsigned AsmVariant, const char *ExtraCode,
343 // Does this asm operand have a single letter operand modifier?
344 if (ExtraCode && ExtraCode[0]) {
345 if (ExtraCode[1] != 0) return true; // Unknown modifier.
347 switch (ExtraCode[0]) {
348 default: return true; // Unknown modifier.
349 case 'a': // Print as a memory address.
350 if (MI->getOperand(OpNum).isReg()) {
352 << ARMInstPrinter::getRegisterName(MI->getOperand(OpNum).getReg())
357 case 'c': // Don't print "#" before an immediate operand.
358 if (!MI->getOperand(OpNum).isImm())
360 O << MI->getOperand(OpNum).getImm();
362 case 'P': // Print a VFP double precision register.
363 case 'q': // Print a NEON quad precision register.
364 printOperand(MI, OpNum, O);
369 report_fatal_error("llvm does not support 'Q', 'R', and 'H' modifiers!");
374 printOperand(MI, OpNum, O);
378 bool ARMAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
379 unsigned OpNum, unsigned AsmVariant,
380 const char *ExtraCode,
382 if (ExtraCode && ExtraCode[0])
383 return true; // Unknown modifier.
385 const MachineOperand &MO = MI->getOperand(OpNum);
386 assert(MO.isReg() && "unexpected inline asm memory operand");
387 O << "[" << ARMInstPrinter::getRegisterName(MO.getReg()) << "]";
391 void ARMAsmPrinter::EmitStartOfAsmFile(Module &M) {
392 if (Subtarget->isTargetDarwin()) {
393 Reloc::Model RelocM = TM.getRelocationModel();
394 if (RelocM == Reloc::PIC_ || RelocM == Reloc::DynamicNoPIC) {
395 // Declare all the text sections up front (before the DWARF sections
396 // emitted by AsmPrinter::doInitialization) so the assembler will keep
397 // them together at the beginning of the object file. This helps
398 // avoid out-of-range branches that are due a fundamental limitation of
399 // the way symbol offsets are encoded with the current Darwin ARM
401 const TargetLoweringObjectFileMachO &TLOFMacho =
402 static_cast<const TargetLoweringObjectFileMachO &>(
403 getObjFileLowering());
404 OutStreamer.SwitchSection(TLOFMacho.getTextSection());
405 OutStreamer.SwitchSection(TLOFMacho.getTextCoalSection());
406 OutStreamer.SwitchSection(TLOFMacho.getConstTextCoalSection());
407 if (RelocM == Reloc::DynamicNoPIC) {
408 const MCSection *sect =
409 OutContext.getMachOSection("__TEXT", "__symbol_stub4",
410 MCSectionMachO::S_SYMBOL_STUBS,
411 12, SectionKind::getText());
412 OutStreamer.SwitchSection(sect);
414 const MCSection *sect =
415 OutContext.getMachOSection("__TEXT", "__picsymbolstub4",
416 MCSectionMachO::S_SYMBOL_STUBS,
417 16, SectionKind::getText());
418 OutStreamer.SwitchSection(sect);
420 const MCSection *StaticInitSect =
421 OutContext.getMachOSection("__TEXT", "__StaticInit",
422 MCSectionMachO::S_REGULAR |
423 MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS,
424 SectionKind::getText());
425 OutStreamer.SwitchSection(StaticInitSect);
429 // Use unified assembler syntax.
430 OutStreamer.EmitAssemblerFlag(MCAF_SyntaxUnified);
432 // Emit ARM Build Attributes
433 if (Subtarget->isTargetELF()) {
440 void ARMAsmPrinter::EmitEndOfAsmFile(Module &M) {
441 if (Subtarget->isTargetDarwin()) {
442 // All darwin targets use mach-o.
443 const TargetLoweringObjectFileMachO &TLOFMacho =
444 static_cast<const TargetLoweringObjectFileMachO &>(getObjFileLowering());
445 MachineModuleInfoMachO &MMIMacho =
446 MMI->getObjFileInfo<MachineModuleInfoMachO>();
448 // Output non-lazy-pointers for external and common global variables.
449 MachineModuleInfoMachO::SymbolListTy Stubs = MMIMacho.GetGVStubList();
451 if (!Stubs.empty()) {
452 // Switch with ".non_lazy_symbol_pointer" directive.
453 OutStreamer.SwitchSection(TLOFMacho.getNonLazySymbolPointerSection());
455 for (unsigned i = 0, e = Stubs.size(); i != e; ++i) {
457 OutStreamer.EmitLabel(Stubs[i].first);
458 // .indirect_symbol _foo
459 MachineModuleInfoImpl::StubValueTy &MCSym = Stubs[i].second;
460 OutStreamer.EmitSymbolAttribute(MCSym.getPointer(),MCSA_IndirectSymbol);
463 // External to current translation unit.
464 OutStreamer.EmitIntValue(0, 4/*size*/, 0/*addrspace*/);
466 // Internal to current translation unit.
468 // When we place the LSDA into the TEXT section, the type info
469 // pointers need to be indirect and pc-rel. We accomplish this by
470 // using NLPs; however, sometimes the types are local to the file.
471 // We need to fill in the value for the NLP in those cases.
472 OutStreamer.EmitValue(MCSymbolRefExpr::Create(MCSym.getPointer(),
474 4/*size*/, 0/*addrspace*/);
478 OutStreamer.AddBlankLine();
481 Stubs = MMIMacho.GetHiddenGVStubList();
482 if (!Stubs.empty()) {
483 OutStreamer.SwitchSection(getObjFileLowering().getDataSection());
485 for (unsigned i = 0, e = Stubs.size(); i != e; ++i) {
487 OutStreamer.EmitLabel(Stubs[i].first);
489 OutStreamer.EmitValue(MCSymbolRefExpr::
490 Create(Stubs[i].second.getPointer(),
492 4/*size*/, 0/*addrspace*/);
496 OutStreamer.AddBlankLine();
499 // Funny Darwin hack: This flag tells the linker that no global symbols
500 // contain code that falls through to other global symbols (e.g. the obvious
501 // implementation of multiple entry points). If this doesn't occur, the
502 // linker can safely perform dead code stripping. Since LLVM never
503 // generates code that does this, it is always safe to set.
504 OutStreamer.EmitAssemblerFlag(MCAF_SubsectionsViaSymbols);
508 //===----------------------------------------------------------------------===//
509 // Helper routines for EmitStartOfAsmFile() and EmitEndOfAsmFile()
511 // The following seem like one-off assembler flags, but they actually need
512 // to appear in the .ARM.attributes section in ELF.
513 // Instead of subclassing the MCELFStreamer, we do the work here.
515 void ARMAsmPrinter::emitAttributes() {
517 emitARMAttributeSection();
519 AttributeEmitter *AttrEmitter;
520 if (OutStreamer.hasRawTextSupport())
521 AttrEmitter = new AsmAttributeEmitter(OutStreamer);
523 MCObjectStreamer &O = static_cast<MCObjectStreamer&>(OutStreamer);
524 AttrEmitter = new ObjectAttributeEmitter(O);
527 AttrEmitter->MaybeSwitchVendor("aeabi");
529 std::string CPUString = Subtarget->getCPUString();
530 if (OutStreamer.hasRawTextSupport()) {
531 if (CPUString != "generic")
532 OutStreamer.EmitRawText(StringRef("\t.cpu ") + CPUString);
534 assert(CPUString == "generic" && "Unsupported .cpu attribute for ELF/.o");
535 // FIXME: Why these defaults?
536 AttrEmitter->EmitAttribute(ARMBuildAttrs::CPU_arch, ARMBuildAttrs::v4T);
537 AttrEmitter->EmitAttribute(ARMBuildAttrs::ARM_ISA_use, 1);
538 AttrEmitter->EmitAttribute(ARMBuildAttrs::THUMB_ISA_use, 1);
541 // FIXME: Emit FPU type
542 if (Subtarget->hasVFP2())
543 AttrEmitter->EmitAttribute(ARMBuildAttrs::VFP_arch, 2);
545 // Signal various FP modes.
547 AttrEmitter->EmitAttribute(ARMBuildAttrs::ABI_FP_denormal, 1);
548 AttrEmitter->EmitAttribute(ARMBuildAttrs::ABI_FP_exceptions, 1);
551 if (NoInfsFPMath && NoNaNsFPMath)
552 AttrEmitter->EmitAttribute(ARMBuildAttrs::ABI_FP_number_model, 1);
554 AttrEmitter->EmitAttribute(ARMBuildAttrs::ABI_FP_number_model, 3);
556 // 8-bytes alignment stuff.
557 AttrEmitter->EmitAttribute(ARMBuildAttrs::ABI_align8_needed, 1);
558 AttrEmitter->EmitAttribute(ARMBuildAttrs::ABI_align8_preserved, 1);
560 // Hard float. Use both S and D registers and conform to AAPCS-VFP.
561 if (Subtarget->isAAPCS_ABI() && FloatABIType == FloatABI::Hard) {
562 AttrEmitter->EmitAttribute(ARMBuildAttrs::ABI_HardFP_use, 3);
563 AttrEmitter->EmitAttribute(ARMBuildAttrs::ABI_VFP_args, 1);
565 // FIXME: Should we signal R9 usage?
567 AttrEmitter->EmitAttribute(ARMBuildAttrs::DIV_use, 1);
569 AttrEmitter->Finish();
573 void ARMAsmPrinter::emitARMAttributeSection() {
575 // [ <section-length> "vendor-name"
576 // [ <file-tag> <size> <attribute>*
577 // | <section-tag> <size> <section-number>* 0 <attribute>*
578 // | <symbol-tag> <size> <symbol-number>* 0 <attribute>*
582 if (OutStreamer.hasRawTextSupport())
585 const ARMElfTargetObjectFile &TLOFELF =
586 static_cast<const ARMElfTargetObjectFile &>
587 (getObjFileLowering());
589 OutStreamer.SwitchSection(TLOFELF.getAttributesSection());
592 OutStreamer.EmitIntValue(0x41, 1);
595 //===----------------------------------------------------------------------===//
597 static MCSymbol *getPICLabel(const char *Prefix, unsigned FunctionNumber,
598 unsigned LabelId, MCContext &Ctx) {
600 MCSymbol *Label = Ctx.GetOrCreateSymbol(Twine(Prefix)
601 + "PC" + Twine(FunctionNumber) + "_" + Twine(LabelId));
605 static MCSymbolRefExpr::VariantKind
606 getModifierVariantKind(ARMCP::ARMCPModifier Modifier) {
608 default: llvm_unreachable("Unknown modifier!");
609 case ARMCP::no_modifier: return MCSymbolRefExpr::VK_None;
610 case ARMCP::TLSGD: return MCSymbolRefExpr::VK_ARM_TLSGD;
611 case ARMCP::TPOFF: return MCSymbolRefExpr::VK_ARM_TPOFF;
612 case ARMCP::GOTTPOFF: return MCSymbolRefExpr::VK_ARM_GOTTPOFF;
613 case ARMCP::GOT: return MCSymbolRefExpr::VK_ARM_GOT;
614 case ARMCP::GOTOFF: return MCSymbolRefExpr::VK_ARM_GOTOFF;
616 return MCSymbolRefExpr::VK_None;
620 EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) {
621 int Size = TM.getTargetData()->getTypeAllocSize(MCPV->getType());
623 ARMConstantPoolValue *ACPV = static_cast<ARMConstantPoolValue*>(MCPV);
626 if (ACPV->isLSDA()) {
627 SmallString<128> Str;
628 raw_svector_ostream OS(Str);
629 OS << MAI->getPrivateGlobalPrefix() << "_LSDA_" << getFunctionNumber();
630 MCSym = OutContext.GetOrCreateSymbol(OS.str());
631 } else if (ACPV->isBlockAddress()) {
632 MCSym = GetBlockAddressSymbol(ACPV->getBlockAddress());
633 } else if (ACPV->isGlobalValue()) {
634 const GlobalValue *GV = ACPV->getGV();
635 bool isIndirect = Subtarget->isTargetDarwin() &&
636 Subtarget->GVIsIndirectSymbol(GV, TM.getRelocationModel());
638 MCSym = Mang->getSymbol(GV);
640 // FIXME: Remove this when Darwin transition to @GOT like syntax.
641 MCSym = GetSymbolWithGlobalValueBase(GV, "$non_lazy_ptr");
643 MachineModuleInfoMachO &MMIMachO =
644 MMI->getObjFileInfo<MachineModuleInfoMachO>();
645 MachineModuleInfoImpl::StubValueTy &StubSym =
646 GV->hasHiddenVisibility() ? MMIMachO.getHiddenGVStubEntry(MCSym) :
647 MMIMachO.getGVStubEntry(MCSym);
648 if (StubSym.getPointer() == 0)
649 StubSym = MachineModuleInfoImpl::
650 StubValueTy(Mang->getSymbol(GV), !GV->hasInternalLinkage());
653 assert(ACPV->isExtSymbol() && "unrecognized constant pool value");
654 MCSym = GetExternalSymbolSymbol(ACPV->getSymbol());
657 // Create an MCSymbol for the reference.
659 MCSymbolRefExpr::Create(MCSym, getModifierVariantKind(ACPV->getModifier()),
662 if (ACPV->getPCAdjustment()) {
663 MCSymbol *PCLabel = getPICLabel(MAI->getPrivateGlobalPrefix(),
667 const MCExpr *PCRelExpr = MCSymbolRefExpr::Create(PCLabel, OutContext);
669 MCBinaryExpr::CreateAdd(PCRelExpr,
670 MCConstantExpr::Create(ACPV->getPCAdjustment(),
673 if (ACPV->mustAddCurrentAddress()) {
674 // We want "(<expr> - .)", but MC doesn't have a concept of the '.'
675 // label, so just emit a local label end reference that instead.
676 MCSymbol *DotSym = OutContext.CreateTempSymbol();
677 OutStreamer.EmitLabel(DotSym);
678 const MCExpr *DotExpr = MCSymbolRefExpr::Create(DotSym, OutContext);
679 PCRelExpr = MCBinaryExpr::CreateSub(PCRelExpr, DotExpr, OutContext);
681 Expr = MCBinaryExpr::CreateSub(Expr, PCRelExpr, OutContext);
683 OutStreamer.EmitValue(Expr, Size);
686 void ARMAsmPrinter::EmitJumpTable(const MachineInstr *MI) {
687 unsigned Opcode = MI->getOpcode();
689 if (Opcode == ARM::BR_JTadd)
691 else if (Opcode == ARM::BR_JTm)
694 const MachineOperand &MO1 = MI->getOperand(OpNum);
695 const MachineOperand &MO2 = MI->getOperand(OpNum+1); // Unique Id
696 unsigned JTI = MO1.getIndex();
698 // Emit a label for the jump table.
699 MCSymbol *JTISymbol = GetARMJTIPICJumpTableLabel2(JTI, MO2.getImm());
700 OutStreamer.EmitLabel(JTISymbol);
702 // Emit each entry of the table.
703 const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo();
704 const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables();
705 const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs;
707 for (unsigned i = 0, e = JTBBs.size(); i != e; ++i) {
708 MachineBasicBlock *MBB = JTBBs[i];
709 // Construct an MCExpr for the entry. We want a value of the form:
710 // (BasicBlockAddr - TableBeginAddr)
712 // For example, a table with entries jumping to basic blocks BB0 and BB1
715 // .word (LBB0 - LJTI_0_0)
716 // .word (LBB1 - LJTI_0_0)
717 const MCExpr *Expr = MCSymbolRefExpr::Create(MBB->getSymbol(), OutContext);
719 if (TM.getRelocationModel() == Reloc::PIC_)
720 Expr = MCBinaryExpr::CreateSub(Expr, MCSymbolRefExpr::Create(JTISymbol,
723 OutStreamer.EmitValue(Expr, 4);
727 void ARMAsmPrinter::EmitJump2Table(const MachineInstr *MI) {
728 unsigned Opcode = MI->getOpcode();
729 int OpNum = (Opcode == ARM::t2BR_JT) ? 2 : 1;
730 const MachineOperand &MO1 = MI->getOperand(OpNum);
731 const MachineOperand &MO2 = MI->getOperand(OpNum+1); // Unique Id
732 unsigned JTI = MO1.getIndex();
734 // Emit a label for the jump table.
735 MCSymbol *JTISymbol = GetARMJTIPICJumpTableLabel2(JTI, MO2.getImm());
736 OutStreamer.EmitLabel(JTISymbol);
738 // Emit each entry of the table.
739 const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo();
740 const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables();
741 const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs;
742 unsigned OffsetWidth = 4;
743 if (MI->getOpcode() == ARM::t2TBB_JT)
745 else if (MI->getOpcode() == ARM::t2TBH_JT)
748 for (unsigned i = 0, e = JTBBs.size(); i != e; ++i) {
749 MachineBasicBlock *MBB = JTBBs[i];
750 const MCExpr *MBBSymbolExpr = MCSymbolRefExpr::Create(MBB->getSymbol(),
752 // If this isn't a TBB or TBH, the entries are direct branch instructions.
753 if (OffsetWidth == 4) {
755 BrInst.setOpcode(ARM::t2B);
756 BrInst.addOperand(MCOperand::CreateExpr(MBBSymbolExpr));
757 OutStreamer.EmitInstruction(BrInst);
760 // Otherwise it's an offset from the dispatch instruction. Construct an
761 // MCExpr for the entry. We want a value of the form:
762 // (BasicBlockAddr - TableBeginAddr) / 2
764 // For example, a TBB table with entries jumping to basic blocks BB0 and BB1
767 // .byte (LBB0 - LJTI_0_0) / 2
768 // .byte (LBB1 - LJTI_0_0) / 2
770 MCBinaryExpr::CreateSub(MBBSymbolExpr,
771 MCSymbolRefExpr::Create(JTISymbol, OutContext),
773 Expr = MCBinaryExpr::CreateDiv(Expr, MCConstantExpr::Create(2, OutContext),
775 OutStreamer.EmitValue(Expr, OffsetWidth);
778 // Make sure the instruction that follows TBB is 2-byte aligned.
779 // FIXME: Constant island pass should insert an "ALIGN" instruction instead.
780 if (MI->getOpcode() == ARM::t2TBB_JT)
784 void ARMAsmPrinter::PrintDebugValueComment(const MachineInstr *MI,
786 unsigned NOps = MI->getNumOperands();
788 OS << '\t' << MAI->getCommentString() << "DEBUG_VALUE: ";
789 // cast away const; DIetc do not take const operands for some reason.
790 DIVariable V(const_cast<MDNode *>(MI->getOperand(NOps-1).getMetadata()));
793 // Frame address. Currently handles register +- offset only.
794 assert(MI->getOperand(0).isReg() && MI->getOperand(1).isImm());
795 OS << '['; printOperand(MI, 0, OS); OS << '+'; printOperand(MI, 1, OS);
798 printOperand(MI, NOps-2, OS);
801 void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) {
802 switch (MI->getOpcode()) {
804 case ARM::t2MOVi32imm: assert(0 && "Should be lowered by thumb2it pass");
805 case ARM::DBG_VALUE: {
806 if (isVerbose() && OutStreamer.hasRawTextSupport()) {
807 SmallString<128> TmpStr;
808 raw_svector_ostream OS(TmpStr);
809 PrintDebugValueComment(MI, OS);
810 OutStreamer.EmitRawText(StringRef(OS.str()));
815 // This is a pseudo op for a label + instruction sequence, which looks like:
818 // This adds the address of LPC0 to r0.
821 OutStreamer.EmitLabel(getPICLabel(MAI->getPrivateGlobalPrefix(),
822 getFunctionNumber(), MI->getOperand(2).getImm(),
825 // Form and emit the add.
827 AddInst.setOpcode(ARM::tADDhirr);
828 AddInst.addOperand(MCOperand::CreateReg(MI->getOperand(0).getReg()));
829 AddInst.addOperand(MCOperand::CreateReg(MI->getOperand(0).getReg()));
830 AddInst.addOperand(MCOperand::CreateReg(ARM::PC));
831 // Add predicate operands.
832 AddInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
833 AddInst.addOperand(MCOperand::CreateReg(0));
834 OutStreamer.EmitInstruction(AddInst);
838 // This is a pseudo op for a label + instruction sequence, which looks like:
841 // This adds the address of LPC0 to r0.
844 OutStreamer.EmitLabel(getPICLabel(MAI->getPrivateGlobalPrefix(),
845 getFunctionNumber(), MI->getOperand(2).getImm(),
848 // Form and emit the add.
850 AddInst.setOpcode(ARM::ADDrr);
851 AddInst.addOperand(MCOperand::CreateReg(MI->getOperand(0).getReg()));
852 AddInst.addOperand(MCOperand::CreateReg(ARM::PC));
853 AddInst.addOperand(MCOperand::CreateReg(MI->getOperand(1).getReg()));
854 // Add predicate operands.
855 AddInst.addOperand(MCOperand::CreateImm(MI->getOperand(3).getImm()));
856 AddInst.addOperand(MCOperand::CreateReg(MI->getOperand(4).getReg()));
857 // Add 's' bit operand (always reg0 for this)
858 AddInst.addOperand(MCOperand::CreateReg(0));
859 OutStreamer.EmitInstruction(AddInst);
869 case ARM::PICLDRSH: {
870 // This is a pseudo op for a label + instruction sequence, which looks like:
873 // The LCP0 label is referenced by a constant pool entry in order to get
874 // a PC-relative address at the ldr instruction.
877 OutStreamer.EmitLabel(getPICLabel(MAI->getPrivateGlobalPrefix(),
878 getFunctionNumber(), MI->getOperand(2).getImm(),
881 // Form and emit the load
883 switch (MI->getOpcode()) {
885 llvm_unreachable("Unexpected opcode!");
886 case ARM::PICSTR: Opcode = ARM::STRrs; break;
887 case ARM::PICSTRB: Opcode = ARM::STRBrs; break;
888 case ARM::PICSTRH: Opcode = ARM::STRH; break;
889 case ARM::PICLDR: Opcode = ARM::LDRrs; break;
890 case ARM::PICLDRB: Opcode = ARM::LDRBrs; break;
891 case ARM::PICLDRH: Opcode = ARM::LDRH; break;
892 case ARM::PICLDRSB: Opcode = ARM::LDRSB; break;
893 case ARM::PICLDRSH: Opcode = ARM::LDRSH; break;
896 LdStInst.setOpcode(Opcode);
897 LdStInst.addOperand(MCOperand::CreateReg(MI->getOperand(0).getReg()));
898 LdStInst.addOperand(MCOperand::CreateReg(ARM::PC));
899 LdStInst.addOperand(MCOperand::CreateReg(MI->getOperand(1).getReg()));
900 LdStInst.addOperand(MCOperand::CreateImm(0));
901 // Add predicate operands.
902 LdStInst.addOperand(MCOperand::CreateImm(MI->getOperand(3).getImm()));
903 LdStInst.addOperand(MCOperand::CreateReg(MI->getOperand(4).getReg()));
904 OutStreamer.EmitInstruction(LdStInst);
908 case ARM::CONSTPOOL_ENTRY: {
909 /// CONSTPOOL_ENTRY - This instruction represents a floating constant pool
910 /// in the function. The first operand is the ID# for this instruction, the
911 /// second is the index into the MachineConstantPool that this is, the third
912 /// is the size in bytes of this constant pool entry.
913 unsigned LabelId = (unsigned)MI->getOperand(0).getImm();
914 unsigned CPIdx = (unsigned)MI->getOperand(1).getIndex();
917 OutStreamer.EmitLabel(GetCPISymbol(LabelId));
919 const MachineConstantPoolEntry &MCPE = MCP->getConstants()[CPIdx];
920 if (MCPE.isMachineConstantPoolEntry())
921 EmitMachineConstantPoolValue(MCPE.Val.MachineCPVal);
923 EmitGlobalConstant(MCPE.Val.ConstVal);
930 // Lower and emit the instruction itself, then the jump table following it.
932 // FIXME: The branch instruction is really a pseudo. We should xform it
934 LowerARMMachineInstrToMCInst(MI, TmpInst, *this);
935 OutStreamer.EmitInstruction(TmpInst);
941 // Lower and emit the instruction itself, then the jump table following it.
944 unsigned Opc = MI->getOpcode() == ARM::BR_JTr ? ARM::MOVr : ARM::tMOVr;
945 TmpInst.setOpcode(Opc);
946 TmpInst.addOperand(MCOperand::CreateReg(ARM::PC));
947 TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(0).getReg()));
948 // Add predicate operands.
949 TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
950 TmpInst.addOperand(MCOperand::CreateReg(0));
951 OutStreamer.EmitInstruction(TmpInst);
953 // Make sure the Thumb jump table is 4-byte aligned.
954 if (Opc == ARM::tMOVr)
957 // Output the data for the jump table itself
962 // Lower and emit the instruction itself, then the jump table following it.
965 if (MI->getOperand(1).getReg() == 0) {
967 TmpInst.setOpcode(ARM::LDRi12);
968 TmpInst.addOperand(MCOperand::CreateReg(ARM::PC));
969 TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(0).getReg()));
970 TmpInst.addOperand(MCOperand::CreateImm(MI->getOperand(2).getImm()));
972 TmpInst.setOpcode(ARM::LDRrs);
973 TmpInst.addOperand(MCOperand::CreateReg(ARM::PC));
974 TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(0).getReg()));
975 TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(1).getReg()));
976 TmpInst.addOperand(MCOperand::CreateImm(0));
978 // Add predicate operands.
979 TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
980 TmpInst.addOperand(MCOperand::CreateReg(0));
981 OutStreamer.EmitInstruction(TmpInst);
983 // Output the data for the jump table itself
987 case ARM::BR_JTadd: {
988 // Lower and emit the instruction itself, then the jump table following it.
989 // add pc, target, idx
991 TmpInst.setOpcode(ARM::ADDrr);
992 TmpInst.addOperand(MCOperand::CreateReg(ARM::PC));
993 TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(0).getReg()));
994 TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(1).getReg()));
995 // Add predicate operands.
996 TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
997 TmpInst.addOperand(MCOperand::CreateReg(0));
998 // Add 's' bit operand (always reg0 for this)
999 TmpInst.addOperand(MCOperand::CreateReg(0));
1000 OutStreamer.EmitInstruction(TmpInst);
1002 // Output the data for the jump table itself
1007 // Non-Darwin binutils don't yet support the "trap" mnemonic.
1008 // FIXME: Remove this special case when they do.
1009 if (!Subtarget->isTargetDarwin()) {
1010 //.long 0xe7ffdefe @ trap
1011 uint32_t Val = 0xe7ffdefeUL;
1012 OutStreamer.AddComment("trap");
1013 OutStreamer.EmitIntValue(Val, 4);
1019 // Non-Darwin binutils don't yet support the "trap" mnemonic.
1020 // FIXME: Remove this special case when they do.
1021 if (!Subtarget->isTargetDarwin()) {
1022 //.short 57086 @ trap
1023 uint16_t Val = 0xdefe;
1024 OutStreamer.AddComment("trap");
1025 OutStreamer.EmitIntValue(Val, 2);
1030 case ARM::t2Int_eh_sjlj_setjmp:
1031 case ARM::t2Int_eh_sjlj_setjmp_nofp:
1032 case ARM::tInt_eh_sjlj_setjmp: {
1033 // Two incoming args: GPR:$src, GPR:$val
1036 // str $val, [$src, #4]
1041 unsigned SrcReg = MI->getOperand(0).getReg();
1042 unsigned ValReg = MI->getOperand(1).getReg();
1043 MCSymbol *Label = GetARMSJLJEHLabel();
1046 TmpInst.setOpcode(ARM::tMOVgpr2tgpr);
1047 TmpInst.addOperand(MCOperand::CreateReg(ValReg));
1048 TmpInst.addOperand(MCOperand::CreateReg(ARM::PC));
1050 TmpInst.addOperand(MCOperand::CreateReg(ARM::CPSR));
1051 OutStreamer.AddComment("eh_setjmp begin");
1052 OutStreamer.EmitInstruction(TmpInst);
1056 TmpInst.setOpcode(ARM::tADDi3);
1057 TmpInst.addOperand(MCOperand::CreateReg(ValReg));
1059 TmpInst.addOperand(MCOperand::CreateReg(ARM::CPSR));
1060 TmpInst.addOperand(MCOperand::CreateReg(ValReg));
1061 TmpInst.addOperand(MCOperand::CreateImm(7));
1063 TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
1064 TmpInst.addOperand(MCOperand::CreateReg(0));
1065 OutStreamer.EmitInstruction(TmpInst);
1069 TmpInst.setOpcode(ARM::tSTR);
1070 TmpInst.addOperand(MCOperand::CreateReg(ValReg));
1071 TmpInst.addOperand(MCOperand::CreateReg(SrcReg));
1072 // The offset immediate is #4. The operand value is scaled by 4 for the
1073 // tSTR instruction.
1074 TmpInst.addOperand(MCOperand::CreateImm(1));
1075 TmpInst.addOperand(MCOperand::CreateReg(0));
1077 TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
1078 TmpInst.addOperand(MCOperand::CreateReg(0));
1079 OutStreamer.EmitInstruction(TmpInst);
1083 TmpInst.setOpcode(ARM::tMOVi8);
1084 TmpInst.addOperand(MCOperand::CreateReg(ARM::R0));
1085 TmpInst.addOperand(MCOperand::CreateReg(ARM::CPSR));
1086 TmpInst.addOperand(MCOperand::CreateImm(0));
1088 TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
1089 TmpInst.addOperand(MCOperand::CreateReg(0));
1090 OutStreamer.EmitInstruction(TmpInst);
1093 const MCExpr *SymbolExpr = MCSymbolRefExpr::Create(Label, OutContext);
1095 TmpInst.setOpcode(ARM::tB);
1096 TmpInst.addOperand(MCOperand::CreateExpr(SymbolExpr));
1097 OutStreamer.EmitInstruction(TmpInst);
1101 TmpInst.setOpcode(ARM::tMOVi8);
1102 TmpInst.addOperand(MCOperand::CreateReg(ARM::R0));
1103 TmpInst.addOperand(MCOperand::CreateReg(ARM::CPSR));
1104 TmpInst.addOperand(MCOperand::CreateImm(1));
1106 TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
1107 TmpInst.addOperand(MCOperand::CreateReg(0));
1108 OutStreamer.AddComment("eh_setjmp end");
1109 OutStreamer.EmitInstruction(TmpInst);
1111 OutStreamer.EmitLabel(Label);
1115 case ARM::Int_eh_sjlj_setjmp_nofp:
1116 case ARM::Int_eh_sjlj_setjmp: {
1117 // Two incoming args: GPR:$src, GPR:$val
1119 // str $val, [$src, #+4]
1123 unsigned SrcReg = MI->getOperand(0).getReg();
1124 unsigned ValReg = MI->getOperand(1).getReg();
1128 TmpInst.setOpcode(ARM::ADDri);
1129 TmpInst.addOperand(MCOperand::CreateReg(ValReg));
1130 TmpInst.addOperand(MCOperand::CreateReg(ARM::PC));
1131 TmpInst.addOperand(MCOperand::CreateImm(8));
1133 TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
1134 TmpInst.addOperand(MCOperand::CreateReg(0));
1135 // 's' bit operand (always reg0 for this).
1136 TmpInst.addOperand(MCOperand::CreateReg(0));
1137 OutStreamer.AddComment("eh_setjmp begin");
1138 OutStreamer.EmitInstruction(TmpInst);
1142 TmpInst.setOpcode(ARM::STRi12);
1143 TmpInst.addOperand(MCOperand::CreateReg(ValReg));
1144 TmpInst.addOperand(MCOperand::CreateReg(SrcReg));
1145 TmpInst.addOperand(MCOperand::CreateImm(4));
1147 TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
1148 TmpInst.addOperand(MCOperand::CreateReg(0));
1149 OutStreamer.EmitInstruction(TmpInst);
1153 TmpInst.setOpcode(ARM::MOVi);
1154 TmpInst.addOperand(MCOperand::CreateReg(ARM::R0));
1155 TmpInst.addOperand(MCOperand::CreateImm(0));
1157 TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
1158 TmpInst.addOperand(MCOperand::CreateReg(0));
1159 // 's' bit operand (always reg0 for this).
1160 TmpInst.addOperand(MCOperand::CreateReg(0));
1161 OutStreamer.EmitInstruction(TmpInst);
1165 TmpInst.setOpcode(ARM::ADDri);
1166 TmpInst.addOperand(MCOperand::CreateReg(ARM::PC));
1167 TmpInst.addOperand(MCOperand::CreateReg(ARM::PC));
1168 TmpInst.addOperand(MCOperand::CreateImm(0));
1170 TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
1171 TmpInst.addOperand(MCOperand::CreateReg(0));
1172 // 's' bit operand (always reg0 for this).
1173 TmpInst.addOperand(MCOperand::CreateReg(0));
1174 OutStreamer.EmitInstruction(TmpInst);
1178 TmpInst.setOpcode(ARM::MOVi);
1179 TmpInst.addOperand(MCOperand::CreateReg(ARM::R0));
1180 TmpInst.addOperand(MCOperand::CreateImm(1));
1182 TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
1183 TmpInst.addOperand(MCOperand::CreateReg(0));
1184 // 's' bit operand (always reg0 for this).
1185 TmpInst.addOperand(MCOperand::CreateReg(0));
1186 OutStreamer.AddComment("eh_setjmp end");
1187 OutStreamer.EmitInstruction(TmpInst);
1191 case ARM::Int_eh_sjlj_longjmp: {
1192 // ldr sp, [$src, #8]
1193 // ldr $scratch, [$src, #4]
1196 unsigned SrcReg = MI->getOperand(0).getReg();
1197 unsigned ScratchReg = MI->getOperand(1).getReg();
1200 TmpInst.setOpcode(ARM::LDRi12);
1201 TmpInst.addOperand(MCOperand::CreateReg(ARM::SP));
1202 TmpInst.addOperand(MCOperand::CreateReg(SrcReg));
1203 TmpInst.addOperand(MCOperand::CreateImm(8));
1205 TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
1206 TmpInst.addOperand(MCOperand::CreateReg(0));
1207 OutStreamer.EmitInstruction(TmpInst);
1211 TmpInst.setOpcode(ARM::LDRi12);
1212 TmpInst.addOperand(MCOperand::CreateReg(ScratchReg));
1213 TmpInst.addOperand(MCOperand::CreateReg(SrcReg));
1214 TmpInst.addOperand(MCOperand::CreateImm(4));
1216 TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
1217 TmpInst.addOperand(MCOperand::CreateReg(0));
1218 OutStreamer.EmitInstruction(TmpInst);
1222 TmpInst.setOpcode(ARM::LDRi12);
1223 TmpInst.addOperand(MCOperand::CreateReg(ARM::R7));
1224 TmpInst.addOperand(MCOperand::CreateReg(SrcReg));
1225 TmpInst.addOperand(MCOperand::CreateImm(0));
1227 TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
1228 TmpInst.addOperand(MCOperand::CreateReg(0));
1229 OutStreamer.EmitInstruction(TmpInst);
1233 TmpInst.setOpcode(ARM::BRIND);
1234 TmpInst.addOperand(MCOperand::CreateReg(ScratchReg));
1236 TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
1237 TmpInst.addOperand(MCOperand::CreateReg(0));
1238 OutStreamer.EmitInstruction(TmpInst);
1242 case ARM::tInt_eh_sjlj_longjmp: {
1243 // ldr $scratch, [$src, #8]
1245 // ldr $scratch, [$src, #4]
1248 unsigned SrcReg = MI->getOperand(0).getReg();
1249 unsigned ScratchReg = MI->getOperand(1).getReg();
1252 TmpInst.setOpcode(ARM::tLDR);
1253 TmpInst.addOperand(MCOperand::CreateReg(ScratchReg));
1254 TmpInst.addOperand(MCOperand::CreateReg(SrcReg));
1255 // The offset immediate is #8. The operand value is scaled by 4 for the
1256 // tSTR instruction.
1257 TmpInst.addOperand(MCOperand::CreateImm(2));
1258 TmpInst.addOperand(MCOperand::CreateReg(0));
1260 TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
1261 TmpInst.addOperand(MCOperand::CreateReg(0));
1262 OutStreamer.EmitInstruction(TmpInst);
1266 TmpInst.setOpcode(ARM::tMOVtgpr2gpr);
1267 TmpInst.addOperand(MCOperand::CreateReg(ARM::SP));
1268 TmpInst.addOperand(MCOperand::CreateReg(ScratchReg));
1270 TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
1271 TmpInst.addOperand(MCOperand::CreateReg(0));
1272 OutStreamer.EmitInstruction(TmpInst);
1276 TmpInst.setOpcode(ARM::tLDR);
1277 TmpInst.addOperand(MCOperand::CreateReg(ScratchReg));
1278 TmpInst.addOperand(MCOperand::CreateReg(SrcReg));
1279 TmpInst.addOperand(MCOperand::CreateImm(1));
1280 TmpInst.addOperand(MCOperand::CreateReg(0));
1282 TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
1283 TmpInst.addOperand(MCOperand::CreateReg(0));
1284 OutStreamer.EmitInstruction(TmpInst);
1288 TmpInst.setOpcode(ARM::tLDR);
1289 TmpInst.addOperand(MCOperand::CreateReg(ARM::R7));
1290 TmpInst.addOperand(MCOperand::CreateReg(SrcReg));
1291 TmpInst.addOperand(MCOperand::CreateImm(0));
1292 TmpInst.addOperand(MCOperand::CreateReg(0));
1294 TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
1295 TmpInst.addOperand(MCOperand::CreateReg(0));
1296 OutStreamer.EmitInstruction(TmpInst);
1300 TmpInst.setOpcode(ARM::tBX_RET_vararg);
1301 TmpInst.addOperand(MCOperand::CreateReg(ScratchReg));
1303 TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
1304 TmpInst.addOperand(MCOperand::CreateReg(0));
1305 OutStreamer.EmitInstruction(TmpInst);
1312 LowerARMMachineInstrToMCInst(MI, TmpInst, *this);
1313 OutStreamer.EmitInstruction(TmpInst);
1316 //===----------------------------------------------------------------------===//
1317 // Target Registry Stuff
1318 //===----------------------------------------------------------------------===//
1320 static MCInstPrinter *createARMMCInstPrinter(const Target &T,
1321 unsigned SyntaxVariant,
1322 const MCAsmInfo &MAI) {
1323 if (SyntaxVariant == 0)
1324 return new ARMInstPrinter(MAI);
1328 // Force static initialization.
1329 extern "C" void LLVMInitializeARMAsmPrinter() {
1330 RegisterAsmPrinter<ARMAsmPrinter> X(TheARMTarget);
1331 RegisterAsmPrinter<ARMAsmPrinter> Y(TheThumbTarget);
1333 TargetRegistry::RegisterMCInstPrinter(TheARMTarget, createARMMCInstPrinter);
1334 TargetRegistry::RegisterMCInstPrinter(TheThumbTarget, createARMMCInstPrinter);