1 //===- MipsAsmPrinter.cpp - Mips LLVM Assembly Printer --------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file contains a printer that converts from our internal representation 10 // of machine-dependent LLVM code to GAS-format MIPS assembly language. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "MipsAsmPrinter.h" 15 #include "MCTargetDesc/MipsABIInfo.h" 16 #include "MCTargetDesc/MipsBaseInfo.h" 17 #include "MCTargetDesc/MipsInstPrinter.h" 18 #include "MCTargetDesc/MipsMCNaCl.h" 19 #include "MCTargetDesc/MipsMCTargetDesc.h" 20 #include "Mips.h" 21 #include "MipsMCInstLower.h" 22 #include "MipsMachineFunction.h" 23 #include "MipsSubtarget.h" 24 #include "MipsTargetMachine.h" 25 #include "MipsTargetStreamer.h" 26 #include "TargetInfo/MipsTargetInfo.h" 27 #include "llvm/ADT/SmallString.h" 28 #include "llvm/ADT/StringRef.h" 29 #include "llvm/ADT/Triple.h" 30 #include "llvm/ADT/Twine.h" 31 #include "llvm/BinaryFormat/ELF.h" 32 #include "llvm/CodeGen/MachineBasicBlock.h" 33 #include "llvm/CodeGen/MachineConstantPool.h" 34 #include "llvm/CodeGen/MachineFrameInfo.h" 35 #include "llvm/CodeGen/MachineFunction.h" 36 #include "llvm/CodeGen/MachineInstr.h" 37 #include "llvm/CodeGen/MachineJumpTableInfo.h" 38 #include "llvm/CodeGen/MachineOperand.h" 39 #include "llvm/CodeGen/TargetRegisterInfo.h" 40 #include "llvm/CodeGen/TargetSubtargetInfo.h" 41 #include "llvm/IR/Attributes.h" 42 #include "llvm/IR/BasicBlock.h" 43 #include "llvm/IR/DataLayout.h" 44 #include "llvm/IR/Function.h" 45 #include "llvm/IR/InlineAsm.h" 46 #include "llvm/IR/Instructions.h" 47 #include "llvm/MC/MCContext.h" 48 #include "llvm/MC/MCExpr.h" 49 #include "llvm/MC/MCInst.h" 50 #include "llvm/MC/MCInstBuilder.h" 51 #include "llvm/MC/MCObjectFileInfo.h" 52 #include "llvm/MC/MCSectionELF.h" 53 #include "llvm/MC/MCSymbol.h" 54 #include "llvm/MC/MCSymbolELF.h" 55 #include "llvm/Support/Casting.h" 56 #include "llvm/Support/ErrorHandling.h" 57 #include "llvm/Support/TargetRegistry.h" 58 #include "llvm/Support/raw_ostream.h" 59 #include "llvm/Target/TargetLoweringObjectFile.h" 60 #include "llvm/Target/TargetMachine.h" 61 #include <cassert> 62 #include <cstdint> 63 #include <map> 64 #include <memory> 65 #include <string> 66 #include <vector> 67 68 using namespace llvm; 69 70 #define DEBUG_TYPE "mips-asm-printer" 71 72 extern cl::opt<bool> EmitJalrReloc; 73 74 MipsTargetStreamer &MipsAsmPrinter::getTargetStreamer() const { 75 return static_cast<MipsTargetStreamer &>(*OutStreamer->getTargetStreamer()); 76 } 77 78 bool MipsAsmPrinter::runOnMachineFunction(MachineFunction &MF) { 79 Subtarget = &MF.getSubtarget<MipsSubtarget>(); 80 81 MipsFI = MF.getInfo<MipsFunctionInfo>(); 82 if (Subtarget->inMips16Mode()) 83 for (std::map< 84 const char *, 85 const Mips16HardFloatInfo::FuncSignature *>::const_iterator 86 it = MipsFI->StubsNeeded.begin(); 87 it != MipsFI->StubsNeeded.end(); ++it) { 88 const char *Symbol = it->first; 89 const Mips16HardFloatInfo::FuncSignature *Signature = it->second; 90 if (StubsNeeded.find(Symbol) == StubsNeeded.end()) 91 StubsNeeded[Symbol] = Signature; 92 } 93 MCP = MF.getConstantPool(); 94 95 // In NaCl, all indirect jump targets must be aligned to bundle size. 96 if (Subtarget->isTargetNaCl()) 97 NaClAlignIndirectJumpTargets(MF); 98 99 AsmPrinter::runOnMachineFunction(MF); 100 101 emitXRayTable(); 102 103 return true; 104 } 105 106 bool MipsAsmPrinter::lowerOperand(const MachineOperand &MO, MCOperand &MCOp) { 107 MCOp = MCInstLowering.LowerOperand(MO); 108 return MCOp.isValid(); 109 } 110 111 #include "MipsGenMCPseudoLowering.inc" 112 113 // Lower PseudoReturn/PseudoIndirectBranch/PseudoIndirectBranch64 to JR, JR_MM, 114 // JALR, or JALR64 as appropriate for the target. 115 void MipsAsmPrinter::emitPseudoIndirectBranch(MCStreamer &OutStreamer, 116 const MachineInstr *MI) { 117 bool HasLinkReg = false; 118 bool InMicroMipsMode = Subtarget->inMicroMipsMode(); 119 MCInst TmpInst0; 120 121 if (Subtarget->hasMips64r6()) { 122 // MIPS64r6 should use (JALR64 ZERO_64, $rs) 123 TmpInst0.setOpcode(Mips::JALR64); 124 HasLinkReg = true; 125 } else if (Subtarget->hasMips32r6()) { 126 // MIPS32r6 should use (JALR ZERO, $rs) 127 if (InMicroMipsMode) 128 TmpInst0.setOpcode(Mips::JRC16_MMR6); 129 else { 130 TmpInst0.setOpcode(Mips::JALR); 131 HasLinkReg = true; 132 } 133 } else if (Subtarget->inMicroMipsMode()) 134 // microMIPS should use (JR_MM $rs) 135 TmpInst0.setOpcode(Mips::JR_MM); 136 else { 137 // Everything else should use (JR $rs) 138 TmpInst0.setOpcode(Mips::JR); 139 } 140 141 MCOperand MCOp; 142 143 if (HasLinkReg) { 144 unsigned ZeroReg = Subtarget->isGP64bit() ? Mips::ZERO_64 : Mips::ZERO; 145 TmpInst0.addOperand(MCOperand::createReg(ZeroReg)); 146 } 147 148 lowerOperand(MI->getOperand(0), MCOp); 149 TmpInst0.addOperand(MCOp); 150 151 EmitToStreamer(OutStreamer, TmpInst0); 152 } 153 154 // If there is an MO_JALR operand, insert: 155 // 156 // .reloc tmplabel, R_{MICRO}MIPS_JALR, symbol 157 // tmplabel: 158 // 159 // This is an optimization hint for the linker which may then replace 160 // an indirect call with a direct branch. 161 static void emitDirectiveRelocJalr(const MachineInstr &MI, 162 MCContext &OutContext, 163 TargetMachine &TM, 164 MCStreamer &OutStreamer, 165 const MipsSubtarget &Subtarget) { 166 for (unsigned int I = MI.getDesc().getNumOperands(), E = MI.getNumOperands(); 167 I < E; ++I) { 168 MachineOperand MO = MI.getOperand(I); 169 if (MO.isMCSymbol() && (MO.getTargetFlags() & MipsII::MO_JALR)) { 170 MCSymbol *Callee = MO.getMCSymbol(); 171 if (Callee && !Callee->getName().empty()) { 172 MCSymbol *OffsetLabel = OutContext.createTempSymbol(); 173 const MCExpr *OffsetExpr = 174 MCSymbolRefExpr::create(OffsetLabel, OutContext); 175 const MCExpr *CaleeExpr = 176 MCSymbolRefExpr::create(Callee, OutContext); 177 OutStreamer.EmitRelocDirective 178 (*OffsetExpr, 179 Subtarget.inMicroMipsMode() ? "R_MICROMIPS_JALR" : "R_MIPS_JALR", 180 CaleeExpr, SMLoc(), *TM.getMCSubtargetInfo()); 181 OutStreamer.EmitLabel(OffsetLabel); 182 return; 183 } 184 } 185 } 186 } 187 188 void MipsAsmPrinter::EmitInstruction(const MachineInstr *MI) { 189 MipsTargetStreamer &TS = getTargetStreamer(); 190 unsigned Opc = MI->getOpcode(); 191 TS.forbidModuleDirective(); 192 193 if (MI->isDebugValue()) { 194 SmallString<128> Str; 195 raw_svector_ostream OS(Str); 196 197 PrintDebugValueComment(MI, OS); 198 return; 199 } 200 if (MI->isDebugLabel()) 201 return; 202 203 // If we just ended a constant pool, mark it as such. 204 if (InConstantPool && Opc != Mips::CONSTPOOL_ENTRY) { 205 OutStreamer->EmitDataRegion(MCDR_DataRegionEnd); 206 InConstantPool = false; 207 } 208 if (Opc == Mips::CONSTPOOL_ENTRY) { 209 // CONSTPOOL_ENTRY - This instruction represents a floating 210 // constant pool in the function. The first operand is the ID# 211 // for this instruction, the second is the index into the 212 // MachineConstantPool that this is, the third is the size in 213 // bytes of this constant pool entry. 214 // The required alignment is specified on the basic block holding this MI. 215 // 216 unsigned LabelId = (unsigned)MI->getOperand(0).getImm(); 217 unsigned CPIdx = (unsigned)MI->getOperand(1).getIndex(); 218 219 // If this is the first entry of the pool, mark it. 220 if (!InConstantPool) { 221 OutStreamer->EmitDataRegion(MCDR_DataRegion); 222 InConstantPool = true; 223 } 224 225 OutStreamer->EmitLabel(GetCPISymbol(LabelId)); 226 227 const MachineConstantPoolEntry &MCPE = MCP->getConstants()[CPIdx]; 228 if (MCPE.isMachineConstantPoolEntry()) 229 EmitMachineConstantPoolValue(MCPE.Val.MachineCPVal); 230 else 231 EmitGlobalConstant(MF->getDataLayout(), MCPE.Val.ConstVal); 232 return; 233 } 234 235 switch (Opc) { 236 case Mips::PATCHABLE_FUNCTION_ENTER: 237 LowerPATCHABLE_FUNCTION_ENTER(*MI); 238 return; 239 case Mips::PATCHABLE_FUNCTION_EXIT: 240 LowerPATCHABLE_FUNCTION_EXIT(*MI); 241 return; 242 case Mips::PATCHABLE_TAIL_CALL: 243 LowerPATCHABLE_TAIL_CALL(*MI); 244 return; 245 } 246 247 if (EmitJalrReloc && 248 (MI->isReturn() || MI->isCall() || MI->isIndirectBranch())) { 249 emitDirectiveRelocJalr(*MI, OutContext, TM, *OutStreamer, *Subtarget); 250 } 251 252 MachineBasicBlock::const_instr_iterator I = MI->getIterator(); 253 MachineBasicBlock::const_instr_iterator E = MI->getParent()->instr_end(); 254 255 do { 256 // Do any auto-generated pseudo lowerings. 257 if (emitPseudoExpansionLowering(*OutStreamer, &*I)) 258 continue; 259 260 if (I->getOpcode() == Mips::PseudoReturn || 261 I->getOpcode() == Mips::PseudoReturn64 || 262 I->getOpcode() == Mips::PseudoIndirectBranch || 263 I->getOpcode() == Mips::PseudoIndirectBranch64 || 264 I->getOpcode() == Mips::TAILCALLREG || 265 I->getOpcode() == Mips::TAILCALLREG64) { 266 emitPseudoIndirectBranch(*OutStreamer, &*I); 267 continue; 268 } 269 270 // The inMips16Mode() test is not permanent. 271 // Some instructions are marked as pseudo right now which 272 // would make the test fail for the wrong reason but 273 // that will be fixed soon. We need this here because we are 274 // removing another test for this situation downstream in the 275 // callchain. 276 // 277 if (I->isPseudo() && !Subtarget->inMips16Mode() 278 && !isLongBranchPseudo(I->getOpcode())) 279 llvm_unreachable("Pseudo opcode found in EmitInstruction()"); 280 281 MCInst TmpInst0; 282 MCInstLowering.Lower(&*I, TmpInst0); 283 EmitToStreamer(*OutStreamer, TmpInst0); 284 } while ((++I != E) && I->isInsideBundle()); // Delay slot check 285 } 286 287 //===----------------------------------------------------------------------===// 288 // 289 // Mips Asm Directives 290 // 291 // -- Frame directive "frame Stackpointer, Stacksize, RARegister" 292 // Describe the stack frame. 293 // 294 // -- Mask directives "(f)mask bitmask, offset" 295 // Tells the assembler which registers are saved and where. 296 // bitmask - contain a little endian bitset indicating which registers are 297 // saved on function prologue (e.g. with a 0x80000000 mask, the 298 // assembler knows the register 31 (RA) is saved at prologue. 299 // offset - the position before stack pointer subtraction indicating where 300 // the first saved register on prologue is located. (e.g. with a 301 // 302 // Consider the following function prologue: 303 // 304 // .frame $fp,48,$ra 305 // .mask 0xc0000000,-8 306 // addiu $sp, $sp, -48 307 // sw $ra, 40($sp) 308 // sw $fp, 36($sp) 309 // 310 // With a 0xc0000000 mask, the assembler knows the register 31 (RA) and 311 // 30 (FP) are saved at prologue. As the save order on prologue is from 312 // left to right, RA is saved first. A -8 offset means that after the 313 // stack pointer subtration, the first register in the mask (RA) will be 314 // saved at address 48-8=40. 315 // 316 //===----------------------------------------------------------------------===// 317 318 //===----------------------------------------------------------------------===// 319 // Mask directives 320 //===----------------------------------------------------------------------===// 321 322 // Create a bitmask with all callee saved registers for CPU or Floating Point 323 // registers. For CPU registers consider RA, GP and FP for saving if necessary. 324 void MipsAsmPrinter::printSavedRegsBitmask() { 325 // CPU and FPU Saved Registers Bitmasks 326 unsigned CPUBitmask = 0, FPUBitmask = 0; 327 int CPUTopSavedRegOff, FPUTopSavedRegOff; 328 329 // Set the CPU and FPU Bitmasks 330 const MachineFrameInfo &MFI = MF->getFrameInfo(); 331 const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo(); 332 const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo(); 333 // size of stack area to which FP callee-saved regs are saved. 334 unsigned CPURegSize = TRI->getRegSizeInBits(Mips::GPR32RegClass) / 8; 335 unsigned FGR32RegSize = TRI->getRegSizeInBits(Mips::FGR32RegClass) / 8; 336 unsigned AFGR64RegSize = TRI->getRegSizeInBits(Mips::AFGR64RegClass) / 8; 337 bool HasAFGR64Reg = false; 338 unsigned CSFPRegsSize = 0; 339 340 for (const auto &I : CSI) { 341 unsigned Reg = I.getReg(); 342 unsigned RegNum = TRI->getEncodingValue(Reg); 343 344 // If it's a floating point register, set the FPU Bitmask. 345 // If it's a general purpose register, set the CPU Bitmask. 346 if (Mips::FGR32RegClass.contains(Reg)) { 347 FPUBitmask |= (1 << RegNum); 348 CSFPRegsSize += FGR32RegSize; 349 } else if (Mips::AFGR64RegClass.contains(Reg)) { 350 FPUBitmask |= (3 << RegNum); 351 CSFPRegsSize += AFGR64RegSize; 352 HasAFGR64Reg = true; 353 } else if (Mips::GPR32RegClass.contains(Reg)) 354 CPUBitmask |= (1 << RegNum); 355 } 356 357 // FP Regs are saved right below where the virtual frame pointer points to. 358 FPUTopSavedRegOff = FPUBitmask ? 359 (HasAFGR64Reg ? -AFGR64RegSize : -FGR32RegSize) : 0; 360 361 // CPU Regs are saved below FP Regs. 362 CPUTopSavedRegOff = CPUBitmask ? -CSFPRegsSize - CPURegSize : 0; 363 364 MipsTargetStreamer &TS = getTargetStreamer(); 365 // Print CPUBitmask 366 TS.emitMask(CPUBitmask, CPUTopSavedRegOff); 367 368 // Print FPUBitmask 369 TS.emitFMask(FPUBitmask, FPUTopSavedRegOff); 370 } 371 372 //===----------------------------------------------------------------------===// 373 // Frame and Set directives 374 //===----------------------------------------------------------------------===// 375 376 /// Frame Directive 377 void MipsAsmPrinter::emitFrameDirective() { 378 const TargetRegisterInfo &RI = *MF->getSubtarget().getRegisterInfo(); 379 380 Register stackReg = RI.getFrameRegister(*MF); 381 unsigned returnReg = RI.getRARegister(); 382 unsigned stackSize = MF->getFrameInfo().getStackSize(); 383 384 getTargetStreamer().emitFrame(stackReg, stackSize, returnReg); 385 } 386 387 /// Emit Set directives. 388 const char *MipsAsmPrinter::getCurrentABIString() const { 389 switch (static_cast<MipsTargetMachine &>(TM).getABI().GetEnumValue()) { 390 case MipsABIInfo::ABI::O32: return "abi32"; 391 case MipsABIInfo::ABI::N32: return "abiN32"; 392 case MipsABIInfo::ABI::N64: return "abi64"; 393 default: llvm_unreachable("Unknown Mips ABI"); 394 } 395 } 396 397 void MipsAsmPrinter::EmitFunctionEntryLabel() { 398 MipsTargetStreamer &TS = getTargetStreamer(); 399 400 // NaCl sandboxing requires that indirect call instructions are masked. 401 // This means that function entry points should be bundle-aligned. 402 if (Subtarget->isTargetNaCl()) 403 EmitAlignment(std::max(MF->getAlignment(), MIPS_NACL_BUNDLE_ALIGN)); 404 405 if (Subtarget->inMicroMipsMode()) { 406 TS.emitDirectiveSetMicroMips(); 407 TS.setUsesMicroMips(); 408 TS.updateABIInfo(*Subtarget); 409 } else 410 TS.emitDirectiveSetNoMicroMips(); 411 412 if (Subtarget->inMips16Mode()) 413 TS.emitDirectiveSetMips16(); 414 else 415 TS.emitDirectiveSetNoMips16(); 416 417 TS.emitDirectiveEnt(*CurrentFnSym); 418 OutStreamer->EmitLabel(CurrentFnSym); 419 } 420 421 /// EmitFunctionBodyStart - Targets can override this to emit stuff before 422 /// the first basic block in the function. 423 void MipsAsmPrinter::EmitFunctionBodyStart() { 424 MipsTargetStreamer &TS = getTargetStreamer(); 425 426 MCInstLowering.Initialize(&MF->getContext()); 427 428 bool IsNakedFunction = MF->getFunction().hasFnAttribute(Attribute::Naked); 429 if (!IsNakedFunction) 430 emitFrameDirective(); 431 432 if (!IsNakedFunction) 433 printSavedRegsBitmask(); 434 435 if (!Subtarget->inMips16Mode()) { 436 TS.emitDirectiveSetNoReorder(); 437 TS.emitDirectiveSetNoMacro(); 438 TS.emitDirectiveSetNoAt(); 439 } 440 } 441 442 /// EmitFunctionBodyEnd - Targets can override this to emit stuff after 443 /// the last basic block in the function. 444 void MipsAsmPrinter::EmitFunctionBodyEnd() { 445 MipsTargetStreamer &TS = getTargetStreamer(); 446 447 // There are instruction for this macros, but they must 448 // always be at the function end, and we can't emit and 449 // break with BB logic. 450 if (!Subtarget->inMips16Mode()) { 451 TS.emitDirectiveSetAt(); 452 TS.emitDirectiveSetMacro(); 453 TS.emitDirectiveSetReorder(); 454 } 455 TS.emitDirectiveEnd(CurrentFnSym->getName()); 456 // Make sure to terminate any constant pools that were at the end 457 // of the function. 458 if (!InConstantPool) 459 return; 460 InConstantPool = false; 461 OutStreamer->EmitDataRegion(MCDR_DataRegionEnd); 462 } 463 464 void MipsAsmPrinter::EmitBasicBlockEnd(const MachineBasicBlock &MBB) { 465 AsmPrinter::EmitBasicBlockEnd(MBB); 466 MipsTargetStreamer &TS = getTargetStreamer(); 467 if (MBB.empty()) 468 TS.emitDirectiveInsn(); 469 } 470 471 /// isBlockOnlyReachableByFallthough - Return true if the basic block has 472 /// exactly one predecessor and the control transfer mechanism between 473 /// the predecessor and this block is a fall-through. 474 bool MipsAsmPrinter::isBlockOnlyReachableByFallthrough(const MachineBasicBlock* 475 MBB) const { 476 // The predecessor has to be immediately before this block. 477 const MachineBasicBlock *Pred = *MBB->pred_begin(); 478 479 // If the predecessor is a switch statement, assume a jump table 480 // implementation, so it is not a fall through. 481 if (const BasicBlock *bb = Pred->getBasicBlock()) 482 if (isa<SwitchInst>(bb->getTerminator())) 483 return false; 484 485 // If this is a landing pad, it isn't a fall through. If it has no preds, 486 // then nothing falls through to it. 487 if (MBB->isEHPad() || MBB->pred_empty()) 488 return false; 489 490 // If there isn't exactly one predecessor, it can't be a fall through. 491 MachineBasicBlock::const_pred_iterator PI = MBB->pred_begin(), PI2 = PI; 492 ++PI2; 493 494 if (PI2 != MBB->pred_end()) 495 return false; 496 497 // The predecessor has to be immediately before this block. 498 if (!Pred->isLayoutSuccessor(MBB)) 499 return false; 500 501 // If the block is completely empty, then it definitely does fall through. 502 if (Pred->empty()) 503 return true; 504 505 // Otherwise, check the last instruction. 506 // Check if the last terminator is an unconditional branch. 507 MachineBasicBlock::const_iterator I = Pred->end(); 508 while (I != Pred->begin() && !(--I)->isTerminator()) ; 509 510 return !I->isBarrier(); 511 } 512 513 // Print out an operand for an inline asm expression. 514 bool MipsAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNum, 515 const char *ExtraCode, raw_ostream &O) { 516 // Does this asm operand have a single letter operand modifier? 517 if (ExtraCode && ExtraCode[0]) { 518 if (ExtraCode[1] != 0) return true; // Unknown modifier. 519 520 const MachineOperand &MO = MI->getOperand(OpNum); 521 switch (ExtraCode[0]) { 522 default: 523 // See if this is a generic print operand 524 return AsmPrinter::PrintAsmOperand(MI, OpNum, ExtraCode, O); 525 case 'X': // hex const int 526 if ((MO.getType()) != MachineOperand::MO_Immediate) 527 return true; 528 O << "0x" << Twine::utohexstr(MO.getImm()); 529 return false; 530 case 'x': // hex const int (low 16 bits) 531 if ((MO.getType()) != MachineOperand::MO_Immediate) 532 return true; 533 O << "0x" << Twine::utohexstr(MO.getImm() & 0xffff); 534 return false; 535 case 'd': // decimal const int 536 if ((MO.getType()) != MachineOperand::MO_Immediate) 537 return true; 538 O << MO.getImm(); 539 return false; 540 case 'm': // decimal const int minus 1 541 if ((MO.getType()) != MachineOperand::MO_Immediate) 542 return true; 543 O << MO.getImm() - 1; 544 return false; 545 case 'y': // exact log2 546 if ((MO.getType()) != MachineOperand::MO_Immediate) 547 return true; 548 if (!isPowerOf2_64(MO.getImm())) 549 return true; 550 O << Log2_64(MO.getImm()); 551 return false; 552 case 'z': 553 // $0 if zero, regular printing otherwise 554 if (MO.getType() == MachineOperand::MO_Immediate && MO.getImm() == 0) { 555 O << "$0"; 556 return false; 557 } 558 // If not, call printOperand as normal. 559 break; 560 case 'D': // Second part of a double word register operand 561 case 'L': // Low order register of a double word register operand 562 case 'M': // High order register of a double word register operand 563 { 564 if (OpNum == 0) 565 return true; 566 const MachineOperand &FlagsOP = MI->getOperand(OpNum - 1); 567 if (!FlagsOP.isImm()) 568 return true; 569 unsigned Flags = FlagsOP.getImm(); 570 unsigned NumVals = InlineAsm::getNumOperandRegisters(Flags); 571 // Number of registers represented by this operand. We are looking 572 // for 2 for 32 bit mode and 1 for 64 bit mode. 573 if (NumVals != 2) { 574 if (Subtarget->isGP64bit() && NumVals == 1 && MO.isReg()) { 575 Register Reg = MO.getReg(); 576 O << '$' << MipsInstPrinter::getRegisterName(Reg); 577 return false; 578 } 579 return true; 580 } 581 582 unsigned RegOp = OpNum; 583 if (!Subtarget->isGP64bit()){ 584 // Endianness reverses which register holds the high or low value 585 // between M and L. 586 switch(ExtraCode[0]) { 587 case 'M': 588 RegOp = (Subtarget->isLittle()) ? OpNum + 1 : OpNum; 589 break; 590 case 'L': 591 RegOp = (Subtarget->isLittle()) ? OpNum : OpNum + 1; 592 break; 593 case 'D': // Always the second part 594 RegOp = OpNum + 1; 595 } 596 if (RegOp >= MI->getNumOperands()) 597 return true; 598 const MachineOperand &MO = MI->getOperand(RegOp); 599 if (!MO.isReg()) 600 return true; 601 Register Reg = MO.getReg(); 602 O << '$' << MipsInstPrinter::getRegisterName(Reg); 603 return false; 604 } 605 break; 606 } 607 case 'w': 608 // Print MSA registers for the 'f' constraint 609 // In LLVM, the 'w' modifier doesn't need to do anything. 610 // We can just call printOperand as normal. 611 break; 612 } 613 } 614 615 printOperand(MI, OpNum, O); 616 return false; 617 } 618 619 bool MipsAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, 620 unsigned OpNum, 621 const char *ExtraCode, 622 raw_ostream &O) { 623 assert(OpNum + 1 < MI->getNumOperands() && "Insufficient operands"); 624 const MachineOperand &BaseMO = MI->getOperand(OpNum); 625 const MachineOperand &OffsetMO = MI->getOperand(OpNum + 1); 626 assert(BaseMO.isReg() && 627 "Unexpected base pointer for inline asm memory operand."); 628 assert(OffsetMO.isImm() && 629 "Unexpected offset for inline asm memory operand."); 630 int Offset = OffsetMO.getImm(); 631 632 // Currently we are expecting either no ExtraCode or 'D','M','L'. 633 if (ExtraCode) { 634 switch (ExtraCode[0]) { 635 case 'D': 636 Offset += 4; 637 break; 638 case 'M': 639 if (Subtarget->isLittle()) 640 Offset += 4; 641 break; 642 case 'L': 643 if (!Subtarget->isLittle()) 644 Offset += 4; 645 break; 646 default: 647 return true; // Unknown modifier. 648 } 649 } 650 651 O << Offset << "($" << MipsInstPrinter::getRegisterName(BaseMO.getReg()) 652 << ")"; 653 654 return false; 655 } 656 657 void MipsAsmPrinter::printOperand(const MachineInstr *MI, int opNum, 658 raw_ostream &O) { 659 const MachineOperand &MO = MI->getOperand(opNum); 660 bool closeP = false; 661 662 if (MO.getTargetFlags()) 663 closeP = true; 664 665 switch(MO.getTargetFlags()) { 666 case MipsII::MO_GPREL: O << "%gp_rel("; break; 667 case MipsII::MO_GOT_CALL: O << "%call16("; break; 668 case MipsII::MO_GOT: O << "%got("; break; 669 case MipsII::MO_ABS_HI: O << "%hi("; break; 670 case MipsII::MO_ABS_LO: O << "%lo("; break; 671 case MipsII::MO_HIGHER: O << "%higher("; break; 672 case MipsII::MO_HIGHEST: O << "%highest(("; break; 673 case MipsII::MO_TLSGD: O << "%tlsgd("; break; 674 case MipsII::MO_GOTTPREL: O << "%gottprel("; break; 675 case MipsII::MO_TPREL_HI: O << "%tprel_hi("; break; 676 case MipsII::MO_TPREL_LO: O << "%tprel_lo("; break; 677 case MipsII::MO_GPOFF_HI: O << "%hi(%neg(%gp_rel("; break; 678 case MipsII::MO_GPOFF_LO: O << "%lo(%neg(%gp_rel("; break; 679 case MipsII::MO_GOT_DISP: O << "%got_disp("; break; 680 case MipsII::MO_GOT_PAGE: O << "%got_page("; break; 681 case MipsII::MO_GOT_OFST: O << "%got_ofst("; break; 682 } 683 684 switch (MO.getType()) { 685 case MachineOperand::MO_Register: 686 O << '$' 687 << StringRef(MipsInstPrinter::getRegisterName(MO.getReg())).lower(); 688 break; 689 690 case MachineOperand::MO_Immediate: 691 O << MO.getImm(); 692 break; 693 694 case MachineOperand::MO_MachineBasicBlock: 695 MO.getMBB()->getSymbol()->print(O, MAI); 696 return; 697 698 case MachineOperand::MO_GlobalAddress: 699 PrintSymbolOperand(MO, O); 700 break; 701 702 case MachineOperand::MO_BlockAddress: { 703 MCSymbol *BA = GetBlockAddressSymbol(MO.getBlockAddress()); 704 O << BA->getName(); 705 break; 706 } 707 708 case MachineOperand::MO_ConstantPoolIndex: 709 O << getDataLayout().getPrivateGlobalPrefix() << "CPI" 710 << getFunctionNumber() << "_" << MO.getIndex(); 711 if (MO.getOffset()) 712 O << "+" << MO.getOffset(); 713 break; 714 715 default: 716 llvm_unreachable("<unknown operand type>"); 717 } 718 719 if (closeP) O << ")"; 720 } 721 722 void MipsAsmPrinter:: 723 printMemOperand(const MachineInstr *MI, int opNum, raw_ostream &O) { 724 // Load/Store memory operands -- imm($reg) 725 // If PIC target the target is loaded as the 726 // pattern lw $25,%call16($28) 727 728 // opNum can be invalid if instruction has reglist as operand. 729 // MemOperand is always last operand of instruction (base + offset). 730 switch (MI->getOpcode()) { 731 default: 732 break; 733 case Mips::SWM32_MM: 734 case Mips::LWM32_MM: 735 opNum = MI->getNumOperands() - 2; 736 break; 737 } 738 739 printOperand(MI, opNum+1, O); 740 O << "("; 741 printOperand(MI, opNum, O); 742 O << ")"; 743 } 744 745 void MipsAsmPrinter:: 746 printMemOperandEA(const MachineInstr *MI, int opNum, raw_ostream &O) { 747 // when using stack locations for not load/store instructions 748 // print the same way as all normal 3 operand instructions. 749 printOperand(MI, opNum, O); 750 O << ", "; 751 printOperand(MI, opNum+1, O); 752 } 753 754 void MipsAsmPrinter:: 755 printFCCOperand(const MachineInstr *MI, int opNum, raw_ostream &O, 756 const char *Modifier) { 757 const MachineOperand &MO = MI->getOperand(opNum); 758 O << Mips::MipsFCCToString((Mips::CondCode)MO.getImm()); 759 } 760 761 void MipsAsmPrinter:: 762 printRegisterList(const MachineInstr *MI, int opNum, raw_ostream &O) { 763 for (int i = opNum, e = MI->getNumOperands(); i != e; ++i) { 764 if (i != opNum) O << ", "; 765 printOperand(MI, i, O); 766 } 767 } 768 769 void MipsAsmPrinter::EmitStartOfAsmFile(Module &M) { 770 MipsTargetStreamer &TS = getTargetStreamer(); 771 772 // MipsTargetStreamer has an initialization order problem when emitting an 773 // object file directly (see MipsTargetELFStreamer for full details). Work 774 // around it by re-initializing the PIC state here. 775 TS.setPic(OutContext.getObjectFileInfo()->isPositionIndependent()); 776 777 // Compute MIPS architecture attributes based on the default subtarget 778 // that we'd have constructed. Module level directives aren't LTO 779 // clean anyhow. 780 // FIXME: For ifunc related functions we could iterate over and look 781 // for a feature string that doesn't match the default one. 782 const Triple &TT = TM.getTargetTriple(); 783 StringRef CPU = MIPS_MC::selectMipsCPU(TT, TM.getTargetCPU()); 784 StringRef FS = TM.getTargetFeatureString(); 785 const MipsTargetMachine &MTM = static_cast<const MipsTargetMachine &>(TM); 786 const MipsSubtarget STI(TT, CPU, FS, MTM.isLittleEndian(), MTM, None); 787 788 bool IsABICalls = STI.isABICalls(); 789 const MipsABIInfo &ABI = MTM.getABI(); 790 if (IsABICalls) { 791 TS.emitDirectiveAbiCalls(); 792 // FIXME: This condition should be a lot more complicated that it is here. 793 // Ideally it should test for properties of the ABI and not the ABI 794 // itself. 795 // For the moment, I'm only correcting enough to make MIPS-IV work. 796 if (!isPositionIndependent() && STI.hasSym32()) 797 TS.emitDirectiveOptionPic0(); 798 } 799 800 // Tell the assembler which ABI we are using 801 std::string SectionName = std::string(".mdebug.") + getCurrentABIString(); 802 OutStreamer->SwitchSection( 803 OutContext.getELFSection(SectionName, ELF::SHT_PROGBITS, 0)); 804 805 // NaN: At the moment we only support: 806 // 1. .nan legacy (default) 807 // 2. .nan 2008 808 STI.isNaN2008() ? TS.emitDirectiveNaN2008() 809 : TS.emitDirectiveNaNLegacy(); 810 811 // TODO: handle O64 ABI 812 813 TS.updateABIInfo(STI); 814 815 // We should always emit a '.module fp=...' but binutils 2.24 does not accept 816 // it. We therefore emit it when it contradicts the ABI defaults (-mfpxx or 817 // -mfp64) and omit it otherwise. 818 if ((ABI.IsO32() && (STI.isABI_FPXX() || STI.isFP64bit())) || 819 STI.useSoftFloat()) 820 TS.emitDirectiveModuleFP(); 821 822 // We should always emit a '.module [no]oddspreg' but binutils 2.24 does not 823 // accept it. We therefore emit it when it contradicts the default or an 824 // option has changed the default (i.e. FPXX) and omit it otherwise. 825 if (ABI.IsO32() && (!STI.useOddSPReg() || STI.isABI_FPXX())) 826 TS.emitDirectiveModuleOddSPReg(); 827 828 // Switch to the .text section. 829 OutStreamer->SwitchSection(getObjFileLowering().getTextSection()); 830 } 831 832 void MipsAsmPrinter::emitInlineAsmStart() const { 833 MipsTargetStreamer &TS = getTargetStreamer(); 834 835 // GCC's choice of assembler options for inline assembly code ('at', 'macro' 836 // and 'reorder') is different from LLVM's choice for generated code ('noat', 837 // 'nomacro' and 'noreorder'). 838 // In order to maintain compatibility with inline assembly code which depends 839 // on GCC's assembler options being used, we have to switch to those options 840 // for the duration of the inline assembly block and then switch back. 841 TS.emitDirectiveSetPush(); 842 TS.emitDirectiveSetAt(); 843 TS.emitDirectiveSetMacro(); 844 TS.emitDirectiveSetReorder(); 845 OutStreamer->AddBlankLine(); 846 } 847 848 void MipsAsmPrinter::emitInlineAsmEnd(const MCSubtargetInfo &StartInfo, 849 const MCSubtargetInfo *EndInfo) const { 850 OutStreamer->AddBlankLine(); 851 getTargetStreamer().emitDirectiveSetPop(); 852 } 853 854 void MipsAsmPrinter::EmitJal(const MCSubtargetInfo &STI, MCSymbol *Symbol) { 855 MCInst I; 856 I.setOpcode(Mips::JAL); 857 I.addOperand( 858 MCOperand::createExpr(MCSymbolRefExpr::create(Symbol, OutContext))); 859 OutStreamer->EmitInstruction(I, STI); 860 } 861 862 void MipsAsmPrinter::EmitInstrReg(const MCSubtargetInfo &STI, unsigned Opcode, 863 unsigned Reg) { 864 MCInst I; 865 I.setOpcode(Opcode); 866 I.addOperand(MCOperand::createReg(Reg)); 867 OutStreamer->EmitInstruction(I, STI); 868 } 869 870 void MipsAsmPrinter::EmitInstrRegReg(const MCSubtargetInfo &STI, 871 unsigned Opcode, unsigned Reg1, 872 unsigned Reg2) { 873 MCInst I; 874 // 875 // Because of the current td files for Mips32, the operands for MTC1 876 // appear backwards from their normal assembly order. It's not a trivial 877 // change to fix this in the td file so we adjust for it here. 878 // 879 if (Opcode == Mips::MTC1) { 880 unsigned Temp = Reg1; 881 Reg1 = Reg2; 882 Reg2 = Temp; 883 } 884 I.setOpcode(Opcode); 885 I.addOperand(MCOperand::createReg(Reg1)); 886 I.addOperand(MCOperand::createReg(Reg2)); 887 OutStreamer->EmitInstruction(I, STI); 888 } 889 890 void MipsAsmPrinter::EmitInstrRegRegReg(const MCSubtargetInfo &STI, 891 unsigned Opcode, unsigned Reg1, 892 unsigned Reg2, unsigned Reg3) { 893 MCInst I; 894 I.setOpcode(Opcode); 895 I.addOperand(MCOperand::createReg(Reg1)); 896 I.addOperand(MCOperand::createReg(Reg2)); 897 I.addOperand(MCOperand::createReg(Reg3)); 898 OutStreamer->EmitInstruction(I, STI); 899 } 900 901 void MipsAsmPrinter::EmitMovFPIntPair(const MCSubtargetInfo &STI, 902 unsigned MovOpc, unsigned Reg1, 903 unsigned Reg2, unsigned FPReg1, 904 unsigned FPReg2, bool LE) { 905 if (!LE) { 906 unsigned temp = Reg1; 907 Reg1 = Reg2; 908 Reg2 = temp; 909 } 910 EmitInstrRegReg(STI, MovOpc, Reg1, FPReg1); 911 EmitInstrRegReg(STI, MovOpc, Reg2, FPReg2); 912 } 913 914 void MipsAsmPrinter::EmitSwapFPIntParams(const MCSubtargetInfo &STI, 915 Mips16HardFloatInfo::FPParamVariant PV, 916 bool LE, bool ToFP) { 917 using namespace Mips16HardFloatInfo; 918 919 unsigned MovOpc = ToFP ? Mips::MTC1 : Mips::MFC1; 920 switch (PV) { 921 case FSig: 922 EmitInstrRegReg(STI, MovOpc, Mips::A0, Mips::F12); 923 break; 924 case FFSig: 925 EmitMovFPIntPair(STI, MovOpc, Mips::A0, Mips::A1, Mips::F12, Mips::F14, LE); 926 break; 927 case FDSig: 928 EmitInstrRegReg(STI, MovOpc, Mips::A0, Mips::F12); 929 EmitMovFPIntPair(STI, MovOpc, Mips::A2, Mips::A3, Mips::F14, Mips::F15, LE); 930 break; 931 case DSig: 932 EmitMovFPIntPair(STI, MovOpc, Mips::A0, Mips::A1, Mips::F12, Mips::F13, LE); 933 break; 934 case DDSig: 935 EmitMovFPIntPair(STI, MovOpc, Mips::A0, Mips::A1, Mips::F12, Mips::F13, LE); 936 EmitMovFPIntPair(STI, MovOpc, Mips::A2, Mips::A3, Mips::F14, Mips::F15, LE); 937 break; 938 case DFSig: 939 EmitMovFPIntPair(STI, MovOpc, Mips::A0, Mips::A1, Mips::F12, Mips::F13, LE); 940 EmitInstrRegReg(STI, MovOpc, Mips::A2, Mips::F14); 941 break; 942 case NoSig: 943 return; 944 } 945 } 946 947 void MipsAsmPrinter::EmitSwapFPIntRetval( 948 const MCSubtargetInfo &STI, Mips16HardFloatInfo::FPReturnVariant RV, 949 bool LE) { 950 using namespace Mips16HardFloatInfo; 951 952 unsigned MovOpc = Mips::MFC1; 953 switch (RV) { 954 case FRet: 955 EmitInstrRegReg(STI, MovOpc, Mips::V0, Mips::F0); 956 break; 957 case DRet: 958 EmitMovFPIntPair(STI, MovOpc, Mips::V0, Mips::V1, Mips::F0, Mips::F1, LE); 959 break; 960 case CFRet: 961 EmitMovFPIntPair(STI, MovOpc, Mips::V0, Mips::V1, Mips::F0, Mips::F1, LE); 962 break; 963 case CDRet: 964 EmitMovFPIntPair(STI, MovOpc, Mips::V0, Mips::V1, Mips::F0, Mips::F1, LE); 965 EmitMovFPIntPair(STI, MovOpc, Mips::A0, Mips::A1, Mips::F2, Mips::F3, LE); 966 break; 967 case NoFPRet: 968 break; 969 } 970 } 971 972 void MipsAsmPrinter::EmitFPCallStub( 973 const char *Symbol, const Mips16HardFloatInfo::FuncSignature *Signature) { 974 using namespace Mips16HardFloatInfo; 975 976 MCSymbol *MSymbol = OutContext.getOrCreateSymbol(StringRef(Symbol)); 977 bool LE = getDataLayout().isLittleEndian(); 978 // Construct a local MCSubtargetInfo here. 979 // This is because the MachineFunction won't exist (but have not yet been 980 // freed) and since we're at the global level we can use the default 981 // constructed subtarget. 982 std::unique_ptr<MCSubtargetInfo> STI(TM.getTarget().createMCSubtargetInfo( 983 TM.getTargetTriple().str(), TM.getTargetCPU(), 984 TM.getTargetFeatureString())); 985 986 // 987 // .global xxxx 988 // 989 OutStreamer->EmitSymbolAttribute(MSymbol, MCSA_Global); 990 const char *RetType; 991 // 992 // make the comment field identifying the return and parameter 993 // types of the floating point stub 994 // # Stub function to call rettype xxxx (params) 995 // 996 switch (Signature->RetSig) { 997 case FRet: 998 RetType = "float"; 999 break; 1000 case DRet: 1001 RetType = "double"; 1002 break; 1003 case CFRet: 1004 RetType = "complex"; 1005 break; 1006 case CDRet: 1007 RetType = "double complex"; 1008 break; 1009 case NoFPRet: 1010 RetType = ""; 1011 break; 1012 } 1013 const char *Parms; 1014 switch (Signature->ParamSig) { 1015 case FSig: 1016 Parms = "float"; 1017 break; 1018 case FFSig: 1019 Parms = "float, float"; 1020 break; 1021 case FDSig: 1022 Parms = "float, double"; 1023 break; 1024 case DSig: 1025 Parms = "double"; 1026 break; 1027 case DDSig: 1028 Parms = "double, double"; 1029 break; 1030 case DFSig: 1031 Parms = "double, float"; 1032 break; 1033 case NoSig: 1034 Parms = ""; 1035 break; 1036 } 1037 OutStreamer->AddComment("\t# Stub function to call " + Twine(RetType) + " " + 1038 Twine(Symbol) + " (" + Twine(Parms) + ")"); 1039 // 1040 // probably not necessary but we save and restore the current section state 1041 // 1042 OutStreamer->PushSection(); 1043 // 1044 // .section mips16.call.fpxxxx,"ax",@progbits 1045 // 1046 MCSectionELF *M = OutContext.getELFSection( 1047 ".mips16.call.fp." + std::string(Symbol), ELF::SHT_PROGBITS, 1048 ELF::SHF_ALLOC | ELF::SHF_EXECINSTR); 1049 OutStreamer->SwitchSection(M, nullptr); 1050 // 1051 // .align 2 1052 // 1053 OutStreamer->EmitValueToAlignment(4); 1054 MipsTargetStreamer &TS = getTargetStreamer(); 1055 // 1056 // .set nomips16 1057 // .set nomicromips 1058 // 1059 TS.emitDirectiveSetNoMips16(); 1060 TS.emitDirectiveSetNoMicroMips(); 1061 // 1062 // .ent __call_stub_fp_xxxx 1063 // .type __call_stub_fp_xxxx,@function 1064 // __call_stub_fp_xxxx: 1065 // 1066 std::string x = "__call_stub_fp_" + std::string(Symbol); 1067 MCSymbolELF *Stub = 1068 cast<MCSymbolELF>(OutContext.getOrCreateSymbol(StringRef(x))); 1069 TS.emitDirectiveEnt(*Stub); 1070 MCSymbol *MType = 1071 OutContext.getOrCreateSymbol("__call_stub_fp_" + Twine(Symbol)); 1072 OutStreamer->EmitSymbolAttribute(MType, MCSA_ELF_TypeFunction); 1073 OutStreamer->EmitLabel(Stub); 1074 1075 // Only handle non-pic for now. 1076 assert(!isPositionIndependent() && 1077 "should not be here if we are compiling pic"); 1078 TS.emitDirectiveSetReorder(); 1079 // 1080 // We need to add a MipsMCExpr class to MCTargetDesc to fully implement 1081 // stubs without raw text but this current patch is for compiler generated 1082 // functions and they all return some value. 1083 // The calling sequence for non pic is different in that case and we need 1084 // to implement %lo and %hi in order to handle the case of no return value 1085 // See the corresponding method in Mips16HardFloat for details. 1086 // 1087 // mov the return address to S2. 1088 // we have no stack space to store it and we are about to make another call. 1089 // We need to make sure that the enclosing function knows to save S2 1090 // This should have already been handled. 1091 // 1092 // Mov $18, $31 1093 1094 EmitInstrRegRegReg(*STI, Mips::OR, Mips::S2, Mips::RA, Mips::ZERO); 1095 1096 EmitSwapFPIntParams(*STI, Signature->ParamSig, LE, true); 1097 1098 // Jal xxxx 1099 // 1100 EmitJal(*STI, MSymbol); 1101 1102 // fix return values 1103 EmitSwapFPIntRetval(*STI, Signature->RetSig, LE); 1104 // 1105 // do the return 1106 // if (Signature->RetSig == NoFPRet) 1107 // llvm_unreachable("should not be any stubs here with no return value"); 1108 // else 1109 EmitInstrReg(*STI, Mips::JR, Mips::S2); 1110 1111 MCSymbol *Tmp = OutContext.createTempSymbol(); 1112 OutStreamer->EmitLabel(Tmp); 1113 const MCSymbolRefExpr *E = MCSymbolRefExpr::create(Stub, OutContext); 1114 const MCSymbolRefExpr *T = MCSymbolRefExpr::create(Tmp, OutContext); 1115 const MCExpr *T_min_E = MCBinaryExpr::createSub(T, E, OutContext); 1116 OutStreamer->emitELFSize(Stub, T_min_E); 1117 TS.emitDirectiveEnd(x); 1118 OutStreamer->PopSection(); 1119 } 1120 1121 void MipsAsmPrinter::EmitEndOfAsmFile(Module &M) { 1122 // Emit needed stubs 1123 // 1124 for (std::map< 1125 const char *, 1126 const Mips16HardFloatInfo::FuncSignature *>::const_iterator 1127 it = StubsNeeded.begin(); 1128 it != StubsNeeded.end(); ++it) { 1129 const char *Symbol = it->first; 1130 const Mips16HardFloatInfo::FuncSignature *Signature = it->second; 1131 EmitFPCallStub(Symbol, Signature); 1132 } 1133 // return to the text section 1134 OutStreamer->SwitchSection(OutContext.getObjectFileInfo()->getTextSection()); 1135 } 1136 1137 void MipsAsmPrinter::EmitSled(const MachineInstr &MI, SledKind Kind) { 1138 const uint8_t NoopsInSledCount = Subtarget->isGP64bit() ? 15 : 11; 1139 // For mips32 we want to emit the following pattern: 1140 // 1141 // .Lxray_sled_N: 1142 // ALIGN 1143 // B .tmpN 1144 // 11 NOP instructions (44 bytes) 1145 // ADDIU T9, T9, 52 1146 // .tmpN 1147 // 1148 // We need the 44 bytes (11 instructions) because at runtime, we'd 1149 // be patching over the full 48 bytes (12 instructions) with the following 1150 // pattern: 1151 // 1152 // ADDIU SP, SP, -8 1153 // NOP 1154 // SW RA, 4(SP) 1155 // SW T9, 0(SP) 1156 // LUI T9, %hi(__xray_FunctionEntry/Exit) 1157 // ORI T9, T9, %lo(__xray_FunctionEntry/Exit) 1158 // LUI T0, %hi(function_id) 1159 // JALR T9 1160 // ORI T0, T0, %lo(function_id) 1161 // LW T9, 0(SP) 1162 // LW RA, 4(SP) 1163 // ADDIU SP, SP, 8 1164 // 1165 // We add 52 bytes to t9 because we want to adjust the function pointer to 1166 // the actual start of function i.e. the address just after the noop sled. 1167 // We do this because gp displacement relocation is emitted at the start of 1168 // of the function i.e after the nop sled and to correctly calculate the 1169 // global offset table address, t9 must hold the address of the instruction 1170 // containing the gp displacement relocation. 1171 // FIXME: Is this correct for the static relocation model? 1172 // 1173 // For mips64 we want to emit the following pattern: 1174 // 1175 // .Lxray_sled_N: 1176 // ALIGN 1177 // B .tmpN 1178 // 15 NOP instructions (60 bytes) 1179 // .tmpN 1180 // 1181 // We need the 60 bytes (15 instructions) because at runtime, we'd 1182 // be patching over the full 64 bytes (16 instructions) with the following 1183 // pattern: 1184 // 1185 // DADDIU SP, SP, -16 1186 // NOP 1187 // SD RA, 8(SP) 1188 // SD T9, 0(SP) 1189 // LUI T9, %highest(__xray_FunctionEntry/Exit) 1190 // ORI T9, T9, %higher(__xray_FunctionEntry/Exit) 1191 // DSLL T9, T9, 16 1192 // ORI T9, T9, %hi(__xray_FunctionEntry/Exit) 1193 // DSLL T9, T9, 16 1194 // ORI T9, T9, %lo(__xray_FunctionEntry/Exit) 1195 // LUI T0, %hi(function_id) 1196 // JALR T9 1197 // ADDIU T0, T0, %lo(function_id) 1198 // LD T9, 0(SP) 1199 // LD RA, 8(SP) 1200 // DADDIU SP, SP, 16 1201 // 1202 OutStreamer->EmitCodeAlignment(4); 1203 auto CurSled = OutContext.createTempSymbol("xray_sled_", true); 1204 OutStreamer->EmitLabel(CurSled); 1205 auto Target = OutContext.createTempSymbol(); 1206 1207 // Emit "B .tmpN" instruction, which jumps over the nop sled to the actual 1208 // start of function 1209 const MCExpr *TargetExpr = MCSymbolRefExpr::create( 1210 Target, MCSymbolRefExpr::VariantKind::VK_None, OutContext); 1211 EmitToStreamer(*OutStreamer, MCInstBuilder(Mips::BEQ) 1212 .addReg(Mips::ZERO) 1213 .addReg(Mips::ZERO) 1214 .addExpr(TargetExpr)); 1215 1216 for (int8_t I = 0; I < NoopsInSledCount; I++) 1217 EmitToStreamer(*OutStreamer, MCInstBuilder(Mips::SLL) 1218 .addReg(Mips::ZERO) 1219 .addReg(Mips::ZERO) 1220 .addImm(0)); 1221 1222 OutStreamer->EmitLabel(Target); 1223 1224 if (!Subtarget->isGP64bit()) { 1225 EmitToStreamer(*OutStreamer, 1226 MCInstBuilder(Mips::ADDiu) 1227 .addReg(Mips::T9) 1228 .addReg(Mips::T9) 1229 .addImm(0x34)); 1230 } 1231 1232 recordSled(CurSled, MI, Kind); 1233 } 1234 1235 void MipsAsmPrinter::LowerPATCHABLE_FUNCTION_ENTER(const MachineInstr &MI) { 1236 EmitSled(MI, SledKind::FUNCTION_ENTER); 1237 } 1238 1239 void MipsAsmPrinter::LowerPATCHABLE_FUNCTION_EXIT(const MachineInstr &MI) { 1240 EmitSled(MI, SledKind::FUNCTION_EXIT); 1241 } 1242 1243 void MipsAsmPrinter::LowerPATCHABLE_TAIL_CALL(const MachineInstr &MI) { 1244 EmitSled(MI, SledKind::TAIL_CALL); 1245 } 1246 1247 void MipsAsmPrinter::PrintDebugValueComment(const MachineInstr *MI, 1248 raw_ostream &OS) { 1249 // TODO: implement 1250 } 1251 1252 // Emit .dtprelword or .dtpreldword directive 1253 // and value for debug thread local expression. 1254 void MipsAsmPrinter::EmitDebugValue(const MCExpr *Value, unsigned Size) const { 1255 if (auto *MipsExpr = dyn_cast<MipsMCExpr>(Value)) { 1256 if (MipsExpr && MipsExpr->getKind() == MipsMCExpr::MEK_DTPREL) { 1257 switch (Size) { 1258 case 4: 1259 OutStreamer->EmitDTPRel32Value(MipsExpr->getSubExpr()); 1260 break; 1261 case 8: 1262 OutStreamer->EmitDTPRel64Value(MipsExpr->getSubExpr()); 1263 break; 1264 default: 1265 llvm_unreachable("Unexpected size of expression value."); 1266 } 1267 return; 1268 } 1269 } 1270 AsmPrinter::EmitDebugValue(Value, Size); 1271 } 1272 1273 // Align all targets of indirect branches on bundle size. Used only if target 1274 // is NaCl. 1275 void MipsAsmPrinter::NaClAlignIndirectJumpTargets(MachineFunction &MF) { 1276 // Align all blocks that are jumped to through jump table. 1277 if (MachineJumpTableInfo *JtInfo = MF.getJumpTableInfo()) { 1278 const std::vector<MachineJumpTableEntry> &JT = JtInfo->getJumpTables(); 1279 for (unsigned I = 0; I < JT.size(); ++I) { 1280 const std::vector<MachineBasicBlock*> &MBBs = JT[I].MBBs; 1281 1282 for (unsigned J = 0; J < MBBs.size(); ++J) 1283 MBBs[J]->setAlignment(MIPS_NACL_BUNDLE_ALIGN); 1284 } 1285 } 1286 1287 // If basic block address is taken, block can be target of indirect branch. 1288 for (auto &MBB : MF) { 1289 if (MBB.hasAddressTaken()) 1290 MBB.setAlignment(MIPS_NACL_BUNDLE_ALIGN); 1291 } 1292 } 1293 1294 bool MipsAsmPrinter::isLongBranchPseudo(int Opcode) const { 1295 return (Opcode == Mips::LONG_BRANCH_LUi 1296 || Opcode == Mips::LONG_BRANCH_LUi2Op 1297 || Opcode == Mips::LONG_BRANCH_LUi2Op_64 1298 || Opcode == Mips::LONG_BRANCH_ADDiu 1299 || Opcode == Mips::LONG_BRANCH_ADDiu2Op 1300 || Opcode == Mips::LONG_BRANCH_DADDiu 1301 || Opcode == Mips::LONG_BRANCH_DADDiu2Op); 1302 } 1303 1304 // Force static initialization. 1305 extern "C" void LLVMInitializeMipsAsmPrinter() { 1306 RegisterAsmPrinter<MipsAsmPrinter> X(getTheMipsTarget()); 1307 RegisterAsmPrinter<MipsAsmPrinter> Y(getTheMipselTarget()); 1308 RegisterAsmPrinter<MipsAsmPrinter> A(getTheMips64Target()); 1309 RegisterAsmPrinter<MipsAsmPrinter> B(getTheMips64elTarget()); 1310 } 1311