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