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