• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===-- Nios2AsmPrinter.cpp - Nios2 LLVM Assembly Printer -----------------===//
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 NIOS2 assembly language.
12 //
13 //===----------------------------------------------------------------------===//
14 
15 #include "InstPrinter/Nios2InstPrinter.h"
16 #include "MCTargetDesc/Nios2BaseInfo.h"
17 #include "Nios2.h"
18 #include "Nios2TargetMachine.h"
19 #include "llvm/CodeGen/AsmPrinter.h"
20 #include "llvm/MC/MCStreamer.h"
21 #include "llvm/Support/TargetRegistry.h"
22 
23 using namespace llvm;
24 
25 #define DEBUG_TYPE "nios2-asm-printer"
26 
27 namespace {
28 
29 class Nios2AsmPrinter : public AsmPrinter {
30 
31 public:
Nios2AsmPrinter(TargetMachine & TM,std::unique_ptr<MCStreamer> Streamer)32   explicit Nios2AsmPrinter(TargetMachine &TM,
33                            std::unique_ptr<MCStreamer> Streamer)
34       : AsmPrinter(TM, std::move(Streamer)) {}
35 
getPassName() const36   StringRef getPassName() const override { return "Nios2 Assembly Printer"; }
37 
38   //- EmitInstruction() must exists or will have run time error.
39   void EmitInstruction(const MachineInstr *MI) override;
40   bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
41                        unsigned AsmVariant, const char *ExtraCode,
42                        raw_ostream &O) override;
43   bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNum,
44                              unsigned AsmVariant, const char *ExtraCode,
45                              raw_ostream &O) override;
46   void printOperand(const MachineInstr *MI, int opNum, raw_ostream &O);
47   void EmitFunctionEntryLabel() override;
48 };
49 } // namespace
50 
51 //- EmitInstruction() must exists or will have run time error.
EmitInstruction(const MachineInstr * MI)52 void Nios2AsmPrinter::EmitInstruction(const MachineInstr *MI) {
53 
54   //  Print out both ordinary instruction and boudle instruction
55   MachineBasicBlock::const_instr_iterator I = MI->getIterator();
56   MachineBasicBlock::const_instr_iterator E = MI->getParent()->instr_end();
57 
58   do {
59 
60     if (I->isPseudo()) {
61       llvm_unreachable("Pseudo opcode found in EmitInstruction()");
62     }
63 
64     MCInst TmpInst0;
65     LowerNios2MachineInstToMCInst(&*I, TmpInst0, *this);
66     EmitToStreamer(*OutStreamer, TmpInst0);
67   } while ((++I != E) && I->isInsideBundle()); // Delay slot check
68 }
69 
70 //		.type	main,@function
71 //->		.ent	main                    # @main
72 //	main:
EmitFunctionEntryLabel()73 void Nios2AsmPrinter::EmitFunctionEntryLabel() {
74   OutStreamer->EmitLabel(CurrentFnSym);
75 }
76 
77 // Print out an operand for an inline asm expression.
PrintAsmOperand(const MachineInstr * MI,unsigned OpNum,unsigned AsmVariant,const char * ExtraCode,raw_ostream & O)78 bool Nios2AsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNum,
79                                       unsigned AsmVariant,
80                                       const char *ExtraCode, raw_ostream &O) {
81   printOperand(MI, OpNum, O);
82   return false;
83 }
84 
PrintAsmMemoryOperand(const MachineInstr * MI,unsigned OpNum,unsigned AsmVariant,const char * ExtraCode,raw_ostream & O)85 bool Nios2AsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
86                                             unsigned OpNum, unsigned AsmVariant,
87                                             const char *ExtraCode,
88                                             raw_ostream &O) {
89   if (ExtraCode && ExtraCode[0])
90     return true; // Unknown modifier
91 
92   const MachineOperand &MO = MI->getOperand(OpNum);
93   assert(MO.isReg() && "unexpected inline asm memory operand");
94   O << "($" << Nios2InstPrinter::getRegisterName(MO.getReg()) << ")";
95 
96   return false;
97 }
98 
printOperand(const MachineInstr * MI,int opNum,raw_ostream & O)99 void Nios2AsmPrinter::printOperand(const MachineInstr *MI, int opNum,
100                                    raw_ostream &O) {
101   const MachineOperand &MO = MI->getOperand(opNum);
102   bool closeP = false;
103 
104   if (MO.getTargetFlags())
105     closeP = true;
106 
107   switch (MO.getTargetFlags()) {
108   case Nios2FG::MO_ABS_HI:
109     O << "%hiadj(";
110     break;
111   case Nios2FG::MO_ABS_LO:
112     O << "%lo(";
113     break;
114   }
115 
116   switch (MO.getType()) {
117   case MachineOperand::MO_Register:
118     O << '$'
119       << StringRef(Nios2InstPrinter::getRegisterName(MO.getReg())).lower();
120     break;
121 
122   case MachineOperand::MO_Immediate:
123     O << MO.getImm();
124     break;
125 
126   case MachineOperand::MO_MachineBasicBlock:
127     MO.getMBB()->getSymbol()->print(O, MAI);
128     return;
129 
130   case MachineOperand::MO_GlobalAddress:
131     getSymbol(MO.getGlobal())->print(O, MAI);
132     break;
133 
134   case MachineOperand::MO_BlockAddress:
135     O << GetBlockAddressSymbol(MO.getBlockAddress())->getName();
136     break;
137 
138   case MachineOperand::MO_ExternalSymbol:
139     O << MO.getSymbolName();
140     break;
141 
142   default:
143     llvm_unreachable("<unknown operand type>");
144   }
145 
146   if (closeP)
147     O << ")";
148 }
149 
150 // Force static initialization.
LLVMInitializeNios2AsmPrinter()151 extern "C" void LLVMInitializeNios2AsmPrinter() {
152   RegisterAsmPrinter<Nios2AsmPrinter> X(getTheNios2Target());
153 }
154