1*9880d681SAndroid Build Coastguard Worker //===-- LanaiAsmPrinter.cpp - Lanai LLVM assembly writer ------------------===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker // The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker //
10*9880d681SAndroid Build Coastguard Worker // This file contains a printer that converts from our internal representation
11*9880d681SAndroid Build Coastguard Worker // of machine-dependent LLVM code to the Lanai assembly language.
12*9880d681SAndroid Build Coastguard Worker //
13*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
14*9880d681SAndroid Build Coastguard Worker
15*9880d681SAndroid Build Coastguard Worker #include "InstPrinter/LanaiInstPrinter.h"
16*9880d681SAndroid Build Coastguard Worker #include "Lanai.h"
17*9880d681SAndroid Build Coastguard Worker #include "LanaiInstrInfo.h"
18*9880d681SAndroid Build Coastguard Worker #include "LanaiMCInstLower.h"
19*9880d681SAndroid Build Coastguard Worker #include "LanaiTargetMachine.h"
20*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/AsmPrinter.h"
21*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineConstantPool.h"
22*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineFunctionPass.h"
23*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineInstr.h"
24*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineModuleInfo.h"
25*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Constants.h"
26*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/DerivedTypes.h"
27*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Mangler.h"
28*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Module.h"
29*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCAsmInfo.h"
30*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCInst.h"
31*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCInstBuilder.h"
32*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCStreamer.h"
33*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCSymbol.h"
34*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/TargetRegistry.h"
35*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/raw_ostream.h"
36*9880d681SAndroid Build Coastguard Worker
37*9880d681SAndroid Build Coastguard Worker #define DEBUG_TYPE "asm-printer"
38*9880d681SAndroid Build Coastguard Worker
39*9880d681SAndroid Build Coastguard Worker using namespace llvm;
40*9880d681SAndroid Build Coastguard Worker
41*9880d681SAndroid Build Coastguard Worker namespace {
42*9880d681SAndroid Build Coastguard Worker class LanaiAsmPrinter : public AsmPrinter {
43*9880d681SAndroid Build Coastguard Worker public:
LanaiAsmPrinter(TargetMachine & TM,std::unique_ptr<MCStreamer> Streamer)44*9880d681SAndroid Build Coastguard Worker explicit LanaiAsmPrinter(TargetMachine &TM,
45*9880d681SAndroid Build Coastguard Worker std::unique_ptr<MCStreamer> Streamer)
46*9880d681SAndroid Build Coastguard Worker : AsmPrinter(TM, std::move(Streamer)) {}
47*9880d681SAndroid Build Coastguard Worker
getPassName() const48*9880d681SAndroid Build Coastguard Worker const char *getPassName() const override { return "Lanai Assembly Printer"; }
49*9880d681SAndroid Build Coastguard Worker
50*9880d681SAndroid Build Coastguard Worker void printOperand(const MachineInstr *MI, int OpNum, raw_ostream &O,
51*9880d681SAndroid Build Coastguard Worker const char *Modifier = 0);
52*9880d681SAndroid Build Coastguard Worker bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
53*9880d681SAndroid Build Coastguard Worker unsigned AsmVariant, const char *ExtraCode,
54*9880d681SAndroid Build Coastguard Worker raw_ostream &O) override;
55*9880d681SAndroid Build Coastguard Worker void EmitInstruction(const MachineInstr *MI) override;
56*9880d681SAndroid Build Coastguard Worker bool isBlockOnlyReachableByFallthrough(
57*9880d681SAndroid Build Coastguard Worker const MachineBasicBlock *MBB) const override;
58*9880d681SAndroid Build Coastguard Worker
59*9880d681SAndroid Build Coastguard Worker private:
60*9880d681SAndroid Build Coastguard Worker void customEmitInstruction(const MachineInstr *MI);
61*9880d681SAndroid Build Coastguard Worker void emitCallInstruction(const MachineInstr *MI);
62*9880d681SAndroid Build Coastguard Worker };
63*9880d681SAndroid Build Coastguard Worker } // end of anonymous namespace
64*9880d681SAndroid Build Coastguard Worker
printOperand(const MachineInstr * MI,int OpNum,raw_ostream & O,const char * Modifier)65*9880d681SAndroid Build Coastguard Worker void LanaiAsmPrinter::printOperand(const MachineInstr *MI, int OpNum,
66*9880d681SAndroid Build Coastguard Worker raw_ostream &O, const char *Modifier) {
67*9880d681SAndroid Build Coastguard Worker const MachineOperand &MO = MI->getOperand(OpNum);
68*9880d681SAndroid Build Coastguard Worker
69*9880d681SAndroid Build Coastguard Worker switch (MO.getType()) {
70*9880d681SAndroid Build Coastguard Worker case MachineOperand::MO_Register:
71*9880d681SAndroid Build Coastguard Worker O << LanaiInstPrinter::getRegisterName(MO.getReg());
72*9880d681SAndroid Build Coastguard Worker break;
73*9880d681SAndroid Build Coastguard Worker
74*9880d681SAndroid Build Coastguard Worker case MachineOperand::MO_Immediate:
75*9880d681SAndroid Build Coastguard Worker O << MO.getImm();
76*9880d681SAndroid Build Coastguard Worker break;
77*9880d681SAndroid Build Coastguard Worker
78*9880d681SAndroid Build Coastguard Worker case MachineOperand::MO_MachineBasicBlock:
79*9880d681SAndroid Build Coastguard Worker O << *MO.getMBB()->getSymbol();
80*9880d681SAndroid Build Coastguard Worker break;
81*9880d681SAndroid Build Coastguard Worker
82*9880d681SAndroid Build Coastguard Worker case MachineOperand::MO_GlobalAddress:
83*9880d681SAndroid Build Coastguard Worker O << *getSymbol(MO.getGlobal());
84*9880d681SAndroid Build Coastguard Worker break;
85*9880d681SAndroid Build Coastguard Worker
86*9880d681SAndroid Build Coastguard Worker case MachineOperand::MO_BlockAddress: {
87*9880d681SAndroid Build Coastguard Worker MCSymbol *BA = GetBlockAddressSymbol(MO.getBlockAddress());
88*9880d681SAndroid Build Coastguard Worker O << BA->getName();
89*9880d681SAndroid Build Coastguard Worker break;
90*9880d681SAndroid Build Coastguard Worker }
91*9880d681SAndroid Build Coastguard Worker
92*9880d681SAndroid Build Coastguard Worker case MachineOperand::MO_ExternalSymbol:
93*9880d681SAndroid Build Coastguard Worker O << *GetExternalSymbolSymbol(MO.getSymbolName());
94*9880d681SAndroid Build Coastguard Worker break;
95*9880d681SAndroid Build Coastguard Worker
96*9880d681SAndroid Build Coastguard Worker case MachineOperand::MO_JumpTableIndex:
97*9880d681SAndroid Build Coastguard Worker O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() << '_'
98*9880d681SAndroid Build Coastguard Worker << MO.getIndex();
99*9880d681SAndroid Build Coastguard Worker break;
100*9880d681SAndroid Build Coastguard Worker
101*9880d681SAndroid Build Coastguard Worker case MachineOperand::MO_ConstantPoolIndex:
102*9880d681SAndroid Build Coastguard Worker O << MAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << '_'
103*9880d681SAndroid Build Coastguard Worker << MO.getIndex();
104*9880d681SAndroid Build Coastguard Worker return;
105*9880d681SAndroid Build Coastguard Worker
106*9880d681SAndroid Build Coastguard Worker default:
107*9880d681SAndroid Build Coastguard Worker llvm_unreachable("<unknown operand type>");
108*9880d681SAndroid Build Coastguard Worker }
109*9880d681SAndroid Build Coastguard Worker }
110*9880d681SAndroid Build Coastguard Worker
111*9880d681SAndroid Build Coastguard Worker // PrintAsmOperand - Print out an operand for an inline asm expression.
PrintAsmOperand(const MachineInstr * MI,unsigned OpNo,unsigned AsmVariant,const char * ExtraCode,raw_ostream & O)112*9880d681SAndroid Build Coastguard Worker bool LanaiAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
113*9880d681SAndroid Build Coastguard Worker unsigned AsmVariant,
114*9880d681SAndroid Build Coastguard Worker const char *ExtraCode, raw_ostream &O) {
115*9880d681SAndroid Build Coastguard Worker // Does this asm operand have a single letter operand modifier?
116*9880d681SAndroid Build Coastguard Worker if (ExtraCode && ExtraCode[0]) {
117*9880d681SAndroid Build Coastguard Worker if (ExtraCode[1])
118*9880d681SAndroid Build Coastguard Worker return true; // Unknown modifier.
119*9880d681SAndroid Build Coastguard Worker
120*9880d681SAndroid Build Coastguard Worker switch (ExtraCode[0]) {
121*9880d681SAndroid Build Coastguard Worker // The highest-numbered register of a pair.
122*9880d681SAndroid Build Coastguard Worker case 'H': {
123*9880d681SAndroid Build Coastguard Worker if (OpNo == 0)
124*9880d681SAndroid Build Coastguard Worker return true;
125*9880d681SAndroid Build Coastguard Worker const MachineOperand &FlagsOP = MI->getOperand(OpNo - 1);
126*9880d681SAndroid Build Coastguard Worker if (!FlagsOP.isImm())
127*9880d681SAndroid Build Coastguard Worker return true;
128*9880d681SAndroid Build Coastguard Worker unsigned Flags = FlagsOP.getImm();
129*9880d681SAndroid Build Coastguard Worker unsigned NumVals = InlineAsm::getNumOperandRegisters(Flags);
130*9880d681SAndroid Build Coastguard Worker if (NumVals != 2)
131*9880d681SAndroid Build Coastguard Worker return true;
132*9880d681SAndroid Build Coastguard Worker unsigned RegOp = OpNo + 1;
133*9880d681SAndroid Build Coastguard Worker if (RegOp >= MI->getNumOperands())
134*9880d681SAndroid Build Coastguard Worker return true;
135*9880d681SAndroid Build Coastguard Worker const MachineOperand &MO = MI->getOperand(RegOp);
136*9880d681SAndroid Build Coastguard Worker if (!MO.isReg())
137*9880d681SAndroid Build Coastguard Worker return true;
138*9880d681SAndroid Build Coastguard Worker unsigned Reg = MO.getReg();
139*9880d681SAndroid Build Coastguard Worker O << LanaiInstPrinter::getRegisterName(Reg);
140*9880d681SAndroid Build Coastguard Worker return false;
141*9880d681SAndroid Build Coastguard Worker }
142*9880d681SAndroid Build Coastguard Worker default:
143*9880d681SAndroid Build Coastguard Worker return true; // Unknown modifier.
144*9880d681SAndroid Build Coastguard Worker }
145*9880d681SAndroid Build Coastguard Worker }
146*9880d681SAndroid Build Coastguard Worker printOperand(MI, OpNo, O);
147*9880d681SAndroid Build Coastguard Worker return false;
148*9880d681SAndroid Build Coastguard Worker }
149*9880d681SAndroid Build Coastguard Worker
150*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
emitCallInstruction(const MachineInstr * MI)151*9880d681SAndroid Build Coastguard Worker void LanaiAsmPrinter::emitCallInstruction(const MachineInstr *MI) {
152*9880d681SAndroid Build Coastguard Worker assert((MI->getOpcode() == Lanai::CALL || MI->getOpcode() == Lanai::CALLR) &&
153*9880d681SAndroid Build Coastguard Worker "Unsupported call function");
154*9880d681SAndroid Build Coastguard Worker
155*9880d681SAndroid Build Coastguard Worker LanaiMCInstLower MCInstLowering(OutContext, *Mang, *this);
156*9880d681SAndroid Build Coastguard Worker MCSubtargetInfo STI = getSubtargetInfo();
157*9880d681SAndroid Build Coastguard Worker // Insert save rca instruction immediately before the call.
158*9880d681SAndroid Build Coastguard Worker // TODO: We should generate a pc-relative mov instruction here instead
159*9880d681SAndroid Build Coastguard Worker // of pc + 16 (should be mov .+16 %rca).
160*9880d681SAndroid Build Coastguard Worker OutStreamer->EmitInstruction(MCInstBuilder(Lanai::ADD_I_LO)
161*9880d681SAndroid Build Coastguard Worker .addReg(Lanai::RCA)
162*9880d681SAndroid Build Coastguard Worker .addReg(Lanai::PC)
163*9880d681SAndroid Build Coastguard Worker .addImm(16),
164*9880d681SAndroid Build Coastguard Worker STI);
165*9880d681SAndroid Build Coastguard Worker
166*9880d681SAndroid Build Coastguard Worker // Push rca onto the stack.
167*9880d681SAndroid Build Coastguard Worker // st %rca, [--%sp]
168*9880d681SAndroid Build Coastguard Worker OutStreamer->EmitInstruction(MCInstBuilder(Lanai::SW_RI)
169*9880d681SAndroid Build Coastguard Worker .addReg(Lanai::RCA)
170*9880d681SAndroid Build Coastguard Worker .addReg(Lanai::SP)
171*9880d681SAndroid Build Coastguard Worker .addImm(-4)
172*9880d681SAndroid Build Coastguard Worker .addImm(LPAC::makePreOp(LPAC::ADD)),
173*9880d681SAndroid Build Coastguard Worker STI);
174*9880d681SAndroid Build Coastguard Worker
175*9880d681SAndroid Build Coastguard Worker // Lower the call instruction.
176*9880d681SAndroid Build Coastguard Worker if (MI->getOpcode() == Lanai::CALL) {
177*9880d681SAndroid Build Coastguard Worker MCInst TmpInst;
178*9880d681SAndroid Build Coastguard Worker MCInstLowering.Lower(MI, TmpInst);
179*9880d681SAndroid Build Coastguard Worker TmpInst.setOpcode(Lanai::BT);
180*9880d681SAndroid Build Coastguard Worker OutStreamer->EmitInstruction(TmpInst, STI);
181*9880d681SAndroid Build Coastguard Worker } else {
182*9880d681SAndroid Build Coastguard Worker OutStreamer->EmitInstruction(MCInstBuilder(Lanai::ADD_R)
183*9880d681SAndroid Build Coastguard Worker .addReg(Lanai::PC)
184*9880d681SAndroid Build Coastguard Worker .addReg(MI->getOperand(0).getReg())
185*9880d681SAndroid Build Coastguard Worker .addReg(Lanai::R0)
186*9880d681SAndroid Build Coastguard Worker .addImm(LPCC::ICC_T),
187*9880d681SAndroid Build Coastguard Worker STI);
188*9880d681SAndroid Build Coastguard Worker }
189*9880d681SAndroid Build Coastguard Worker }
190*9880d681SAndroid Build Coastguard Worker
customEmitInstruction(const MachineInstr * MI)191*9880d681SAndroid Build Coastguard Worker void LanaiAsmPrinter::customEmitInstruction(const MachineInstr *MI) {
192*9880d681SAndroid Build Coastguard Worker LanaiMCInstLower MCInstLowering(OutContext, *Mang, *this);
193*9880d681SAndroid Build Coastguard Worker MCSubtargetInfo STI = getSubtargetInfo();
194*9880d681SAndroid Build Coastguard Worker MCInst TmpInst;
195*9880d681SAndroid Build Coastguard Worker MCInstLowering.Lower(MI, TmpInst);
196*9880d681SAndroid Build Coastguard Worker OutStreamer->EmitInstruction(TmpInst, STI);
197*9880d681SAndroid Build Coastguard Worker }
198*9880d681SAndroid Build Coastguard Worker
EmitInstruction(const MachineInstr * MI)199*9880d681SAndroid Build Coastguard Worker void LanaiAsmPrinter::EmitInstruction(const MachineInstr *MI) {
200*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::const_instr_iterator I = MI->getIterator();
201*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::const_instr_iterator E = MI->getParent()->instr_end();
202*9880d681SAndroid Build Coastguard Worker
203*9880d681SAndroid Build Coastguard Worker do {
204*9880d681SAndroid Build Coastguard Worker if (I->isCall()) {
205*9880d681SAndroid Build Coastguard Worker emitCallInstruction(&*I);
206*9880d681SAndroid Build Coastguard Worker continue;
207*9880d681SAndroid Build Coastguard Worker }
208*9880d681SAndroid Build Coastguard Worker
209*9880d681SAndroid Build Coastguard Worker customEmitInstruction(&*I);
210*9880d681SAndroid Build Coastguard Worker } while ((++I != E) && I->isInsideBundle());
211*9880d681SAndroid Build Coastguard Worker }
212*9880d681SAndroid Build Coastguard Worker
213*9880d681SAndroid Build Coastguard Worker // isBlockOnlyReachableByFallthough - Return true if the basic block has
214*9880d681SAndroid Build Coastguard Worker // exactly one predecessor and the control transfer mechanism between
215*9880d681SAndroid Build Coastguard Worker // the predecessor and this block is a fall-through.
216*9880d681SAndroid Build Coastguard Worker // FIXME: could the overridden cases be handled in AnalyzeBranch?
isBlockOnlyReachableByFallthrough(const MachineBasicBlock * MBB) const217*9880d681SAndroid Build Coastguard Worker bool LanaiAsmPrinter::isBlockOnlyReachableByFallthrough(
218*9880d681SAndroid Build Coastguard Worker const MachineBasicBlock *MBB) const {
219*9880d681SAndroid Build Coastguard Worker // The predecessor has to be immediately before this block.
220*9880d681SAndroid Build Coastguard Worker const MachineBasicBlock *Pred = *MBB->pred_begin();
221*9880d681SAndroid Build Coastguard Worker
222*9880d681SAndroid Build Coastguard Worker // If the predecessor is a switch statement, assume a jump table
223*9880d681SAndroid Build Coastguard Worker // implementation, so it is not a fall through.
224*9880d681SAndroid Build Coastguard Worker if (const BasicBlock *B = Pred->getBasicBlock())
225*9880d681SAndroid Build Coastguard Worker if (isa<SwitchInst>(B->getTerminator()))
226*9880d681SAndroid Build Coastguard Worker return false;
227*9880d681SAndroid Build Coastguard Worker
228*9880d681SAndroid Build Coastguard Worker // Check default implementation
229*9880d681SAndroid Build Coastguard Worker if (!AsmPrinter::isBlockOnlyReachableByFallthrough(MBB))
230*9880d681SAndroid Build Coastguard Worker return false;
231*9880d681SAndroid Build Coastguard Worker
232*9880d681SAndroid Build Coastguard Worker // Otherwise, check the last instruction.
233*9880d681SAndroid Build Coastguard Worker // Check if the last terminator is an unconditional branch.
234*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::const_iterator I = Pred->end();
235*9880d681SAndroid Build Coastguard Worker while (I != Pred->begin() && !(--I)->isTerminator()) {
236*9880d681SAndroid Build Coastguard Worker }
237*9880d681SAndroid Build Coastguard Worker
238*9880d681SAndroid Build Coastguard Worker return !I->isBarrier();
239*9880d681SAndroid Build Coastguard Worker }
240*9880d681SAndroid Build Coastguard Worker
241*9880d681SAndroid Build Coastguard Worker // Force static initialization.
LLVMInitializeLanaiAsmPrinter()242*9880d681SAndroid Build Coastguard Worker extern "C" void LLVMInitializeLanaiAsmPrinter() {
243*9880d681SAndroid Build Coastguard Worker RegisterAsmPrinter<LanaiAsmPrinter> X(TheLanaiTarget);
244*9880d681SAndroid Build Coastguard Worker }
245