1 //===-- MipsAsmPrinter.cpp - Mips LLVM assembly writer --------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file contains a printer that converts from our internal representation
11 // of machine-dependent LLVM code to GAS-format MIPS assembly language.
13 //===----------------------------------------------------------------------===//
15 #define DEBUG_TYPE "mips-asm-printer"
17 #include "MipsSubtarget.h"
18 #include "MipsInstrInfo.h"
19 #include "MipsTargetMachine.h"
20 #include "MipsMachineFunction.h"
21 #include "llvm/BasicBlock.h"
22 #include "llvm/Instructions.h"
23 #include "llvm/CodeGen/AsmPrinter.h"
24 #include "llvm/CodeGen/MachineFunctionPass.h"
25 #include "llvm/CodeGen/MachineConstantPool.h"
26 #include "llvm/CodeGen/MachineFrameInfo.h"
27 #include "llvm/CodeGen/MachineInstr.h"
28 #include "llvm/MC/MCStreamer.h"
29 #include "llvm/MC/MCAsmInfo.h"
30 #include "llvm/MC/MCSymbol.h"
31 #include "llvm/Target/Mangler.h"
32 #include "llvm/Target/TargetData.h"
33 #include "llvm/Target/TargetLoweringObjectFile.h"
34 #include "llvm/Target/TargetMachine.h"
35 #include "llvm/Target/TargetOptions.h"
36 #include "llvm/Target/TargetRegistry.h"
37 #include "llvm/ADT/SmallString.h"
38 #include "llvm/ADT/StringExtras.h"
39 #include "llvm/ADT/Twine.h"
40 #include "llvm/Support/raw_ostream.h"
44 class MipsAsmPrinter
: public AsmPrinter
{
45 const MipsSubtarget
*Subtarget
;
47 explicit MipsAsmPrinter(TargetMachine
&TM
, MCStreamer
&Streamer
)
48 : AsmPrinter(TM
, Streamer
) {
49 Subtarget
= &TM
.getSubtarget
<MipsSubtarget
>();
52 virtual const char *getPassName() const {
53 return "Mips Assembly Printer";
56 bool PrintAsmOperand(const MachineInstr
*MI
, unsigned OpNo
,
57 unsigned AsmVariant
, const char *ExtraCode
,
59 void printOperand(const MachineInstr
*MI
, int opNum
, raw_ostream
&O
);
60 void printUnsignedImm(const MachineInstr
*MI
, int opNum
, raw_ostream
&O
);
61 void printMemOperand(const MachineInstr
*MI
, int opNum
, raw_ostream
&O
,
62 const char *Modifier
= 0);
63 void printFCCOperand(const MachineInstr
*MI
, int opNum
, raw_ostream
&O
,
64 const char *Modifier
= 0);
65 void printSavedRegsBitmask(raw_ostream
&O
);
66 void printHex32(unsigned int Value
, raw_ostream
&O
);
68 const char *getCurrentABIString() const;
69 void emitFrameDirective();
71 void printInstruction(const MachineInstr
*MI
, raw_ostream
&O
); // autogen'd.
72 void EmitInstruction(const MachineInstr
*MI
) {
74 raw_svector_ostream
OS(Str
);
75 printInstruction(MI
, OS
);
76 OutStreamer
.EmitRawText(OS
.str());
78 virtual void EmitFunctionBodyStart();
79 virtual void EmitFunctionBodyEnd();
80 virtual bool isBlockOnlyReachableByFallthrough(const MachineBasicBlock
*MBB
) const;
81 static const char *getRegisterName(unsigned RegNo
);
83 virtual void EmitFunctionEntryLabel();
84 void EmitStartOfAsmFile(Module
&M
);
86 } // end of anonymous namespace
88 #include "MipsGenAsmWriter.inc"
90 //===----------------------------------------------------------------------===//
92 // Mips Asm Directives
94 // -- Frame directive "frame Stackpointer, Stacksize, RARegister"
95 // Describe the stack frame.
97 // -- Mask directives "(f)mask bitmask, offset"
98 // Tells the assembler which registers are saved and where.
99 // bitmask - contain a little endian bitset indicating which registers are
100 // saved on function prologue (e.g. with a 0x80000000 mask, the
101 // assembler knows the register 31 (RA) is saved at prologue.
102 // offset - the position before stack pointer subtraction indicating where
103 // the first saved register on prologue is located. (e.g. with a
105 // Consider the following function prologue:
108 // .mask 0xc0000000,-8
109 // addiu $sp, $sp, -48
113 // With a 0xc0000000 mask, the assembler knows the register 31 (RA) and
114 // 30 (FP) are saved at prologue. As the save order on prologue is from
115 // left to right, RA is saved first. A -8 offset means that after the
116 // stack pointer subtration, the first register in the mask (RA) will be
117 // saved at address 48-8=40.
119 //===----------------------------------------------------------------------===//
121 //===----------------------------------------------------------------------===//
123 //===----------------------------------------------------------------------===//
125 // Create a bitmask with all callee saved registers for CPU or Floating Point
126 // registers. For CPU registers consider RA, GP and FP for saving if necessary.
127 void MipsAsmPrinter::printSavedRegsBitmask(raw_ostream
&O
) {
128 const TargetRegisterInfo
&RI
= *TM
.getRegisterInfo();
129 const MipsFunctionInfo
*MipsFI
= MF
->getInfo
<MipsFunctionInfo
>();
131 // CPU and FPU Saved Registers Bitmasks
132 unsigned int CPUBitmask
= 0;
133 unsigned int FPUBitmask
= 0;
135 // Set the CPU and FPU Bitmasks
136 const MachineFrameInfo
*MFI
= MF
->getFrameInfo();
137 const std::vector
<CalleeSavedInfo
> &CSI
= MFI
->getCalleeSavedInfo();
138 for (unsigned i
= 0, e
= CSI
.size(); i
!= e
; ++i
) {
139 unsigned Reg
= CSI
[i
].getReg();
140 unsigned RegNum
= MipsRegisterInfo::getRegisterNumbering(Reg
);
141 if (Mips::CPURegsRegisterClass
->contains(Reg
))
142 CPUBitmask
|= (1 << RegNum
);
144 FPUBitmask
|= (1 << RegNum
);
147 // Return Address and Frame registers must also be set in CPUBitmask.
149 CPUBitmask
|= (1 << MipsRegisterInfo::
150 getRegisterNumbering(RI
.getFrameRegister(*MF
)));
152 if (MFI
->adjustsStack())
153 CPUBitmask
|= (1 << MipsRegisterInfo::
154 getRegisterNumbering(RI
.getRARegister()));
157 O
<< "\t.mask \t"; printHex32(CPUBitmask
, O
);
158 O
<< ',' << MipsFI
->getCPUTopSavedRegOff() << '\n';
161 O
<< "\t.fmask\t"; printHex32(FPUBitmask
, O
); O
<< ","
162 << MipsFI
->getFPUTopSavedRegOff() << '\n';
165 // Print a 32 bit hex number with all numbers.
166 void MipsAsmPrinter::printHex32(unsigned Value
, raw_ostream
&O
) {
168 for (int i
= 7; i
>= 0; i
--)
169 O
<< utohexstr((Value
& (0xF << (i
*4))) >> (i
*4));
172 //===----------------------------------------------------------------------===//
173 // Frame and Set directives
174 //===----------------------------------------------------------------------===//
177 void MipsAsmPrinter::emitFrameDirective() {
178 const TargetRegisterInfo
&RI
= *TM
.getRegisterInfo();
180 unsigned stackReg
= RI
.getFrameRegister(*MF
);
181 unsigned returnReg
= RI
.getRARegister();
182 unsigned stackSize
= MF
->getFrameInfo()->getStackSize();
184 OutStreamer
.EmitRawText("\t.frame\t$" +
185 Twine(LowercaseString(getRegisterName(stackReg
))) +
186 "," + Twine(stackSize
) + ",$" +
187 Twine(LowercaseString(getRegisterName(returnReg
))));
190 /// Emit Set directives.
191 const char *MipsAsmPrinter::getCurrentABIString() const {
192 switch (Subtarget
->getTargetABI()) {
193 case MipsSubtarget::O32
: return "abi32";
194 case MipsSubtarget::O64
: return "abiO64";
195 case MipsSubtarget::N32
: return "abiN32";
196 case MipsSubtarget::N64
: return "abi64";
197 case MipsSubtarget::EABI
: return "eabi32"; // TODO: handle eabi64
201 llvm_unreachable("Unknown Mips ABI");
205 void MipsAsmPrinter::EmitFunctionEntryLabel() {
206 OutStreamer
.EmitRawText("\t.ent\t" + Twine(CurrentFnSym
->getName()));
207 OutStreamer
.EmitLabel(CurrentFnSym
);
210 /// EmitFunctionBodyStart - Targets can override this to emit stuff before
211 /// the first basic block in the function.
212 void MipsAsmPrinter::EmitFunctionBodyStart() {
213 emitFrameDirective();
215 SmallString
<128> Str
;
216 raw_svector_ostream
OS(Str
);
217 printSavedRegsBitmask(OS
);
218 OutStreamer
.EmitRawText(OS
.str());
221 /// EmitFunctionBodyEnd - Targets can override this to emit stuff after
222 /// the last basic block in the function.
223 void MipsAsmPrinter::EmitFunctionBodyEnd() {
224 // There are instruction for this macros, but they must
225 // always be at the function end, and we can't emit and
226 // break with BB logic.
227 OutStreamer
.EmitRawText(StringRef("\t.set\tmacro"));
228 OutStreamer
.EmitRawText(StringRef("\t.set\treorder"));
229 OutStreamer
.EmitRawText("\t.end\t" + Twine(CurrentFnSym
->getName()));
233 /// isBlockOnlyReachableByFallthough - Return true if the basic block has
234 /// exactly one predecessor and the control transfer mechanism between
235 /// the predecessor and this block is a fall-through.
236 bool MipsAsmPrinter::isBlockOnlyReachableByFallthrough(const MachineBasicBlock
*MBB
)
238 // The predecessor has to be immediately before this block.
239 const MachineBasicBlock
*Pred
= *MBB
->pred_begin();
241 // If the predecessor is a switch statement, assume a jump table
242 // implementation, so it is not a fall through.
243 if (const BasicBlock
*bb
= Pred
->getBasicBlock())
244 if (isa
<SwitchInst
>(bb
->getTerminator()))
247 return AsmPrinter::isBlockOnlyReachableByFallthrough(MBB
);
250 // Print out an operand for an inline asm expression.
251 bool MipsAsmPrinter::PrintAsmOperand(const MachineInstr
*MI
, unsigned OpNo
,
252 unsigned AsmVariant
,const char *ExtraCode
,
254 // Does this asm operand have a single letter operand modifier?
255 if (ExtraCode
&& ExtraCode
[0])
256 return true; // Unknown modifier.
258 printOperand(MI
, OpNo
, O
);
262 void MipsAsmPrinter::printOperand(const MachineInstr
*MI
, int opNum
,
264 const MachineOperand
&MO
= MI
->getOperand(opNum
);
267 if (MO
.getTargetFlags())
270 switch(MO
.getTargetFlags()) {
271 case MipsII::MO_GPREL
: O
<< "%gp_rel("; break;
272 case MipsII::MO_GOT_CALL
: O
<< "%call16("; break;
274 if (MI
->getOpcode() == Mips::LW
)
279 case MipsII::MO_ABS_HILO
:
280 if (MI
->getOpcode() == Mips::LUi
)
287 switch (MO
.getType()) {
288 case MachineOperand::MO_Register
:
289 O
<< '$' << LowercaseString(getRegisterName(MO
.getReg()));
292 case MachineOperand::MO_Immediate
:
293 O
<< (short int)MO
.getImm();
296 case MachineOperand::MO_MachineBasicBlock
:
297 O
<< *MO
.getMBB()->getSymbol();
300 case MachineOperand::MO_GlobalAddress
:
301 O
<< *Mang
->getSymbol(MO
.getGlobal());
304 case MachineOperand::MO_ExternalSymbol
:
305 O
<< *GetExternalSymbolSymbol(MO
.getSymbolName());
308 case MachineOperand::MO_JumpTableIndex
:
309 O
<< MAI
->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
310 << '_' << MO
.getIndex();
313 case MachineOperand::MO_ConstantPoolIndex
:
314 O
<< MAI
->getPrivateGlobalPrefix() << "CPI"
315 << getFunctionNumber() << "_" << MO
.getIndex();
317 O
<< "+" << MO
.getOffset();
321 llvm_unreachable("<unknown operand type>");
324 if (closeP
) O
<< ")";
327 void MipsAsmPrinter::printUnsignedImm(const MachineInstr
*MI
, int opNum
,
329 const MachineOperand
&MO
= MI
->getOperand(opNum
);
331 O
<< (unsigned short int)MO
.getImm();
333 printOperand(MI
, opNum
, O
);
336 void MipsAsmPrinter::
337 printMemOperand(const MachineInstr
*MI
, int opNum
, raw_ostream
&O
,
338 const char *Modifier
) {
339 // when using stack locations for not load/store instructions
340 // print the same way as all normal 3 operand instructions.
341 if (Modifier
&& !strcmp(Modifier
, "stackloc")) {
342 printOperand(MI
, opNum
+1, O
);
344 printOperand(MI
, opNum
, O
);
348 // Load/Store memory operands -- imm($reg)
349 // If PIC target the target is loaded as the
350 // pattern lw $25,%call16($28)
351 printOperand(MI
, opNum
, O
);
353 printOperand(MI
, opNum
+1, O
);
357 void MipsAsmPrinter::
358 printFCCOperand(const MachineInstr
*MI
, int opNum
, raw_ostream
&O
,
359 const char *Modifier
) {
360 const MachineOperand
& MO
= MI
->getOperand(opNum
);
361 O
<< Mips::MipsFCCToString((Mips::CondCode
)MO
.getImm());
364 void MipsAsmPrinter::EmitStartOfAsmFile(Module
&M
) {
365 // FIXME: Use SwitchSection.
367 // Tell the assembler which ABI we are using
368 OutStreamer
.EmitRawText("\t.section .mdebug." + Twine(getCurrentABIString()));
370 // TODO: handle O64 ABI
371 if (Subtarget
->isABI_EABI()) {
372 if (Subtarget
->isGP32bit())
373 OutStreamer
.EmitRawText(StringRef("\t.section .gcc_compiled_long32"));
375 OutStreamer
.EmitRawText(StringRef("\t.section .gcc_compiled_long64"));
378 // return to previous section
379 OutStreamer
.EmitRawText(StringRef("\t.previous"));
382 // Force static initialization.
383 extern "C" void LLVMInitializeMipsAsmPrinter() {
384 RegisterAsmPrinter
<MipsAsmPrinter
> X(TheMipsTarget
);
385 RegisterAsmPrinter
<MipsAsmPrinter
> Y(TheMipselTarget
);