LLVM  9.0.0svn
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 
15 #include "Lanai.h"
16 #include "LanaiInstrInfo.h"
17 #include "LanaiMCInstLower.h"
18 #include "LanaiTargetMachine.h"
24 #include "llvm/IR/Constants.h"
25 #include "llvm/IR/DerivedTypes.h"
26 #include "llvm/IR/Mangler.h"
27 #include "llvm/IR/Module.h"
28 #include "llvm/MC/MCAsmInfo.h"
29 #include "llvm/MC/MCInst.h"
30 #include "llvm/MC/MCInstBuilder.h"
31 #include "llvm/MC/MCStreamer.h"
32 #include "llvm/MC/MCSymbol.h"
35 
36 #define DEBUG_TYPE "asm-printer"
37 
38 using namespace llvm;
39 
40 namespace {
41 class LanaiAsmPrinter : public AsmPrinter {
42 public:
43  explicit LanaiAsmPrinter(TargetMachine &TM,
44  std::unique_ptr<MCStreamer> Streamer)
45  : AsmPrinter(TM, std::move(Streamer)) {}
46 
47  StringRef getPassName() const override { return "Lanai Assembly Printer"; }
48 
49  void printOperand(const MachineInstr *MI, int OpNum, raw_ostream &O);
50  bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
51  const char *ExtraCode, raw_ostream &O) override;
52  void EmitInstruction(const MachineInstr *MI) override;
53  bool isBlockOnlyReachableByFallthrough(
54  const MachineBasicBlock *MBB) const override;
55 
56 private:
57  void customEmitInstruction(const MachineInstr *MI);
58  void emitCallInstruction(const MachineInstr *MI);
59 };
60 } // end of anonymous namespace
61 
62 void LanaiAsmPrinter::printOperand(const MachineInstr *MI, int OpNum,
63  raw_ostream &O) {
64  const MachineOperand &MO = MI->getOperand(OpNum);
65 
66  switch (MO.getType()) {
69  break;
70 
72  O << MO.getImm();
73  break;
74 
76  O << *MO.getMBB()->getSymbol();
77  break;
78 
80  O << *getSymbol(MO.getGlobal());
81  break;
82 
84  MCSymbol *BA = GetBlockAddressSymbol(MO.getBlockAddress());
85  O << BA->getName();
86  break;
87  }
88 
90  O << *GetExternalSymbolSymbol(MO.getSymbolName());
91  break;
92 
94  O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() << '_'
95  << MO.getIndex();
96  break;
97 
99  O << MAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << '_'
100  << MO.getIndex();
101  return;
102 
103  default:
104  llvm_unreachable("<unknown operand type>");
105  }
106 }
107 
108 // PrintAsmOperand - Print out an operand for an inline asm expression.
109 bool LanaiAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
110  const char *ExtraCode, raw_ostream &O) {
111  // Does this asm operand have a single letter operand modifier?
112  if (ExtraCode && ExtraCode[0]) {
113  if (ExtraCode[1])
114  return true; // Unknown modifier.
115 
116  switch (ExtraCode[0]) {
117  // The highest-numbered register of a pair.
118  case 'H': {
119  if (OpNo == 0)
120  return true;
121  const MachineOperand &FlagsOP = MI->getOperand(OpNo - 1);
122  if (!FlagsOP.isImm())
123  return true;
124  unsigned Flags = FlagsOP.getImm();
125  unsigned NumVals = InlineAsm::getNumOperandRegisters(Flags);
126  if (NumVals != 2)
127  return true;
128  unsigned RegOp = OpNo + 1;
129  if (RegOp >= MI->getNumOperands())
130  return true;
131  const MachineOperand &MO = MI->getOperand(RegOp);
132  if (!MO.isReg())
133  return true;
134  unsigned Reg = MO.getReg();
136  return false;
137  }
138  default:
139  return true; // Unknown modifier.
140  }
141  }
142  printOperand(MI, OpNo, O);
143  return false;
144 }
145 
146 //===----------------------------------------------------------------------===//
147 void LanaiAsmPrinter::emitCallInstruction(const MachineInstr *MI) {
148  assert((MI->getOpcode() == Lanai::CALL || MI->getOpcode() == Lanai::CALLR) &&
149  "Unsupported call function");
150 
151  LanaiMCInstLower MCInstLowering(OutContext, *this);
152  MCSubtargetInfo STI = getSubtargetInfo();
153  // Insert save rca instruction immediately before the call.
154  // TODO: We should generate a pc-relative mov instruction here instead
155  // of pc + 16 (should be mov .+16 %rca).
156  OutStreamer->EmitInstruction(MCInstBuilder(Lanai::ADD_I_LO)
157  .addReg(Lanai::RCA)
158  .addReg(Lanai::PC)
159  .addImm(16),
160  STI);
161 
162  // Push rca onto the stack.
163  // st %rca, [--%sp]
164  OutStreamer->EmitInstruction(MCInstBuilder(Lanai::SW_RI)
165  .addReg(Lanai::RCA)
166  .addReg(Lanai::SP)
167  .addImm(-4)
168  .addImm(LPAC::makePreOp(LPAC::ADD)),
169  STI);
170 
171  // Lower the call instruction.
172  if (MI->getOpcode() == Lanai::CALL) {
173  MCInst TmpInst;
174  MCInstLowering.Lower(MI, TmpInst);
175  TmpInst.setOpcode(Lanai::BT);
176  OutStreamer->EmitInstruction(TmpInst, STI);
177  } else {
178  OutStreamer->EmitInstruction(MCInstBuilder(Lanai::ADD_R)
179  .addReg(Lanai::PC)
180  .addReg(MI->getOperand(0).getReg())
181  .addReg(Lanai::R0)
183  STI);
184  }
185 }
186 
187 void LanaiAsmPrinter::customEmitInstruction(const MachineInstr *MI) {
188  LanaiMCInstLower MCInstLowering(OutContext, *this);
189  MCSubtargetInfo STI = getSubtargetInfo();
190  MCInst TmpInst;
191  MCInstLowering.Lower(MI, TmpInst);
192  OutStreamer->EmitInstruction(TmpInst, STI);
193 }
194 
195 void LanaiAsmPrinter::EmitInstruction(const MachineInstr *MI) {
198 
199  do {
200  if (I->isCall()) {
201  emitCallInstruction(&*I);
202  continue;
203  }
204 
205  customEmitInstruction(&*I);
206  } while ((++I != E) && I->isInsideBundle());
207 }
208 
209 // isBlockOnlyReachableByFallthough - Return true if the basic block has
210 // exactly one predecessor and the control transfer mechanism between
211 // the predecessor and this block is a fall-through.
212 // FIXME: could the overridden cases be handled in AnalyzeBranch?
213 bool LanaiAsmPrinter::isBlockOnlyReachableByFallthrough(
214  const MachineBasicBlock *MBB) const {
215  // The predecessor has to be immediately before this block.
216  const MachineBasicBlock *Pred = *MBB->pred_begin();
217 
218  // If the predecessor is a switch statement, assume a jump table
219  // implementation, so it is not a fall through.
220  if (const BasicBlock *B = Pred->getBasicBlock())
221  if (isa<SwitchInst>(B->getTerminator()))
222  return false;
223 
224  // Check default implementation
226  return false;
227 
228  // Otherwise, check the last instruction.
229  // Check if the last terminator is an unconditional branch.
231  while (I != Pred->begin() && !(--I)->isTerminator()) {
232  }
233 
234  return !I->isBarrier();
235 }
236 
237 // Force static initialization.
238 extern "C" void LLVMInitializeLanaiAsmPrinter() {
240 }
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")
instr_iterator instr_end()
MachineBasicBlock * getMBB() const
This class represents lattice values for constants.
Definition: AllocatorList.h:23
Target & getTheLanaiTarget()
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition: MCSymbol.h:41
void LLVMInitializeLanaiAsmPrinter()
unsigned getReg() const
getReg - Returns the register number.
Address of indexed Jump Table for switch.
unsigned Reg
MachineBasicBlock reference.
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
This file declares the MachineConstantPool class which is an abstract constant pool to keep track of ...
unsigned getNumOperands() const
Retuns the total number of operands.
Definition: MachineInstr.h:411
Name of external global symbol.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
Definition: MachineInstr.h:408
const char * getSymbolName() const
RegisterAsmPrinter - Helper template for registering a target specific assembly printer, for use in the target machine initialization function.
Expected< const typename ELFT::Sym * > getSymbol(typename ELFT::SymRange Symbols, uint32_t Index)
Definition: ELF.h:334
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:158
Address of a global value.
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
LLVM Basic Block Representation.
Definition: BasicBlock.h:57
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
const GlobalValue * getGlobal() const
virtual bool isBlockOnlyReachableByFallthrough(const MachineBasicBlock *MBB) const
Return true if the basic block has exactly one predecessor and the control transfer mechanism between...
This class is intended to be used as a driving class for all asm writers.
Definition: AsmPrinter.h:78
static unsigned getNumOperandRegisters(unsigned Flag)
getNumOperandRegisters - Extract the number of registers field from the inline asm operand flag...
Definition: InlineAsm.h:335
Address of a basic block.
MCInstBuilder & addImm(int64_t Val)
Add a new integer immediate operand.
Definition: MCInstBuilder.h:37
self_iterator getIterator()
Definition: ilist_node.h:81
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Iterator for intrusive lists based on ilist_node.
void setOpcode(unsigned Op)
Definition: MCInst.h:170
MachineOperand class - Representation of each machine instruction operand.
Module.h This file contains the declarations for the Module class.
static const char * getRegisterName(unsigned RegNo)
int64_t getImm() const
static unsigned makePreOp(unsigned AluOp)
Definition: LanaiAluCode.h:62
const MachineBasicBlock * getParent() const
Definition: MachineInstr.h:253
Representation of each machine instruction.
Definition: MachineInstr.h:63
static bool printOperand(raw_ostream &OS, const SelectionDAG *G, const SDValue Value)
BitTracker BT
Definition: BitTracker.cpp:73
const BlockAddress * getBlockAddress() const
MCSymbol * getSymbol() const
Return the MCSymbol for this basic block.
#define I(x, y, z)
Definition: MD5.cpp:58
Generic base class for all target subtargets.
const BasicBlock * getBasicBlock() const
Return the LLVM basic block that this instance corresponded to originally.
bool isReg() const
isReg - Tests if this is a MO_Register operand.
StringRef getName() const
getName - Get the symbol name.
Definition: MCSymbol.h:202
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This class implements an extremely fast bulk output stream that can only output to a stream...
Definition: raw_ostream.h:45
Primary interface to the complete machine description for the target machine.
Definition: TargetMachine.h:65
IRTranslator LLVM IR MI
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:48
Address of indexed Constant in Constant Pool.
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:413
MachineOperandType getType() const
getType - Returns the MachineOperandType for this operand.
void Lower(const MachineInstr *MI, MCInst &OutMI) const