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