ARMAsmPrinter.cpp revision d092a87ba3f905a6801a0bdf816267329cf0391c
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 "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" 54#include <cctype> 55using namespace llvm; 56 57namespace llvm { 58 namespace ARM { 59 enum DW_ISA { 60 DW_ISA_ARM_thumb = 1, 61 DW_ISA_ARM_arm = 2 62 }; 63 } 64} 65 66namespace { 67 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 { 73 public: 74 virtual void MaybeSwitchVendor(StringRef Vendor) = 0; 75 virtual void EmitAttribute(unsigned Attribute, unsigned Value) = 0; 76 virtual void Finish() = 0; 77 virtual ~AttributeEmitter() {} 78 }; 79 80 class AsmAttributeEmitter : public AttributeEmitter { 81 MCStreamer &Streamer; 82 83 public: 84 AsmAttributeEmitter(MCStreamer &Streamer_) : Streamer(Streamer_) {} 85 void MaybeSwitchVendor(StringRef Vendor) { } 86 87 void EmitAttribute(unsigned Attribute, unsigned Value) { 88 Streamer.EmitRawText("\t.eabi_attribute " + 89 Twine(Attribute) + ", " + Twine(Value)); 90 } 91 92 void Finish() { } 93 }; 94 95 class ObjectAttributeEmitter : public AttributeEmitter { 96 MCObjectStreamer &Streamer; 97 StringRef CurrentVendor; 98 SmallString<64> Contents; 99 100 public: 101 ObjectAttributeEmitter(MCObjectStreamer &Streamer_) : 102 Streamer(Streamer_), CurrentVendor("") { } 103 104 void MaybeSwitchVendor(StringRef Vendor) { 105 assert(!Vendor.empty() && "Vendor cannot be empty."); 106 107 if (CurrentVendor.empty()) 108 CurrentVendor = Vendor; 109 else if (CurrentVendor == Vendor) 110 return; 111 else 112 Finish(); 113 114 CurrentVendor = Vendor; 115 116 assert(Contents.size() == 0); 117 } 118 119 void EmitAttribute(unsigned Attribute, unsigned Value) { 120 // FIXME: should be ULEB 121 Contents += Attribute; 122 Contents += Value; 123 } 124 125 void Finish() { 126 const size_t ContentsSize = Contents.size(); 127 128 // Vendor size + Vendor name + '\0' 129 const size_t VendorHeaderSize = 4 + CurrentVendor.size() + 1; 130 131 // Tag + Tag Size 132 const size_t TagHeaderSize = 1 + 4; 133 134 Streamer.EmitIntValue(VendorHeaderSize + TagHeaderSize + ContentsSize, 4); 135 Streamer.EmitBytes(CurrentVendor, 0); 136 Streamer.EmitIntValue(0, 1); // '\0' 137 138 Streamer.EmitIntValue(ARMBuildAttrs::File, 1); 139 Streamer.EmitIntValue(TagHeaderSize + ContentsSize, 4); 140 141 Streamer.EmitBytes(Contents, 0); 142 143 Contents.clear(); 144 } 145 }; 146 147 class ARMAsmPrinter : public AsmPrinter { 148 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; 152 153 /// AFI - Keep a pointer to ARMFunctionInfo for the current 154 /// MachineFunction. 155 ARMFunctionInfo *AFI; 156 157 /// MCP - Keep a pointer to constantpool entries of the current 158 /// MachineFunction. 159 const MachineConstantPool *MCP; 160 161 public: 162 explicit ARMAsmPrinter(TargetMachine &TM, MCStreamer &Streamer) 163 : AsmPrinter(TM, Streamer), AFI(NULL), MCP(NULL) { 164 Subtarget = &TM.getSubtarget<ARMSubtarget>(); 165 } 166 167 virtual const char *getPassName() const { 168 return "ARM Assembly Printer"; 169 } 170 171 void printOperand(const MachineInstr *MI, int OpNum, raw_ostream &O, 172 const char *Modifier = 0); 173 174 virtual bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNum, 175 unsigned AsmVariant, const char *ExtraCode, 176 raw_ostream &O); 177 virtual bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNum, 178 unsigned AsmVariant, 179 const char *ExtraCode, raw_ostream &O); 180 181 void EmitJumpTable(const MachineInstr *MI); 182 void EmitJump2Table(const MachineInstr *MI); 183 virtual void EmitInstruction(const MachineInstr *MI); 184 bool runOnMachineFunction(MachineFunction &F); 185 186 virtual void EmitConstantPool() {} // we emit constant pools customly! 187 virtual void EmitFunctionEntryLabel(); 188 void EmitStartOfAsmFile(Module &M); 189 void EmitEndOfAsmFile(Module &M); 190 191 private: 192 // Helpers for EmitStartOfAsmFile() and EmitEndOfAsmFile() 193 void emitAttributes(); 194 195 // Helper for ELF .o only 196 void emitARMAttributeSection(); 197 198 public: 199 void PrintDebugValueComment(const MachineInstr *MI, raw_ostream &OS); 200 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()); 207 else { 208 DEBUG(dbgs() << "DBG_VALUE instruction ignored! " << *MI << "\n"); 209 } 210 return Location; 211 } 212 213 virtual unsigned getISAEncoding() { 214 // ARM/Darwin adds ISA to the DWARF info for each function. 215 if (!Subtarget->isTargetDarwin()) 216 return 0; 217 return Subtarget->isThumb() ? 218 llvm::ARM::DW_ISA_ARM_thumb : llvm::ARM::DW_ISA_ARM_arm; 219 } 220 221 MCSymbol *GetARMSetPICJumpTableLabel2(unsigned uid, unsigned uid2, 222 const MachineBasicBlock *MBB) const; 223 MCSymbol *GetARMJTIPICJumpTableLabel2(unsigned uid, unsigned uid2) const; 224 225 MCSymbol *GetARMSJLJEHLabel(void) const; 226 227 /// EmitMachineConstantPoolValue - Print a machine constantpool value to 228 /// the .s file. 229 virtual void EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV); 230 }; 231} // end of anonymous namespace 232 233void ARMAsmPrinter::EmitFunctionEntryLabel() { 234 if (AFI->isThumbFunction()) { 235 OutStreamer.EmitAssemblerFlag(MCAF_Code16); 236 OutStreamer.EmitThumbFunc(Subtarget->isTargetDarwin()? CurrentFnSym : 0); 237 } 238 239 OutStreamer.EmitLabel(CurrentFnSym); 240} 241 242/// runOnMachineFunction - This uses the EmitInstruction() 243/// method to print assembly for each instruction. 244/// 245bool ARMAsmPrinter::runOnMachineFunction(MachineFunction &MF) { 246 AFI = MF.getInfo<ARMFunctionInfo>(); 247 MCP = MF.getConstantPool(); 248 249 return AsmPrinter::runOnMachineFunction(MF); 250} 251 252void 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(); 256 257 switch (MO.getType()) { 258 default: 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); 265 break; 266 } 267 case MachineOperand::MO_Immediate: { 268 int64_t Imm = MO.getImm(); 269 O << '#'; 270 if ((Modifier && strcmp(Modifier, "lo16") == 0) || 271 (TF == ARMII::MO_LO16)) 272 O << ":lower16:"; 273 else if ((Modifier && strcmp(Modifier, "hi16") == 0) || 274 (TF == ARMII::MO_HI16)) 275 O << ":upper16:"; 276 O << Imm; 277 break; 278 } 279 case MachineOperand::MO_MachineBasicBlock: 280 O << *MO.getMBB()->getSymbol(); 281 return; 282 case MachineOperand::MO_GlobalAddress: { 283 const GlobalValue *GV = MO.getGlobal(); 284 if ((Modifier && strcmp(Modifier, "lo16") == 0) || 285 (TF & ARMII::MO_LO16)) 286 O << ":lower16:"; 287 else if ((Modifier && strcmp(Modifier, "hi16") == 0) || 288 (TF & ARMII::MO_HI16)) 289 O << ":upper16:"; 290 O << *Mang->getSymbol(GV); 291 292 printOffset(MO.getOffset(), O); 293 if (TF == ARMII::MO_PLT) 294 O << "(PLT)"; 295 break; 296 } 297 case MachineOperand::MO_ExternalSymbol: { 298 O << *GetExternalSymbolSymbol(MO.getSymbolName()); 299 if (TF == ARMII::MO_PLT) 300 O << "(PLT)"; 301 break; 302 } 303 case MachineOperand::MO_ConstantPoolIndex: 304 O << *GetCPISymbol(MO.getIndex()); 305 break; 306 case MachineOperand::MO_JumpTableIndex: 307 O << *GetJTISymbol(MO.getIndex()); 308 break; 309 } 310} 311 312//===--------------------------------------------------------------------===// 313 314MCSymbol *ARMAsmPrinter:: 315GetARMSetPICJumpTableLabel2(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()); 322} 323 324MCSymbol *ARMAsmPrinter:: 325GetARMJTIPICJumpTableLabel2(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()); 330} 331 332 333MCSymbol *ARMAsmPrinter::GetARMSJLJEHLabel(void) const { 334 SmallString<60> Name; 335 raw_svector_ostream(Name) << MAI->getPrivateGlobalPrefix() << "SJLJEH" 336 << getFunctionNumber(); 337 return OutContext.GetOrCreateSymbol(Name.str()); 338} 339 340bool ARMAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNum, 341 unsigned AsmVariant, const char *ExtraCode, 342 raw_ostream &O) { 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. 346 347 switch (ExtraCode[0]) { 348 default: return true; // Unknown modifier. 349 case 'a': // Print as a memory address. 350 if (MI->getOperand(OpNum).isReg()) { 351 O << "[" 352 << ARMInstPrinter::getRegisterName(MI->getOperand(OpNum).getReg()) 353 << "]"; 354 return false; 355 } 356 // Fallthrough 357 case 'c': // Don't print "#" before an immediate operand. 358 if (!MI->getOperand(OpNum).isImm()) 359 return true; 360 O << MI->getOperand(OpNum).getImm(); 361 return false; 362 case 'P': // Print a VFP double precision register. 363 case 'q': // Print a NEON quad precision register. 364 printOperand(MI, OpNum, O); 365 return false; 366 case 'Q': 367 case 'R': 368 case 'H': 369 report_fatal_error("llvm does not support 'Q', 'R', and 'H' modifiers!"); 370 return true; 371 } 372 } 373 374 printOperand(MI, OpNum, O); 375 return false; 376} 377 378bool ARMAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, 379 unsigned OpNum, unsigned AsmVariant, 380 const char *ExtraCode, 381 raw_ostream &O) { 382 if (ExtraCode && ExtraCode[0]) 383 return true; // Unknown modifier. 384 385 const MachineOperand &MO = MI->getOperand(OpNum); 386 assert(MO.isReg() && "unexpected inline asm memory operand"); 387 O << "[" << ARMInstPrinter::getRegisterName(MO.getReg()) << "]"; 388 return false; 389} 390 391void 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 400 // relocations. 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); 413 } else { 414 const MCSection *sect = 415 OutContext.getMachOSection("__TEXT", "__picsymbolstub4", 416 MCSectionMachO::S_SYMBOL_STUBS, 417 16, SectionKind::getText()); 418 OutStreamer.SwitchSection(sect); 419 } 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); 426 } 427 } 428 429 // Use unified assembler syntax. 430 OutStreamer.EmitAssemblerFlag(MCAF_SyntaxUnified); 431 432 // Emit ARM Build Attributes 433 if (Subtarget->isTargetELF()) { 434 435 emitAttributes(); 436 } 437} 438 439 440void 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>(); 447 448 // Output non-lazy-pointers for external and common global variables. 449 MachineModuleInfoMachO::SymbolListTy Stubs = MMIMacho.GetGVStubList(); 450 451 if (!Stubs.empty()) { 452 // Switch with ".non_lazy_symbol_pointer" directive. 453 OutStreamer.SwitchSection(TLOFMacho.getNonLazySymbolPointerSection()); 454 EmitAlignment(2); 455 for (unsigned i = 0, e = Stubs.size(); i != e; ++i) { 456 // L_foo$stub: 457 OutStreamer.EmitLabel(Stubs[i].first); 458 // .indirect_symbol _foo 459 MachineModuleInfoImpl::StubValueTy &MCSym = Stubs[i].second; 460 OutStreamer.EmitSymbolAttribute(MCSym.getPointer(),MCSA_IndirectSymbol); 461 462 if (MCSym.getInt()) 463 // External to current translation unit. 464 OutStreamer.EmitIntValue(0, 4/*size*/, 0/*addrspace*/); 465 else 466 // Internal to current translation unit. 467 // 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(), 473 OutContext), 474 4/*size*/, 0/*addrspace*/); 475 } 476 477 Stubs.clear(); 478 OutStreamer.AddBlankLine(); 479 } 480 481 Stubs = MMIMacho.GetHiddenGVStubList(); 482 if (!Stubs.empty()) { 483 OutStreamer.SwitchSection(getObjFileLowering().getDataSection()); 484 EmitAlignment(2); 485 for (unsigned i = 0, e = Stubs.size(); i != e; ++i) { 486 // L_foo$stub: 487 OutStreamer.EmitLabel(Stubs[i].first); 488 // .long _foo 489 OutStreamer.EmitValue(MCSymbolRefExpr:: 490 Create(Stubs[i].second.getPointer(), 491 OutContext), 492 4/*size*/, 0/*addrspace*/); 493 } 494 495 Stubs.clear(); 496 OutStreamer.AddBlankLine(); 497 } 498 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); 505 } 506} 507 508//===----------------------------------------------------------------------===// 509// Helper routines for EmitStartOfAsmFile() and EmitEndOfAsmFile() 510// FIXME: 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. 514 515void ARMAsmPrinter::emitAttributes() { 516 517 emitARMAttributeSection(); 518 519 AttributeEmitter *AttrEmitter; 520 if (OutStreamer.hasRawTextSupport()) 521 AttrEmitter = new AsmAttributeEmitter(OutStreamer); 522 else { 523 MCObjectStreamer &O = static_cast<MCObjectStreamer&>(OutStreamer); 524 AttrEmitter = new ObjectAttributeEmitter(O); 525 } 526 527 AttrEmitter->MaybeSwitchVendor("aeabi"); 528 529 std::string CPUString = Subtarget->getCPUString(); 530 if (OutStreamer.hasRawTextSupport()) { 531 if (CPUString != "generic") 532 OutStreamer.EmitRawText(StringRef("\t.cpu ") + CPUString); 533 } else { 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); 539 } 540 541 // FIXME: Emit FPU type 542 if (Subtarget->hasVFP2()) 543 AttrEmitter->EmitAttribute(ARMBuildAttrs::VFP_arch, 2); 544 545 // Signal various FP modes. 546 if (!UnsafeFPMath) { 547 AttrEmitter->EmitAttribute(ARMBuildAttrs::ABI_FP_denormal, 1); 548 AttrEmitter->EmitAttribute(ARMBuildAttrs::ABI_FP_exceptions, 1); 549 } 550 551 if (NoInfsFPMath && NoNaNsFPMath) 552 AttrEmitter->EmitAttribute(ARMBuildAttrs::ABI_FP_number_model, 1); 553 else 554 AttrEmitter->EmitAttribute(ARMBuildAttrs::ABI_FP_number_model, 3); 555 556 // 8-bytes alignment stuff. 557 AttrEmitter->EmitAttribute(ARMBuildAttrs::ABI_align8_needed, 1); 558 AttrEmitter->EmitAttribute(ARMBuildAttrs::ABI_align8_preserved, 1); 559 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); 564 } 565 // FIXME: Should we signal R9 usage? 566 567 AttrEmitter->EmitAttribute(ARMBuildAttrs::DIV_use, 1); 568 569 AttrEmitter->Finish(); 570 delete AttrEmitter; 571} 572 573void ARMAsmPrinter::emitARMAttributeSection() { 574 // <format-version> 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>* 579 // ]+ 580 // ]* 581 582 if (OutStreamer.hasRawTextSupport()) 583 return; 584 585 const ARMElfTargetObjectFile &TLOFELF = 586 static_cast<const ARMElfTargetObjectFile &> 587 (getObjFileLowering()); 588 589 OutStreamer.SwitchSection(TLOFELF.getAttributesSection()); 590 591 // Format version 592 OutStreamer.EmitIntValue(0x41, 1); 593} 594 595//===----------------------------------------------------------------------===// 596 597static MCSymbol *getPICLabel(const char *Prefix, unsigned FunctionNumber, 598 unsigned LabelId, MCContext &Ctx) { 599 600 MCSymbol *Label = Ctx.GetOrCreateSymbol(Twine(Prefix) 601 + "PC" + Twine(FunctionNumber) + "_" + Twine(LabelId)); 602 return Label; 603} 604 605static MCSymbolRefExpr::VariantKind 606getModifierVariantKind(ARMCP::ARMCPModifier Modifier) { 607 switch (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; 615 } 616 return MCSymbolRefExpr::VK_None; 617} 618 619void ARMAsmPrinter:: 620EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) { 621 int Size = TM.getTargetData()->getTypeAllocSize(MCPV->getType()); 622 623 ARMConstantPoolValue *ACPV = static_cast<ARMConstantPoolValue*>(MCPV); 624 625 MCSymbol *MCSym; 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()); 637 if (!isIndirect) 638 MCSym = Mang->getSymbol(GV); 639 else { 640 // FIXME: Remove this when Darwin transition to @GOT like syntax. 641 MCSym = GetSymbolWithGlobalValueBase(GV, "$non_lazy_ptr"); 642 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()); 651 } 652 } else { 653 assert(ACPV->isExtSymbol() && "unrecognized constant pool value"); 654 MCSym = GetExternalSymbolSymbol(ACPV->getSymbol()); 655 } 656 657 // Create an MCSymbol for the reference. 658 const MCExpr *Expr = 659 MCSymbolRefExpr::Create(MCSym, getModifierVariantKind(ACPV->getModifier()), 660 OutContext); 661 662 if (ACPV->getPCAdjustment()) { 663 MCSymbol *PCLabel = getPICLabel(MAI->getPrivateGlobalPrefix(), 664 getFunctionNumber(), 665 ACPV->getLabelId(), 666 OutContext); 667 const MCExpr *PCRelExpr = MCSymbolRefExpr::Create(PCLabel, OutContext); 668 PCRelExpr = 669 MCBinaryExpr::CreateAdd(PCRelExpr, 670 MCConstantExpr::Create(ACPV->getPCAdjustment(), 671 OutContext), 672 OutContext); 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); 680 } 681 Expr = MCBinaryExpr::CreateSub(Expr, PCRelExpr, OutContext); 682 } 683 OutStreamer.EmitValue(Expr, Size); 684} 685 686void ARMAsmPrinter::EmitJumpTable(const MachineInstr *MI) { 687 unsigned Opcode = MI->getOpcode(); 688 int OpNum = 1; 689 if (Opcode == ARM::BR_JTadd) 690 OpNum = 2; 691 else if (Opcode == ARM::BR_JTm) 692 OpNum = 3; 693 694 const MachineOperand &MO1 = MI->getOperand(OpNum); 695 const MachineOperand &MO2 = MI->getOperand(OpNum+1); // Unique Id 696 unsigned JTI = MO1.getIndex(); 697 698 // Emit a label for the jump table. 699 MCSymbol *JTISymbol = GetARMJTIPICJumpTableLabel2(JTI, MO2.getImm()); 700 OutStreamer.EmitLabel(JTISymbol); 701 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; 706 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) 711 // 712 // For example, a table with entries jumping to basic blocks BB0 and BB1 713 // would look like: 714 // LJTI_0_0: 715 // .word (LBB0 - LJTI_0_0) 716 // .word (LBB1 - LJTI_0_0) 717 const MCExpr *Expr = MCSymbolRefExpr::Create(MBB->getSymbol(), OutContext); 718 719 if (TM.getRelocationModel() == Reloc::PIC_) 720 Expr = MCBinaryExpr::CreateSub(Expr, MCSymbolRefExpr::Create(JTISymbol, 721 OutContext), 722 OutContext); 723 OutStreamer.EmitValue(Expr, 4); 724 } 725} 726 727void 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(); 733 734 // Emit a label for the jump table. 735 MCSymbol *JTISymbol = GetARMJTIPICJumpTableLabel2(JTI, MO2.getImm()); 736 OutStreamer.EmitLabel(JTISymbol); 737 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) 744 OffsetWidth = 1; 745 else if (MI->getOpcode() == ARM::t2TBH_JT) 746 OffsetWidth = 2; 747 748 for (unsigned i = 0, e = JTBBs.size(); i != e; ++i) { 749 MachineBasicBlock *MBB = JTBBs[i]; 750 const MCExpr *MBBSymbolExpr = MCSymbolRefExpr::Create(MBB->getSymbol(), 751 OutContext); 752 // If this isn't a TBB or TBH, the entries are direct branch instructions. 753 if (OffsetWidth == 4) { 754 MCInst BrInst; 755 BrInst.setOpcode(ARM::t2B); 756 BrInst.addOperand(MCOperand::CreateExpr(MBBSymbolExpr)); 757 OutStreamer.EmitInstruction(BrInst); 758 continue; 759 } 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 763 // 764 // For example, a TBB table with entries jumping to basic blocks BB0 and BB1 765 // would look like: 766 // LJTI_0_0: 767 // .byte (LBB0 - LJTI_0_0) / 2 768 // .byte (LBB1 - LJTI_0_0) / 2 769 const MCExpr *Expr = 770 MCBinaryExpr::CreateSub(MBBSymbolExpr, 771 MCSymbolRefExpr::Create(JTISymbol, OutContext), 772 OutContext); 773 Expr = MCBinaryExpr::CreateDiv(Expr, MCConstantExpr::Create(2, OutContext), 774 OutContext); 775 OutStreamer.EmitValue(Expr, OffsetWidth); 776 } 777 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) 781 EmitAlignment(1); 782} 783 784void ARMAsmPrinter::PrintDebugValueComment(const MachineInstr *MI, 785 raw_ostream &OS) { 786 unsigned NOps = MI->getNumOperands(); 787 assert(NOps==4); 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())); 791 OS << V.getName(); 792 OS << " <- "; 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); 796 OS << ']'; 797 OS << "+"; 798 printOperand(MI, NOps-2, OS); 799} 800 801void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) { 802 switch (MI->getOpcode()) { 803 default: break; 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())); 811 } 812 return; 813 } 814 case ARM::tPICADD: { 815 // This is a pseudo op for a label + instruction sequence, which looks like: 816 // LPC0: 817 // add r0, pc 818 // This adds the address of LPC0 to r0. 819 820 // Emit the label. 821 OutStreamer.EmitLabel(getPICLabel(MAI->getPrivateGlobalPrefix(), 822 getFunctionNumber(), MI->getOperand(2).getImm(), 823 OutContext)); 824 825 // Form and emit the add. 826 MCInst AddInst; 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); 835 return; 836 } 837 case ARM::PICADD: { 838 // This is a pseudo op for a label + instruction sequence, which looks like: 839 // LPC0: 840 // add r0, pc, r0 841 // This adds the address of LPC0 to r0. 842 843 // Emit the label. 844 OutStreamer.EmitLabel(getPICLabel(MAI->getPrivateGlobalPrefix(), 845 getFunctionNumber(), MI->getOperand(2).getImm(), 846 OutContext)); 847 848 // Form and emit the add. 849 MCInst AddInst; 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); 860 return; 861 } 862 case ARM::PICSTR: 863 case ARM::PICSTRB: 864 case ARM::PICSTRH: 865 case ARM::PICLDR: 866 case ARM::PICLDRB: 867 case ARM::PICLDRH: 868 case ARM::PICLDRSB: 869 case ARM::PICLDRSH: { 870 // This is a pseudo op for a label + instruction sequence, which looks like: 871 // LPC0: 872 // OP r0, [pc, r0] 873 // The LCP0 label is referenced by a constant pool entry in order to get 874 // a PC-relative address at the ldr instruction. 875 876 // Emit the label. 877 OutStreamer.EmitLabel(getPICLabel(MAI->getPrivateGlobalPrefix(), 878 getFunctionNumber(), MI->getOperand(2).getImm(), 879 OutContext)); 880 881 // Form and emit the load 882 unsigned Opcode; 883 switch (MI->getOpcode()) { 884 default: 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; 894 } 895 MCInst LdStInst; 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); 905 906 return; 907 } 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(); 915 916 EmitAlignment(2); 917 OutStreamer.EmitLabel(GetCPISymbol(LabelId)); 918 919 const MachineConstantPoolEntry &MCPE = MCP->getConstants()[CPIdx]; 920 if (MCPE.isMachineConstantPoolEntry()) 921 EmitMachineConstantPoolValue(MCPE.Val.MachineCPVal); 922 else 923 EmitGlobalConstant(MCPE.Val.ConstVal); 924 925 return; 926 } 927 case ARM::t2TBB_JT: 928 case ARM::t2TBH_JT: 929 case ARM::t2BR_JT: { 930 // Lower and emit the instruction itself, then the jump table following it. 931 MCInst TmpInst; 932 // FIXME: The branch instruction is really a pseudo. We should xform it 933 // explicitly. 934 LowerARMMachineInstrToMCInst(MI, TmpInst, *this); 935 OutStreamer.EmitInstruction(TmpInst); 936 EmitJump2Table(MI); 937 return; 938 } 939 case ARM::tBR_JTr: 940 case ARM::BR_JTr: { 941 // Lower and emit the instruction itself, then the jump table following it. 942 // mov pc, target 943 MCInst TmpInst; 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); 952 953 // Make sure the Thumb jump table is 4-byte aligned. 954 if (Opc == ARM::tMOVr) 955 EmitAlignment(2); 956 957 // Output the data for the jump table itself 958 EmitJumpTable(MI); 959 return; 960 } 961 case ARM::BR_JTm: { 962 // Lower and emit the instruction itself, then the jump table following it. 963 // ldr pc, target 964 MCInst TmpInst; 965 if (MI->getOperand(1).getReg() == 0) { 966 // literal offset 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())); 971 } else { 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)); 977 } 978 // Add predicate operands. 979 TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL)); 980 TmpInst.addOperand(MCOperand::CreateReg(0)); 981 OutStreamer.EmitInstruction(TmpInst); 982 983 // Output the data for the jump table itself 984 EmitJumpTable(MI); 985 return; 986 } 987 case ARM::BR_JTadd: { 988 // Lower and emit the instruction itself, then the jump table following it. 989 // add pc, target, idx 990 MCInst TmpInst; 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); 1001 1002 // Output the data for the jump table itself 1003 EmitJumpTable(MI); 1004 return; 1005 } 1006 case ARM::TRAP: { 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); 1014 return; 1015 } 1016 break; 1017 } 1018 case ARM::tTRAP: { 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); 1026 return; 1027 } 1028 break; 1029 } 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 1034 // mov $val, pc 1035 // adds $val, #7 1036 // str $val, [$src, #4] 1037 // movs r0, #0 1038 // b 1f 1039 // movs r0, #1 1040 // 1: 1041 unsigned SrcReg = MI->getOperand(0).getReg(); 1042 unsigned ValReg = MI->getOperand(1).getReg(); 1043 MCSymbol *Label = GetARMSJLJEHLabel(); 1044 { 1045 MCInst TmpInst; 1046 TmpInst.setOpcode(ARM::tMOVgpr2tgpr); 1047 TmpInst.addOperand(MCOperand::CreateReg(ValReg)); 1048 TmpInst.addOperand(MCOperand::CreateReg(ARM::PC)); 1049 // 's' bit operand 1050 TmpInst.addOperand(MCOperand::CreateReg(ARM::CPSR)); 1051 OutStreamer.AddComment("eh_setjmp begin"); 1052 OutStreamer.EmitInstruction(TmpInst); 1053 } 1054 { 1055 MCInst TmpInst; 1056 TmpInst.setOpcode(ARM::tADDi3); 1057 TmpInst.addOperand(MCOperand::CreateReg(ValReg)); 1058 // 's' bit operand 1059 TmpInst.addOperand(MCOperand::CreateReg(ARM::CPSR)); 1060 TmpInst.addOperand(MCOperand::CreateReg(ValReg)); 1061 TmpInst.addOperand(MCOperand::CreateImm(7)); 1062 // Predicate. 1063 TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL)); 1064 TmpInst.addOperand(MCOperand::CreateReg(0)); 1065 OutStreamer.EmitInstruction(TmpInst); 1066 } 1067 { 1068 MCInst 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)); 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::tMOVi8); 1084 TmpInst.addOperand(MCOperand::CreateReg(ARM::R0)); 1085 TmpInst.addOperand(MCOperand::CreateReg(ARM::CPSR)); 1086 TmpInst.addOperand(MCOperand::CreateImm(0)); 1087 // Predicate. 1088 TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL)); 1089 TmpInst.addOperand(MCOperand::CreateReg(0)); 1090 OutStreamer.EmitInstruction(TmpInst); 1091 } 1092 { 1093 const MCExpr *SymbolExpr = MCSymbolRefExpr::Create(Label, OutContext); 1094 MCInst TmpInst; 1095 TmpInst.setOpcode(ARM::tB); 1096 TmpInst.addOperand(MCOperand::CreateExpr(SymbolExpr)); 1097 OutStreamer.EmitInstruction(TmpInst); 1098 } 1099 { 1100 MCInst 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)); 1105 // Predicate. 1106 TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL)); 1107 TmpInst.addOperand(MCOperand::CreateReg(0)); 1108 OutStreamer.AddComment("eh_setjmp end"); 1109 OutStreamer.EmitInstruction(TmpInst); 1110 } 1111 OutStreamer.EmitLabel(Label); 1112 return; 1113 } 1114 1115 case ARM::Int_eh_sjlj_setjmp_nofp: 1116 case ARM::Int_eh_sjlj_setjmp: { 1117 // Two incoming args: GPR:$src, GPR:$val 1118 // add $val, pc, #8 1119 // str $val, [$src, #+4] 1120 // mov r0, #0 1121 // add pc, pc, #0 1122 // mov r0, #1 1123 unsigned SrcReg = MI->getOperand(0).getReg(); 1124 unsigned ValReg = MI->getOperand(1).getReg(); 1125 1126 { 1127 MCInst TmpInst; 1128 TmpInst.setOpcode(ARM::ADDri); 1129 TmpInst.addOperand(MCOperand::CreateReg(ValReg)); 1130 TmpInst.addOperand(MCOperand::CreateReg(ARM::PC)); 1131 TmpInst.addOperand(MCOperand::CreateImm(8)); 1132 // Predicate. 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); 1139 } 1140 { 1141 MCInst TmpInst; 1142 TmpInst.setOpcode(ARM::STRi12); 1143 TmpInst.addOperand(MCOperand::CreateReg(ValReg)); 1144 TmpInst.addOperand(MCOperand::CreateReg(SrcReg)); 1145 TmpInst.addOperand(MCOperand::CreateImm(4)); 1146 // Predicate. 1147 TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL)); 1148 TmpInst.addOperand(MCOperand::CreateReg(0)); 1149 OutStreamer.EmitInstruction(TmpInst); 1150 } 1151 { 1152 MCInst TmpInst; 1153 TmpInst.setOpcode(ARM::MOVi); 1154 TmpInst.addOperand(MCOperand::CreateReg(ARM::R0)); 1155 TmpInst.addOperand(MCOperand::CreateImm(0)); 1156 // Predicate. 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); 1162 } 1163 { 1164 MCInst 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)); 1169 // Predicate. 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); 1175 } 1176 { 1177 MCInst TmpInst; 1178 TmpInst.setOpcode(ARM::MOVi); 1179 TmpInst.addOperand(MCOperand::CreateReg(ARM::R0)); 1180 TmpInst.addOperand(MCOperand::CreateImm(1)); 1181 // Predicate. 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); 1188 } 1189 return; 1190 } 1191 case ARM::Int_eh_sjlj_longjmp: { 1192 // ldr sp, [$src, #8] 1193 // ldr $scratch, [$src, #4] 1194 // ldr r7, [$src] 1195 // bx $scratch 1196 unsigned SrcReg = MI->getOperand(0).getReg(); 1197 unsigned ScratchReg = MI->getOperand(1).getReg(); 1198 { 1199 MCInst TmpInst; 1200 TmpInst.setOpcode(ARM::LDRi12); 1201 TmpInst.addOperand(MCOperand::CreateReg(ARM::SP)); 1202 TmpInst.addOperand(MCOperand::CreateReg(SrcReg)); 1203 TmpInst.addOperand(MCOperand::CreateImm(8)); 1204 // Predicate. 1205 TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL)); 1206 TmpInst.addOperand(MCOperand::CreateReg(0)); 1207 OutStreamer.EmitInstruction(TmpInst); 1208 } 1209 { 1210 MCInst TmpInst; 1211 TmpInst.setOpcode(ARM::LDRi12); 1212 TmpInst.addOperand(MCOperand::CreateReg(ScratchReg)); 1213 TmpInst.addOperand(MCOperand::CreateReg(SrcReg)); 1214 TmpInst.addOperand(MCOperand::CreateImm(4)); 1215 // Predicate. 1216 TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL)); 1217 TmpInst.addOperand(MCOperand::CreateReg(0)); 1218 OutStreamer.EmitInstruction(TmpInst); 1219 } 1220 { 1221 MCInst 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)); 1226 // Predicate. 1227 TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL)); 1228 TmpInst.addOperand(MCOperand::CreateReg(0)); 1229 OutStreamer.EmitInstruction(TmpInst); 1230 } 1231 { 1232 MCInst TmpInst; 1233 TmpInst.setOpcode(ARM::BRIND); 1234 TmpInst.addOperand(MCOperand::CreateReg(ScratchReg)); 1235 // Predicate. 1236 TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL)); 1237 TmpInst.addOperand(MCOperand::CreateReg(0)); 1238 OutStreamer.EmitInstruction(TmpInst); 1239 } 1240 return; 1241 } 1242 case ARM::tInt_eh_sjlj_longjmp: { 1243 // ldr $scratch, [$src, #8] 1244 // mov sp, $scratch 1245 // ldr $scratch, [$src, #4] 1246 // ldr r7, [$src] 1247 // bx $scratch 1248 unsigned SrcReg = MI->getOperand(0).getReg(); 1249 unsigned ScratchReg = MI->getOperand(1).getReg(); 1250 { 1251 MCInst TmpInst; 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)); 1259 // Predicate. 1260 TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL)); 1261 TmpInst.addOperand(MCOperand::CreateReg(0)); 1262 OutStreamer.EmitInstruction(TmpInst); 1263 } 1264 { 1265 MCInst TmpInst; 1266 TmpInst.setOpcode(ARM::tMOVtgpr2gpr); 1267 TmpInst.addOperand(MCOperand::CreateReg(ARM::SP)); 1268 TmpInst.addOperand(MCOperand::CreateReg(ScratchReg)); 1269 // Predicate. 1270 TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL)); 1271 TmpInst.addOperand(MCOperand::CreateReg(0)); 1272 OutStreamer.EmitInstruction(TmpInst); 1273 } 1274 { 1275 MCInst 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)); 1281 // Predicate. 1282 TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL)); 1283 TmpInst.addOperand(MCOperand::CreateReg(0)); 1284 OutStreamer.EmitInstruction(TmpInst); 1285 } 1286 { 1287 MCInst 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)); 1293 // Predicate. 1294 TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL)); 1295 TmpInst.addOperand(MCOperand::CreateReg(0)); 1296 OutStreamer.EmitInstruction(TmpInst); 1297 } 1298 { 1299 MCInst TmpInst; 1300 TmpInst.setOpcode(ARM::tBX_RET_vararg); 1301 TmpInst.addOperand(MCOperand::CreateReg(ScratchReg)); 1302 // Predicate. 1303 TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL)); 1304 TmpInst.addOperand(MCOperand::CreateReg(0)); 1305 OutStreamer.EmitInstruction(TmpInst); 1306 } 1307 return; 1308 } 1309 } 1310 1311 MCInst TmpInst; 1312 LowerARMMachineInstrToMCInst(MI, TmpInst, *this); 1313 OutStreamer.EmitInstruction(TmpInst); 1314} 1315 1316//===----------------------------------------------------------------------===// 1317// Target Registry Stuff 1318//===----------------------------------------------------------------------===// 1319 1320static MCInstPrinter *createARMMCInstPrinter(const Target &T, 1321 unsigned SyntaxVariant, 1322 const MCAsmInfo &MAI) { 1323 if (SyntaxVariant == 0) 1324 return new ARMInstPrinter(MAI); 1325 return 0; 1326} 1327 1328// Force static initialization. 1329extern "C" void LLVMInitializeARMAsmPrinter() { 1330 RegisterAsmPrinter<ARMAsmPrinter> X(TheARMTarget); 1331 RegisterAsmPrinter<ARMAsmPrinter> Y(TheThumbTarget); 1332 1333 TargetRegistry::RegisterMCInstPrinter(TheARMTarget, createARMMCInstPrinter); 1334 TargetRegistry::RegisterMCInstPrinter(TheThumbTarget, createARMMCInstPrinter); 1335} 1336 1337