comparison lib/Target/Mips/MipsAsmPrinter.cpp @ 77:54457678186b LLVM3.6

LLVM 3.6
author Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
date Mon, 08 Sep 2014 22:06:00 +0900
parents e4204d083e25
children 60c9769439b8
comparison
equal deleted inserted replaced
34:e874dbf0ad9d 77:54457678186b
10 // This file contains a printer that converts from our internal representation 10 // This file contains a printer that converts from our internal representation
11 // of machine-dependent LLVM code to GAS-format MIPS assembly language. 11 // of machine-dependent LLVM code to GAS-format MIPS assembly language.
12 // 12 //
13 //===----------------------------------------------------------------------===// 13 //===----------------------------------------------------------------------===//
14 14
15 #define DEBUG_TYPE "mips-asm-printer"
16 #include "InstPrinter/MipsInstPrinter.h" 15 #include "InstPrinter/MipsInstPrinter.h"
17 #include "MCTargetDesc/MipsBaseInfo.h" 16 #include "MCTargetDesc/MipsBaseInfo.h"
17 #include "MCTargetDesc/MipsMCNaCl.h"
18 #include "Mips.h" 18 #include "Mips.h"
19 #include "MipsAsmPrinter.h" 19 #include "MipsAsmPrinter.h"
20 #include "MipsInstrInfo.h" 20 #include "MipsInstrInfo.h"
21 #include "MipsMCInstLower.h" 21 #include "MipsMCInstLower.h"
22 #include "MipsTargetStreamer.h" 22 #include "MipsTargetStreamer.h"
25 #include "llvm/ADT/Twine.h" 25 #include "llvm/ADT/Twine.h"
26 #include "llvm/CodeGen/MachineConstantPool.h" 26 #include "llvm/CodeGen/MachineConstantPool.h"
27 #include "llvm/CodeGen/MachineFrameInfo.h" 27 #include "llvm/CodeGen/MachineFrameInfo.h"
28 #include "llvm/CodeGen/MachineFunctionPass.h" 28 #include "llvm/CodeGen/MachineFunctionPass.h"
29 #include "llvm/CodeGen/MachineInstr.h" 29 #include "llvm/CodeGen/MachineInstr.h"
30 #include "llvm/CodeGen/MachineJumpTableInfo.h"
30 #include "llvm/CodeGen/MachineMemOperand.h" 31 #include "llvm/CodeGen/MachineMemOperand.h"
31 #include "llvm/IR/BasicBlock.h" 32 #include "llvm/IR/BasicBlock.h"
32 #include "llvm/IR/DataLayout.h" 33 #include "llvm/IR/DataLayout.h"
33 #include "llvm/IR/InlineAsm.h" 34 #include "llvm/IR/InlineAsm.h"
34 #include "llvm/IR/Instructions.h" 35 #include "llvm/IR/Instructions.h"
36 #include "llvm/IR/Mangler.h"
35 #include "llvm/MC/MCAsmInfo.h" 37 #include "llvm/MC/MCAsmInfo.h"
38 #include "llvm/MC/MCContext.h"
36 #include "llvm/MC/MCELFStreamer.h" 39 #include "llvm/MC/MCELFStreamer.h"
40 #include "llvm/MC/MCExpr.h"
37 #include "llvm/MC/MCInst.h" 41 #include "llvm/MC/MCInst.h"
42 #include "llvm/MC/MCSection.h"
43 #include "llvm/MC/MCSectionELF.h"
38 #include "llvm/MC/MCSymbol.h" 44 #include "llvm/MC/MCSymbol.h"
39 #include "llvm/Support/ELF.h" 45 #include "llvm/Support/ELF.h"
40 #include "llvm/Support/TargetRegistry.h" 46 #include "llvm/Support/TargetRegistry.h"
41 #include "llvm/Support/raw_ostream.h" 47 #include "llvm/Support/raw_ostream.h"
42 #include "llvm/Target/Mangler.h"
43 #include "llvm/Target/TargetLoweringObjectFile.h" 48 #include "llvm/Target/TargetLoweringObjectFile.h"
44 #include "llvm/Target/TargetOptions.h" 49 #include "llvm/Target/TargetOptions.h"
50 #include <string>
45 51
46 using namespace llvm; 52 using namespace llvm;
47 53
54 #define DEBUG_TYPE "mips-asm-printer"
55
48 MipsTargetStreamer &MipsAsmPrinter::getTargetStreamer() { 56 MipsTargetStreamer &MipsAsmPrinter::getTargetStreamer() {
49 return static_cast<MipsTargetStreamer &>(OutStreamer.getTargetStreamer()); 57 return static_cast<MipsTargetStreamer &>(*OutStreamer.getTargetStreamer());
50 } 58 }
51 59
52 bool MipsAsmPrinter::runOnMachineFunction(MachineFunction &MF) { 60 bool MipsAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
61 Subtarget = &TM.getSubtarget<MipsSubtarget>();
62
53 // Initialize TargetLoweringObjectFile. 63 // Initialize TargetLoweringObjectFile.
54 if (Subtarget->allowMixed16_32()) 64 const_cast<TargetLoweringObjectFile &>(getObjFileLowering())
55 const_cast<TargetLoweringObjectFile&>(getObjFileLowering())
56 .Initialize(OutContext, TM); 65 .Initialize(OutContext, TM);
66
57 MipsFI = MF.getInfo<MipsFunctionInfo>(); 67 MipsFI = MF.getInfo<MipsFunctionInfo>();
68 if (Subtarget->inMips16Mode())
69 for (std::map<
70 const char *,
71 const llvm::Mips16HardFloatInfo::FuncSignature *>::const_iterator
72 it = MipsFI->StubsNeeded.begin();
73 it != MipsFI->StubsNeeded.end(); ++it) {
74 const char *Symbol = it->first;
75 const llvm::Mips16HardFloatInfo::FuncSignature *Signature = it->second;
76 if (StubsNeeded.find(Symbol) == StubsNeeded.end())
77 StubsNeeded[Symbol] = Signature;
78 }
58 MCP = MF.getConstantPool(); 79 MCP = MF.getConstantPool();
80
81 // In NaCl, all indirect jump targets must be aligned to bundle size.
82 if (Subtarget->isTargetNaCl())
83 NaClAlignIndirectJumpTargets(MF);
84
59 AsmPrinter::runOnMachineFunction(MF); 85 AsmPrinter::runOnMachineFunction(MF);
60 return true; 86 return true;
61 } 87 }
62 88
63 bool MipsAsmPrinter::lowerOperand(const MachineOperand &MO, MCOperand &MCOp) { 89 bool MipsAsmPrinter::lowerOperand(const MachineOperand &MO, MCOperand &MCOp) {
65 return MCOp.isValid(); 91 return MCOp.isValid();
66 } 92 }
67 93
68 #include "MipsGenMCPseudoLowering.inc" 94 #include "MipsGenMCPseudoLowering.inc"
69 95
96 // Lower PseudoReturn/PseudoIndirectBranch/PseudoIndirectBranch64 to JR, JR_MM,
97 // JALR, or JALR64 as appropriate for the target
98 void MipsAsmPrinter::emitPseudoIndirectBranch(MCStreamer &OutStreamer,
99 const MachineInstr *MI) {
100 bool HasLinkReg = false;
101 MCInst TmpInst0;
102
103 if (Subtarget->hasMips64r6()) {
104 // MIPS64r6 should use (JALR64 ZERO_64, $rs)
105 TmpInst0.setOpcode(Mips::JALR64);
106 HasLinkReg = true;
107 } else if (Subtarget->hasMips32r6()) {
108 // MIPS32r6 should use (JALR ZERO, $rs)
109 TmpInst0.setOpcode(Mips::JALR);
110 HasLinkReg = true;
111 } else if (Subtarget->inMicroMipsMode())
112 // microMIPS should use (JR_MM $rs)
113 TmpInst0.setOpcode(Mips::JR_MM);
114 else {
115 // Everything else should use (JR $rs)
116 TmpInst0.setOpcode(Mips::JR);
117 }
118
119 MCOperand MCOp;
120
121 if (HasLinkReg) {
122 unsigned ZeroReg = Subtarget->isGP64bit() ? Mips::ZERO_64 : Mips::ZERO;
123 TmpInst0.addOperand(MCOperand::CreateReg(ZeroReg));
124 }
125
126 lowerOperand(MI->getOperand(0), MCOp);
127 TmpInst0.addOperand(MCOp);
128
129 EmitToStreamer(OutStreamer, TmpInst0);
130 }
131
70 void MipsAsmPrinter::EmitInstruction(const MachineInstr *MI) { 132 void MipsAsmPrinter::EmitInstruction(const MachineInstr *MI) {
133 MipsTargetStreamer &TS = getTargetStreamer();
134 TS.forbidModuleDirective();
135
71 if (MI->isDebugValue()) { 136 if (MI->isDebugValue()) {
72 SmallString<128> Str; 137 SmallString<128> Str;
73 raw_svector_ostream OS(Str); 138 raw_svector_ostream OS(Str);
74 139
75 PrintDebugValueComment(MI, OS); 140 PrintDebugValueComment(MI, OS);
115 do { 180 do {
116 // Do any auto-generated pseudo lowerings. 181 // Do any auto-generated pseudo lowerings.
117 if (emitPseudoExpansionLowering(OutStreamer, &*I)) 182 if (emitPseudoExpansionLowering(OutStreamer, &*I))
118 continue; 183 continue;
119 184
185 if (I->getOpcode() == Mips::PseudoReturn ||
186 I->getOpcode() == Mips::PseudoReturn64 ||
187 I->getOpcode() == Mips::PseudoIndirectBranch ||
188 I->getOpcode() == Mips::PseudoIndirectBranch64) {
189 emitPseudoIndirectBranch(OutStreamer, &*I);
190 continue;
191 }
192
120 // The inMips16Mode() test is not permanent. 193 // The inMips16Mode() test is not permanent.
121 // Some instructions are marked as pseudo right now which 194 // Some instructions are marked as pseudo right now which
122 // would make the test fail for the wrong reason but 195 // would make the test fail for the wrong reason but
123 // that will be fixed soon. We need this here because we are 196 // that will be fixed soon. We need this here because we are
124 // removing another test for this situation downstream in the 197 // removing another test for this situation downstream in the
125 // callchain. 198 // callchain.
126 // 199 //
127 if (I->isPseudo() && !Subtarget->inMips16Mode()) 200 if (I->isPseudo() && !Subtarget->inMips16Mode()
201 && !isLongBranchPseudo(I->getOpcode()))
128 llvm_unreachable("Pseudo opcode found in EmitInstruction()"); 202 llvm_unreachable("Pseudo opcode found in EmitInstruction()");
129 203
130 MCInst TmpInst0; 204 MCInst TmpInst0;
131 MCInstLowering.Lower(I, TmpInst0); 205 MCInstLowering.Lower(I, TmpInst0);
132 OutStreamer.EmitInstruction(TmpInst0); 206 EmitToStreamer(OutStreamer, TmpInst0);
133 } while ((++I != E) && I->isInsideBundle()); // Delay slot check 207 } while ((++I != E) && I->isInsideBundle()); // Delay slot check
134 } 208 }
135 209
136 //===----------------------------------------------------------------------===// 210 //===----------------------------------------------------------------------===//
137 // 211 //
168 // Mask directives 242 // Mask directives
169 //===----------------------------------------------------------------------===// 243 //===----------------------------------------------------------------------===//
170 244
171 // Create a bitmask with all callee saved registers for CPU or Floating Point 245 // Create a bitmask with all callee saved registers for CPU or Floating Point
172 // registers. For CPU registers consider RA, GP and FP for saving if necessary. 246 // registers. For CPU registers consider RA, GP and FP for saving if necessary.
173 void MipsAsmPrinter::printSavedRegsBitmask(raw_ostream &O) { 247 void MipsAsmPrinter::printSavedRegsBitmask() {
174 // CPU and FPU Saved Registers Bitmasks 248 // CPU and FPU Saved Registers Bitmasks
175 unsigned CPUBitmask = 0, FPUBitmask = 0; 249 unsigned CPUBitmask = 0, FPUBitmask = 0;
176 int CPUTopSavedRegOff, FPUTopSavedRegOff; 250 int CPUTopSavedRegOff, FPUTopSavedRegOff;
177 251
178 // Set the CPU and FPU Bitmasks 252 // Set the CPU and FPU Bitmasks
190 for (i = 0; i != e; ++i) { 264 for (i = 0; i != e; ++i) {
191 unsigned Reg = CSI[i].getReg(); 265 unsigned Reg = CSI[i].getReg();
192 if (Mips::GPR32RegClass.contains(Reg)) 266 if (Mips::GPR32RegClass.contains(Reg))
193 break; 267 break;
194 268
195 unsigned RegNum = TM.getRegisterInfo()->getEncodingValue(Reg); 269 unsigned RegNum =
270 TM.getSubtargetImpl()->getRegisterInfo()->getEncodingValue(Reg);
196 if (Mips::AFGR64RegClass.contains(Reg)) { 271 if (Mips::AFGR64RegClass.contains(Reg)) {
197 FPUBitmask |= (3 << RegNum); 272 FPUBitmask |= (3 << RegNum);
198 CSFPRegsSize += AFGR64RegSize; 273 CSFPRegsSize += AFGR64RegSize;
199 HasAFGR64Reg = true; 274 HasAFGR64Reg = true;
200 continue; 275 continue;
205 } 280 }
206 281
207 // Set CPU Bitmask. 282 // Set CPU Bitmask.
208 for (; i != e; ++i) { 283 for (; i != e; ++i) {
209 unsigned Reg = CSI[i].getReg(); 284 unsigned Reg = CSI[i].getReg();
210 unsigned RegNum = TM.getRegisterInfo()->getEncodingValue(Reg); 285 unsigned RegNum =
286 TM.getSubtargetImpl()->getRegisterInfo()->getEncodingValue(Reg);
211 CPUBitmask |= (1 << RegNum); 287 CPUBitmask |= (1 << RegNum);
212 } 288 }
213 289
214 // FP Regs are saved right below where the virtual frame pointer points to. 290 // FP Regs are saved right below where the virtual frame pointer points to.
215 FPUTopSavedRegOff = FPUBitmask ? 291 FPUTopSavedRegOff = FPUBitmask ?
216 (HasAFGR64Reg ? -AFGR64RegSize : -FGR32RegSize) : 0; 292 (HasAFGR64Reg ? -AFGR64RegSize : -FGR32RegSize) : 0;
217 293
218 // CPU Regs are saved below FP Regs. 294 // CPU Regs are saved below FP Regs.
219 CPUTopSavedRegOff = CPUBitmask ? -CSFPRegsSize - CPURegSize : 0; 295 CPUTopSavedRegOff = CPUBitmask ? -CSFPRegsSize - CPURegSize : 0;
220 296
297 MipsTargetStreamer &TS = getTargetStreamer();
221 // Print CPUBitmask 298 // Print CPUBitmask
222 O << "\t.mask \t"; printHex32(CPUBitmask, O); 299 TS.emitMask(CPUBitmask, CPUTopSavedRegOff);
223 O << ',' << CPUTopSavedRegOff << '\n';
224 300
225 // Print FPUBitmask 301 // Print FPUBitmask
226 O << "\t.fmask\t"; printHex32(FPUBitmask, O); 302 TS.emitFMask(FPUBitmask, FPUTopSavedRegOff);
227 O << "," << FPUTopSavedRegOff << '\n';
228 }
229
230 // Print a 32 bit hex number with all numbers.
231 void MipsAsmPrinter::printHex32(unsigned Value, raw_ostream &O) {
232 O << "0x";
233 for (int i = 7; i >= 0; i--)
234 O.write_hex((Value & (0xF << (i*4))) >> (i*4));
235 } 303 }
236 304
237 //===----------------------------------------------------------------------===// 305 //===----------------------------------------------------------------------===//
238 // Frame and Set directives 306 // Frame and Set directives
239 //===----------------------------------------------------------------------===// 307 //===----------------------------------------------------------------------===//
240 308
241 /// Frame Directive 309 /// Frame Directive
242 void MipsAsmPrinter::emitFrameDirective() { 310 void MipsAsmPrinter::emitFrameDirective() {
243 const TargetRegisterInfo &RI = *TM.getRegisterInfo(); 311 const TargetRegisterInfo &RI = *TM.getSubtargetImpl()->getRegisterInfo();
244 312
245 unsigned stackReg = RI.getFrameRegister(*MF); 313 unsigned stackReg = RI.getFrameRegister(*MF);
246 unsigned returnReg = RI.getRARegister(); 314 unsigned returnReg = RI.getRARegister();
247 unsigned stackSize = MF->getFrameInfo()->getStackSize(); 315 unsigned stackSize = MF->getFrameInfo()->getStackSize();
248 316
249 if (OutStreamer.hasRawTextSupport()) 317 getTargetStreamer().emitFrame(stackReg, stackSize, returnReg);
250 OutStreamer.EmitRawText("\t.frame\t$" +
251 StringRef(MipsInstPrinter::getRegisterName(stackReg)).lower() +
252 "," + Twine(stackSize) + ",$" +
253 StringRef(MipsInstPrinter::getRegisterName(returnReg)).lower());
254 } 318 }
255 319
256 /// Emit Set directives. 320 /// Emit Set directives.
257 const char *MipsAsmPrinter::getCurrentABIString() const { 321 const char *MipsAsmPrinter::getCurrentABIString() const {
258 switch (Subtarget->getTargetABI()) { 322 switch (Subtarget->getTargetABI()) {
263 default: llvm_unreachable("Unknown Mips ABI"); 327 default: llvm_unreachable("Unknown Mips ABI");
264 } 328 }
265 } 329 }
266 330
267 void MipsAsmPrinter::EmitFunctionEntryLabel() { 331 void MipsAsmPrinter::EmitFunctionEntryLabel() {
268 if (OutStreamer.hasRawTextSupport()) { 332 MipsTargetStreamer &TS = getTargetStreamer();
269 if (Subtarget->inMips16Mode()) 333
270 OutStreamer.EmitRawText(StringRef("\t.set\tmips16")); 334 // NaCl sandboxing requires that indirect call instructions are masked.
271 else 335 // This means that function entry points should be bundle-aligned.
272 OutStreamer.EmitRawText(StringRef("\t.set\tnomips16")); 336 if (Subtarget->isTargetNaCl())
273 // leave out until FSF available gas has micromips changes 337 EmitAlignment(std::max(MF->getAlignment(), MIPS_NACL_BUNDLE_ALIGN));
274 // OutStreamer.EmitRawText(StringRef("\t.set\tnomicromips"));
275 OutStreamer.EmitRawText("\t.ent\t" + Twine(CurrentFnSym->getName()));
276 }
277 338
278 if (Subtarget->inMicroMipsMode()) 339 if (Subtarget->inMicroMipsMode())
279 getTargetStreamer().emitMipsHackSTOCG(CurrentFnSym, 340 TS.emitDirectiveSetMicroMips();
280 (unsigned)ELF::STO_MIPS_MICROMIPS); 341 else
342 TS.emitDirectiveSetNoMicroMips();
343
344 if (Subtarget->inMips16Mode())
345 TS.emitDirectiveSetMips16();
346 else
347 TS.emitDirectiveSetNoMips16();
348
349 TS.emitDirectiveEnt(*CurrentFnSym);
281 OutStreamer.EmitLabel(CurrentFnSym); 350 OutStreamer.EmitLabel(CurrentFnSym);
282 } 351 }
283 352
284 /// EmitFunctionBodyStart - Targets can override this to emit stuff before 353 /// EmitFunctionBodyStart - Targets can override this to emit stuff before
285 /// the first basic block in the function. 354 /// the first basic block in the function.
286 void MipsAsmPrinter::EmitFunctionBodyStart() { 355 void MipsAsmPrinter::EmitFunctionBodyStart() {
356 MipsTargetStreamer &TS = getTargetStreamer();
357
287 MCInstLowering.Initialize(&MF->getContext()); 358 MCInstLowering.Initialize(&MF->getContext());
288 359
289 bool IsNakedFunction = 360 bool IsNakedFunction =
290 MF->getFunction()-> 361 MF->getFunction()->
291 getAttributes().hasAttribute(AttributeSet::FunctionIndex, 362 getAttributes().hasAttribute(AttributeSet::FunctionIndex,
292 Attribute::Naked); 363 Attribute::Naked);
293 if (!IsNakedFunction) 364 if (!IsNakedFunction)
294 emitFrameDirective(); 365 emitFrameDirective();
295 366
296 if (OutStreamer.hasRawTextSupport()) { 367 if (!IsNakedFunction)
297 SmallString<128> Str; 368 printSavedRegsBitmask();
298 raw_svector_ostream OS(Str); 369
299 if (!IsNakedFunction) 370 if (!Subtarget->inMips16Mode()) {
300 printSavedRegsBitmask(OS); 371 TS.emitDirectiveSetNoReorder();
301 OutStreamer.EmitRawText(OS.str()); 372 TS.emitDirectiveSetNoMacro();
302 if (!Subtarget->inMips16Mode()) { 373 TS.emitDirectiveSetNoAt();
303 OutStreamer.EmitRawText(StringRef("\t.set\tnoreorder"));
304 OutStreamer.EmitRawText(StringRef("\t.set\tnomacro"));
305 OutStreamer.EmitRawText(StringRef("\t.set\tnoat"));
306 }
307 } 374 }
308 } 375 }
309 376
310 /// EmitFunctionBodyEnd - Targets can override this to emit stuff after 377 /// EmitFunctionBodyEnd - Targets can override this to emit stuff after
311 /// the last basic block in the function. 378 /// the last basic block in the function.
312 void MipsAsmPrinter::EmitFunctionBodyEnd() { 379 void MipsAsmPrinter::EmitFunctionBodyEnd() {
380 MipsTargetStreamer &TS = getTargetStreamer();
381
313 // There are instruction for this macros, but they must 382 // There are instruction for this macros, but they must
314 // always be at the function end, and we can't emit and 383 // always be at the function end, and we can't emit and
315 // break with BB logic. 384 // break with BB logic.
316 if (OutStreamer.hasRawTextSupport()) { 385 if (!Subtarget->inMips16Mode()) {
317 if (!Subtarget->inMips16Mode()) { 386 TS.emitDirectiveSetAt();
318 OutStreamer.EmitRawText(StringRef("\t.set\tat")); 387 TS.emitDirectiveSetMacro();
319 OutStreamer.EmitRawText(StringRef("\t.set\tmacro")); 388 TS.emitDirectiveSetReorder();
320 OutStreamer.EmitRawText(StringRef("\t.set\treorder")); 389 }
321 } 390 TS.emitDirectiveEnd(CurrentFnSym->getName());
322 OutStreamer.EmitRawText("\t.end\t" + Twine(CurrentFnSym->getName()));
323 }
324 // Make sure to terminate any constant pools that were at the end 391 // Make sure to terminate any constant pools that were at the end
325 // of the function. 392 // of the function.
326 if (!InConstantPool) 393 if (!InConstantPool)
327 return; 394 return;
328 InConstantPool = false; 395 InConstantPool = false;
493 return false; 560 return false;
494 } 561 }
495 562
496 void MipsAsmPrinter::printOperand(const MachineInstr *MI, int opNum, 563 void MipsAsmPrinter::printOperand(const MachineInstr *MI, int opNum,
497 raw_ostream &O) { 564 raw_ostream &O) {
565 const DataLayout *DL = TM.getSubtargetImpl()->getDataLayout();
498 const MachineOperand &MO = MI->getOperand(opNum); 566 const MachineOperand &MO = MI->getOperand(opNum);
499 bool closeP = false; 567 bool closeP = false;
500 568
501 if (MO.getTargetFlags()) 569 if (MO.getTargetFlags())
502 closeP = true; 570 closeP = true;
541 O << BA->getName(); 609 O << BA->getName();
542 break; 610 break;
543 } 611 }
544 612
545 case MachineOperand::MO_ConstantPoolIndex: 613 case MachineOperand::MO_ConstantPoolIndex:
546 O << MAI->getPrivateGlobalPrefix() << "CPI" 614 O << DL->getPrivateGlobalPrefix() << "CPI"
547 << getFunctionNumber() << "_" << MO.getIndex(); 615 << getFunctionNumber() << "_" << MO.getIndex();
548 if (MO.getOffset()) 616 if (MO.getOffset())
549 O << "+" << MO.getOffset(); 617 O << "+" << MO.getOffset();
550 break; 618 break;
551 619
601 const MachineOperand &MO = MI->getOperand(opNum); 669 const MachineOperand &MO = MI->getOperand(opNum);
602 O << Mips::MipsFCCToString((Mips::CondCode)MO.getImm()); 670 O << Mips::MipsFCCToString((Mips::CondCode)MO.getImm());
603 } 671 }
604 672
605 void MipsAsmPrinter::EmitStartOfAsmFile(Module &M) { 673 void MipsAsmPrinter::EmitStartOfAsmFile(Module &M) {
606 // FIXME: Use SwitchSection. 674 bool IsABICalls = Subtarget->isABICalls();
607 675 if (IsABICalls) {
608 // TODO: Need to add -mabicalls and -mno-abicalls flags. 676 getTargetStreamer().emitDirectiveAbiCalls();
609 // Currently we assume that -mabicalls is the default. 677 Reloc::Model RM = TM.getRelocationModel();
610 if (OutStreamer.hasRawTextSupport()) { 678 // FIXME: This condition should be a lot more complicated that it is here.
611 OutStreamer.EmitRawText(StringRef("\t.abicalls")); 679 // Ideally it should test for properties of the ABI and not the ABI
612 Reloc::Model RM = Subtarget->getRelocationModel(); 680 // itself.
613 if (RM == Reloc::Static && !Subtarget->hasMips64()) 681 // For the moment, I'm only correcting enough to make MIPS-IV work.
614 OutStreamer.EmitRawText(StringRef("\t.option\tpic0")); 682 if (RM == Reloc::Static && !Subtarget->isABI_N64())
683 getTargetStreamer().emitDirectiveOptionPic0();
615 } 684 }
616 685
617 // Tell the assembler which ABI we are using 686 // Tell the assembler which ABI we are using
618 if (OutStreamer.hasRawTextSupport()) 687 std::string SectionName = std::string(".mdebug.") + getCurrentABIString();
619 OutStreamer.EmitRawText("\t.section .mdebug." + 688 OutStreamer.SwitchSection(OutContext.getELFSection(
620 Twine(getCurrentABIString())); 689 SectionName, ELF::SHT_PROGBITS, 0, SectionKind::getDataRel()));
690
691 // NaN: At the moment we only support:
692 // 1. .nan legacy (default)
693 // 2. .nan 2008
694 Subtarget->isNaN2008() ? getTargetStreamer().emitDirectiveNaN2008()
695 : getTargetStreamer().emitDirectiveNaNLegacy();
621 696
622 // TODO: handle O64 ABI 697 // TODO: handle O64 ABI
623 if (OutStreamer.hasRawTextSupport()) { 698
624 if (Subtarget->isABI_EABI()) { 699 if (Subtarget->isABI_EABI()) {
625 if (Subtarget->isGP32bit()) 700 if (Subtarget->isGP32bit())
626 OutStreamer.EmitRawText(StringRef("\t.section .gcc_compiled_long32")); 701 OutStreamer.SwitchSection(
627 else 702 OutContext.getELFSection(".gcc_compiled_long32", ELF::SHT_PROGBITS, 0,
628 OutStreamer.EmitRawText(StringRef("\t.section .gcc_compiled_long64")); 703 SectionKind::getDataRel()));
629 } 704 else
630 } 705 OutStreamer.SwitchSection(
631 706 OutContext.getELFSection(".gcc_compiled_long64", ELF::SHT_PROGBITS, 0,
632 // return to previous section 707 SectionKind::getDataRel()));
633 if (OutStreamer.hasRawTextSupport()) 708 }
634 OutStreamer.EmitRawText(StringRef("\t.previous")); 709
635 710 getTargetStreamer().updateABIInfo(*Subtarget);
636 } 711
637 712 // We should always emit a '.module fp=...' but binutils 2.24 does not accept
638 static void emitELFHeaderFlagsCG(MipsTargetStreamer &TargetStreamer, 713 // it. We therefore emit it when it contradicts the ABI defaults (-mfpxx or
639 const MipsSubtarget &Subtarget) { 714 // -mfp64) and omit it otherwise.
640 // Update e_header flags 715 if (Subtarget->isABI_O32() && (Subtarget->isABI_FPXX() ||
641 unsigned EFlags = 0; 716 Subtarget->isFP64bit()))
642 717 getTargetStreamer().emitDirectiveModuleFP();
643 // TODO: Need to add -mabicalls and -mno-abicalls flags. 718
644 // Currently we assume that -mabicalls is the default. 719 // We should always emit a '.module [no]oddspreg' but binutils 2.24 does not
645 EFlags |= ELF::EF_MIPS_CPIC; 720 // accept it. We therefore emit it when it contradicts the default or an
646 721 // option has changed the default (i.e. FPXX) and omit it otherwise.
647 if (Subtarget.inMips16Mode()) 722 if (Subtarget->isABI_O32() && (!Subtarget->useOddSPReg() ||
648 EFlags |= ELF::EF_MIPS_ARCH_ASE_M16; 723 Subtarget->isABI_FPXX()))
649 else 724 getTargetStreamer().emitDirectiveModuleOddSPReg(Subtarget->useOddSPReg(),
650 EFlags |= ELF::EF_MIPS_NOREORDER; 725 Subtarget->isABI_O32());
651 726 }
652 // Architecture 727
653 if (Subtarget.hasMips64r2()) 728 void MipsAsmPrinter::EmitJal(MCSymbol *Symbol) {
654 EFlags |= ELF::EF_MIPS_ARCH_64R2; 729 MCInst I;
655 else if (Subtarget.hasMips64()) 730 I.setOpcode(Mips::JAL);
656 EFlags |= ELF::EF_MIPS_ARCH_64; 731 I.addOperand(
657 else if (Subtarget.hasMips32r2()) 732 MCOperand::CreateExpr(MCSymbolRefExpr::Create(Symbol, OutContext)));
658 EFlags |= ELF::EF_MIPS_ARCH_32R2; 733 OutStreamer.EmitInstruction(I, getSubtargetInfo());
659 else 734 }
660 EFlags |= ELF::EF_MIPS_ARCH_32; 735
661 736 void MipsAsmPrinter::EmitInstrReg(unsigned Opcode, unsigned Reg) {
662 if (Subtarget.inMicroMipsMode()) 737 MCInst I;
663 EFlags |= ELF::EF_MIPS_MICROMIPS; 738 I.setOpcode(Opcode);
664 739 I.addOperand(MCOperand::CreateReg(Reg));
665 // ABI 740 OutStreamer.EmitInstruction(I, getSubtargetInfo());
666 if (Subtarget.isABI_O32()) 741 }
667 EFlags |= ELF::EF_MIPS_ABI_O32; 742
668 743 void MipsAsmPrinter::EmitInstrRegReg(unsigned Opcode, unsigned Reg1,
669 // Relocation Model 744 unsigned Reg2) {
670 Reloc::Model RM = Subtarget.getRelocationModel(); 745 MCInst I;
671 if (RM == Reloc::PIC_ || RM == Reloc::Default) 746 //
672 EFlags |= ELF::EF_MIPS_PIC; 747 // Because of the current td files for Mips32, the operands for MTC1
673 else if (RM == Reloc::Static) 748 // appear backwards from their normal assembly order. It's not a trivial
674 ; // Do nothing for Reloc::Static 749 // change to fix this in the td file so we adjust for it here.
675 else 750 //
676 llvm_unreachable("Unsupported relocation model for e_flags"); 751 if (Opcode == Mips::MTC1) {
677 752 unsigned Temp = Reg1;
678 TargetStreamer.emitMipsHackELFFlags(EFlags); 753 Reg1 = Reg2;
754 Reg2 = Temp;
755 }
756 I.setOpcode(Opcode);
757 I.addOperand(MCOperand::CreateReg(Reg1));
758 I.addOperand(MCOperand::CreateReg(Reg2));
759 OutStreamer.EmitInstruction(I, getSubtargetInfo());
760 }
761
762 void MipsAsmPrinter::EmitInstrRegRegReg(unsigned Opcode, unsigned Reg1,
763 unsigned Reg2, unsigned Reg3) {
764 MCInst I;
765 I.setOpcode(Opcode);
766 I.addOperand(MCOperand::CreateReg(Reg1));
767 I.addOperand(MCOperand::CreateReg(Reg2));
768 I.addOperand(MCOperand::CreateReg(Reg3));
769 OutStreamer.EmitInstruction(I, getSubtargetInfo());
770 }
771
772 void MipsAsmPrinter::EmitMovFPIntPair(unsigned MovOpc, unsigned Reg1,
773 unsigned Reg2, unsigned FPReg1,
774 unsigned FPReg2, bool LE) {
775 if (!LE) {
776 unsigned temp = Reg1;
777 Reg1 = Reg2;
778 Reg2 = temp;
779 }
780 EmitInstrRegReg(MovOpc, Reg1, FPReg1);
781 EmitInstrRegReg(MovOpc, Reg2, FPReg2);
782 }
783
784 void MipsAsmPrinter::EmitSwapFPIntParams(Mips16HardFloatInfo::FPParamVariant PV,
785 bool LE, bool ToFP) {
786 using namespace Mips16HardFloatInfo;
787 unsigned MovOpc = ToFP ? Mips::MTC1 : Mips::MFC1;
788 switch (PV) {
789 case FSig:
790 EmitInstrRegReg(MovOpc, Mips::A0, Mips::F12);
791 break;
792 case FFSig:
793 EmitMovFPIntPair(MovOpc, Mips::A0, Mips::A1, Mips::F12, Mips::F14, LE);
794 break;
795 case FDSig:
796 EmitInstrRegReg(MovOpc, Mips::A0, Mips::F12);
797 EmitMovFPIntPair(MovOpc, Mips::A2, Mips::A3, Mips::F14, Mips::F15, LE);
798 break;
799 case DSig:
800 EmitMovFPIntPair(MovOpc, Mips::A0, Mips::A1, Mips::F12, Mips::F13, LE);
801 break;
802 case DDSig:
803 EmitMovFPIntPair(MovOpc, Mips::A0, Mips::A1, Mips::F12, Mips::F13, LE);
804 EmitMovFPIntPair(MovOpc, Mips::A2, Mips::A3, Mips::F14, Mips::F15, LE);
805 break;
806 case DFSig:
807 EmitMovFPIntPair(MovOpc, Mips::A0, Mips::A1, Mips::F12, Mips::F13, LE);
808 EmitInstrRegReg(MovOpc, Mips::A2, Mips::F14);
809 break;
810 case NoSig:
811 return;
812 }
813 }
814
815 void
816 MipsAsmPrinter::EmitSwapFPIntRetval(Mips16HardFloatInfo::FPReturnVariant RV,
817 bool LE) {
818 using namespace Mips16HardFloatInfo;
819 unsigned MovOpc = Mips::MFC1;
820 switch (RV) {
821 case FRet:
822 EmitInstrRegReg(MovOpc, Mips::V0, Mips::F0);
823 break;
824 case DRet:
825 EmitMovFPIntPair(MovOpc, Mips::V0, Mips::V1, Mips::F0, Mips::F1, LE);
826 break;
827 case CFRet:
828 EmitMovFPIntPair(MovOpc, Mips::V0, Mips::V1, Mips::F0, Mips::F1, LE);
829 break;
830 case CDRet:
831 EmitMovFPIntPair(MovOpc, Mips::V0, Mips::V1, Mips::F0, Mips::F1, LE);
832 EmitMovFPIntPair(MovOpc, Mips::A0, Mips::A1, Mips::F2, Mips::F3, LE);
833 break;
834 case NoFPRet:
835 break;
836 }
837 }
838
839 void MipsAsmPrinter::EmitFPCallStub(
840 const char *Symbol, const Mips16HardFloatInfo::FuncSignature *Signature) {
841 MCSymbol *MSymbol = OutContext.GetOrCreateSymbol(StringRef(Symbol));
842 using namespace Mips16HardFloatInfo;
843 bool LE = Subtarget->isLittle();
844 //
845 // .global xxxx
846 //
847 OutStreamer.EmitSymbolAttribute(MSymbol, MCSA_Global);
848 const char *RetType;
849 //
850 // make the comment field identifying the return and parameter
851 // types of the floating point stub
852 // # Stub function to call rettype xxxx (params)
853 //
854 switch (Signature->RetSig) {
855 case FRet:
856 RetType = "float";
857 break;
858 case DRet:
859 RetType = "double";
860 break;
861 case CFRet:
862 RetType = "complex";
863 break;
864 case CDRet:
865 RetType = "double complex";
866 break;
867 case NoFPRet:
868 RetType = "";
869 break;
870 }
871 const char *Parms;
872 switch (Signature->ParamSig) {
873 case FSig:
874 Parms = "float";
875 break;
876 case FFSig:
877 Parms = "float, float";
878 break;
879 case FDSig:
880 Parms = "float, double";
881 break;
882 case DSig:
883 Parms = "double";
884 break;
885 case DDSig:
886 Parms = "double, double";
887 break;
888 case DFSig:
889 Parms = "double, float";
890 break;
891 case NoSig:
892 Parms = "";
893 break;
894 }
895 OutStreamer.AddComment("\t# Stub function to call " + Twine(RetType) + " " +
896 Twine(Symbol) + " (" + Twine(Parms) + ")");
897 //
898 // probably not necessary but we save and restore the current section state
899 //
900 OutStreamer.PushSection();
901 //
902 // .section mips16.call.fpxxxx,"ax",@progbits
903 //
904 const MCSectionELF *M = OutContext.getELFSection(
905 ".mips16.call.fp." + std::string(Symbol), ELF::SHT_PROGBITS,
906 ELF::SHF_ALLOC | ELF::SHF_EXECINSTR, SectionKind::getText());
907 OutStreamer.SwitchSection(M, nullptr);
908 //
909 // .align 2
910 //
911 OutStreamer.EmitValueToAlignment(4);
912 MipsTargetStreamer &TS = getTargetStreamer();
913 //
914 // .set nomips16
915 // .set nomicromips
916 //
917 TS.emitDirectiveSetNoMips16();
918 TS.emitDirectiveSetNoMicroMips();
919 //
920 // .ent __call_stub_fp_xxxx
921 // .type __call_stub_fp_xxxx,@function
922 // __call_stub_fp_xxxx:
923 //
924 std::string x = "__call_stub_fp_" + std::string(Symbol);
925 MCSymbol *Stub = OutContext.GetOrCreateSymbol(StringRef(x));
926 TS.emitDirectiveEnt(*Stub);
927 MCSymbol *MType =
928 OutContext.GetOrCreateSymbol("__call_stub_fp_" + Twine(Symbol));
929 OutStreamer.EmitSymbolAttribute(MType, MCSA_ELF_TypeFunction);
930 OutStreamer.EmitLabel(Stub);
931 //
932 // we just handle non pic for now. these function will not be
933 // called otherwise. when the full stub generation is moved here
934 // we need to deal with pic.
935 //
936 if (Subtarget->getRelocationModel() == Reloc::PIC_)
937 llvm_unreachable("should not be here if we are compiling pic");
938 TS.emitDirectiveSetReorder();
939 //
940 // We need to add a MipsMCExpr class to MCTargetDesc to fully implement
941 // stubs without raw text but this current patch is for compiler generated
942 // functions and they all return some value.
943 // The calling sequence for non pic is different in that case and we need
944 // to implement %lo and %hi in order to handle the case of no return value
945 // See the corresponding method in Mips16HardFloat for details.
946 //
947 // mov the return address to S2.
948 // we have no stack space to store it and we are about to make another call.
949 // We need to make sure that the enclosing function knows to save S2
950 // This should have already been handled.
951 //
952 // Mov $18, $31
953
954 EmitInstrRegRegReg(Mips::ADDu, Mips::S2, Mips::RA, Mips::ZERO);
955
956 EmitSwapFPIntParams(Signature->ParamSig, LE, true);
957
958 // Jal xxxx
959 //
960 EmitJal(MSymbol);
961
962 // fix return values
963 EmitSwapFPIntRetval(Signature->RetSig, LE);
964 //
965 // do the return
966 // if (Signature->RetSig == NoFPRet)
967 // llvm_unreachable("should not be any stubs here with no return value");
968 // else
969 EmitInstrReg(Mips::JR, Mips::S2);
970
971 MCSymbol *Tmp = OutContext.CreateTempSymbol();
972 OutStreamer.EmitLabel(Tmp);
973 const MCSymbolRefExpr *E = MCSymbolRefExpr::Create(Stub, OutContext);
974 const MCSymbolRefExpr *T = MCSymbolRefExpr::Create(Tmp, OutContext);
975 const MCExpr *T_min_E = MCBinaryExpr::CreateSub(T, E, OutContext);
976 OutStreamer.EmitELFSize(Stub, T_min_E);
977 TS.emitDirectiveEnd(x);
978 OutStreamer.PopSection();
679 } 979 }
680 980
681 void MipsAsmPrinter::EmitEndOfAsmFile(Module &M) { 981 void MipsAsmPrinter::EmitEndOfAsmFile(Module &M) {
682 // Emit Mips ELF register info 982 // Emit needed stubs
683 Subtarget->getMReginfo().emitMipsReginfoSectionCG( 983 //
684 OutStreamer, getObjFileLowering(), *Subtarget); 984 for (std::map<
685 emitELFHeaderFlagsCG(getTargetStreamer(), *Subtarget); 985 const char *,
986 const llvm::Mips16HardFloatInfo::FuncSignature *>::const_iterator
987 it = StubsNeeded.begin();
988 it != StubsNeeded.end(); ++it) {
989 const char *Symbol = it->first;
990 const llvm::Mips16HardFloatInfo::FuncSignature *Signature = it->second;
991 EmitFPCallStub(Symbol, Signature);
992 }
993 // return to the text section
994 OutStreamer.SwitchSection(OutContext.getObjectFileInfo()->getTextSection());
686 } 995 }
687 996
688 void MipsAsmPrinter::PrintDebugValueComment(const MachineInstr *MI, 997 void MipsAsmPrinter::PrintDebugValueComment(const MachineInstr *MI,
689 raw_ostream &OS) { 998 raw_ostream &OS) {
690 // TODO: implement 999 // TODO: implement
1000 }
1001
1002 // Align all targets of indirect branches on bundle size. Used only if target
1003 // is NaCl.
1004 void MipsAsmPrinter::NaClAlignIndirectJumpTargets(MachineFunction &MF) {
1005 // Align all blocks that are jumped to through jump table.
1006 if (MachineJumpTableInfo *JtInfo = MF.getJumpTableInfo()) {
1007 const std::vector<MachineJumpTableEntry> &JT = JtInfo->getJumpTables();
1008 for (unsigned I = 0; I < JT.size(); ++I) {
1009 const std::vector<MachineBasicBlock*> &MBBs = JT[I].MBBs;
1010
1011 for (unsigned J = 0; J < MBBs.size(); ++J)
1012 MBBs[J]->setAlignment(MIPS_NACL_BUNDLE_ALIGN);
1013 }
1014 }
1015
1016 // If basic block address is taken, block can be target of indirect branch.
1017 for (MachineFunction::iterator MBB = MF.begin(), E = MF.end();
1018 MBB != E; ++MBB) {
1019 if (MBB->hasAddressTaken())
1020 MBB->setAlignment(MIPS_NACL_BUNDLE_ALIGN);
1021 }
1022 }
1023
1024 bool MipsAsmPrinter::isLongBranchPseudo(int Opcode) const {
1025 return (Opcode == Mips::LONG_BRANCH_LUi
1026 || Opcode == Mips::LONG_BRANCH_ADDiu
1027 || Opcode == Mips::LONG_BRANCH_DADDiu);
691 } 1028 }
692 1029
693 // Force static initialization. 1030 // Force static initialization.
694 extern "C" void LLVMInitializeMipsAsmPrinter() { 1031 extern "C" void LLVMInitializeMipsAsmPrinter() {
695 RegisterAsmPrinter<MipsAsmPrinter> X(TheMipsTarget); 1032 RegisterAsmPrinter<MipsAsmPrinter> X(TheMipsTarget);