LLVM  8.0.1
LanaiAsmPrinter.cpp
Go to the documentation of this file.
1 //===-- LanaiAsmPrinter.cpp - Lanai LLVM assembly writer ------------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file contains a printer that converts from our internal representation
11 // of machine-dependent LLVM code to the Lanai assembly language.
12 //
13 //===----------------------------------------------------------------------===//
14 
16 #include "Lanai.h"
17 #include "LanaiInstrInfo.h"
18 #include "LanaiMCInstLower.h"
19 #include "LanaiTargetMachine.h"
25 #include "llvm/IR/Constants.h"
26 #include "llvm/IR/DerivedTypes.h"
27 #include "llvm/IR/Mangler.h"
28 #include "llvm/IR/Module.h"
29 #include "llvm/MC/MCAsmInfo.h"
30 #include "llvm/MC/MCInst.h"
31 #include "llvm/MC/MCInstBuilder.h"
32 #include "llvm/MC/MCStreamer.h"
33 #include "llvm/MC/MCSymbol.h"
36 
37 #define DEBUG_TYPE "asm-printer"
38 
39 using namespace llvm;
40 
41 namespace {
42 class LanaiAsmPrinter : public AsmPrinter {
43 public:
44  explicit LanaiAsmPrinter(TargetMachine &TM,
45  std::unique_ptr<MCStreamer> Streamer)
46  : AsmPrinter(TM, std::move(Streamer)) {}
47 
48  StringRef getPassName() const override { return "Lanai Assembly Printer"; }
49 
50  void printOperand(const MachineInstr *MI, int OpNum, raw_ostream &O);
51  bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
52  unsigned AsmVariant, const char *ExtraCode,
53  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  unsigned /*AsmVariant*/,
113  const char *ExtraCode, raw_ostream &O) {
114  // Does this asm operand have a single letter operand modifier?
115  if (ExtraCode && ExtraCode[0]) {
116  if (ExtraCode[1])
117  return true; // Unknown modifier.
118 
119  switch (ExtraCode[0]) {
120  // The highest-numbered register of a pair.
121  case 'H': {
122  if (OpNo == 0)
123  return true;
124  const MachineOperand &FlagsOP = MI->getOperand(OpNo - 1);
125  if (!FlagsOP.isImm())
126  return true;
127  unsigned Flags = FlagsOP.getImm();
128  unsigned NumVals = InlineAsm::getNumOperandRegisters(Flags);
129  if (NumVals != 2)
130  return true;
131  unsigned RegOp = OpNo + 1;
132  if (RegOp >= MI->getNumOperands())
133  return true;
134  const MachineOperand &MO = MI->getOperand(RegOp);
135  if (!MO.isReg())
136  return true;
137  unsigned Reg = MO.getReg();
139  return false;
140  }
141  default:
142  return true; // Unknown modifier.
143  }
144  }
145  printOperand(MI, OpNo, O);
146  return false;
147 }
148 
149 //===----------------------------------------------------------------------===//
150 void LanaiAsmPrinter::emitCallInstruction(const MachineInstr *MI) {
151  assert((MI->getOpcode() == Lanai::CALL || MI->getOpcode() == Lanai::CALLR) &&
152  "Unsupported call function");
153 
154  LanaiMCInstLower MCInstLowering(OutContext, *this);
155  MCSubtargetInfo STI = getSubtargetInfo();
156  // Insert save rca instruction immediately before the call.
157  // TODO: We should generate a pc-relative mov instruction here instead
158  // of pc + 16 (should be mov .+16 %rca).
159  OutStreamer->EmitInstruction(MCInstBuilder(Lanai::ADD_I_LO)
160  .addReg(Lanai::RCA)
161  .addReg(Lanai::PC)
162  .addImm(16),
163  STI);
164 
165  // Push rca onto the stack.
166  // st %rca, [--%sp]
167  OutStreamer->EmitInstruction(MCInstBuilder(Lanai::SW_RI)
168  .addReg(Lanai::RCA)
169  .addReg(Lanai::SP)
170  .addImm(-4)
171  .addImm(LPAC::makePreOp(LPAC::ADD)),
172  STI);
173 
174  // Lower the call instruction.
175  if (MI->getOpcode() == Lanai::CALL) {
176  MCInst TmpInst;
177  MCInstLowering.Lower(MI, TmpInst);
178  TmpInst.setOpcode(Lanai::BT);
179  OutStreamer->EmitInstruction(TmpInst, STI);
180  } else {
181  OutStreamer->EmitInstruction(MCInstBuilder(Lanai::ADD_R)
182  .addReg(Lanai::PC)
183  .addReg(MI->getOperand(0).getReg())
184  .addReg(Lanai::R0)
186  STI);
187  }
188 }
189 
190 void LanaiAsmPrinter::customEmitInstruction(const MachineInstr *MI) {
191  LanaiMCInstLower MCInstLowering(OutContext, *this);
192  MCSubtargetInfo STI = getSubtargetInfo();
193  MCInst TmpInst;
194  MCInstLowering.Lower(MI, TmpInst);
195  OutStreamer->EmitInstruction(TmpInst, STI);
196 }
197 
198 void LanaiAsmPrinter::EmitInstruction(const MachineInstr *MI) {
201 
202  do {
203  if (I->isCall()) {
204  emitCallInstruction(&*I);
205  continue;
206  }
207 
208  customEmitInstruction(&*I);
209  } while ((++I != E) && I->isInsideBundle());
210 }
211 
212 // isBlockOnlyReachableByFallthough - Return true if the basic block has
213 // exactly one predecessor and the control transfer mechanism between
214 // the predecessor and this block is a fall-through.
215 // FIXME: could the overridden cases be handled in AnalyzeBranch?
216 bool LanaiAsmPrinter::isBlockOnlyReachableByFallthrough(
217  const MachineBasicBlock *MBB) const {
218  // The predecessor has to be immediately before this block.
219  const MachineBasicBlock *Pred = *MBB->pred_begin();
220 
221  // If the predecessor is a switch statement, assume a jump table
222  // implementation, so it is not a fall through.
223  if (const BasicBlock *B = Pred->getBasicBlock())
224  if (isa<SwitchInst>(B->getTerminator()))
225  return false;
226 
227  // Check default implementation
229  return false;
230 
231  // Otherwise, check the last instruction.
232  // Check if the last terminator is an unconditional branch.
234  while (I != Pred->begin() && !(--I)->isTerminator()) {
235  }
236 
237  return !I->isBarrier();
238 }
239 
240 // Force static initialization.
241 extern "C" void LLVMInitializeLanaiAsmPrinter() {
243 }
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:24
Target & getTheLanaiTarget()
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition: MCSymbol.h:42
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:412
Name of external global symbol.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
Definition: MachineInstr.h:409
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:337
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:161
Address of a global value.
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
LLVM Basic Block Representation.
Definition: BasicBlock.h:58
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:79
static unsigned getNumOperandRegisters(unsigned Flag)
getNumOperandRegisters - Extract the number of registers field from the inline asm operand flag...
Definition: InlineAsm.h:336
Address of a basic block.
MCInstBuilder & addImm(int64_t Val)
Add a new integer immediate operand.
Definition: MCInstBuilder.h:38
self_iterator getIterator()
Definition: ilist_node.h:82
#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:173
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:63
const MachineBasicBlock * getParent() const
Definition: MachineInstr.h:254
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:74
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:203
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:46
Primary interface to the complete machine description for the target machine.
Definition: TargetMachine.h:59
IRTranslator LLVM IR MI
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:49
Address of indexed Constant in Constant Pool.
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:414
MachineOperandType getType() const
getType - Returns the MachineOperandType for this operand.
void Lower(const MachineInstr *MI, MCInst &OutMI) const