Mercurial > hg > CbC > CbC_llvm
comparison lib/Target/Mips/MipsAsmPrinter.cpp @ 95:afa8332a0e37 LLVM3.8
LLVM 3.8
author | Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp> |
---|---|
date | Tue, 13 Oct 2015 17:48:58 +0900 |
parents | 60c9769439b8 |
children | 7d135dc70f03 |
comparison
equal
deleted
inserted
replaced
84:f3e34b893a5f | 95:afa8332a0e37 |
---|---|
20 #include "MipsInstrInfo.h" | 20 #include "MipsInstrInfo.h" |
21 #include "MipsMCInstLower.h" | 21 #include "MipsMCInstLower.h" |
22 #include "MipsTargetMachine.h" | 22 #include "MipsTargetMachine.h" |
23 #include "MipsTargetStreamer.h" | 23 #include "MipsTargetStreamer.h" |
24 #include "llvm/ADT/SmallString.h" | 24 #include "llvm/ADT/SmallString.h" |
25 #include "llvm/ADT/StringExtras.h" | |
26 #include "llvm/ADT/Twine.h" | 25 #include "llvm/ADT/Twine.h" |
27 #include "llvm/CodeGen/MachineConstantPool.h" | 26 #include "llvm/CodeGen/MachineConstantPool.h" |
28 #include "llvm/CodeGen/MachineFrameInfo.h" | 27 #include "llvm/CodeGen/MachineFrameInfo.h" |
29 #include "llvm/CodeGen/MachineFunctionPass.h" | 28 #include "llvm/CodeGen/MachineFunctionPass.h" |
30 #include "llvm/CodeGen/MachineInstr.h" | 29 #include "llvm/CodeGen/MachineInstr.h" |
40 #include "llvm/MC/MCELFStreamer.h" | 39 #include "llvm/MC/MCELFStreamer.h" |
41 #include "llvm/MC/MCExpr.h" | 40 #include "llvm/MC/MCExpr.h" |
42 #include "llvm/MC/MCInst.h" | 41 #include "llvm/MC/MCInst.h" |
43 #include "llvm/MC/MCSection.h" | 42 #include "llvm/MC/MCSection.h" |
44 #include "llvm/MC/MCSectionELF.h" | 43 #include "llvm/MC/MCSectionELF.h" |
45 #include "llvm/MC/MCSymbol.h" | 44 #include "llvm/MC/MCSymbolELF.h" |
46 #include "llvm/Support/ELF.h" | 45 #include "llvm/Support/ELF.h" |
47 #include "llvm/Support/TargetRegistry.h" | 46 #include "llvm/Support/TargetRegistry.h" |
48 #include "llvm/Support/raw_ostream.h" | 47 #include "llvm/Support/raw_ostream.h" |
49 #include "llvm/Target/TargetLoweringObjectFile.h" | 48 #include "llvm/Target/TargetLoweringObjectFile.h" |
50 #include "llvm/Target/TargetOptions.h" | 49 #include "llvm/Target/TargetOptions.h" |
53 using namespace llvm; | 52 using namespace llvm; |
54 | 53 |
55 #define DEBUG_TYPE "mips-asm-printer" | 54 #define DEBUG_TYPE "mips-asm-printer" |
56 | 55 |
57 MipsTargetStreamer &MipsAsmPrinter::getTargetStreamer() const { | 56 MipsTargetStreamer &MipsAsmPrinter::getTargetStreamer() const { |
58 return static_cast<MipsTargetStreamer &>(*OutStreamer.getTargetStreamer()); | 57 return static_cast<MipsTargetStreamer &>(*OutStreamer->getTargetStreamer()); |
59 } | 58 } |
60 | 59 |
61 bool MipsAsmPrinter::runOnMachineFunction(MachineFunction &MF) { | 60 bool MipsAsmPrinter::runOnMachineFunction(MachineFunction &MF) { |
62 Subtarget = &TM.getSubtarget<MipsSubtarget>(); | 61 Subtarget = &MF.getSubtarget<MipsSubtarget>(); |
63 | 62 |
64 // Initialize TargetLoweringObjectFile. | 63 // Initialize TargetLoweringObjectFile. |
65 const_cast<TargetLoweringObjectFile &>(getObjFileLowering()) | 64 const_cast<TargetLoweringObjectFile &>(getObjFileLowering()) |
66 .Initialize(OutContext, TM); | 65 .Initialize(OutContext, TM); |
67 | 66 |
119 | 118 |
120 MCOperand MCOp; | 119 MCOperand MCOp; |
121 | 120 |
122 if (HasLinkReg) { | 121 if (HasLinkReg) { |
123 unsigned ZeroReg = Subtarget->isGP64bit() ? Mips::ZERO_64 : Mips::ZERO; | 122 unsigned ZeroReg = Subtarget->isGP64bit() ? Mips::ZERO_64 : Mips::ZERO; |
124 TmpInst0.addOperand(MCOperand::CreateReg(ZeroReg)); | 123 TmpInst0.addOperand(MCOperand::createReg(ZeroReg)); |
125 } | 124 } |
126 | 125 |
127 lowerOperand(MI->getOperand(0), MCOp); | 126 lowerOperand(MI->getOperand(0), MCOp); |
128 TmpInst0.addOperand(MCOp); | 127 TmpInst0.addOperand(MCOp); |
129 | 128 |
142 return; | 141 return; |
143 } | 142 } |
144 | 143 |
145 // If we just ended a constant pool, mark it as such. | 144 // If we just ended a constant pool, mark it as such. |
146 if (InConstantPool && MI->getOpcode() != Mips::CONSTPOOL_ENTRY) { | 145 if (InConstantPool && MI->getOpcode() != Mips::CONSTPOOL_ENTRY) { |
147 OutStreamer.EmitDataRegion(MCDR_DataRegionEnd); | 146 OutStreamer->EmitDataRegion(MCDR_DataRegionEnd); |
148 InConstantPool = false; | 147 InConstantPool = false; |
149 } | 148 } |
150 if (MI->getOpcode() == Mips::CONSTPOOL_ENTRY) { | 149 if (MI->getOpcode() == Mips::CONSTPOOL_ENTRY) { |
151 // CONSTPOOL_ENTRY - This instruction represents a floating | 150 // CONSTPOOL_ENTRY - This instruction represents a floating |
152 //constant pool in the function. The first operand is the ID# | 151 //constant pool in the function. The first operand is the ID# |
158 unsigned LabelId = (unsigned)MI->getOperand(0).getImm(); | 157 unsigned LabelId = (unsigned)MI->getOperand(0).getImm(); |
159 unsigned CPIdx = (unsigned)MI->getOperand(1).getIndex(); | 158 unsigned CPIdx = (unsigned)MI->getOperand(1).getIndex(); |
160 | 159 |
161 // If this is the first entry of the pool, mark it. | 160 // If this is the first entry of the pool, mark it. |
162 if (!InConstantPool) { | 161 if (!InConstantPool) { |
163 OutStreamer.EmitDataRegion(MCDR_DataRegion); | 162 OutStreamer->EmitDataRegion(MCDR_DataRegion); |
164 InConstantPool = true; | 163 InConstantPool = true; |
165 } | 164 } |
166 | 165 |
167 OutStreamer.EmitLabel(GetCPISymbol(LabelId)); | 166 OutStreamer->EmitLabel(GetCPISymbol(LabelId)); |
168 | 167 |
169 const MachineConstantPoolEntry &MCPE = MCP->getConstants()[CPIdx]; | 168 const MachineConstantPoolEntry &MCPE = MCP->getConstants()[CPIdx]; |
170 if (MCPE.isMachineConstantPoolEntry()) | 169 if (MCPE.isMachineConstantPoolEntry()) |
171 EmitMachineConstantPoolValue(MCPE.Val.MachineCPVal); | 170 EmitMachineConstantPoolValue(MCPE.Val.MachineCPVal); |
172 else | 171 else |
173 EmitGlobalConstant(MCPE.Val.ConstVal); | 172 EmitGlobalConstant(MF->getDataLayout(), MCPE.Val.ConstVal); |
174 return; | 173 return; |
175 } | 174 } |
176 | 175 |
177 | 176 |
178 MachineBasicBlock::const_instr_iterator I = MI; | 177 MachineBasicBlock::const_instr_iterator I = MI; |
179 MachineBasicBlock::const_instr_iterator E = MI->getParent()->instr_end(); | 178 MachineBasicBlock::const_instr_iterator E = MI->getParent()->instr_end(); |
180 | 179 |
181 do { | 180 do { |
182 // Do any auto-generated pseudo lowerings. | 181 // Do any auto-generated pseudo lowerings. |
183 if (emitPseudoExpansionLowering(OutStreamer, &*I)) | 182 if (emitPseudoExpansionLowering(*OutStreamer, &*I)) |
184 continue; | 183 continue; |
185 | 184 |
186 if (I->getOpcode() == Mips::PseudoReturn || | 185 if (I->getOpcode() == Mips::PseudoReturn || |
187 I->getOpcode() == Mips::PseudoReturn64 || | 186 I->getOpcode() == Mips::PseudoReturn64 || |
188 I->getOpcode() == Mips::PseudoIndirectBranch || | 187 I->getOpcode() == Mips::PseudoIndirectBranch || |
189 I->getOpcode() == Mips::PseudoIndirectBranch64) { | 188 I->getOpcode() == Mips::PseudoIndirectBranch64) { |
190 emitPseudoIndirectBranch(OutStreamer, &*I); | 189 emitPseudoIndirectBranch(*OutStreamer, &*I); |
191 continue; | 190 continue; |
192 } | 191 } |
193 | 192 |
194 // The inMips16Mode() test is not permanent. | 193 // The inMips16Mode() test is not permanent. |
195 // Some instructions are marked as pseudo right now which | 194 // Some instructions are marked as pseudo right now which |
202 && !isLongBranchPseudo(I->getOpcode())) | 201 && !isLongBranchPseudo(I->getOpcode())) |
203 llvm_unreachable("Pseudo opcode found in EmitInstruction()"); | 202 llvm_unreachable("Pseudo opcode found in EmitInstruction()"); |
204 | 203 |
205 MCInst TmpInst0; | 204 MCInst TmpInst0; |
206 MCInstLowering.Lower(I, TmpInst0); | 205 MCInstLowering.Lower(I, TmpInst0); |
207 EmitToStreamer(OutStreamer, TmpInst0); | 206 EmitToStreamer(*OutStreamer, TmpInst0); |
208 } while ((++I != E) && I->isInsideBundle()); // Delay slot check | 207 } while ((++I != E) && I->isInsideBundle()); // Delay slot check |
209 } | 208 } |
210 | 209 |
211 //===----------------------------------------------------------------------===// | 210 //===----------------------------------------------------------------------===// |
212 // | 211 // |
250 unsigned CPUBitmask = 0, FPUBitmask = 0; | 249 unsigned CPUBitmask = 0, FPUBitmask = 0; |
251 int CPUTopSavedRegOff, FPUTopSavedRegOff; | 250 int CPUTopSavedRegOff, FPUTopSavedRegOff; |
252 | 251 |
253 // Set the CPU and FPU Bitmasks | 252 // Set the CPU and FPU Bitmasks |
254 const MachineFrameInfo *MFI = MF->getFrameInfo(); | 253 const MachineFrameInfo *MFI = MF->getFrameInfo(); |
254 const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo(); | |
255 const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo(); | 255 const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo(); |
256 // size of stack area to which FP callee-saved regs are saved. | 256 // size of stack area to which FP callee-saved regs are saved. |
257 unsigned CPURegSize = Mips::GPR32RegClass.getSize(); | 257 unsigned CPURegSize = Mips::GPR32RegClass.getSize(); |
258 unsigned FGR32RegSize = Mips::FGR32RegClass.getSize(); | 258 unsigned FGR32RegSize = Mips::FGR32RegClass.getSize(); |
259 unsigned AFGR64RegSize = Mips::AFGR64RegClass.getSize(); | 259 unsigned AFGR64RegSize = Mips::AFGR64RegClass.getSize(); |
260 bool HasAFGR64Reg = false; | 260 bool HasAFGR64Reg = false; |
261 unsigned CSFPRegsSize = 0; | 261 unsigned CSFPRegsSize = 0; |
262 unsigned i, e = CSI.size(); | 262 |
263 | 263 for (const auto &I : CSI) { |
264 // Set FPU Bitmask. | 264 unsigned Reg = I.getReg(); |
265 for (i = 0; i != e; ++i) { | 265 unsigned RegNum = TRI->getEncodingValue(Reg); |
266 unsigned Reg = CSI[i].getReg(); | 266 |
267 if (Mips::GPR32RegClass.contains(Reg)) | 267 // If it's a floating point register, set the FPU Bitmask. |
268 break; | 268 // If it's a general purpose register, set the CPU Bitmask. |
269 | 269 if (Mips::FGR32RegClass.contains(Reg)) { |
270 unsigned RegNum = | 270 FPUBitmask |= (1 << RegNum); |
271 TM.getSubtargetImpl()->getRegisterInfo()->getEncodingValue(Reg); | 271 CSFPRegsSize += FGR32RegSize; |
272 if (Mips::AFGR64RegClass.contains(Reg)) { | 272 } else if (Mips::AFGR64RegClass.contains(Reg)) { |
273 FPUBitmask |= (3 << RegNum); | 273 FPUBitmask |= (3 << RegNum); |
274 CSFPRegsSize += AFGR64RegSize; | 274 CSFPRegsSize += AFGR64RegSize; |
275 HasAFGR64Reg = true; | 275 HasAFGR64Reg = true; |
276 continue; | 276 } else if (Mips::GPR32RegClass.contains(Reg)) |
277 } | 277 CPUBitmask |= (1 << RegNum); |
278 | |
279 FPUBitmask |= (1 << RegNum); | |
280 CSFPRegsSize += FGR32RegSize; | |
281 } | |
282 | |
283 // Set CPU Bitmask. | |
284 for (; i != e; ++i) { | |
285 unsigned Reg = CSI[i].getReg(); | |
286 unsigned RegNum = | |
287 TM.getSubtargetImpl()->getRegisterInfo()->getEncodingValue(Reg); | |
288 CPUBitmask |= (1 << RegNum); | |
289 } | 278 } |
290 | 279 |
291 // FP Regs are saved right below where the virtual frame pointer points to. | 280 // FP Regs are saved right below where the virtual frame pointer points to. |
292 FPUTopSavedRegOff = FPUBitmask ? | 281 FPUTopSavedRegOff = FPUBitmask ? |
293 (HasAFGR64Reg ? -AFGR64RegSize : -FGR32RegSize) : 0; | 282 (HasAFGR64Reg ? -AFGR64RegSize : -FGR32RegSize) : 0; |
307 // Frame and Set directives | 296 // Frame and Set directives |
308 //===----------------------------------------------------------------------===// | 297 //===----------------------------------------------------------------------===// |
309 | 298 |
310 /// Frame Directive | 299 /// Frame Directive |
311 void MipsAsmPrinter::emitFrameDirective() { | 300 void MipsAsmPrinter::emitFrameDirective() { |
312 const TargetRegisterInfo &RI = *TM.getSubtargetImpl()->getRegisterInfo(); | 301 const TargetRegisterInfo &RI = *MF->getSubtarget().getRegisterInfo(); |
313 | 302 |
314 unsigned stackReg = RI.getFrameRegister(*MF); | 303 unsigned stackReg = RI.getFrameRegister(*MF); |
315 unsigned returnReg = RI.getRARegister(); | 304 unsigned returnReg = RI.getRARegister(); |
316 unsigned stackSize = MF->getFrameInfo()->getStackSize(); | 305 unsigned stackSize = MF->getFrameInfo()->getStackSize(); |
317 | 306 |
346 TS.emitDirectiveSetMips16(); | 335 TS.emitDirectiveSetMips16(); |
347 else | 336 else |
348 TS.emitDirectiveSetNoMips16(); | 337 TS.emitDirectiveSetNoMips16(); |
349 | 338 |
350 TS.emitDirectiveEnt(*CurrentFnSym); | 339 TS.emitDirectiveEnt(*CurrentFnSym); |
351 OutStreamer.EmitLabel(CurrentFnSym); | 340 OutStreamer->EmitLabel(CurrentFnSym); |
352 } | 341 } |
353 | 342 |
354 /// EmitFunctionBodyStart - Targets can override this to emit stuff before | 343 /// EmitFunctionBodyStart - Targets can override this to emit stuff before |
355 /// the first basic block in the function. | 344 /// the first basic block in the function. |
356 void MipsAsmPrinter::EmitFunctionBodyStart() { | 345 void MipsAsmPrinter::EmitFunctionBodyStart() { |
389 // Make sure to terminate any constant pools that were at the end | 378 // Make sure to terminate any constant pools that were at the end |
390 // of the function. | 379 // of the function. |
391 if (!InConstantPool) | 380 if (!InConstantPool) |
392 return; | 381 return; |
393 InConstantPool = false; | 382 InConstantPool = false; |
394 OutStreamer.EmitDataRegion(MCDR_DataRegionEnd); | 383 OutStreamer->EmitDataRegion(MCDR_DataRegionEnd); |
384 } | |
385 | |
386 void MipsAsmPrinter::EmitBasicBlockEnd(const MachineBasicBlock &MBB) { | |
387 MipsTargetStreamer &TS = getTargetStreamer(); | |
388 if (MBB.size() == 0) | |
389 TS.emitDirectiveInsn(); | |
395 } | 390 } |
396 | 391 |
397 /// isBlockOnlyReachableByFallthough - Return true if the basic block has | 392 /// isBlockOnlyReachableByFallthough - Return true if the basic block has |
398 /// exactly one predecessor and the control transfer mechanism between | 393 /// exactly one predecessor and the control transfer mechanism between |
399 /// the predecessor and this block is a fall-through. | 394 /// the predecessor and this block is a fall-through. |
408 if (isa<SwitchInst>(bb->getTerminator())) | 403 if (isa<SwitchInst>(bb->getTerminator())) |
409 return false; | 404 return false; |
410 | 405 |
411 // If this is a landing pad, it isn't a fall through. If it has no preds, | 406 // If this is a landing pad, it isn't a fall through. If it has no preds, |
412 // then nothing falls through to it. | 407 // then nothing falls through to it. |
413 if (MBB->isLandingPad() || MBB->pred_empty()) | 408 if (MBB->isEHPad() || MBB->pred_empty()) |
414 return false; | 409 return false; |
415 | 410 |
416 // If there isn't exactly one predecessor, it can't be a fall through. | 411 // If there isn't exactly one predecessor, it can't be a fall through. |
417 MachineBasicBlock::const_pred_iterator PI = MBB->pred_begin(), PI2 = PI; | 412 MachineBasicBlock::const_pred_iterator PI = MBB->pred_begin(), PI2 = PI; |
418 ++PI2; | 413 ++PI2; |
436 return !I->isBarrier(); | 431 return !I->isBarrier(); |
437 } | 432 } |
438 | 433 |
439 // Print out an operand for an inline asm expression. | 434 // Print out an operand for an inline asm expression. |
440 bool MipsAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNum, | 435 bool MipsAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNum, |
441 unsigned AsmVariant,const char *ExtraCode, | 436 unsigned AsmVariant, const char *ExtraCode, |
442 raw_ostream &O) { | 437 raw_ostream &O) { |
443 // Does this asm operand have a single letter operand modifier? | 438 // Does this asm operand have a single letter operand modifier? |
444 if (ExtraCode && ExtraCode[0]) { | 439 if (ExtraCode && ExtraCode[0]) { |
445 if (ExtraCode[1] != 0) return true; // Unknown modifier. | 440 if (ExtraCode[1] != 0) return true; // Unknown modifier. |
446 | 441 |
450 // See if this is a generic print operand | 445 // See if this is a generic print operand |
451 return AsmPrinter::PrintAsmOperand(MI,OpNum,AsmVariant,ExtraCode,O); | 446 return AsmPrinter::PrintAsmOperand(MI,OpNum,AsmVariant,ExtraCode,O); |
452 case 'X': // hex const int | 447 case 'X': // hex const int |
453 if ((MO.getType()) != MachineOperand::MO_Immediate) | 448 if ((MO.getType()) != MachineOperand::MO_Immediate) |
454 return true; | 449 return true; |
455 O << "0x" << StringRef(utohexstr(MO.getImm())).lower(); | 450 O << "0x" << Twine::utohexstr(MO.getImm()); |
456 return false; | 451 return false; |
457 case 'x': // hex const int (low 16 bits) | 452 case 'x': // hex const int (low 16 bits) |
458 if ((MO.getType()) != MachineOperand::MO_Immediate) | 453 if ((MO.getType()) != MachineOperand::MO_Immediate) |
459 return true; | 454 return true; |
460 O << "0x" << StringRef(utohexstr(MO.getImm() & 0xffff)).lower(); | 455 O << "0x" << Twine::utohexstr(MO.getImm() & 0xffff); |
461 return false; | 456 return false; |
462 case 'd': // decimal const int | 457 case 'd': // decimal const int |
463 if ((MO.getType()) != MachineOperand::MO_Immediate) | 458 if ((MO.getType()) != MachineOperand::MO_Immediate) |
464 return true; | 459 return true; |
465 O << MO.getImm(); | 460 O << MO.getImm(); |
538 | 533 |
539 bool MipsAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, | 534 bool MipsAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, |
540 unsigned OpNum, unsigned AsmVariant, | 535 unsigned OpNum, unsigned AsmVariant, |
541 const char *ExtraCode, | 536 const char *ExtraCode, |
542 raw_ostream &O) { | 537 raw_ostream &O) { |
543 int Offset = 0; | 538 assert(OpNum + 1 < MI->getNumOperands() && "Insufficient operands"); |
539 const MachineOperand &BaseMO = MI->getOperand(OpNum); | |
540 const MachineOperand &OffsetMO = MI->getOperand(OpNum + 1); | |
541 assert(BaseMO.isReg() && "Unexpected base pointer for inline asm memory operand."); | |
542 assert(OffsetMO.isImm() && "Unexpected offset for inline asm memory operand."); | |
543 int Offset = OffsetMO.getImm(); | |
544 | |
544 // Currently we are expecting either no ExtraCode or 'D' | 545 // Currently we are expecting either no ExtraCode or 'D' |
545 if (ExtraCode) { | 546 if (ExtraCode) { |
546 if (ExtraCode[0] == 'D') | 547 if (ExtraCode[0] == 'D') |
547 Offset = 4; | 548 Offset += 4; |
548 else | 549 else |
549 return true; // Unknown modifier. | 550 return true; // Unknown modifier. |
550 } | 551 // FIXME: M = high order bits |
551 | 552 // FIXME: L = low order bits |
552 const MachineOperand &MO = MI->getOperand(OpNum); | 553 } |
553 assert(MO.isReg() && "unexpected inline asm memory operand"); | 554 |
554 O << Offset << "($" << MipsInstPrinter::getRegisterName(MO.getReg()) << ")"; | 555 O << Offset << "($" << MipsInstPrinter::getRegisterName(BaseMO.getReg()) << ")"; |
555 | 556 |
556 return false; | 557 return false; |
557 } | 558 } |
558 | 559 |
559 void MipsAsmPrinter::printOperand(const MachineInstr *MI, int opNum, | 560 void MipsAsmPrinter::printOperand(const MachineInstr *MI, int opNum, |
560 raw_ostream &O) { | 561 raw_ostream &O) { |
561 const DataLayout *DL = TM.getDataLayout(); | |
562 const MachineOperand &MO = MI->getOperand(opNum); | 562 const MachineOperand &MO = MI->getOperand(opNum); |
563 bool closeP = false; | 563 bool closeP = false; |
564 | 564 |
565 if (MO.getTargetFlags()) | 565 if (MO.getTargetFlags()) |
566 closeP = true; | 566 closeP = true; |
591 case MachineOperand::MO_Immediate: | 591 case MachineOperand::MO_Immediate: |
592 O << MO.getImm(); | 592 O << MO.getImm(); |
593 break; | 593 break; |
594 | 594 |
595 case MachineOperand::MO_MachineBasicBlock: | 595 case MachineOperand::MO_MachineBasicBlock: |
596 O << *MO.getMBB()->getSymbol(); | 596 MO.getMBB()->getSymbol()->print(O, MAI); |
597 return; | 597 return; |
598 | 598 |
599 case MachineOperand::MO_GlobalAddress: | 599 case MachineOperand::MO_GlobalAddress: |
600 O << *getSymbol(MO.getGlobal()); | 600 getSymbol(MO.getGlobal())->print(O, MAI); |
601 break; | 601 break; |
602 | 602 |
603 case MachineOperand::MO_BlockAddress: { | 603 case MachineOperand::MO_BlockAddress: { |
604 MCSymbol *BA = GetBlockAddressSymbol(MO.getBlockAddress()); | 604 MCSymbol *BA = GetBlockAddressSymbol(MO.getBlockAddress()); |
605 O << BA->getName(); | 605 O << BA->getName(); |
606 break; | 606 break; |
607 } | 607 } |
608 | 608 |
609 case MachineOperand::MO_ConstantPoolIndex: | 609 case MachineOperand::MO_ConstantPoolIndex: |
610 O << DL->getPrivateGlobalPrefix() << "CPI" | 610 O << getDataLayout().getPrivateGlobalPrefix() << "CPI" |
611 << getFunctionNumber() << "_" << MO.getIndex(); | 611 << getFunctionNumber() << "_" << MO.getIndex(); |
612 if (MO.getOffset()) | 612 if (MO.getOffset()) |
613 O << "+" << MO.getOffset(); | 613 O << "+" << MO.getOffset(); |
614 break; | 614 break; |
615 | 615 |
691 // Compute MIPS architecture attributes based on the default subtarget | 691 // Compute MIPS architecture attributes based on the default subtarget |
692 // that we'd have constructed. Module level directives aren't LTO | 692 // that we'd have constructed. Module level directives aren't LTO |
693 // clean anyhow. | 693 // clean anyhow. |
694 // FIXME: For ifunc related functions we could iterate over and look | 694 // FIXME: For ifunc related functions we could iterate over and look |
695 // for a feature string that doesn't match the default one. | 695 // for a feature string that doesn't match the default one. |
696 StringRef TT = TM.getTargetTriple(); | 696 const Triple &TT = TM.getTargetTriple(); |
697 StringRef CPU = | 697 StringRef CPU = MIPS_MC::selectMipsCPU(TT, TM.getTargetCPU()); |
698 MIPS_MC::selectMipsCPU(TM.getTargetTriple(), TM.getTargetCPU()); | |
699 StringRef FS = TM.getTargetFeatureString(); | 698 StringRef FS = TM.getTargetFeatureString(); |
700 const MipsTargetMachine &MTM = static_cast<const MipsTargetMachine &>(TM); | 699 const MipsTargetMachine &MTM = static_cast<const MipsTargetMachine &>(TM); |
701 const MipsSubtarget STI(TT, CPU, FS, MTM.isLittleEndian(), MTM); | 700 const MipsSubtarget STI(TT, CPU, FS, MTM.isLittleEndian(), MTM); |
702 | 701 |
703 bool IsABICalls = STI.isABICalls(); | 702 bool IsABICalls = STI.isABICalls(); |
713 getTargetStreamer().emitDirectiveOptionPic0(); | 712 getTargetStreamer().emitDirectiveOptionPic0(); |
714 } | 713 } |
715 | 714 |
716 // Tell the assembler which ABI we are using | 715 // Tell the assembler which ABI we are using |
717 std::string SectionName = std::string(".mdebug.") + getCurrentABIString(); | 716 std::string SectionName = std::string(".mdebug.") + getCurrentABIString(); |
718 OutStreamer.SwitchSection( | 717 OutStreamer->SwitchSection( |
719 OutContext.getELFSection(SectionName, ELF::SHT_PROGBITS, 0)); | 718 OutContext.getELFSection(SectionName, ELF::SHT_PROGBITS, 0)); |
720 | 719 |
721 // NaN: At the moment we only support: | 720 // NaN: At the moment we only support: |
722 // 1. .nan legacy (default) | 721 // 1. .nan legacy (default) |
723 // 2. .nan 2008 | 722 // 2. .nan 2008 |
726 | 725 |
727 // TODO: handle O64 ABI | 726 // TODO: handle O64 ABI |
728 | 727 |
729 if (ABI.IsEABI()) { | 728 if (ABI.IsEABI()) { |
730 if (STI.isGP32bit()) | 729 if (STI.isGP32bit()) |
731 OutStreamer.SwitchSection(OutContext.getELFSection(".gcc_compiled_long32", | 730 OutStreamer->SwitchSection(OutContext.getELFSection(".gcc_compiled_long32", |
732 ELF::SHT_PROGBITS, 0)); | 731 ELF::SHT_PROGBITS, 0)); |
733 else | 732 else |
734 OutStreamer.SwitchSection(OutContext.getELFSection(".gcc_compiled_long64", | 733 OutStreamer->SwitchSection(OutContext.getELFSection(".gcc_compiled_long64", |
735 ELF::SHT_PROGBITS, 0)); | 734 ELF::SHT_PROGBITS, 0)); |
736 } | 735 } |
737 | 736 |
738 getTargetStreamer().updateABIInfo(STI); | 737 getTargetStreamer().updateABIInfo(STI); |
739 | 738 |
740 // We should always emit a '.module fp=...' but binutils 2.24 does not accept | 739 // We should always emit a '.module fp=...' but binutils 2.24 does not accept |
745 | 744 |
746 // We should always emit a '.module [no]oddspreg' but binutils 2.24 does not | 745 // We should always emit a '.module [no]oddspreg' but binutils 2.24 does not |
747 // accept it. We therefore emit it when it contradicts the default or an | 746 // accept it. We therefore emit it when it contradicts the default or an |
748 // option has changed the default (i.e. FPXX) and omit it otherwise. | 747 // option has changed the default (i.e. FPXX) and omit it otherwise. |
749 if (ABI.IsO32() && (!STI.useOddSPReg() || STI.isABI_FPXX())) | 748 if (ABI.IsO32() && (!STI.useOddSPReg() || STI.isABI_FPXX())) |
750 getTargetStreamer().emitDirectiveModuleOddSPReg(STI.useOddSPReg(), | 749 getTargetStreamer().emitDirectiveModuleOddSPReg(); |
751 ABI.IsO32()); | 750 } |
752 } | 751 |
753 | 752 void MipsAsmPrinter::emitInlineAsmStart() const { |
754 void MipsAsmPrinter::emitInlineAsmStart( | |
755 const MCSubtargetInfo &StartInfo) const { | |
756 MipsTargetStreamer &TS = getTargetStreamer(); | 753 MipsTargetStreamer &TS = getTargetStreamer(); |
757 | 754 |
758 // GCC's choice of assembler options for inline assembly code ('at', 'macro' | 755 // GCC's choice of assembler options for inline assembly code ('at', 'macro' |
759 // and 'reorder') is different from LLVM's choice for generated code ('noat', | 756 // and 'reorder') is different from LLVM's choice for generated code ('noat', |
760 // 'nomacro' and 'noreorder'). | 757 // 'nomacro' and 'noreorder'). |
763 // for the duration of the inline assembly block and then switch back. | 760 // for the duration of the inline assembly block and then switch back. |
764 TS.emitDirectiveSetPush(); | 761 TS.emitDirectiveSetPush(); |
765 TS.emitDirectiveSetAt(); | 762 TS.emitDirectiveSetAt(); |
766 TS.emitDirectiveSetMacro(); | 763 TS.emitDirectiveSetMacro(); |
767 TS.emitDirectiveSetReorder(); | 764 TS.emitDirectiveSetReorder(); |
768 OutStreamer.AddBlankLine(); | 765 OutStreamer->AddBlankLine(); |
769 } | 766 } |
770 | 767 |
771 void MipsAsmPrinter::emitInlineAsmEnd(const MCSubtargetInfo &StartInfo, | 768 void MipsAsmPrinter::emitInlineAsmEnd(const MCSubtargetInfo &StartInfo, |
772 const MCSubtargetInfo *EndInfo) const { | 769 const MCSubtargetInfo *EndInfo) const { |
773 OutStreamer.AddBlankLine(); | 770 OutStreamer->AddBlankLine(); |
774 getTargetStreamer().emitDirectiveSetPop(); | 771 getTargetStreamer().emitDirectiveSetPop(); |
775 } | 772 } |
776 | 773 |
777 void MipsAsmPrinter::EmitJal(MCSymbol *Symbol) { | 774 void MipsAsmPrinter::EmitJal(const MCSubtargetInfo &STI, MCSymbol *Symbol) { |
778 MCInst I; | 775 MCInst I; |
779 I.setOpcode(Mips::JAL); | 776 I.setOpcode(Mips::JAL); |
780 I.addOperand( | 777 I.addOperand( |
781 MCOperand::CreateExpr(MCSymbolRefExpr::Create(Symbol, OutContext))); | 778 MCOperand::createExpr(MCSymbolRefExpr::create(Symbol, OutContext))); |
782 OutStreamer.EmitInstruction(I, getSubtargetInfo()); | 779 OutStreamer->EmitInstruction(I, STI); |
783 } | 780 } |
784 | 781 |
785 void MipsAsmPrinter::EmitInstrReg(unsigned Opcode, unsigned Reg) { | 782 void MipsAsmPrinter::EmitInstrReg(const MCSubtargetInfo &STI, unsigned Opcode, |
783 unsigned Reg) { | |
786 MCInst I; | 784 MCInst I; |
787 I.setOpcode(Opcode); | 785 I.setOpcode(Opcode); |
788 I.addOperand(MCOperand::CreateReg(Reg)); | 786 I.addOperand(MCOperand::createReg(Reg)); |
789 OutStreamer.EmitInstruction(I, getSubtargetInfo()); | 787 OutStreamer->EmitInstruction(I, STI); |
790 } | 788 } |
791 | 789 |
792 void MipsAsmPrinter::EmitInstrRegReg(unsigned Opcode, unsigned Reg1, | 790 void MipsAsmPrinter::EmitInstrRegReg(const MCSubtargetInfo &STI, |
791 unsigned Opcode, unsigned Reg1, | |
793 unsigned Reg2) { | 792 unsigned Reg2) { |
794 MCInst I; | 793 MCInst I; |
795 // | 794 // |
796 // Because of the current td files for Mips32, the operands for MTC1 | 795 // Because of the current td files for Mips32, the operands for MTC1 |
797 // appear backwards from their normal assembly order. It's not a trivial | 796 // appear backwards from their normal assembly order. It's not a trivial |
801 unsigned Temp = Reg1; | 800 unsigned Temp = Reg1; |
802 Reg1 = Reg2; | 801 Reg1 = Reg2; |
803 Reg2 = Temp; | 802 Reg2 = Temp; |
804 } | 803 } |
805 I.setOpcode(Opcode); | 804 I.setOpcode(Opcode); |
806 I.addOperand(MCOperand::CreateReg(Reg1)); | 805 I.addOperand(MCOperand::createReg(Reg1)); |
807 I.addOperand(MCOperand::CreateReg(Reg2)); | 806 I.addOperand(MCOperand::createReg(Reg2)); |
808 OutStreamer.EmitInstruction(I, getSubtargetInfo()); | 807 OutStreamer->EmitInstruction(I, STI); |
809 } | 808 } |
810 | 809 |
811 void MipsAsmPrinter::EmitInstrRegRegReg(unsigned Opcode, unsigned Reg1, | 810 void MipsAsmPrinter::EmitInstrRegRegReg(const MCSubtargetInfo &STI, |
811 unsigned Opcode, unsigned Reg1, | |
812 unsigned Reg2, unsigned Reg3) { | 812 unsigned Reg2, unsigned Reg3) { |
813 MCInst I; | 813 MCInst I; |
814 I.setOpcode(Opcode); | 814 I.setOpcode(Opcode); |
815 I.addOperand(MCOperand::CreateReg(Reg1)); | 815 I.addOperand(MCOperand::createReg(Reg1)); |
816 I.addOperand(MCOperand::CreateReg(Reg2)); | 816 I.addOperand(MCOperand::createReg(Reg2)); |
817 I.addOperand(MCOperand::CreateReg(Reg3)); | 817 I.addOperand(MCOperand::createReg(Reg3)); |
818 OutStreamer.EmitInstruction(I, getSubtargetInfo()); | 818 OutStreamer->EmitInstruction(I, STI); |
819 } | 819 } |
820 | 820 |
821 void MipsAsmPrinter::EmitMovFPIntPair(unsigned MovOpc, unsigned Reg1, | 821 void MipsAsmPrinter::EmitMovFPIntPair(const MCSubtargetInfo &STI, |
822 unsigned MovOpc, unsigned Reg1, | |
822 unsigned Reg2, unsigned FPReg1, | 823 unsigned Reg2, unsigned FPReg1, |
823 unsigned FPReg2, bool LE) { | 824 unsigned FPReg2, bool LE) { |
824 if (!LE) { | 825 if (!LE) { |
825 unsigned temp = Reg1; | 826 unsigned temp = Reg1; |
826 Reg1 = Reg2; | 827 Reg1 = Reg2; |
827 Reg2 = temp; | 828 Reg2 = temp; |
828 } | 829 } |
829 EmitInstrRegReg(MovOpc, Reg1, FPReg1); | 830 EmitInstrRegReg(STI, MovOpc, Reg1, FPReg1); |
830 EmitInstrRegReg(MovOpc, Reg2, FPReg2); | 831 EmitInstrRegReg(STI, MovOpc, Reg2, FPReg2); |
831 } | 832 } |
832 | 833 |
833 void MipsAsmPrinter::EmitSwapFPIntParams(Mips16HardFloatInfo::FPParamVariant PV, | 834 void MipsAsmPrinter::EmitSwapFPIntParams(const MCSubtargetInfo &STI, |
835 Mips16HardFloatInfo::FPParamVariant PV, | |
834 bool LE, bool ToFP) { | 836 bool LE, bool ToFP) { |
835 using namespace Mips16HardFloatInfo; | 837 using namespace Mips16HardFloatInfo; |
836 unsigned MovOpc = ToFP ? Mips::MTC1 : Mips::MFC1; | 838 unsigned MovOpc = ToFP ? Mips::MTC1 : Mips::MFC1; |
837 switch (PV) { | 839 switch (PV) { |
838 case FSig: | 840 case FSig: |
839 EmitInstrRegReg(MovOpc, Mips::A0, Mips::F12); | 841 EmitInstrRegReg(STI, MovOpc, Mips::A0, Mips::F12); |
840 break; | 842 break; |
841 case FFSig: | 843 case FFSig: |
842 EmitMovFPIntPair(MovOpc, Mips::A0, Mips::A1, Mips::F12, Mips::F14, LE); | 844 EmitMovFPIntPair(STI, MovOpc, Mips::A0, Mips::A1, Mips::F12, Mips::F14, LE); |
843 break; | 845 break; |
844 case FDSig: | 846 case FDSig: |
845 EmitInstrRegReg(MovOpc, Mips::A0, Mips::F12); | 847 EmitInstrRegReg(STI, MovOpc, Mips::A0, Mips::F12); |
846 EmitMovFPIntPair(MovOpc, Mips::A2, Mips::A3, Mips::F14, Mips::F15, LE); | 848 EmitMovFPIntPair(STI, MovOpc, Mips::A2, Mips::A3, Mips::F14, Mips::F15, LE); |
847 break; | 849 break; |
848 case DSig: | 850 case DSig: |
849 EmitMovFPIntPair(MovOpc, Mips::A0, Mips::A1, Mips::F12, Mips::F13, LE); | 851 EmitMovFPIntPair(STI, MovOpc, Mips::A0, Mips::A1, Mips::F12, Mips::F13, LE); |
850 break; | 852 break; |
851 case DDSig: | 853 case DDSig: |
852 EmitMovFPIntPair(MovOpc, Mips::A0, Mips::A1, Mips::F12, Mips::F13, LE); | 854 EmitMovFPIntPair(STI, MovOpc, Mips::A0, Mips::A1, Mips::F12, Mips::F13, LE); |
853 EmitMovFPIntPair(MovOpc, Mips::A2, Mips::A3, Mips::F14, Mips::F15, LE); | 855 EmitMovFPIntPair(STI, MovOpc, Mips::A2, Mips::A3, Mips::F14, Mips::F15, LE); |
854 break; | 856 break; |
855 case DFSig: | 857 case DFSig: |
856 EmitMovFPIntPair(MovOpc, Mips::A0, Mips::A1, Mips::F12, Mips::F13, LE); | 858 EmitMovFPIntPair(STI, MovOpc, Mips::A0, Mips::A1, Mips::F12, Mips::F13, LE); |
857 EmitInstrRegReg(MovOpc, Mips::A2, Mips::F14); | 859 EmitInstrRegReg(STI, MovOpc, Mips::A2, Mips::F14); |
858 break; | 860 break; |
859 case NoSig: | 861 case NoSig: |
860 return; | 862 return; |
861 } | 863 } |
862 } | 864 } |
863 | 865 |
864 void | 866 void MipsAsmPrinter::EmitSwapFPIntRetval( |
865 MipsAsmPrinter::EmitSwapFPIntRetval(Mips16HardFloatInfo::FPReturnVariant RV, | 867 const MCSubtargetInfo &STI, Mips16HardFloatInfo::FPReturnVariant RV, |
866 bool LE) { | 868 bool LE) { |
867 using namespace Mips16HardFloatInfo; | 869 using namespace Mips16HardFloatInfo; |
868 unsigned MovOpc = Mips::MFC1; | 870 unsigned MovOpc = Mips::MFC1; |
869 switch (RV) { | 871 switch (RV) { |
870 case FRet: | 872 case FRet: |
871 EmitInstrRegReg(MovOpc, Mips::V0, Mips::F0); | 873 EmitInstrRegReg(STI, MovOpc, Mips::V0, Mips::F0); |
872 break; | 874 break; |
873 case DRet: | 875 case DRet: |
874 EmitMovFPIntPair(MovOpc, Mips::V0, Mips::V1, Mips::F0, Mips::F1, LE); | 876 EmitMovFPIntPair(STI, MovOpc, Mips::V0, Mips::V1, Mips::F0, Mips::F1, LE); |
875 break; | 877 break; |
876 case CFRet: | 878 case CFRet: |
877 EmitMovFPIntPair(MovOpc, Mips::V0, Mips::V1, Mips::F0, Mips::F1, LE); | 879 EmitMovFPIntPair(STI, MovOpc, Mips::V0, Mips::V1, Mips::F0, Mips::F1, LE); |
878 break; | 880 break; |
879 case CDRet: | 881 case CDRet: |
880 EmitMovFPIntPair(MovOpc, Mips::V0, Mips::V1, Mips::F0, Mips::F1, LE); | 882 EmitMovFPIntPair(STI, MovOpc, Mips::V0, Mips::V1, Mips::F0, Mips::F1, LE); |
881 EmitMovFPIntPair(MovOpc, Mips::A0, Mips::A1, Mips::F2, Mips::F3, LE); | 883 EmitMovFPIntPair(STI, MovOpc, Mips::A0, Mips::A1, Mips::F2, Mips::F3, LE); |
882 break; | 884 break; |
883 case NoFPRet: | 885 case NoFPRet: |
884 break; | 886 break; |
885 } | 887 } |
886 } | 888 } |
887 | 889 |
888 void MipsAsmPrinter::EmitFPCallStub( | 890 void MipsAsmPrinter::EmitFPCallStub( |
889 const char *Symbol, const Mips16HardFloatInfo::FuncSignature *Signature) { | 891 const char *Symbol, const Mips16HardFloatInfo::FuncSignature *Signature) { |
890 MCSymbol *MSymbol = OutContext.GetOrCreateSymbol(StringRef(Symbol)); | 892 MCSymbol *MSymbol = OutContext.getOrCreateSymbol(StringRef(Symbol)); |
891 using namespace Mips16HardFloatInfo; | 893 using namespace Mips16HardFloatInfo; |
892 bool LE = Subtarget->isLittle(); | 894 bool LE = getDataLayout().isLittleEndian(); |
895 // Construct a local MCSubtargetInfo here. | |
896 // This is because the MachineFunction won't exist (but have not yet been | |
897 // freed) and since we're at the global level we can use the default | |
898 // constructed subtarget. | |
899 std::unique_ptr<MCSubtargetInfo> STI(TM.getTarget().createMCSubtargetInfo( | |
900 TM.getTargetTriple().str(), TM.getTargetCPU(), | |
901 TM.getTargetFeatureString())); | |
902 | |
893 // | 903 // |
894 // .global xxxx | 904 // .global xxxx |
895 // | 905 // |
896 OutStreamer.EmitSymbolAttribute(MSymbol, MCSA_Global); | 906 OutStreamer->EmitSymbolAttribute(MSymbol, MCSA_Global); |
897 const char *RetType; | 907 const char *RetType; |
898 // | 908 // |
899 // make the comment field identifying the return and parameter | 909 // make the comment field identifying the return and parameter |
900 // types of the floating point stub | 910 // types of the floating point stub |
901 // # Stub function to call rettype xxxx (params) | 911 // # Stub function to call rettype xxxx (params) |
939 break; | 949 break; |
940 case NoSig: | 950 case NoSig: |
941 Parms = ""; | 951 Parms = ""; |
942 break; | 952 break; |
943 } | 953 } |
944 OutStreamer.AddComment("\t# Stub function to call " + Twine(RetType) + " " + | 954 OutStreamer->AddComment("\t# Stub function to call " + Twine(RetType) + " " + |
945 Twine(Symbol) + " (" + Twine(Parms) + ")"); | 955 Twine(Symbol) + " (" + Twine(Parms) + ")"); |
946 // | 956 // |
947 // probably not necessary but we save and restore the current section state | 957 // probably not necessary but we save and restore the current section state |
948 // | 958 // |
949 OutStreamer.PushSection(); | 959 OutStreamer->PushSection(); |
950 // | 960 // |
951 // .section mips16.call.fpxxxx,"ax",@progbits | 961 // .section mips16.call.fpxxxx,"ax",@progbits |
952 // | 962 // |
953 const MCSectionELF *M = OutContext.getELFSection( | 963 MCSectionELF *M = OutContext.getELFSection( |
954 ".mips16.call.fp." + std::string(Symbol), ELF::SHT_PROGBITS, | 964 ".mips16.call.fp." + std::string(Symbol), ELF::SHT_PROGBITS, |
955 ELF::SHF_ALLOC | ELF::SHF_EXECINSTR); | 965 ELF::SHF_ALLOC | ELF::SHF_EXECINSTR); |
956 OutStreamer.SwitchSection(M, nullptr); | 966 OutStreamer->SwitchSection(M, nullptr); |
957 // | 967 // |
958 // .align 2 | 968 // .align 2 |
959 // | 969 // |
960 OutStreamer.EmitValueToAlignment(4); | 970 OutStreamer->EmitValueToAlignment(4); |
961 MipsTargetStreamer &TS = getTargetStreamer(); | 971 MipsTargetStreamer &TS = getTargetStreamer(); |
962 // | 972 // |
963 // .set nomips16 | 973 // .set nomips16 |
964 // .set nomicromips | 974 // .set nomicromips |
965 // | 975 // |
969 // .ent __call_stub_fp_xxxx | 979 // .ent __call_stub_fp_xxxx |
970 // .type __call_stub_fp_xxxx,@function | 980 // .type __call_stub_fp_xxxx,@function |
971 // __call_stub_fp_xxxx: | 981 // __call_stub_fp_xxxx: |
972 // | 982 // |
973 std::string x = "__call_stub_fp_" + std::string(Symbol); | 983 std::string x = "__call_stub_fp_" + std::string(Symbol); |
974 MCSymbol *Stub = OutContext.GetOrCreateSymbol(StringRef(x)); | 984 MCSymbolELF *Stub = |
985 cast<MCSymbolELF>(OutContext.getOrCreateSymbol(StringRef(x))); | |
975 TS.emitDirectiveEnt(*Stub); | 986 TS.emitDirectiveEnt(*Stub); |
976 MCSymbol *MType = | 987 MCSymbol *MType = |
977 OutContext.GetOrCreateSymbol("__call_stub_fp_" + Twine(Symbol)); | 988 OutContext.getOrCreateSymbol("__call_stub_fp_" + Twine(Symbol)); |
978 OutStreamer.EmitSymbolAttribute(MType, MCSA_ELF_TypeFunction); | 989 OutStreamer->EmitSymbolAttribute(MType, MCSA_ELF_TypeFunction); |
979 OutStreamer.EmitLabel(Stub); | 990 OutStreamer->EmitLabel(Stub); |
980 // | 991 |
981 // we just handle non pic for now. these function will not be | 992 // Only handle non-pic for now. |
982 // called otherwise. when the full stub generation is moved here | 993 assert(TM.getRelocationModel() != Reloc::PIC_ && |
983 // we need to deal with pic. | 994 "should not be here if we are compiling pic"); |
984 // | |
985 if (TM.getRelocationModel() == Reloc::PIC_) | |
986 llvm_unreachable("should not be here if we are compiling pic"); | |
987 TS.emitDirectiveSetReorder(); | 995 TS.emitDirectiveSetReorder(); |
988 // | 996 // |
989 // We need to add a MipsMCExpr class to MCTargetDesc to fully implement | 997 // We need to add a MipsMCExpr class to MCTargetDesc to fully implement |
990 // stubs without raw text but this current patch is for compiler generated | 998 // stubs without raw text but this current patch is for compiler generated |
991 // functions and they all return some value. | 999 // functions and they all return some value. |
998 // We need to make sure that the enclosing function knows to save S2 | 1006 // We need to make sure that the enclosing function knows to save S2 |
999 // This should have already been handled. | 1007 // This should have already been handled. |
1000 // | 1008 // |
1001 // Mov $18, $31 | 1009 // Mov $18, $31 |
1002 | 1010 |
1003 EmitInstrRegRegReg(Mips::ADDu, Mips::S2, Mips::RA, Mips::ZERO); | 1011 EmitInstrRegRegReg(*STI, Mips::OR, Mips::S2, Mips::RA, Mips::ZERO); |
1004 | 1012 |
1005 EmitSwapFPIntParams(Signature->ParamSig, LE, true); | 1013 EmitSwapFPIntParams(*STI, Signature->ParamSig, LE, true); |
1006 | 1014 |
1007 // Jal xxxx | 1015 // Jal xxxx |
1008 // | 1016 // |
1009 EmitJal(MSymbol); | 1017 EmitJal(*STI, MSymbol); |
1010 | 1018 |
1011 // fix return values | 1019 // fix return values |
1012 EmitSwapFPIntRetval(Signature->RetSig, LE); | 1020 EmitSwapFPIntRetval(*STI, Signature->RetSig, LE); |
1013 // | 1021 // |
1014 // do the return | 1022 // do the return |
1015 // if (Signature->RetSig == NoFPRet) | 1023 // if (Signature->RetSig == NoFPRet) |
1016 // llvm_unreachable("should not be any stubs here with no return value"); | 1024 // llvm_unreachable("should not be any stubs here with no return value"); |
1017 // else | 1025 // else |
1018 EmitInstrReg(Mips::JR, Mips::S2); | 1026 EmitInstrReg(*STI, Mips::JR, Mips::S2); |
1019 | 1027 |
1020 MCSymbol *Tmp = OutContext.CreateTempSymbol(); | 1028 MCSymbol *Tmp = OutContext.createTempSymbol(); |
1021 OutStreamer.EmitLabel(Tmp); | 1029 OutStreamer->EmitLabel(Tmp); |
1022 const MCSymbolRefExpr *E = MCSymbolRefExpr::Create(Stub, OutContext); | 1030 const MCSymbolRefExpr *E = MCSymbolRefExpr::create(Stub, OutContext); |
1023 const MCSymbolRefExpr *T = MCSymbolRefExpr::Create(Tmp, OutContext); | 1031 const MCSymbolRefExpr *T = MCSymbolRefExpr::create(Tmp, OutContext); |
1024 const MCExpr *T_min_E = MCBinaryExpr::CreateSub(T, E, OutContext); | 1032 const MCExpr *T_min_E = MCBinaryExpr::createSub(T, E, OutContext); |
1025 OutStreamer.EmitELFSize(Stub, T_min_E); | 1033 OutStreamer->emitELFSize(Stub, T_min_E); |
1026 TS.emitDirectiveEnd(x); | 1034 TS.emitDirectiveEnd(x); |
1027 OutStreamer.PopSection(); | 1035 OutStreamer->PopSection(); |
1028 } | 1036 } |
1029 | 1037 |
1030 void MipsAsmPrinter::EmitEndOfAsmFile(Module &M) { | 1038 void MipsAsmPrinter::EmitEndOfAsmFile(Module &M) { |
1031 // Emit needed stubs | 1039 // Emit needed stubs |
1032 // | 1040 // |
1038 const char *Symbol = it->first; | 1046 const char *Symbol = it->first; |
1039 const llvm::Mips16HardFloatInfo::FuncSignature *Signature = it->second; | 1047 const llvm::Mips16HardFloatInfo::FuncSignature *Signature = it->second; |
1040 EmitFPCallStub(Symbol, Signature); | 1048 EmitFPCallStub(Symbol, Signature); |
1041 } | 1049 } |
1042 // return to the text section | 1050 // return to the text section |
1043 OutStreamer.SwitchSection(OutContext.getObjectFileInfo()->getTextSection()); | 1051 OutStreamer->SwitchSection(OutContext.getObjectFileInfo()->getTextSection()); |
1044 } | 1052 } |
1045 | 1053 |
1046 void MipsAsmPrinter::PrintDebugValueComment(const MachineInstr *MI, | 1054 void MipsAsmPrinter::PrintDebugValueComment(const MachineInstr *MI, |
1047 raw_ostream &OS) { | 1055 raw_ostream &OS) { |
1048 // TODO: implement | 1056 // TODO: implement |