Mercurial > hg > CbC > CbC_llvm
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); |