LLVM 19.0.0git
LanaiAsmPrinter.cpp
Go to the documentation of this file.
1//===-- LanaiAsmPrinter.cpp - Lanai LLVM assembly writer ------------------===//
2//
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
6//
7//===----------------------------------------------------------------------===//
8//
9// This file contains a printer that converts from our internal representation
10// of machine-dependent LLVM code to the Lanai assembly language.
11//
12//===----------------------------------------------------------------------===//
13
14#include "LanaiAluCode.h"
15#include "LanaiCondCode.h"
16#include "LanaiInstrInfo.h"
17#include "LanaiMCInstLower.h"
18#include "LanaiTargetMachine.h"
26#include "llvm/IR/Constants.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"
33#include "llvm/MC/MCStreamer.h"
34#include "llvm/MC/MCSymbol.h"
37
38#define DEBUG_TYPE "asm-printer"
39
40using namespace llvm;
41
42namespace {
43class LanaiAsmPrinter : public AsmPrinter {
44public:
45 explicit LanaiAsmPrinter(TargetMachine &TM,
46 std::unique_ptr<MCStreamer> Streamer)
47 : AsmPrinter(TM, std::move(Streamer)) {}
48
49 StringRef getPassName() const override { return "Lanai Assembly Printer"; }
50
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;
56 const MachineBasicBlock *MBB) const override;
57
58private:
59 void customEmitInstruction(const MachineInstr *MI);
60 void emitCallInstruction(const MachineInstr *MI);
61};
62} // end of anonymous namespace
63
64void LanaiAsmPrinter::printOperand(const MachineInstr *MI, int OpNum,
65 raw_ostream &O) {
66 const MachineOperand &MO = MI->getOperand(OpNum);
67
68 switch (MO.getType()) {
71 break;
72
74 O << MO.getImm();
75 break;
76
78 O << *MO.getMBB()->getSymbol();
79 break;
80
82 O << *getSymbol(MO.getGlobal());
83 break;
84
86 MCSymbol *BA = GetBlockAddressSymbol(MO.getBlockAddress());
87 O << BA->getName();
88 break;
89 }
90
92 O << *GetExternalSymbolSymbol(MO.getSymbolName());
93 break;
94
96 O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() << '_'
97 << MO.getIndex();
98 break;
99
101 O << MAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << '_'
102 << MO.getIndex();
103 return;
104
105 default:
106 llvm_unreachable("<unknown operand type>");
107 }
108}
109
110// PrintAsmOperand - Print out an operand for an inline asm expression.
111bool 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]) {
115 if (ExtraCode[1])
116 return true; // Unknown modifier.
117
118 switch (ExtraCode[0]) {
119 // The highest-numbered register of a pair.
120 case 'H': {
121 if (OpNo == 0)
122 return true;
123 const MachineOperand &FlagsOP = MI->getOperand(OpNo - 1);
124 if (!FlagsOP.isImm())
125 return true;
126 const InlineAsm::Flag Flags(FlagsOP.getImm());
127 const unsigned NumVals = Flags.getNumOperandRegisters();
128 if (NumVals != 2)
129 return true;
130 unsigned RegOp = OpNo + 1;
131 if (RegOp >= MI->getNumOperands())
132 return true;
133 const MachineOperand &MO = MI->getOperand(RegOp);
134 if (!MO.isReg())
135 return true;
136 Register Reg = MO.getReg();
138 return false;
139 }
140 default:
141 return AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, O);
142 }
143 }
144 printOperand(MI, OpNo, O);
145 return false;
146}
147
148//===----------------------------------------------------------------------===//
149void LanaiAsmPrinter::emitCallInstruction(const MachineInstr *MI) {
150 assert((MI->getOpcode() == Lanai::CALL || MI->getOpcode() == Lanai::CALLR) &&
151 "Unsupported call function");
152
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)
159 .addReg(Lanai::RCA)
160 .addReg(Lanai::PC)
161 .addImm(16),
162 STI);
163
164 // Push rca onto the stack.
165 // st %rca, [--%sp]
166 OutStreamer->emitInstruction(MCInstBuilder(Lanai::SW_RI)
167 .addReg(Lanai::RCA)
168 .addReg(Lanai::SP)
169 .addImm(-4)
170 .addImm(LPAC::makePreOp(LPAC::ADD)),
171 STI);
172
173 // Lower the call instruction.
174 if (MI->getOpcode() == Lanai::CALL) {
175 MCInst TmpInst;
176 MCInstLowering.Lower(MI, TmpInst);
177 TmpInst.setOpcode(Lanai::BT);
178 OutStreamer->emitInstruction(TmpInst, STI);
179 } else {
180 OutStreamer->emitInstruction(MCInstBuilder(Lanai::ADD_R)
181 .addReg(Lanai::PC)
182 .addReg(MI->getOperand(0).getReg())
183 .addReg(Lanai::R0)
185 STI);
186 }
187}
188
189void LanaiAsmPrinter::customEmitInstruction(const MachineInstr *MI) {
190 LanaiMCInstLower MCInstLowering(OutContext, *this);
191 MCSubtargetInfo STI = getSubtargetInfo();
192 MCInst TmpInst;
193 MCInstLowering.Lower(MI, TmpInst);
194 OutStreamer->emitInstruction(TmpInst, STI);
195}
196
197void LanaiAsmPrinter::emitInstruction(const MachineInstr *MI) {
198 Lanai_MC::verifyInstructionPredicates(MI->getOpcode(),
199 getSubtargetInfo().getFeatureBits());
200
202 MachineBasicBlock::const_instr_iterator E = MI->getParent()->instr_end();
203
204 do {
205 if (I->isCall()) {
206 emitCallInstruction(&*I);
207 continue;
208 }
209
210 customEmitInstruction(&*I);
211 } while ((++I != E) && I->isInsideBundle());
212}
213
214// isBlockOnlyReachableByFallthough - Return true if the basic block has
215// exactly one predecessor and the control transfer mechanism between
216// the predecessor and this block is a fall-through.
217// FIXME: could the overridden cases be handled in analyzeBranch?
218bool LanaiAsmPrinter::isBlockOnlyReachableByFallthrough(
219 const MachineBasicBlock *MBB) const {
220 // The predecessor has to be immediately before this block.
221 const MachineBasicBlock *Pred = *MBB->pred_begin();
222
223 // If the predecessor is a switch statement, assume a jump table
224 // implementation, so it is not a fall through.
225 if (const BasicBlock *B = Pred->getBasicBlock())
226 if (isa<SwitchInst>(B->getTerminator()))
227 return false;
228
229 // Check default implementation
231 return false;
232
233 // Otherwise, check the last instruction.
234 // Check if the last terminator is an unconditional branch.
236 while (I != Pred->begin() && !(--I)->isTerminator()) {
237 }
238
239 return !I->isBarrier();
240}
241
242// Force static initialization.
245}
MachineBasicBlock & MBB
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define LLVM_EXTERNAL_VISIBILITY
Definition: Compiler.h:135
This file contains the declarations for the subclasses of Constant, which represent the different fla...
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")
IRTranslator LLVM IR MI
LLVM_EXTERNAL_VISIBILITY void LLVMInitializeLanaiAsmPrinter()
#define I(x, y, z)
Definition: MD5.cpp:58
This file declares the MachineConstantPool class which is an abstract constant pool to keep track of ...
Module.h This file contains the declarations for the Module class.
const char LLVMTargetMachineRef TM
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static bool printOperand(raw_ostream &OS, const SelectionDAG *G, const SDValue Value)
This class is intended to be used as a driving class for all asm writers.
Definition: AsmPrinter.h:84
virtual void emitInstruction(const MachineInstr *)
Targets should implement this to emit instructions.
Definition: AsmPrinter.h:567
virtual bool isBlockOnlyReachableByFallthrough(const MachineBasicBlock *MBB) const
Return true if the basic block has exactly one predecessor and the control transfer mechanism between...
virtual bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, const char *ExtraCode, raw_ostream &OS)
Print the specified operand of MI, an INLINEASM instruction, using the specified assembler variant.
LLVM Basic Block Representation.
Definition: BasicBlock.h:60
static const char * getRegisterName(MCRegister Reg)
MCInstBuilder & addReg(unsigned Reg)
Add a new register operand.
Definition: MCInstBuilder.h:37
MCInstBuilder & addImm(int64_t Val)
Add a new integer immediate operand.
Definition: MCInstBuilder.h:43
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:184
void setOpcode(unsigned Op)
Definition: MCInst.h:197
Generic base class for all target subtargets.
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition: MCSymbol.h:40
StringRef getName() const
getName - Get the symbol name.
Definition: MCSymbol.h:205
MCSymbol * getSymbol() const
Return the MCSymbol for this basic block.
const BasicBlock * getBasicBlock() const
Return the LLVM basic block that this instance corresponded to originally.
Instructions::const_iterator const_instr_iterator
Representation of each machine instruction.
Definition: MachineInstr.h:69
MachineOperand class - Representation of each machine instruction operand.
const GlobalValue * getGlobal() const
int64_t getImm() const
bool isReg() const
isReg - Tests if this is a MO_Register operand.
MachineBasicBlock * getMBB() const
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
const BlockAddress * getBlockAddress() const
MachineOperandType getType() const
getType - Returns the MachineOperandType for this operand.
const char * getSymbolName() const
Register getReg() const
getReg - Returns the register number.
@ MO_Immediate
Immediate operand.
@ MO_ConstantPoolIndex
Address of indexed Constant in Constant Pool.
@ MO_GlobalAddress
Address of a global value.
@ MO_BlockAddress
Address of a basic block.
@ MO_MachineBasicBlock
MachineBasicBlock reference.
@ MO_Register
Register operand.
@ MO_ExternalSymbol
Name of external global symbol.
@ MO_JumpTableIndex
Address of indexed Jump Table for switch.
virtual StringRef getPassName() const
getPassName - Return a nice clean name for a pass.
Definition: Pass.cpp:81
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
Primary interface to the complete machine description for the target machine.
Definition: TargetMachine.h:76
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:52
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
static unsigned makePreOp(unsigned AluOp)
Definition: LanaiAluCode.h:61
Reg
All possible values of the reg field in the ModR/M byte.
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
Target & getTheLanaiTarget()
RegisterAsmPrinter - Helper template for registering a target specific assembly printer,...