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