1 //===-- LanaiAsmPrinter.cpp - Lanai LLVM assembly writer ------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // This file contains a printer that converts from our internal representation
10 // of machine-dependent LLVM code to the Lanai assembly language.
12 //===----------------------------------------------------------------------===//
14 #include "MCTargetDesc/LanaiInstPrinter.h"
15 #include "LanaiAluCode.h"
16 #include "LanaiCondCode.h"
17 #include "LanaiInstrInfo.h"
18 #include "LanaiMCInstLower.h"
19 #include "LanaiTargetMachine.h"
20 #include "TargetInfo/LanaiTargetInfo.h"
21 #include "llvm/CodeGen/AsmPrinter.h"
22 #include "llvm/CodeGen/MachineConstantPool.h"
23 #include "llvm/CodeGen/MachineFunctionPass.h"
24 #include "llvm/CodeGen/MachineInstr.h"
25 #include "llvm/CodeGen/MachineModuleInfo.h"
26 #include "llvm/IR/Constants.h"
27 #include "llvm/IR/DerivedTypes.h"
28 #include "llvm/IR/Mangler.h"
29 #include "llvm/IR/Module.h"
30 #include "llvm/MC/MCAsmInfo.h"
31 #include "llvm/MC/MCInst.h"
32 #include "llvm/MC/MCInstBuilder.h"
33 #include "llvm/MC/MCStreamer.h"
34 #include "llvm/MC/MCSymbol.h"
35 #include "llvm/Support/TargetRegistry.h"
36 #include "llvm/Support/raw_ostream.h"
38 #define DEBUG_TYPE "asm-printer"
43 class LanaiAsmPrinter
: public AsmPrinter
{
45 explicit LanaiAsmPrinter(TargetMachine
&TM
,
46 std::unique_ptr
<MCStreamer
> Streamer
)
47 : AsmPrinter(TM
, std::move(Streamer
)) {}
49 StringRef
getPassName() const override
{ return "Lanai Assembly Printer"; }
51 void printOperand(const MachineInstr
*MI
, int OpNum
, raw_ostream
&O
);
52 bool PrintAsmOperand(const MachineInstr
*MI
, unsigned OpNo
,
53 const char *ExtraCode
, raw_ostream
&O
) override
;
54 void EmitInstruction(const MachineInstr
*MI
) override
;
55 bool isBlockOnlyReachableByFallthrough(
56 const MachineBasicBlock
*MBB
) const override
;
59 void customEmitInstruction(const MachineInstr
*MI
);
60 void emitCallInstruction(const MachineInstr
*MI
);
62 } // end of anonymous namespace
64 void LanaiAsmPrinter::printOperand(const MachineInstr
*MI
, int OpNum
,
66 const MachineOperand
&MO
= MI
->getOperand(OpNum
);
68 switch (MO
.getType()) {
69 case MachineOperand::MO_Register
:
70 O
<< LanaiInstPrinter::getRegisterName(MO
.getReg());
73 case MachineOperand::MO_Immediate
:
77 case MachineOperand::MO_MachineBasicBlock
:
78 O
<< *MO
.getMBB()->getSymbol();
81 case MachineOperand::MO_GlobalAddress
:
82 O
<< *getSymbol(MO
.getGlobal());
85 case MachineOperand::MO_BlockAddress
: {
86 MCSymbol
*BA
= GetBlockAddressSymbol(MO
.getBlockAddress());
91 case MachineOperand::MO_ExternalSymbol
:
92 O
<< *GetExternalSymbolSymbol(MO
.getSymbolName());
95 case MachineOperand::MO_JumpTableIndex
:
96 O
<< MAI
->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() << '_'
100 case MachineOperand::MO_ConstantPoolIndex
:
101 O
<< MAI
->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << '_'
106 llvm_unreachable("<unknown operand type>");
110 // PrintAsmOperand - Print out an operand for an inline asm expression.
111 bool LanaiAsmPrinter::PrintAsmOperand(const MachineInstr
*MI
, unsigned OpNo
,
112 const char *ExtraCode
, raw_ostream
&O
) {
113 // Does this asm operand have a single letter operand modifier?
114 if (ExtraCode
&& ExtraCode
[0]) {
116 return true; // Unknown modifier.
118 switch (ExtraCode
[0]) {
119 // The highest-numbered register of a pair.
123 const MachineOperand
&FlagsOP
= MI
->getOperand(OpNo
- 1);
124 if (!FlagsOP
.isImm())
126 unsigned Flags
= FlagsOP
.getImm();
127 unsigned NumVals
= InlineAsm::getNumOperandRegisters(Flags
);
130 unsigned RegOp
= OpNo
+ 1;
131 if (RegOp
>= MI
->getNumOperands())
133 const MachineOperand
&MO
= MI
->getOperand(RegOp
);
136 unsigned Reg
= MO
.getReg();
137 O
<< LanaiInstPrinter::getRegisterName(Reg
);
141 return AsmPrinter::PrintAsmOperand(MI
, OpNo
, ExtraCode
, O
);
144 printOperand(MI
, OpNo
, O
);
148 //===----------------------------------------------------------------------===//
149 void LanaiAsmPrinter::emitCallInstruction(const MachineInstr
*MI
) {
150 assert((MI
->getOpcode() == Lanai::CALL
|| MI
->getOpcode() == Lanai::CALLR
) &&
151 "Unsupported call function");
153 LanaiMCInstLower
MCInstLowering(OutContext
, *this);
154 MCSubtargetInfo STI
= getSubtargetInfo();
155 // Insert save rca instruction immediately before the call.
156 // TODO: We should generate a pc-relative mov instruction here instead
157 // of pc + 16 (should be mov .+16 %rca).
158 OutStreamer
->EmitInstruction(MCInstBuilder(Lanai::ADD_I_LO
)
164 // Push rca onto the stack.
166 OutStreamer
->EmitInstruction(MCInstBuilder(Lanai::SW_RI
)
170 .addImm(LPAC::makePreOp(LPAC::ADD
)),
173 // Lower the call instruction.
174 if (MI
->getOpcode() == Lanai::CALL
) {
176 MCInstLowering
.Lower(MI
, TmpInst
);
177 TmpInst
.setOpcode(Lanai::BT
);
178 OutStreamer
->EmitInstruction(TmpInst
, STI
);
180 OutStreamer
->EmitInstruction(MCInstBuilder(Lanai::ADD_R
)
182 .addReg(MI
->getOperand(0).getReg())
184 .addImm(LPCC::ICC_T
),
189 void LanaiAsmPrinter::customEmitInstruction(const MachineInstr
*MI
) {
190 LanaiMCInstLower
MCInstLowering(OutContext
, *this);
191 MCSubtargetInfo STI
= getSubtargetInfo();
193 MCInstLowering
.Lower(MI
, TmpInst
);
194 OutStreamer
->EmitInstruction(TmpInst
, STI
);
197 void LanaiAsmPrinter::EmitInstruction(const MachineInstr
*MI
) {
198 MachineBasicBlock::const_instr_iterator I
= MI
->getIterator();
199 MachineBasicBlock::const_instr_iterator E
= MI
->getParent()->instr_end();
203 emitCallInstruction(&*I
);
207 customEmitInstruction(&*I
);
208 } while ((++I
!= E
) && I
->isInsideBundle());
211 // isBlockOnlyReachableByFallthough - Return true if the basic block has
212 // exactly one predecessor and the control transfer mechanism between
213 // the predecessor and this block is a fall-through.
214 // FIXME: could the overridden cases be handled in AnalyzeBranch?
215 bool LanaiAsmPrinter::isBlockOnlyReachableByFallthrough(
216 const MachineBasicBlock
*MBB
) const {
217 // The predecessor has to be immediately before this block.
218 const MachineBasicBlock
*Pred
= *MBB
->pred_begin();
220 // If the predecessor is a switch statement, assume a jump table
221 // implementation, so it is not a fall through.
222 if (const BasicBlock
*B
= Pred
->getBasicBlock())
223 if (isa
<SwitchInst
>(B
->getTerminator()))
226 // Check default implementation
227 if (!AsmPrinter::isBlockOnlyReachableByFallthrough(MBB
))
230 // Otherwise, check the last instruction.
231 // Check if the last terminator is an unconditional branch.
232 MachineBasicBlock::const_iterator I
= Pred
->end();
233 while (I
!= Pred
->begin() && !(--I
)->isTerminator()) {
236 return !I
->isBarrier();
239 // Force static initialization.
240 extern "C" void LLVMInitializeLanaiAsmPrinter() {
241 RegisterAsmPrinter
<LanaiAsmPrinter
> X(getTheLanaiTarget());