ARMAsmPrinter.cpp revision e21e39666e8a41ffd4971d8bb023b70b59297267
1//===-- ARMAsmPrinter.cpp - ARM LLVM assembly writer ----------------------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file was developed by the "Instituto Nokia de Tecnologia" and 6// is distributed under the University of Illinois Open Source 7// License. See LICENSE.TXT for details. 8// 9//===----------------------------------------------------------------------===// 10// 11// This file contains a printer that converts from our internal representation 12// of machine-dependent LLVM code to GAS-format ARM assembly language. 13// 14//===----------------------------------------------------------------------===// 15 16#define DEBUG_TYPE "asm-printer" 17#include "ARM.h" 18#include "ARMTargetMachine.h" 19#include "ARMAddressingModes.h" 20#include "ARMConstantPoolValue.h" 21#include "ARMMachineFunctionInfo.h" 22#include "llvm/Constants.h" 23#include "llvm/Module.h" 24#include "llvm/CodeGen/AsmPrinter.h" 25#include "llvm/CodeGen/DwarfWriter.h" 26#include "llvm/CodeGen/MachineModuleInfo.h" 27#include "llvm/CodeGen/MachineFunctionPass.h" 28#include "llvm/CodeGen/MachineJumpTableInfo.h" 29#include "llvm/Target/TargetAsmInfo.h" 30#include "llvm/Target/TargetData.h" 31#include "llvm/Target/TargetMachine.h" 32#include "llvm/Target/TargetOptions.h" 33#include "llvm/ADT/Statistic.h" 34#include "llvm/ADT/StringExtras.h" 35#include "llvm/Support/Compiler.h" 36#include "llvm/Support/Mangler.h" 37#include "llvm/Support/MathExtras.h" 38#include <cctype> 39using namespace llvm; 40 41STATISTIC(EmittedInsts, "Number of machine instrs printed"); 42 43namespace { 44 struct VISIBILITY_HIDDEN ARMAsmPrinter : public AsmPrinter { 45 ARMAsmPrinter(std::ostream &O, TargetMachine &TM, const TargetAsmInfo *T) 46 : AsmPrinter(O, TM, T), DW(O, this, T), AFI(NULL), InCPMode(false) { 47 Subtarget = &TM.getSubtarget<ARMSubtarget>(); 48 } 49 50 DwarfWriter DW; 51 52 /// Subtarget - Keep a pointer to the ARMSubtarget around so that we can 53 /// make the right decision when printing asm code for different targets. 54 const ARMSubtarget *Subtarget; 55 56 /// AFI - Keep a pointer to ARMFunctionInfo for the current 57 /// MachineFunction 58 ARMFunctionInfo *AFI; 59 60 /// We name each basic block in a Function with a unique number, so 61 /// that we can consistently refer to them later. This is cleared 62 /// at the beginning of each call to runOnMachineFunction(). 63 /// 64 typedef std::map<const Value *, unsigned> ValueMapTy; 65 ValueMapTy NumberForBB; 66 67 /// Keeps the set of GlobalValues that require non-lazy-pointers for 68 /// indirect access. 69 std::set<std::string> GVNonLazyPtrs; 70 71 /// Keeps the set of external function GlobalAddresses that the asm 72 /// printer should generate stubs for. 73 std::set<std::string> FnStubs; 74 75 /// True if asm printer is printing a series of CONSTPOOL_ENTRY. 76 bool InCPMode; 77 78 virtual const char *getPassName() const { 79 return "ARM Assembly Printer"; 80 } 81 82 void printOperand(const MachineInstr *MI, int opNum, 83 const char *Modifier = 0); 84 void printSOImmOperand(const MachineInstr *MI, int opNum); 85 void printSOImm2PartOperand(const MachineInstr *MI, int opNum); 86 void printSORegOperand(const MachineInstr *MI, int opNum); 87 void printAddrMode2Operand(const MachineInstr *MI, int OpNo); 88 void printAddrMode2OffsetOperand(const MachineInstr *MI, int OpNo); 89 void printAddrMode3Operand(const MachineInstr *MI, int OpNo); 90 void printAddrMode3OffsetOperand(const MachineInstr *MI, int OpNo); 91 void printAddrMode4Operand(const MachineInstr *MI, int OpNo, 92 const char *Modifier = 0); 93 void printAddrMode5Operand(const MachineInstr *MI, int OpNo, 94 const char *Modifier = 0); 95 void printAddrModePCOperand(const MachineInstr *MI, int OpNo, 96 const char *Modifier = 0); 97 void printThumbAddrModeRROperand(const MachineInstr *MI, int OpNo); 98 void printThumbAddrModeRI5Operand(const MachineInstr *MI, int OpNo, 99 unsigned Scale); 100 void printThumbAddrModeS1Operand(const MachineInstr *MI, int OpNo); 101 void printThumbAddrModeS2Operand(const MachineInstr *MI, int OpNo); 102 void printThumbAddrModeS4Operand(const MachineInstr *MI, int OpNo); 103 void printThumbAddrModeSPOperand(const MachineInstr *MI, int OpNo); 104 void printCCOperand(const MachineInstr *MI, int opNum); 105 void printPCLabel(const MachineInstr *MI, int opNum); 106 void printRegisterList(const MachineInstr *MI, int opNum); 107 void printCPInstOperand(const MachineInstr *MI, int opNum, 108 const char *Modifier); 109 void printJTBlockOperand(const MachineInstr *MI, int opNum); 110 111 virtual bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, 112 unsigned AsmVariant, const char *ExtraCode); 113 114 bool printInstruction(const MachineInstr *MI); // autogenerated. 115 void printMachineInstruction(const MachineInstr *MI); 116 bool runOnMachineFunction(MachineFunction &F); 117 bool doInitialization(Module &M); 118 bool doFinalization(Module &M); 119 120 virtual void EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) { 121 printDataDirective(MCPV->getType()); 122 123 ARMConstantPoolValue *ACPV = (ARMConstantPoolValue*)MCPV; 124 GlobalValue *GV = ACPV->getGV(); 125 std::string Name = GV ? Mang->getValueName(GV) : TAI->getGlobalPrefix(); 126 if (!GV) 127 Name += ACPV->getSymbol(); 128 if (ACPV->isNonLazyPointer()) { 129 GVNonLazyPtrs.insert(Name); 130 O << TAI->getPrivateGlobalPrefix() << Name << "$non_lazy_ptr"; 131 } else if (ACPV->isStub()) { 132 FnStubs.insert(Name); 133 O << TAI->getPrivateGlobalPrefix() << Name << "$stub"; 134 } else 135 O << Name; 136 if (ACPV->getPCAdjustment() != 0) 137 O << "-(" << TAI->getPrivateGlobalPrefix() << "PC" 138 << utostr(ACPV->getLabelId()) 139 << "+" << (unsigned)ACPV->getPCAdjustment() << ")"; 140 O << "\n"; 141 142 // If the constant pool value is a extern weak symbol, remember to emit 143 // the weak reference. 144 if (GV && GV->hasExternalWeakLinkage()) 145 ExtWeakSymbols.insert(GV); 146 } 147 148 void getAnalysisUsage(AnalysisUsage &AU) const { 149 AU.setPreservesAll(); 150 AU.addRequired<MachineModuleInfo>(); 151 } 152 }; 153} // end of anonymous namespace 154 155#include "ARMGenAsmWriter.inc" 156 157/// createARMCodePrinterPass - Returns a pass that prints the ARM 158/// assembly code for a MachineFunction to the given output stream, 159/// using the given target machine description. This should work 160/// regardless of whether the function is in SSA form. 161/// 162FunctionPass *llvm::createARMCodePrinterPass(std::ostream &o, 163 ARMTargetMachine &tm) { 164 return new ARMAsmPrinter(o, tm, tm.getTargetAsmInfo()); 165} 166 167/// runOnMachineFunction - This uses the printInstruction() 168/// method to print assembly for each instruction. 169/// 170bool ARMAsmPrinter::runOnMachineFunction(MachineFunction &MF) { 171 AFI = MF.getInfo<ARMFunctionInfo>(); 172 173 if (Subtarget->isTargetDarwin()) { 174 DW.SetModuleInfo(&getAnalysis<MachineModuleInfo>()); 175 } 176 177 SetupMachineFunction(MF); 178 O << "\n"; 179 180 // NOTE: we don't print out constant pools here, they are handled as 181 // instructions. 182 183 O << "\n"; 184 // Print out labels for the function. 185 const Function *F = MF.getFunction(); 186 switch (F->getLinkage()) { 187 default: assert(0 && "Unknown linkage type!"); 188 case Function::InternalLinkage: 189 SwitchToTextSection("\t.text", F); 190 break; 191 case Function::ExternalLinkage: 192 SwitchToTextSection("\t.text", F); 193 O << "\t.globl\t" << CurrentFnName << "\n"; 194 break; 195 case Function::WeakLinkage: 196 case Function::LinkOnceLinkage: 197 if (Subtarget->isTargetDarwin()) { 198 SwitchToTextSection( 199 ".section __TEXT,__textcoal_nt,coalesced,pure_instructions", F); 200 O << "\t.globl\t" << CurrentFnName << "\n"; 201 O << "\t.weak_definition\t" << CurrentFnName << "\n"; 202 } else { 203 O << TAI->getWeakRefDirective() << CurrentFnName << "\n"; 204 } 205 break; 206 } 207 208 if (F->hasHiddenVisibility()) 209 if (const char *Directive = TAI->getHiddenDirective()) 210 O << Directive << CurrentFnName << "\n"; 211 212 if (AFI->isThumbFunction()) { 213 EmitAlignment(1, F); 214 O << "\t.code\t16\n"; 215 O << "\t.thumb_func"; 216 if (Subtarget->isTargetDarwin()) 217 O << "\t" << CurrentFnName; 218 O << "\n"; 219 InCPMode = false; 220 } else 221 EmitAlignment(2, F); 222 223 O << CurrentFnName << ":\n"; 224 if (Subtarget->isTargetDarwin()) { 225 // Emit pre-function debug information. 226 DW.BeginFunction(&MF); 227 } 228 229 // Print out code for the function. 230 for (MachineFunction::const_iterator I = MF.begin(), E = MF.end(); 231 I != E; ++I) { 232 // Print a label for the basic block. 233 if (I != MF.begin()) { 234 printBasicBlockLabel(I, true); 235 O << '\n'; 236 } 237 for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end(); 238 II != E; ++II) { 239 // Print the assembly for the instruction. 240 printMachineInstruction(II); 241 } 242 } 243 244 if (TAI->hasDotTypeDotSizeDirective()) 245 O << "\t.size " << CurrentFnName << ", .-" << CurrentFnName << "\n"; 246 247 if (Subtarget->isTargetDarwin()) { 248 // Emit post-function debug information. 249 DW.EndFunction(); 250 } 251 252 return false; 253} 254 255void ARMAsmPrinter::printOperand(const MachineInstr *MI, int opNum, 256 const char *Modifier) { 257 const MachineOperand &MO = MI->getOperand(opNum); 258 switch (MO.getType()) { 259 case MachineOperand::MO_Register: 260 if (MRegisterInfo::isPhysicalRegister(MO.getReg())) 261 O << TM.getRegisterInfo()->get(MO.getReg()).Name; 262 else 263 assert(0 && "not implemented"); 264 break; 265 case MachineOperand::MO_Immediate: { 266 if (!Modifier || strcmp(Modifier, "no_hash") != 0) 267 O << "#"; 268 269 O << (int)MO.getImmedValue(); 270 break; 271 } 272 case MachineOperand::MO_MachineBasicBlock: 273 printBasicBlockLabel(MO.getMachineBasicBlock()); 274 return; 275 case MachineOperand::MO_GlobalAddress: { 276 bool isCallOp = Modifier && !strcmp(Modifier, "call"); 277 GlobalValue *GV = MO.getGlobal(); 278 std::string Name = Mang->getValueName(GV); 279 bool isExt = (GV->isDeclaration() || GV->hasWeakLinkage() || 280 GV->hasLinkOnceLinkage()); 281 if (isExt && isCallOp && Subtarget->isTargetDarwin() && 282 TM.getRelocationModel() != Reloc::Static) { 283 O << TAI->getPrivateGlobalPrefix() << Name << "$stub"; 284 FnStubs.insert(Name); 285 } else 286 O << Name; 287 288 if (GV->hasExternalWeakLinkage()) 289 ExtWeakSymbols.insert(GV); 290 break; 291 } 292 case MachineOperand::MO_ExternalSymbol: { 293 bool isCallOp = Modifier && !strcmp(Modifier, "call"); 294 std::string Name(TAI->getGlobalPrefix()); 295 Name += MO.getSymbolName(); 296 if (isCallOp && Subtarget->isTargetDarwin() && 297 TM.getRelocationModel() != Reloc::Static) { 298 O << TAI->getPrivateGlobalPrefix() << Name << "$stub"; 299 FnStubs.insert(Name); 300 } else 301 O << Name; 302 break; 303 } 304 case MachineOperand::MO_ConstantPoolIndex: 305 O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() 306 << '_' << MO.getConstantPoolIndex(); 307 break; 308 case MachineOperand::MO_JumpTableIndex: 309 O << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() 310 << '_' << MO.getJumpTableIndex(); 311 break; 312 default: 313 O << "<unknown operand type>"; abort (); break; 314 } 315} 316 317static void printSOImm(std::ostream &O, int64_t V, const TargetAsmInfo *TAI) { 318 assert(V < (1 << 12) && "Not a valid so_imm value!"); 319 unsigned Imm = ARM_AM::getSOImmValImm(V); 320 unsigned Rot = ARM_AM::getSOImmValRot(V); 321 322 // Print low-level immediate formation info, per 323 // A5.1.3: "Data-processing operands - Immediate". 324 if (Rot) { 325 O << "#" << Imm << ", " << Rot; 326 // Pretty printed version. 327 O << ' ' << TAI->getCommentString() << ' ' << (int)ARM_AM::rotr32(Imm, Rot); 328 } else { 329 O << "#" << Imm; 330 } 331} 332 333/// printSOImmOperand - SOImm is 4-bit rotate amount in bits 8-11 with 8-bit 334/// immediate in bits 0-7. 335void ARMAsmPrinter::printSOImmOperand(const MachineInstr *MI, int OpNum) { 336 const MachineOperand &MO = MI->getOperand(OpNum); 337 assert(MO.isImmediate() && "Not a valid so_imm value!"); 338 printSOImm(O, MO.getImmedValue(), TAI); 339} 340 341/// printSOImm2PartOperand - SOImm is broken into two pieces using a mov 342/// followed by a or to materialize. 343void ARMAsmPrinter::printSOImm2PartOperand(const MachineInstr *MI, int OpNum) { 344 const MachineOperand &MO = MI->getOperand(OpNum); 345 assert(MO.isImmediate() && "Not a valid so_imm value!"); 346 unsigned V1 = ARM_AM::getSOImmTwoPartFirst(MO.getImmedValue()); 347 unsigned V2 = ARM_AM::getSOImmTwoPartSecond(MO.getImmedValue()); 348 printSOImm(O, ARM_AM::getSOImmVal(V1), TAI); 349 O << "\n\torr "; 350 printOperand(MI, 0); 351 O << ", "; 352 printOperand(MI, 0); 353 O << ", "; 354 printSOImm(O, ARM_AM::getSOImmVal(V2), TAI); 355} 356 357// so_reg is a 4-operand unit corresponding to register forms of the A5.1 358// "Addressing Mode 1 - Data-processing operands" forms. This includes: 359// REG 0 0 - e.g. R5 360// REG REG 0,SH_OPC - e.g. R5, ROR R3 361// REG 0 IMM,SH_OPC - e.g. R5, LSL #3 362void ARMAsmPrinter::printSORegOperand(const MachineInstr *MI, int Op) { 363 const MachineOperand &MO1 = MI->getOperand(Op); 364 const MachineOperand &MO2 = MI->getOperand(Op+1); 365 const MachineOperand &MO3 = MI->getOperand(Op+2); 366 367 assert(MRegisterInfo::isPhysicalRegister(MO1.getReg())); 368 O << TM.getRegisterInfo()->get(MO1.getReg()).Name; 369 370 // Print the shift opc. 371 O << ", " 372 << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(MO3.getImmedValue())) 373 << " "; 374 375 if (MO2.getReg()) { 376 assert(MRegisterInfo::isPhysicalRegister(MO2.getReg())); 377 O << TM.getRegisterInfo()->get(MO2.getReg()).Name; 378 assert(ARM_AM::getSORegOffset(MO3.getImm()) == 0); 379 } else { 380 O << "#" << ARM_AM::getSORegOffset(MO3.getImm()); 381 } 382} 383 384void ARMAsmPrinter::printAddrMode2Operand(const MachineInstr *MI, int Op) { 385 const MachineOperand &MO1 = MI->getOperand(Op); 386 const MachineOperand &MO2 = MI->getOperand(Op+1); 387 const MachineOperand &MO3 = MI->getOperand(Op+2); 388 389 if (!MO1.isRegister()) { // FIXME: This is for CP entries, but isn't right. 390 printOperand(MI, Op); 391 return; 392 } 393 394 O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).Name; 395 396 if (!MO2.getReg()) { 397 if (ARM_AM::getAM2Offset(MO3.getImm())) // Don't print +0. 398 O << ", #" 399 << (char)ARM_AM::getAM2Op(MO3.getImm()) 400 << ARM_AM::getAM2Offset(MO3.getImm()); 401 O << "]"; 402 return; 403 } 404 405 O << ", " 406 << (char)ARM_AM::getAM2Op(MO3.getImm()) 407 << TM.getRegisterInfo()->get(MO2.getReg()).Name; 408 409 if (unsigned ShImm = ARM_AM::getAM2Offset(MO3.getImm())) 410 O << ", " 411 << ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO3.getImmedValue())) 412 << " #" << ShImm; 413 O << "]"; 414} 415 416void ARMAsmPrinter::printAddrMode2OffsetOperand(const MachineInstr *MI, int Op){ 417 const MachineOperand &MO1 = MI->getOperand(Op); 418 const MachineOperand &MO2 = MI->getOperand(Op+1); 419 420 if (!MO1.getReg()) { 421 if (ARM_AM::getAM2Offset(MO2.getImm())) // Don't print +0. 422 O << "#" 423 << (char)ARM_AM::getAM2Op(MO2.getImm()) 424 << ARM_AM::getAM2Offset(MO2.getImm()); 425 return; 426 } 427 428 O << (char)ARM_AM::getAM2Op(MO2.getImm()) 429 << TM.getRegisterInfo()->get(MO1.getReg()).Name; 430 431 if (unsigned ShImm = ARM_AM::getAM2Offset(MO2.getImm())) 432 O << ", " 433 << ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO2.getImmedValue())) 434 << " #" << ShImm; 435} 436 437void ARMAsmPrinter::printAddrMode3Operand(const MachineInstr *MI, int Op) { 438 const MachineOperand &MO1 = MI->getOperand(Op); 439 const MachineOperand &MO2 = MI->getOperand(Op+1); 440 const MachineOperand &MO3 = MI->getOperand(Op+2); 441 442 assert(MRegisterInfo::isPhysicalRegister(MO1.getReg())); 443 O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).Name; 444 445 if (MO2.getReg()) { 446 O << ", " 447 << (char)ARM_AM::getAM3Op(MO3.getImm()) 448 << TM.getRegisterInfo()->get(MO2.getReg()).Name 449 << "]"; 450 return; 451 } 452 453 if (unsigned ImmOffs = ARM_AM::getAM3Offset(MO3.getImm())) 454 O << ", #" 455 << (char)ARM_AM::getAM3Op(MO3.getImm()) 456 << ImmOffs; 457 O << "]"; 458} 459 460void ARMAsmPrinter::printAddrMode3OffsetOperand(const MachineInstr *MI, int Op){ 461 const MachineOperand &MO1 = MI->getOperand(Op); 462 const MachineOperand &MO2 = MI->getOperand(Op+1); 463 464 if (MO1.getReg()) { 465 O << (char)ARM_AM::getAM3Op(MO2.getImm()) 466 << TM.getRegisterInfo()->get(MO1.getReg()).Name; 467 return; 468 } 469 470 unsigned ImmOffs = ARM_AM::getAM3Offset(MO2.getImm()); 471 O << "#" 472 << (char)ARM_AM::getAM3Op(MO2.getImm()) 473 << ImmOffs; 474} 475 476void ARMAsmPrinter::printAddrMode4Operand(const MachineInstr *MI, int Op, 477 const char *Modifier) { 478 const MachineOperand &MO1 = MI->getOperand(Op); 479 const MachineOperand &MO2 = MI->getOperand(Op+1); 480 ARM_AM::AMSubMode Mode = ARM_AM::getAM4SubMode(MO2.getImm()); 481 if (Modifier && strcmp(Modifier, "submode") == 0) { 482 if (MO1.getReg() == ARM::SP) { 483 bool isLDM = (MI->getOpcode() == ARM::LDM || 484 MI->getOpcode() == ARM::LDM_RET); 485 O << ARM_AM::getAMSubModeAltStr(Mode, isLDM); 486 } else 487 O << ARM_AM::getAMSubModeStr(Mode); 488 } else { 489 printOperand(MI, Op); 490 if (ARM_AM::getAM4WBFlag(MO2.getImm())) 491 O << "!"; 492 } 493} 494 495void ARMAsmPrinter::printAddrMode5Operand(const MachineInstr *MI, int Op, 496 const char *Modifier) { 497 const MachineOperand &MO1 = MI->getOperand(Op); 498 const MachineOperand &MO2 = MI->getOperand(Op+1); 499 500 if (!MO1.isRegister()) { // FIXME: This is for CP entries, but isn't right. 501 printOperand(MI, Op); 502 return; 503 } 504 505 assert(MRegisterInfo::isPhysicalRegister(MO1.getReg())); 506 507 if (Modifier && strcmp(Modifier, "submode") == 0) { 508 ARM_AM::AMSubMode Mode = ARM_AM::getAM5SubMode(MO2.getImm()); 509 if (MO1.getReg() == ARM::SP) { 510 bool isFLDM = (MI->getOpcode() == ARM::FLDMD || 511 MI->getOpcode() == ARM::FLDMS); 512 O << ARM_AM::getAMSubModeAltStr(Mode, isFLDM); 513 } else 514 O << ARM_AM::getAMSubModeStr(Mode); 515 return; 516 } else if (Modifier && strcmp(Modifier, "base") == 0) { 517 // Used for FSTM{D|S} and LSTM{D|S} operations. 518 O << TM.getRegisterInfo()->get(MO1.getReg()).Name; 519 if (ARM_AM::getAM5WBFlag(MO2.getImm())) 520 O << "!"; 521 return; 522 } 523 524 O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).Name; 525 526 if (unsigned ImmOffs = ARM_AM::getAM5Offset(MO2.getImm())) { 527 O << ", #" 528 << (char)ARM_AM::getAM5Op(MO2.getImm()) 529 << ImmOffs*4; 530 } 531 O << "]"; 532} 533 534void ARMAsmPrinter::printAddrModePCOperand(const MachineInstr *MI, int Op, 535 const char *Modifier) { 536 if (Modifier && strcmp(Modifier, "label") == 0) { 537 printPCLabel(MI, Op+1); 538 return; 539 } 540 541 const MachineOperand &MO1 = MI->getOperand(Op); 542 assert(MRegisterInfo::isPhysicalRegister(MO1.getReg())); 543 O << "[pc, +" << TM.getRegisterInfo()->get(MO1.getReg()).Name << "]"; 544} 545 546void 547ARMAsmPrinter::printThumbAddrModeRROperand(const MachineInstr *MI, int Op) { 548 const MachineOperand &MO1 = MI->getOperand(Op); 549 const MachineOperand &MO2 = MI->getOperand(Op+1); 550 O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).Name; 551 O << ", " << TM.getRegisterInfo()->get(MO2.getReg()).Name << "]"; 552} 553 554void 555ARMAsmPrinter::printThumbAddrModeRI5Operand(const MachineInstr *MI, int Op, 556 unsigned Scale) { 557 const MachineOperand &MO1 = MI->getOperand(Op); 558 const MachineOperand &MO2 = MI->getOperand(Op+1); 559 const MachineOperand &MO3 = MI->getOperand(Op+2); 560 561 if (!MO1.isRegister()) { // FIXME: This is for CP entries, but isn't right. 562 printOperand(MI, Op); 563 return; 564 } 565 566 O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).Name; 567 if (MO3.getReg()) 568 O << ", " << TM.getRegisterInfo()->get(MO3.getReg()).Name; 569 else if (unsigned ImmOffs = MO2.getImm()) { 570 O << ", #" << ImmOffs; 571 if (Scale > 1) 572 O << " * " << Scale; 573 } 574 O << "]"; 575} 576 577void 578ARMAsmPrinter::printThumbAddrModeS1Operand(const MachineInstr *MI, int Op) { 579 printThumbAddrModeRI5Operand(MI, Op, 1); 580} 581void 582ARMAsmPrinter::printThumbAddrModeS2Operand(const MachineInstr *MI, int Op) { 583 printThumbAddrModeRI5Operand(MI, Op, 2); 584} 585void 586ARMAsmPrinter::printThumbAddrModeS4Operand(const MachineInstr *MI, int Op) { 587 printThumbAddrModeRI5Operand(MI, Op, 4); 588} 589 590void ARMAsmPrinter::printThumbAddrModeSPOperand(const MachineInstr *MI,int Op) { 591 const MachineOperand &MO1 = MI->getOperand(Op); 592 const MachineOperand &MO2 = MI->getOperand(Op+1); 593 O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).Name; 594 if (unsigned ImmOffs = MO2.getImm()) 595 O << ", #" << ImmOffs << " * 4"; 596 O << "]"; 597} 598 599void ARMAsmPrinter::printCCOperand(const MachineInstr *MI, int opNum) { 600 int CC = (int)MI->getOperand(opNum).getImmedValue(); 601 O << ARMCondCodeToString((ARMCC::CondCodes)CC); 602} 603 604void ARMAsmPrinter::printPCLabel(const MachineInstr *MI, int opNum) { 605 int Id = (int)MI->getOperand(opNum).getImmedValue(); 606 O << TAI->getPrivateGlobalPrefix() << "PC" << Id; 607} 608 609void ARMAsmPrinter::printRegisterList(const MachineInstr *MI, int opNum) { 610 O << "{"; 611 for (unsigned i = opNum, e = MI->getNumOperands(); i != e; ++i) { 612 printOperand(MI, i); 613 if (i != e-1) O << ", "; 614 } 615 O << "}"; 616} 617 618void ARMAsmPrinter::printCPInstOperand(const MachineInstr *MI, int OpNo, 619 const char *Modifier) { 620 assert(Modifier && "This operand only works with a modifier!"); 621 // There are two aspects to a CONSTANTPOOL_ENTRY operand, the label and the 622 // data itself. 623 if (!strcmp(Modifier, "label")) { 624 unsigned ID = MI->getOperand(OpNo).getImm(); 625 O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() 626 << '_' << ID << ":\n"; 627 } else { 628 assert(!strcmp(Modifier, "cpentry") && "Unknown modifier for CPE"); 629 unsigned CPI = MI->getOperand(OpNo).getConstantPoolIndex(); 630 631 const MachineConstantPoolEntry &MCPE = // Chasing pointers is fun? 632 MI->getParent()->getParent()->getConstantPool()->getConstants()[CPI]; 633 634 if (MCPE.isMachineConstantPoolEntry()) 635 EmitMachineConstantPoolValue(MCPE.Val.MachineCPVal); 636 else 637 EmitGlobalConstant(MCPE.Val.ConstVal); 638 } 639} 640 641void ARMAsmPrinter::printJTBlockOperand(const MachineInstr *MI, int OpNo) { 642 const MachineOperand &MO1 = MI->getOperand(OpNo); 643 const MachineOperand &MO2 = MI->getOperand(OpNo+1); // Unique Id 644 unsigned JTI = MO1.getJumpTableIndex(); 645 O << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() 646 << '_' << JTI << '_' << MO2.getImmedValue() << ":\n"; 647 648 const char *JTEntryDirective = TAI->getJumpTableDirective(); 649 if (!JTEntryDirective) 650 JTEntryDirective = TAI->getData32bitsDirective(); 651 652 const MachineFunction *MF = MI->getParent()->getParent(); 653 MachineJumpTableInfo *MJTI = MF->getJumpTableInfo(); 654 const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables(); 655 const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs; 656 bool UseSet= TAI->getSetDirective() && TM.getRelocationModel() == Reloc::PIC_; 657 std::set<MachineBasicBlock*> JTSets; 658 for (unsigned i = 0, e = JTBBs.size(); i != e; ++i) { 659 MachineBasicBlock *MBB = JTBBs[i]; 660 if (UseSet && JTSets.insert(MBB).second) 661 printSetLabel(JTI, MO2.getImmedValue(), MBB); 662 663 O << JTEntryDirective << ' '; 664 if (UseSet) 665 O << TAI->getPrivateGlobalPrefix() << getFunctionNumber() 666 << '_' << JTI << '_' << MO2.getImmedValue() 667 << "_set_" << MBB->getNumber(); 668 else if (TM.getRelocationModel() == Reloc::PIC_) { 669 printBasicBlockLabel(MBB, false, false); 670 // If the arch uses custom Jump Table directives, don't calc relative to JT 671 if (!TAI->getJumpTableDirective()) 672 O << '-' << TAI->getPrivateGlobalPrefix() << "JTI" 673 << getFunctionNumber() << '_' << JTI << '_' << MO2.getImmedValue(); 674 } else 675 printBasicBlockLabel(MBB, false, false); 676 if (i != e-1) 677 O << '\n'; 678 } 679} 680 681 682bool ARMAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, 683 unsigned AsmVariant, const char *ExtraCode){ 684 // Does this asm operand have a single letter operand modifier? 685 if (ExtraCode && ExtraCode[0]) { 686 if (ExtraCode[1] != 0) return true; // Unknown modifier. 687 688 switch (ExtraCode[0]) { 689 default: return true; // Unknown modifier. 690 case 'c': // Don't print "$" before a global var name or constant. 691 case 'P': // Print a VFP double precision register. 692 printOperand(MI, OpNo); 693 return false; 694 case 'Q': 695 if (TM.getTargetData()->isLittleEndian()) 696 break; 697 // Fallthrough 698 case 'R': 699 if (TM.getTargetData()->isBigEndian()) 700 break; 701 // Fallthrough 702 case 'H': // Write second word of DI / DF reference. 703 // Verify that this operand has two consecutive registers. 704 if (!MI->getOperand(OpNo).isRegister() || 705 OpNo+1 == MI->getNumOperands() || 706 !MI->getOperand(OpNo+1).isRegister()) 707 return true; 708 ++OpNo; // Return the high-part. 709 } 710 } 711 712 printOperand(MI, OpNo); 713 return false; 714} 715 716void ARMAsmPrinter::printMachineInstruction(const MachineInstr *MI) { 717 ++EmittedInsts; 718 719 int Opc = MI->getOpcode(); 720 switch (Opc) { 721 case ARM::CONSTPOOL_ENTRY: 722 if (!InCPMode && AFI->isThumbFunction()) { 723 EmitAlignment(2); 724 InCPMode = true; 725 } 726 break; 727 default: { 728 if (InCPMode && AFI->isThumbFunction()) 729 InCPMode = false; 730 switch (Opc) { 731 case ARM::PICADD: 732 case ARM::PICLD: 733 case ARM::tPICADD: 734 break; 735 default: 736 O << "\t"; 737 break; 738 } 739 }} 740 741 // Call the autogenerated instruction printer routines. 742 printInstruction(MI); 743} 744 745bool ARMAsmPrinter::doInitialization(Module &M) { 746 if (Subtarget->isTargetDarwin()) { 747 // Emit initial debug information. 748 DW.BeginModule(&M); 749 } 750 751 return AsmPrinter::doInitialization(M); 752} 753 754bool ARMAsmPrinter::doFinalization(Module &M) { 755 const TargetData *TD = TM.getTargetData(); 756 757 for (Module::const_global_iterator I = M.global_begin(), E = M.global_end(); 758 I != E; ++I) { 759 if (!I->hasInitializer()) // External global require no code 760 continue; 761 762 if (EmitSpecialLLVMGlobal(I)) { 763 if (Subtarget->isTargetDarwin() && 764 TM.getRelocationModel() == Reloc::Static) { 765 if (I->getName() == "llvm.global_ctors") 766 O << ".reference .constructors_used\n"; 767 else if (I->getName() == "llvm.global_dtors") 768 O << ".reference .destructors_used\n"; 769 } 770 continue; 771 } 772 773 std::string name = Mang->getValueName(I); 774 Constant *C = I->getInitializer(); 775 const Type *Type = C->getType(); 776 unsigned Size = TD->getTypeSize(Type); 777 unsigned Align = TD->getPreferredAlignmentLog(I); 778 779 if (I->hasHiddenVisibility()) 780 if (const char *Directive = TAI->getHiddenDirective()) 781 O << Directive << name << "\n"; 782 if (Subtarget->isTargetELF()) 783 O << "\t.type " << name << ",%object\n"; 784 785 if (C->isNullValue()) { 786 if (I->hasExternalLinkage()) { 787 if (const char *Directive = TAI->getZeroFillDirective()) { 788 O << "\t.globl\t" << name << "\n"; 789 O << Directive << "__DATA__, __common, " << name << ", " 790 << Size << ", " << Align << "\n"; 791 continue; 792 } 793 } 794 795 if (!I->hasSection() && 796 (I->hasInternalLinkage() || I->hasWeakLinkage() || 797 I->hasLinkOnceLinkage())) { 798 if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it. 799 if (!NoZerosInBSS && TAI->getBSSSection()) 800 SwitchToDataSection(TAI->getBSSSection(), I); 801 else 802 SwitchToDataSection(TAI->getDataSection(), I); 803 if (TAI->getLCOMMDirective() != NULL) { 804 if (I->hasInternalLinkage()) { 805 O << TAI->getLCOMMDirective() << name << "," << Size; 806 if (Subtarget->isTargetDarwin()) 807 O << "," << Align; 808 } else 809 O << TAI->getCOMMDirective() << name << "," << Size; 810 } else { 811 if (I->hasInternalLinkage()) 812 O << "\t.local\t" << name << "\n"; 813 O << TAI->getCOMMDirective() << name << "," << Size; 814 if (TAI->getCOMMDirectiveTakesAlignment()) 815 O << "," << (TAI->getAlignmentIsInBytes() ? (1 << Align) : Align); 816 } 817 O << "\t\t" << TAI->getCommentString() << " " << I->getName() << "\n"; 818 continue; 819 } 820 } 821 822 switch (I->getLinkage()) { 823 case GlobalValue::LinkOnceLinkage: 824 case GlobalValue::WeakLinkage: 825 if (Subtarget->isTargetDarwin()) { 826 O << "\t.globl " << name << "\n" 827 << "\t.weak_definition " << name << "\n"; 828 SwitchToDataSection("\t.section __DATA,__const_coal,coalesced", I); 829 } else { 830 std::string SectionName("\t.section\t.llvm.linkonce.d." + 831 name + 832 ",\"aw\",%progbits"); 833 SwitchToDataSection(SectionName.c_str(), I); 834 O << "\t.weak " << name << "\n"; 835 } 836 break; 837 case GlobalValue::AppendingLinkage: 838 // FIXME: appending linkage variables should go into a section of 839 // their name or something. For now, just emit them as external. 840 case GlobalValue::ExternalLinkage: 841 O << "\t.globl " << name << "\n"; 842 // FALL THROUGH 843 case GlobalValue::InternalLinkage: { 844 if (I->isConstant()) { 845 const ConstantArray *CVA = dyn_cast<ConstantArray>(C); 846 if (TAI->getCStringSection() && CVA && CVA->isCString()) { 847 SwitchToDataSection(TAI->getCStringSection(), I); 848 break; 849 } 850 } 851 // FIXME: special handling for ".ctors" & ".dtors" sections 852 if (I->hasSection() && 853 (I->getSection() == ".ctors" || 854 I->getSection() == ".dtors")) { 855 assert(!Subtarget->isTargetDarwin()); 856 std::string SectionName = ".section " + I->getSection(); 857 SectionName += ",\"aw\",%progbits"; 858 SwitchToDataSection(SectionName.c_str()); 859 } else { 860 if (C->isNullValue() && !NoZerosInBSS && TAI->getBSSSection()) 861 SwitchToDataSection(TAI->getBSSSection(), I); 862 else if (!I->isConstant()) 863 SwitchToDataSection(TAI->getDataSection(), I); 864 else { 865 // Read-only data. 866 bool HasReloc = C->ContainsRelocations(); 867 if (HasReloc && 868 Subtarget->isTargetDarwin() && 869 TM.getRelocationModel() != Reloc::Static) 870 SwitchToDataSection("\t.const_data\n"); 871 else if (!HasReloc && Size == 4 && 872 TAI->getFourByteConstantSection()) 873 SwitchToDataSection(TAI->getFourByteConstantSection(), I); 874 else if (!HasReloc && Size == 8 && 875 TAI->getEightByteConstantSection()) 876 SwitchToDataSection(TAI->getEightByteConstantSection(), I); 877 else if (!HasReloc && Size == 16 && 878 TAI->getSixteenByteConstantSection()) 879 SwitchToDataSection(TAI->getSixteenByteConstantSection(), I); 880 else if (TAI->getReadOnlySection()) 881 SwitchToDataSection(TAI->getReadOnlySection(), I); 882 else 883 SwitchToDataSection(TAI->getDataSection(), I); 884 } 885 } 886 887 break; 888 } 889 default: 890 assert(0 && "Unknown linkage type!"); 891 break; 892 } 893 894 EmitAlignment(Align, I); 895 O << name << ":\t\t\t\t" << TAI->getCommentString() << " " << I->getName() 896 << "\n"; 897 if (TAI->hasDotTypeDotSizeDirective()) 898 O << "\t.size " << name << ", " << Size << "\n"; 899 // If the initializer is a extern weak symbol, remember to emit the weak 900 // reference! 901 if (const GlobalValue *GV = dyn_cast<GlobalValue>(C)) 902 if (GV->hasExternalWeakLinkage()) 903 ExtWeakSymbols.insert(GV); 904 905 EmitGlobalConstant(C); 906 O << '\n'; 907 } 908 909 if (Subtarget->isTargetDarwin()) { 910 SwitchToDataSection(""); 911 912 // Output stubs for dynamically-linked functions 913 unsigned j = 1; 914 for (std::set<std::string>::iterator i = FnStubs.begin(), e = FnStubs.end(); 915 i != e; ++i, ++j) { 916 if (TM.getRelocationModel() == Reloc::PIC_) 917 SwitchToTextSection(".section __TEXT,__picsymbolstub4,symbol_stubs," 918 "none,16", 0); 919 else 920 SwitchToTextSection(".section __TEXT,__symbol_stub4,symbol_stubs," 921 "none,12", 0); 922 923 EmitAlignment(2); 924 O << "\t.code\t32\n"; 925 926 O << "L" << *i << "$stub:\n"; 927 O << "\t.indirect_symbol " << *i << "\n"; 928 O << "\tldr ip, L" << *i << "$slp\n"; 929 if (TM.getRelocationModel() == Reloc::PIC_) { 930 O << "L" << *i << "$scv:\n"; 931 O << "\tadd ip, pc, ip\n"; 932 } 933 O << "\tldr pc, [ip, #0]\n"; 934 O << "L" << *i << "$slp:\n"; 935 if (TM.getRelocationModel() == Reloc::PIC_) 936 O << "\t.long\tL" << *i << "$lazy_ptr-(L" << *i << "$scv+8)\n"; 937 else 938 O << "\t.long\tL" << *i << "$lazy_ptr\n"; 939 SwitchToDataSection(".lazy_symbol_pointer", 0); 940 O << "L" << *i << "$lazy_ptr:\n"; 941 O << "\t.indirect_symbol " << *i << "\n"; 942 O << "\t.long\tdyld_stub_binding_helper\n"; 943 } 944 O << "\n"; 945 946 // Output non-lazy-pointers for external and common global variables. 947 if (GVNonLazyPtrs.begin() != GVNonLazyPtrs.end()) 948 SwitchToDataSection(".non_lazy_symbol_pointer", 0); 949 for (std::set<std::string>::iterator i = GVNonLazyPtrs.begin(), 950 e = GVNonLazyPtrs.end(); i != e; ++i) { 951 O << "L" << *i << "$non_lazy_ptr:\n"; 952 O << "\t.indirect_symbol " << *i << "\n"; 953 O << "\t.long\t0\n"; 954 } 955 956 // Emit initial debug information. 957 DW.EndModule(); 958 959 // Funny Darwin hack: This flag tells the linker that no global symbols 960 // contain code that falls through to other global symbols (e.g. the obvious 961 // implementation of multiple entry points). If this doesn't occur, the 962 // linker can safely perform dead code stripping. Since LLVM never 963 // generates code that does this, it is always safe to set. 964 O << "\t.subsections_via_symbols\n"; 965 } 966 967 AsmPrinter::doFinalization(M); 968 return false; // success 969} 970