LLVM API Documentation

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
SparcCodeEmitter.cpp
Go to the documentation of this file.
1 //===-- Sparc/SparcCodeEmitter.cpp - Convert Sparc Code to Machine Code ---===//
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 the pass that transforms the Sparc machine instructions
11 // into relocatable machine code.
12 //
13 //===---------------------------------------------------------------------===//
14 
15 #define DEBUG_TYPE "jit"
16 #include "Sparc.h"
18 #include "SparcRelocations.h"
19 #include "SparcTargetMachine.h"
20 #include "llvm/ADT/Statistic.h"
24 #include "llvm/Support/Debug.h"
25 
26 using namespace llvm;
27 
28 STATISTIC(NumEmitted, "Number of machine instructions emitted");
29 
30 namespace {
31 
32 class SparcCodeEmitter : public MachineFunctionPass {
33  SparcJITInfo *JTI;
34  const SparcInstrInfo *II;
35  const DataLayout *TD;
36  const SparcSubtarget *Subtarget;
38  JITCodeEmitter &MCE;
39  const std::vector<MachineConstantPoolEntry> *MCPEs;
40  bool IsPIC;
41 
42  void getAnalysisUsage(AnalysisUsage &AU) const {
45  }
46 
47  static char ID;
48 
49 public:
50  SparcCodeEmitter(TargetMachine &tm, JITCodeEmitter &mce)
51  : MachineFunctionPass(ID), JTI(0), II(0), TD(0),
52  TM(tm), MCE(mce), MCPEs(0),
53  IsPIC(TM.getRelocationModel() == Reloc::PIC_) {}
54 
55  bool runOnMachineFunction(MachineFunction &MF);
56 
57  virtual const char *getPassName() const {
58  return "Sparc Machine Code Emitter";
59  }
60 
61  /// getBinaryCodeForInstr - This function, generated by the
62  /// CodeEmitterGenerator using TableGen, produces the binary encoding for
63  /// machine instructions.
64  uint64_t getBinaryCodeForInstr(const MachineInstr &MI) const;
65 
66  void emitInstruction(MachineBasicBlock::instr_iterator MI,
67  MachineBasicBlock &MBB);
68 
69 private:
70  /// getMachineOpValue - Return binary encoding of operand. If the machine
71  /// operand requires relocation, record the relocation and return zero.
72  unsigned getMachineOpValue(const MachineInstr &MI,
73  const MachineOperand &MO) const;
74 
75  void emitWord(unsigned Word);
76 
77  unsigned getRelocation(const MachineInstr &MI,
78  const MachineOperand &MO) const;
79 
80  void emitGlobalAddress(const GlobalValue *GV, unsigned Reloc) const;
81  void emitExternalSymbolAddress(const char *ES, unsigned Reloc) const;
82  void emitConstPoolAddress(unsigned CPI, unsigned Reloc) const;
83  void emitMachineBasicBlock(MachineBasicBlock *BB, unsigned Reloc) const;
84 };
85 } // end anonymous namespace.
86 
87 char SparcCodeEmitter::ID = 0;
88 
89 bool SparcCodeEmitter::runOnMachineFunction(MachineFunction &MF) {
91  const_cast<TargetMachine &>(MF.getTarget()));
92 
93  JTI = Target.getJITInfo();
94  II = Target.getInstrInfo();
95  TD = Target.getDataLayout();
96  Subtarget = &TM.getSubtarget<SparcSubtarget> ();
97  MCPEs = &MF.getConstantPool()->getConstants();
98  JTI->Initialize(MF, IsPIC);
99  MCE.setModuleInfo(&getAnalysis<MachineModuleInfo> ());
100 
101  do {
102  DEBUG(errs() << "JITTing function '"
103  << MF.getName() << "'\n");
104  MCE.startFunction(MF);
105 
106  for (MachineFunction::iterator MBB = MF.begin(), E = MF.end();
107  MBB != E; ++MBB){
108  MCE.StartMachineBasicBlock(MBB);
109  for (MachineBasicBlock::instr_iterator I = MBB->instr_begin(),
110  E = MBB->instr_end(); I != E;)
111  emitInstruction(*I++, *MBB);
112  }
113  } while (MCE.finishFunction(MF));
114 
115  return false;
116 }
117 
118 void SparcCodeEmitter::emitInstruction(MachineBasicBlock::instr_iterator MI,
119  MachineBasicBlock &MBB) {
120  DEBUG(errs() << "JIT: " << (void*)MCE.getCurrentPCValue() << ":\t" << *MI);
121 
122  MCE.processDebugLoc(MI->getDebugLoc(), true);
123 
124  ++NumEmitted;
125 
126  switch (MI->getOpcode()) {
127  default: {
128  emitWord(getBinaryCodeForInstr(*MI));
129  break;
130  }
132  // We allow inline assembler nodes with empty bodies - they can
133  // implicitly define registers, which is ok for JIT.
134  if (MI->getOperand(0).getSymbolName()[0]) {
135  report_fatal_error("JIT does not support inline asm!");
136  }
137  break;
138  }
140  case TargetOpcode::EH_LABEL: {
141  MCE.emitLabel(MI->getOperand(0).getMCSymbol());
142  break;
143  }
145  case TargetOpcode::KILL: {
146  // Do nothing.
147  break;
148  }
149  case SP::GETPCX: {
150  report_fatal_error("JIT does not support pseudo instruction GETPCX yet!");
151  break;
152  }
153  }
154 
155  MCE.processDebugLoc(MI->getDebugLoc(), false);
156 }
157 
158 void SparcCodeEmitter::emitWord(unsigned Word) {
159  DEBUG(errs() << " 0x";
160  errs().write_hex(Word) << "\n");
161  MCE.emitWordBE(Word);
162 }
163 
164 /// getMachineOpValue - Return binary encoding of operand. If the machine
165 /// operand requires relocation, record the relocation and return zero.
166 unsigned SparcCodeEmitter::getMachineOpValue(const MachineInstr &MI,
167  const MachineOperand &MO) const {
168  if (MO.isReg())
169  return TM.getRegisterInfo()->getEncodingValue(MO.getReg());
170  else if (MO.isImm())
171  return static_cast<unsigned>(MO.getImm());
172  else if (MO.isGlobal())
173  emitGlobalAddress(MO.getGlobal(), getRelocation(MI, MO));
174  else if (MO.isSymbol())
175  emitExternalSymbolAddress(MO.getSymbolName(), getRelocation(MI, MO));
176  else if (MO.isCPI())
177  emitConstPoolAddress(MO.getIndex(), getRelocation(MI, MO));
178  else if (MO.isMBB())
179  emitMachineBasicBlock(MO.getMBB(), getRelocation(MI, MO));
180  else
181  llvm_unreachable("Unable to encode MachineOperand!");
182  return 0;
183 }
184 unsigned SparcCodeEmitter::getRelocation(const MachineInstr &MI,
185  const MachineOperand &MO) const {
186 
187  unsigned TF = MO.getTargetFlags();
188  switch (TF) {
189  default:
190  case SPII::MO_NO_FLAG: break;
191  case SPII::MO_LO: return SP::reloc_sparc_lo;
192  case SPII::MO_HI: return SP::reloc_sparc_hi;
193  case SPII::MO_H44:
194  case SPII::MO_M44:
195  case SPII::MO_L44:
196  case SPII::MO_HH:
197  case SPII::MO_HM: assert(0 && "FIXME: Implement Medium/Large code model.");
198  }
199 
200  unsigned Opc = MI.getOpcode();
201  switch (Opc) {
202  default: break;
203  case SP::CALL: return SP::reloc_sparc_pc30;
204  case SP::BA:
205  case SP::BCOND:
206  case SP::FBCOND: return SP::reloc_sparc_pc22;
207  case SP::BPXCC: return SP::reloc_sparc_pc19;
208  }
209  llvm_unreachable("unknown reloc!");
210 }
211 
212 void SparcCodeEmitter::emitGlobalAddress(const GlobalValue *GV,
213  unsigned Reloc) const {
214  MCE.addRelocation(MachineRelocation::getGV(MCE.getCurrentPCOffset(), Reloc,
215  const_cast<GlobalValue *>(GV), 0,
216  true));
217 }
218 
219 void SparcCodeEmitter::
220 emitExternalSymbolAddress(const char *ES, unsigned Reloc) const {
221  MCE.addRelocation(MachineRelocation::getExtSym(MCE.getCurrentPCOffset(),
222  Reloc, ES, 0, 0));
223 }
224 
225 void SparcCodeEmitter::
226 emitConstPoolAddress(unsigned CPI, unsigned Reloc) const {
227  MCE.addRelocation(MachineRelocation::getConstPool(MCE.getCurrentPCOffset(),
228  Reloc, CPI, 0, false));
229 }
230 
231 void SparcCodeEmitter::emitMachineBasicBlock(MachineBasicBlock *BB,
232  unsigned Reloc) const {
233  MCE.addRelocation(MachineRelocation::getBB(MCE.getCurrentPCOffset(),
234  Reloc, BB));
235 }
236 
237 
238 /// createSparcJITCodeEmitterPass - Return a pass that emits the collected Sparc
239 /// code to the specified MCE object.
241  JITCodeEmitter &JCE) {
242  return new SparcCodeEmitter(TM, JCE);
243 }
244 
245 #include "SparcGenCodeEmitter.inc"
raw_ostream & errs()
const GlobalValue * getGlobal() const
MachineBasicBlock * getMBB() const
const char * getSymbolName() const
Instructions::iterator instr_iterator
LLVM_ATTRIBUTE_NORETURN void report_fatal_error(const char *reason, bool gen_crash_diag=true)
FunctionPass * createSparcJITCodeEmitterPass(SparcTargetMachine &TM, JITCodeEmitter &JCE)
AnalysisUsage & addRequired()
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
#define llvm_unreachable(msg)
bool isReg() const
isReg - Tests if this is a MO_Register operand.
ID
LLVM Calling Convention Representation.
Definition: CallingConv.h:26
bool isCPI() const
isCPI - Tests if this is a MO_ConstantPoolIndex operand.
bool isGlobal() const
isGlobal - Tests if this is a MO_GlobalAddress operand.
virtual const SparcInstrInfo * getInstrInfo() const
int getOpcode() const
Definition: MachineInstr.h:261
raw_ostream & write_hex(unsigned long long N)
write_hex - Output N in hexadecimal, without any prefix or padding.
int64_t getImm() const
static MachineRelocation getBB(uintptr_t offset, unsigned RelocationType, MachineBasicBlock *MBB, intptr_t cst=0)
unsigned getTargetFlags() const
STATISTIC(NumEmitted,"Number of machine instructions emitted")
bool isSymbol() const
isSymbol - Tests if this is a MO_ExternalSymbol operand.
MachineConstantPool * getConstantPool()
bool isMBB() const
isMBB - Tests if this is a MO_MachineBasicBlock operand.
static MachineRelocation getGV(uintptr_t offset, unsigned RelocationType, GlobalValue *GV, intptr_t cst=0, bool MayNeedFarStub=0, bool GOTrelative=0)
virtual void getAnalysisUsage(AnalysisUsage &AU) const
IMPLICIT_DEF - This is the MachineInstr-level equivalent of undef.
Definition: TargetOpcodes.h:52
#define I(x, y, z)
Definition: MD5.cpp:54
const TargetMachine & getTarget() const
unsigned getReg() const
getReg - Returns the register number.
static MachineRelocation getConstPool(uintptr_t offset, unsigned RelocationType, unsigned CPI, intptr_t cst=0, bool letTargetResolve=false)
BasicBlockListType::iterator iterator
#define DEBUG(X)
Definition: Debug.h:97
virtual SparcJITInfo * getJITInfo()
const std::vector< MachineConstantPoolEntry > & getConstants() const
virtual const DataLayout * getDataLayout() const
StringRef getName() const
static MachineRelocation getExtSym(uintptr_t offset, unsigned RelocationType, const char *ES, intptr_t cst=0, bool GOTrelative=0, bool NeedStub=true)
INITIALIZE_PASS(GlobalMerge,"global-merge","Global Merge", false, false) bool GlobalMerge const DataLayout * TD