xref: /aosp_15_r20/external/llvm/lib/Target/Lanai/LanaiAsmPrinter.cpp (revision 9880d6810fe72a1726cb53787c6711e909410d58)
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