Remove support for not using .loc directives.
[oota-llvm.git] / lib / Target / Sparc / SparcAsmPrinter.cpp
1 //===-- SparcAsmPrinter.cpp - Sparc LLVM assembly writer ------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file contains a printer that converts from our internal representation
11 // of machine-dependent LLVM code to GAS-format SPARC assembly language.
12 //
13 //===----------------------------------------------------------------------===//
14
15 #define DEBUG_TYPE "asm-printer"
16 #include "Sparc.h"
17 #include "InstPrinter/SparcInstPrinter.h"
18 #include "MCTargetDesc/SparcBaseInfo.h"
19 #include "MCTargetDesc/SparcMCExpr.h"
20 #include "SparcInstrInfo.h"
21 #include "SparcTargetMachine.h"
22 #include "SparcTargetStreamer.h"
23 #include "llvm/ADT/SmallString.h"
24 #include "llvm/CodeGen/AsmPrinter.h"
25 #include "llvm/CodeGen/MachineInstr.h"
26 #include "llvm/CodeGen/MachineModuleInfoImpls.h"
27 #include "llvm/CodeGen/MachineRegisterInfo.h"
28 #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
29 #include "llvm/IR/Mangler.h"
30 #include "llvm/MC/MCAsmInfo.h"
31 #include "llvm/MC/MCContext.h"
32 #include "llvm/MC/MCInst.h"
33 #include "llvm/MC/MCStreamer.h"
34 #include "llvm/MC/MCSymbol.h"
35 #include "llvm/Support/TargetRegistry.h"
36 #include "llvm/Support/raw_ostream.h"
37 using namespace llvm;
38
39 namespace {
40   class SparcAsmPrinter : public AsmPrinter {
41     SparcTargetStreamer &getTargetStreamer() {
42       return static_cast<SparcTargetStreamer &>(
43           *OutStreamer.getTargetStreamer());
44     }
45   public:
46     explicit SparcAsmPrinter(TargetMachine &TM, MCStreamer &Streamer)
47       : AsmPrinter(TM, Streamer) {}
48
49     virtual const char *getPassName() const {
50       return "Sparc Assembly Printer";
51     }
52
53     void printOperand(const MachineInstr *MI, int opNum, raw_ostream &OS);
54     void printMemOperand(const MachineInstr *MI, int opNum, raw_ostream &OS,
55                          const char *Modifier = 0);
56     void printCCOperand(const MachineInstr *MI, int opNum, raw_ostream &OS);
57
58     virtual void EmitFunctionBodyStart();
59     virtual void EmitInstruction(const MachineInstr *MI);
60     virtual void EmitEndOfAsmFile(Module &M);
61
62     static const char *getRegisterName(unsigned RegNo) {
63       return SparcInstPrinter::getRegisterName(RegNo);
64     }
65
66     bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
67                          unsigned AsmVariant, const char *ExtraCode,
68                          raw_ostream &O);
69     bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
70                                unsigned AsmVariant, const char *ExtraCode,
71                                raw_ostream &O);
72
73     void LowerGETPCXAndEmitMCInsts(const MachineInstr *MI,
74                                    const MCSubtargetInfo &STI);
75
76   };
77 } // end of anonymous namespace
78
79 static MCOperand createSparcMCOperand(SparcMCExpr::VariantKind Kind,
80                                       MCSymbol *Sym, MCContext &OutContext) {
81   const MCSymbolRefExpr *MCSym = MCSymbolRefExpr::Create(Sym,
82                                                          OutContext);
83   const SparcMCExpr *expr = SparcMCExpr::Create(Kind, MCSym, OutContext);
84   return MCOperand::CreateExpr(expr);
85
86 }
87 static MCOperand createPCXCallOP(MCSymbol *Label,
88                                  MCContext &OutContext) {
89   return createSparcMCOperand(SparcMCExpr::VK_Sparc_None, Label, OutContext);
90 }
91
92 static MCOperand createPCXRelExprOp(SparcMCExpr::VariantKind Kind,
93                                     MCSymbol *GOTLabel, MCSymbol *StartLabel,
94                                     MCSymbol *CurLabel,
95                                     MCContext &OutContext)
96 {
97   const MCSymbolRefExpr *GOT = MCSymbolRefExpr::Create(GOTLabel, OutContext);
98   const MCSymbolRefExpr *Start = MCSymbolRefExpr::Create(StartLabel,
99                                                          OutContext);
100   const MCSymbolRefExpr *Cur = MCSymbolRefExpr::Create(CurLabel,
101                                                        OutContext);
102
103   const MCBinaryExpr *Sub = MCBinaryExpr::CreateSub(Cur, Start, OutContext);
104   const MCBinaryExpr *Add = MCBinaryExpr::CreateAdd(GOT, Sub, OutContext);
105   const SparcMCExpr *expr = SparcMCExpr::Create(Kind,
106                                                 Add, OutContext);
107   return MCOperand::CreateExpr(expr);
108 }
109
110 static void EmitCall(MCStreamer &OutStreamer,
111                      MCOperand &Callee,
112                      const MCSubtargetInfo &STI)
113 {
114   MCInst CallInst;
115   CallInst.setOpcode(SP::CALL);
116   CallInst.addOperand(Callee);
117   OutStreamer.EmitInstruction(CallInst, STI);
118 }
119
120 static void EmitSETHI(MCStreamer &OutStreamer,
121                       MCOperand &Imm, MCOperand &RD,
122                       const MCSubtargetInfo &STI)
123 {
124   MCInst SETHIInst;
125   SETHIInst.setOpcode(SP::SETHIi);
126   SETHIInst.addOperand(RD);
127   SETHIInst.addOperand(Imm);
128   OutStreamer.EmitInstruction(SETHIInst, STI);
129 }
130
131 static void EmitBinary(MCStreamer &OutStreamer, unsigned Opcode,
132                        MCOperand &RS1, MCOperand &Src2, MCOperand &RD,
133                        const MCSubtargetInfo &STI)
134 {
135   MCInst Inst;
136   Inst.setOpcode(Opcode);
137   Inst.addOperand(RD);
138   Inst.addOperand(RS1);
139   Inst.addOperand(Src2);
140   OutStreamer.EmitInstruction(Inst, STI);
141 }
142
143 static void EmitOR(MCStreamer &OutStreamer,
144                    MCOperand &RS1, MCOperand &Imm, MCOperand &RD,
145                    const MCSubtargetInfo &STI) {
146   EmitBinary(OutStreamer, SP::ORri, RS1, Imm, RD, STI);
147 }
148
149 static void EmitADD(MCStreamer &OutStreamer,
150                     MCOperand &RS1, MCOperand &RS2, MCOperand &RD,
151                     const MCSubtargetInfo &STI) {
152   EmitBinary(OutStreamer, SP::ADDrr, RS1, RS2, RD, STI);
153 }
154
155 static void EmitSHL(MCStreamer &OutStreamer,
156                     MCOperand &RS1, MCOperand &Imm, MCOperand &RD,
157                     const MCSubtargetInfo &STI) {
158   EmitBinary(OutStreamer, SP::SLLri, RS1, Imm, RD, STI);
159 }
160
161
162 static void EmitHiLo(MCStreamer &OutStreamer,  MCSymbol *GOTSym,
163                      SparcMCExpr::VariantKind HiKind,
164                      SparcMCExpr::VariantKind LoKind,
165                      MCOperand &RD,
166                      MCContext &OutContext,
167                      const MCSubtargetInfo &STI) {
168
169   MCOperand hi = createSparcMCOperand(HiKind, GOTSym, OutContext);
170   MCOperand lo = createSparcMCOperand(LoKind, GOTSym, OutContext);
171   EmitSETHI(OutStreamer, hi, RD, STI);
172   EmitOR(OutStreamer, RD, lo, RD, STI);
173 }
174
175 void SparcAsmPrinter::LowerGETPCXAndEmitMCInsts(const MachineInstr *MI,
176                                                 const MCSubtargetInfo &STI)
177 {
178   MCSymbol *GOTLabel   =
179     OutContext.GetOrCreateSymbol(Twine("_GLOBAL_OFFSET_TABLE_"));
180
181   const MachineOperand &MO = MI->getOperand(0);
182   assert(MO.getReg() != SP::O7 &&
183          "%o7 is assigned as destination for getpcx!");
184
185   MCOperand MCRegOP = MCOperand::CreateReg(MO.getReg());
186
187
188   if (TM.getRelocationModel() != Reloc::PIC_) {
189     // Just load the address of GOT to MCRegOP.
190     switch(TM.getCodeModel()) {
191     default:
192       llvm_unreachable("Unsupported absolute code model");
193     case CodeModel::Small:
194       EmitHiLo(OutStreamer, GOTLabel,
195                SparcMCExpr::VK_Sparc_HI, SparcMCExpr::VK_Sparc_LO,
196                MCRegOP, OutContext, STI);
197       break;
198     case CodeModel::Medium: {
199       EmitHiLo(OutStreamer, GOTLabel,
200                SparcMCExpr::VK_Sparc_H44, SparcMCExpr::VK_Sparc_M44,
201                MCRegOP, OutContext, STI);
202       MCOperand imm = MCOperand::CreateExpr(MCConstantExpr::Create(12,
203                                                                    OutContext));
204       EmitSHL(OutStreamer, MCRegOP, imm, MCRegOP, STI);
205       MCOperand lo = createSparcMCOperand(SparcMCExpr::VK_Sparc_L44,
206                                           GOTLabel, OutContext);
207       EmitOR(OutStreamer, MCRegOP, lo, MCRegOP, STI);
208       break;
209     }
210     case CodeModel::Large: {
211       EmitHiLo(OutStreamer, GOTLabel,
212                SparcMCExpr::VK_Sparc_HH, SparcMCExpr::VK_Sparc_HM,
213                MCRegOP, OutContext, STI);
214       MCOperand imm = MCOperand::CreateExpr(MCConstantExpr::Create(32,
215                                                                    OutContext));
216       EmitSHL(OutStreamer, MCRegOP, imm, MCRegOP, STI);
217       // Use register %o7 to load the lower 32 bits.
218       MCOperand RegO7 = MCOperand::CreateReg(SP::O7);
219       EmitHiLo(OutStreamer, GOTLabel,
220                SparcMCExpr::VK_Sparc_HI, SparcMCExpr::VK_Sparc_LO,
221                RegO7, OutContext, STI);
222       EmitADD(OutStreamer, MCRegOP, RegO7, MCRegOP, STI);
223     }
224     }
225     return;
226   }
227
228   MCSymbol *StartLabel = OutContext.CreateTempSymbol();
229   MCSymbol *EndLabel   = OutContext.CreateTempSymbol();
230   MCSymbol *SethiLabel = OutContext.CreateTempSymbol();
231
232   MCOperand RegO7   = MCOperand::CreateReg(SP::O7);
233
234   // <StartLabel>:
235   //   call <EndLabel>
236   // <SethiLabel>:
237   //     sethi %hi(_GLOBAL_OFFSET_TABLE_+(<SethiLabel>-<StartLabel>)), <MO>
238   // <EndLabel>:
239   //   or  <MO>, %lo(_GLOBAL_OFFSET_TABLE_+(<EndLabel>-<StartLabel>))), <MO>
240   //   add <MO>, %o7, <MO>
241
242   OutStreamer.EmitLabel(StartLabel);
243   MCOperand Callee =  createPCXCallOP(EndLabel, OutContext);
244   EmitCall(OutStreamer, Callee, STI);
245   OutStreamer.EmitLabel(SethiLabel);
246   MCOperand hiImm = createPCXRelExprOp(SparcMCExpr::VK_Sparc_HI,
247                                        GOTLabel, StartLabel, SethiLabel,
248                                        OutContext);
249   EmitSETHI(OutStreamer, hiImm, MCRegOP, STI);
250   OutStreamer.EmitLabel(EndLabel);
251   MCOperand loImm = createPCXRelExprOp(SparcMCExpr::VK_Sparc_LO,
252                                        GOTLabel, StartLabel, EndLabel,
253                                        OutContext);
254   EmitOR(OutStreamer, MCRegOP, loImm, MCRegOP, STI);
255   EmitADD(OutStreamer, MCRegOP, RegO7, MCRegOP, STI);
256 }
257
258 void SparcAsmPrinter::EmitInstruction(const MachineInstr *MI)
259 {
260
261   switch (MI->getOpcode()) {
262   default: break;
263   case TargetOpcode::DBG_VALUE:
264     // FIXME: Debug Value.
265     return;
266   case SP::GETPCX:
267     LowerGETPCXAndEmitMCInsts(MI, getSubtargetInfo());
268     return;
269   }
270   MachineBasicBlock::const_instr_iterator I = MI;
271   MachineBasicBlock::const_instr_iterator E = MI->getParent()->instr_end();
272   do {
273     MCInst TmpInst;
274     LowerSparcMachineInstrToMCInst(I, TmpInst, *this);
275     EmitToStreamer(OutStreamer, TmpInst);
276   } while ((++I != E) && I->isInsideBundle()); // Delay slot check.
277 }
278
279 void SparcAsmPrinter::EmitFunctionBodyStart() {
280   if (!TM.getSubtarget<SparcSubtarget>().is64Bit())
281     return;
282
283   const MachineRegisterInfo &MRI = MF->getRegInfo();
284   const unsigned globalRegs[] = { SP::G2, SP::G3, SP::G6, SP::G7, 0 };
285   for (unsigned i = 0; globalRegs[i] != 0; ++i) {
286     unsigned reg = globalRegs[i];
287     if (MRI.use_empty(reg))
288       continue;
289
290     if  (reg == SP::G6 || reg == SP::G7)
291       getTargetStreamer().emitSparcRegisterIgnore(reg);
292     else
293       getTargetStreamer().emitSparcRegisterScratch(reg);
294   }
295 }
296
297 void SparcAsmPrinter::printOperand(const MachineInstr *MI, int opNum,
298                                    raw_ostream &O) {
299   const DataLayout *DL = TM.getDataLayout();
300   const MachineOperand &MO = MI->getOperand (opNum);
301   unsigned TF = MO.getTargetFlags();
302 #ifndef NDEBUG
303   // Verify the target flags.
304   if (MO.isGlobal() || MO.isSymbol() || MO.isCPI()) {
305     if (MI->getOpcode() == SP::CALL)
306       assert(TF == SPII::MO_NO_FLAG &&
307              "Cannot handle target flags on call address");
308     else if (MI->getOpcode() == SP::SETHIi || MI->getOpcode() == SP::SETHIXi)
309       assert((TF == SPII::MO_HI || TF == SPII::MO_H44 || TF == SPII::MO_HH
310               || TF == SPII::MO_TLS_GD_HI22
311               || TF == SPII::MO_TLS_LDM_HI22
312               || TF == SPII::MO_TLS_LDO_HIX22
313               || TF == SPII::MO_TLS_IE_HI22
314               || TF == SPII::MO_TLS_LE_HIX22) &&
315              "Invalid target flags for address operand on sethi");
316     else if (MI->getOpcode() == SP::TLS_CALL)
317       assert((TF == SPII::MO_NO_FLAG
318               || TF == SPII::MO_TLS_GD_CALL
319               || TF == SPII::MO_TLS_LDM_CALL) &&
320              "Cannot handle target flags on tls call address");
321     else if (MI->getOpcode() == SP::TLS_ADDrr)
322       assert((TF == SPII::MO_TLS_GD_ADD || TF == SPII::MO_TLS_LDM_ADD
323               || TF == SPII::MO_TLS_LDO_ADD || TF == SPII::MO_TLS_IE_ADD) &&
324              "Cannot handle target flags on add for TLS");
325     else if (MI->getOpcode() == SP::TLS_LDrr)
326       assert(TF == SPII::MO_TLS_IE_LD &&
327              "Cannot handle target flags on ld for TLS");
328     else if (MI->getOpcode() == SP::TLS_LDXrr)
329       assert(TF == SPII::MO_TLS_IE_LDX &&
330              "Cannot handle target flags on ldx for TLS");
331     else if (MI->getOpcode() == SP::XORri || MI->getOpcode() == SP::XORXri)
332       assert((TF == SPII::MO_TLS_LDO_LOX10 || TF == SPII::MO_TLS_LE_LOX10) &&
333              "Cannot handle target flags on xor for TLS");
334     else
335       assert((TF == SPII::MO_LO || TF == SPII::MO_M44 || TF == SPII::MO_L44
336               || TF == SPII::MO_HM
337               || TF == SPII::MO_TLS_GD_LO10
338               || TF == SPII::MO_TLS_LDM_LO10
339               || TF == SPII::MO_TLS_IE_LO10 ) &&
340              "Invalid target flags for small address operand");
341   }
342 #endif
343
344   bool CloseParen = true;
345   switch (TF) {
346   default:
347       llvm_unreachable("Unknown target flags on operand");
348   case SPII::MO_NO_FLAG:
349     CloseParen = false;
350     break;
351   case SPII::MO_LO:  O << "%lo(";  break;
352   case SPII::MO_HI:  O << "%hi(";  break;
353   case SPII::MO_H44: O << "%h44("; break;
354   case SPII::MO_M44: O << "%m44("; break;
355   case SPII::MO_L44: O << "%l44("; break;
356   case SPII::MO_HH:  O << "%hh(";  break;
357   case SPII::MO_HM:  O << "%hm(";  break;
358   case SPII::MO_TLS_GD_HI22:   O << "%tgd_hi22(";   break;
359   case SPII::MO_TLS_GD_LO10:   O << "%tgd_lo10(";   break;
360   case SPII::MO_TLS_GD_ADD:    O << "%tgd_add(";    break;
361   case SPII::MO_TLS_GD_CALL:   O << "%tgd_call(";   break;
362   case SPII::MO_TLS_LDM_HI22:  O << "%tldm_hi22(";  break;
363   case SPII::MO_TLS_LDM_LO10:  O << "%tldm_lo10(";  break;
364   case SPII::MO_TLS_LDM_ADD:   O << "%tldm_add(";   break;
365   case SPII::MO_TLS_LDM_CALL:  O << "%tldm_call(";  break;
366   case SPII::MO_TLS_LDO_HIX22: O << "%tldo_hix22("; break;
367   case SPII::MO_TLS_LDO_LOX10: O << "%tldo_lox10("; break;
368   case SPII::MO_TLS_LDO_ADD:   O << "%tldo_add(";   break;
369   case SPII::MO_TLS_IE_HI22:   O << "%tie_hi22(";   break;
370   case SPII::MO_TLS_IE_LO10:   O << "%tie_lo10(";   break;
371   case SPII::MO_TLS_IE_LD:     O << "%tie_ld(";     break;
372   case SPII::MO_TLS_IE_LDX:    O << "%tie_ldx(";    break;
373   case SPII::MO_TLS_IE_ADD:    O << "%tie_add(";    break;
374   case SPII::MO_TLS_LE_HIX22:  O << "%tle_hix22(";  break;
375   case SPII::MO_TLS_LE_LOX10:  O << "%tle_lox10(";   break;
376   }
377
378   switch (MO.getType()) {
379   case MachineOperand::MO_Register:
380     O << "%" << StringRef(getRegisterName(MO.getReg())).lower();
381     break;
382
383   case MachineOperand::MO_Immediate:
384     O << (int)MO.getImm();
385     break;
386   case MachineOperand::MO_MachineBasicBlock:
387     O << *MO.getMBB()->getSymbol();
388     return;
389   case MachineOperand::MO_GlobalAddress:
390     O << *getSymbol(MO.getGlobal());
391     break;
392   case MachineOperand::MO_BlockAddress:
393     O <<  GetBlockAddressSymbol(MO.getBlockAddress())->getName();
394     break;
395   case MachineOperand::MO_ExternalSymbol:
396     O << MO.getSymbolName();
397     break;
398   case MachineOperand::MO_ConstantPoolIndex:
399     O << DL->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << "_"
400       << MO.getIndex();
401     break;
402   default:
403     llvm_unreachable("<unknown operand type>");
404   }
405   if (CloseParen) O << ")";
406 }
407
408 void SparcAsmPrinter::printMemOperand(const MachineInstr *MI, int opNum,
409                                       raw_ostream &O, const char *Modifier) {
410   printOperand(MI, opNum, O);
411
412   // If this is an ADD operand, emit it like normal operands.
413   if (Modifier && !strcmp(Modifier, "arith")) {
414     O << ", ";
415     printOperand(MI, opNum+1, O);
416     return;
417   }
418
419   if (MI->getOperand(opNum+1).isReg() &&
420       MI->getOperand(opNum+1).getReg() == SP::G0)
421     return;   // don't print "+%g0"
422   if (MI->getOperand(opNum+1).isImm() &&
423       MI->getOperand(opNum+1).getImm() == 0)
424     return;   // don't print "+0"
425
426   O << "+";
427   printOperand(MI, opNum+1, O);
428 }
429
430 /// PrintAsmOperand - Print out an operand for an inline asm expression.
431 ///
432 bool SparcAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
433                                       unsigned AsmVariant,
434                                       const char *ExtraCode,
435                                       raw_ostream &O) {
436   if (ExtraCode && ExtraCode[0]) {
437     if (ExtraCode[1] != 0) return true; // Unknown modifier.
438
439     switch (ExtraCode[0]) {
440     default:
441       // See if this is a generic print operand
442       return AsmPrinter::PrintAsmOperand(MI, OpNo, AsmVariant, ExtraCode, O);
443     case 'r':
444      break;
445     }
446   }
447
448   printOperand(MI, OpNo, O);
449
450   return false;
451 }
452
453 bool SparcAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
454                                             unsigned OpNo, unsigned AsmVariant,
455                                             const char *ExtraCode,
456                                             raw_ostream &O) {
457   if (ExtraCode && ExtraCode[0])
458     return true;  // Unknown modifier
459
460   O << '[';
461   printMemOperand(MI, OpNo, O);
462   O << ']';
463
464   return false;
465 }
466
467 void SparcAsmPrinter::EmitEndOfAsmFile(Module &M) {
468   const TargetLoweringObjectFileELF &TLOFELF =
469     static_cast<const TargetLoweringObjectFileELF &>(getObjFileLowering());
470   MachineModuleInfoELF &MMIELF = MMI->getObjFileInfo<MachineModuleInfoELF>();
471
472   // Generate stubs for global variables.
473   MachineModuleInfoELF::SymbolListTy Stubs = MMIELF.GetGVStubList();
474   if (!Stubs.empty()) {
475     OutStreamer.SwitchSection(TLOFELF.getDataSection());
476     unsigned PtrSize = TM.getDataLayout()->getPointerSize(0);
477     for (unsigned i = 0, e = Stubs.size(); i != e; ++i) {
478       OutStreamer.EmitLabel(Stubs[i].first);
479       OutStreamer.EmitSymbolValue(Stubs[i].second.getPointer(), PtrSize);
480     }
481   }
482 }
483
484 // Force static initialization.
485 extern "C" void LLVMInitializeSparcAsmPrinter() {
486   RegisterAsmPrinter<SparcAsmPrinter> X(TheSparcTarget);
487   RegisterAsmPrinter<SparcAsmPrinter> Y(TheSparcV9Target);
488 }