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 "LanaiAluCode.h"
16 #include "LanaiCondCode.h"
17 #include "LanaiInstrInfo.h"
18 #include "LanaiMCInstLower.h"
19 #include "LanaiTargetMachine.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"
37 
38 #define DEBUG_TYPE "asm-printer"
39 
40 using namespace llvm;
41 
42 namespace {
43 class LanaiAsmPrinter : public AsmPrinter {
44 public:
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;
55  bool isBlockOnlyReachableByFallthrough(
56  const MachineBasicBlock *MBB) const override;
57 
58 private:
59  void customEmitInstruction(const MachineInstr *MI);
60  void emitCallInstruction(const MachineInstr *MI);
61 };
62 } // end of anonymous namespace
63 
64 void 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.
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]) {
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 AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, O);
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()
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:414
Name of external global symbol.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
Definition: MachineInstr.h:411
const char * getSymbolName() const
RegisterAsmPrinter - Helper template for registering a target specific assembly printer, for use in the target machine initialization function.
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)
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...
int64_t getImm() const
static unsigned makePreOp(unsigned AluOp)
Definition: LanaiAluCode.h:62
const MachineBasicBlock * getParent() const
Definition: MachineInstr.h:256
Representation of each machine instruction.
Definition: MachineInstr.h:64
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:204
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.
Register getReg() const
getReg - Returns the register number.
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:416
MachineOperandType getType() const
getType - Returns the MachineOperandType for this operand.
void Lower(const MachineInstr *MI, MCInst &OutMI) const