blob: 1abf19591774a37381ce5aceca9d335be243d046 [file] [log] [blame]
Nikolai Bozhenov1cf9c542017-12-07 12:35:02 +00001//===-- 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
23using namespace llvm;
24
25#define DEBUG_TYPE "nios2-asm-printer"
26
27namespace {
28
29class Nios2AsmPrinter : public AsmPrinter {
30
31public:
32 explicit Nios2AsmPrinter(TargetMachine &TM,
33 std::unique_ptr<MCStreamer> Streamer)
34 : AsmPrinter(TM, std::move(Streamer)) {}
35
36 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.
52void 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:
73void Nios2AsmPrinter::EmitFunctionEntryLabel() {
74 OutStreamer->EmitLabel(CurrentFnSym);
75}
76
77// Print out an operand for an inline asm expression.
78bool 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
85bool 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
99void 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.
151extern "C" void LLVMInitializeNios2AsmPrinter() {
152 RegisterAsmPrinter<Nios2AsmPrinter> X(getTheNios2Target());
153}