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  unsigned AsmVariant, const char *ExtraCode,
52  raw_ostream &O) override;
53  void EmitInstruction(const MachineInstr *MI) override;
54  bool isBlockOnlyReachableByFallthrough(
55  const MachineBasicBlock *MBB) const override;
56 
57 private:
58  void customEmitInstruction(const MachineInstr *MI);
59  void emitCallInstruction(const MachineInstr *MI);
60 };
61 } // end of anonymous namespace
62 
63 void LanaiAsmPrinter::printOperand(const MachineInstr *MI, int OpNum,
64  raw_ostream &O) {
65  const MachineOperand &MO = MI->getOperand(OpNum);
66 
67  switch (MO.getType()) {
70  break;
71 
73  O << MO.getImm();
74  break;
75 
77  O << *MO.getMBB()->getSymbol();
78  break;
79 
81  O << *getSymbol(MO.getGlobal());
82  break;
83 
85  MCSymbol *BA = GetBlockAddressSymbol(MO.getBlockAddress());
86  O << BA->getName();
87  break;
88  }
89 
91  O << *GetExternalSymbolSymbol(MO.getSymbolName());
92  break;
93 
95  O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() << '_'
96  << MO.getIndex();
97  break;
98 
100  O << MAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << '_'
101  << MO.getIndex();
102  return;
103 
104  default:
105  llvm_unreachable("<unknown operand type>");
106  }
107 }
108 
109 // PrintAsmOperand - Print out an operand for an inline asm expression.
110 bool LanaiAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
111  unsigned /*AsmVariant*/,
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  unsigned Flags = FlagsOP.getImm();
127  unsigned NumVals = InlineAsm::getNumOperandRegisters(Flags);
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  unsigned Reg = MO.getReg();
138  return false;
139  }
140  default:
141  return true; // Unknown modifier.
142  }
143  }
144  printOperand(MI, OpNo, O);
145  return false;
146 }
147 
148 //===----------------------------------------------------------------------===//
149 void 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 
189 void 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 
197 void LanaiAsmPrinter::EmitInstruction(const MachineInstr *MI) {
200 
201  do {
202  if (I->isCall()) {
203  emitCallInstruction(&*I);
204  continue;
205  }
206 
207  customEmitInstruction(&*I);
208  } while ((++I != E) && I->isInsideBundle());
209 }
210 
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();
219 
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()))
224  return false;
225 
226  // Check default implementation
228  return false;
229 
230  // Otherwise, check the last instruction.
231  // Check if the last terminator is an unconditional branch.
233  while (I != Pred->begin() && !(--I)->isTerminator()) {
234  }
235 
236  return !I->isBarrier();
237 }
238 
239 // Force static initialization.
240 extern "C" void LLVMInitializeLanaiAsmPrinter() {
242 }
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:336
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:58
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