blob: da0beaff700df47c6605df260fb4aa096aaa0352 [file] [log] [blame]
Brian Gaekee785e532004-02-25 19:28:19 +00001//===-- SparcV8CodeEmitter.cpp - JIT Code Emitter for SparcV8 -----*- C++ -*-=//
Misha Brukmanb5f662f2005-04-21 23:30:14 +00002//
Brian Gaekee785e532004-02-25 19:28:19 +00003// The LLVM Compiler Infrastructure
4//
5// This file was developed by the LLVM research group and is distributed under
6// the University of Illinois Open Source License. See LICENSE.TXT for details.
Misha Brukmanb5f662f2005-04-21 23:30:14 +00007//
Brian Gaekee785e532004-02-25 19:28:19 +00008//===----------------------------------------------------------------------===//
Misha Brukmanb5f662f2005-04-21 23:30:14 +00009//
Brian Gaekee785e532004-02-25 19:28:19 +000010//
11//===----------------------------------------------------------------------===//
12
Misha Brukmand8e6e7f2004-10-19 19:49:42 +000013#include "SparcV8.h"
Brian Gaekee785e532004-02-25 19:28:19 +000014#include "SparcV8TargetMachine.h"
Misha Brukmand8e6e7f2004-10-19 19:49:42 +000015#include "llvm/Module.h"
16#include "llvm/CodeGen/MachineCodeEmitter.h"
17#include "llvm/CodeGen/MachineFunctionPass.h"
18#include "llvm/CodeGen/Passes.h"
19#include "llvm/Support/Debug.h"
20#include <cstdlib>
21#include <map>
22#include <vector>
Chris Lattner08a6b3c2005-10-24 06:38:35 +000023using namespace llvm;
Brian Gaekee785e532004-02-25 19:28:19 +000024
Misha Brukmand8e6e7f2004-10-19 19:49:42 +000025namespace {
26 class SparcV8CodeEmitter : public MachineFunctionPass {
27 TargetMachine &TM;
28 MachineCodeEmitter &MCE;
29
30 /// getMachineOpValue - evaluates the MachineOperand of a given MachineInstr
31 ///
32 int64_t getMachineOpValue(MachineInstr &MI, MachineOperand &MO);
33
34 // Tracks which instruction references which BasicBlock
35 std::vector<std::pair<const BasicBlock*,
36 std::pair<unsigned*,MachineInstr*> > > BBRefs;
37 // Tracks where each BasicBlock starts
38 std::map<const BasicBlock*, long> BBLocations;
39
40 public:
41 SparcV8CodeEmitter(TargetMachine &T, MachineCodeEmitter &M)
42 : TM(T), MCE(M) {}
43
44 const char *getPassName() const { return "SparcV8 Machine Code Emitter"; }
45
46 /// runOnMachineFunction - emits the given MachineFunction to memory
47 ///
48 bool runOnMachineFunction(MachineFunction &MF);
49
50 /// emitBasicBlock - emits the given MachineBasicBlock to memory
51 ///
52 void emitBasicBlock(MachineBasicBlock &MBB);
53
54 /// emitWord - write a 32-bit word to memory at the current PC
55 ///
56 void emitWord(unsigned w) { MCE.emitWord(w); }
57
58 /// getValueBit - return the particular bit of Val
59 ///
60 unsigned getValueBit(int64_t Val, unsigned bit) { return (Val >> bit) & 1; }
61
62 /// getBinaryCodeForInstr - This function, generated by the
63 /// CodeEmitterGenerator using TableGen, produces the binary encoding for
64 /// machine instructions.
65 ///
66 unsigned getBinaryCodeForInstr(MachineInstr &MI);
67 };
68}
69
Brian Gaekee785e532004-02-25 19:28:19 +000070/// addPassesToEmitMachineCode - Add passes to the specified pass manager to get
71/// machine code emitted. This uses a MachineCodeEmitter object to handle
72/// actually outputting the machine code and resolving things like the address
73/// of functions. This method should returns true if machine code emission is
74/// not supported.
75///
76bool SparcV8TargetMachine::addPassesToEmitMachineCode(FunctionPassManager &PM,
77 MachineCodeEmitter &MCE) {
Misha Brukmand8e6e7f2004-10-19 19:49:42 +000078 // Keep as `true' until this is a functional JIT to allow llvm-gcc to build
Brian Gaekee785e532004-02-25 19:28:19 +000079 return true;
Misha Brukmanb5f662f2005-04-21 23:30:14 +000080
Misha Brukmand8e6e7f2004-10-19 19:49:42 +000081 // Machine code emitter pass for SparcV8
82 PM.add(new SparcV8CodeEmitter(*this, MCE));
83 // Delete machine code for this function after emitting it
84 PM.add(createMachineCodeDeleter());
85 return false;
86}
87
88bool SparcV8CodeEmitter::runOnMachineFunction(MachineFunction &MF) {
89 MCE.startFunction(MF);
90 MCE.emitConstantPool(MF.getConstantPool());
91 for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I)
92 emitBasicBlock(*I);
93 MCE.finishFunction(MF);
94
95 // Resolve branches to BasicBlocks for the entire function
96 for (unsigned i = 0, e = BBRefs.size(); i != e; ++i) {
97 long Location = BBLocations[BBRefs[i].first];
98 unsigned *Ref = BBRefs[i].second.first;
99 MachineInstr *MI = BBRefs[i].second.second;
100 DEBUG(std::cerr << "Fixup @ " << std::hex << Ref << " to 0x" << Location
101 << " in instr: " << std::dec << *MI);
102 for (unsigned ii = 0, ee = MI->getNumOperands(); ii != ee; ++ii) {
103 MachineOperand &op = MI->getOperand(ii);
104 if (op.isPCRelativeDisp()) {
105 // the instruction's branch target is made such that it branches to
106 // PC + (branchTarget * 4), so undo that arithmetic here:
107 // Location is the target of the branch
108 // Ref is the location of the instruction, and hence the PC
109 int64_t branchTarget = (Location - (long)Ref) >> 2;
110 MI->SetMachineOperandConst(ii, MachineOperand::MO_SignExtendedImmed,
111 branchTarget);
112 unsigned fixedInstr = SparcV8CodeEmitter::getBinaryCodeForInstr(*MI);
113 MCE.emitWordAt(fixedInstr, Ref);
114 break;
115 }
116 }
117 }
118 BBRefs.clear();
119 BBLocations.clear();
120
121 return false;
122}
123
124void SparcV8CodeEmitter::emitBasicBlock(MachineBasicBlock &MBB) {
125 for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end(); I != E; ++I)
126 emitWord(getBinaryCodeForInstr(*I));
127}
128
129int64_t SparcV8CodeEmitter::getMachineOpValue(MachineInstr &MI,
130 MachineOperand &MO) {
131 int64_t rv = 0; // Return value; defaults to 0 for unhandled cases
132 // or things that get fixed up later by the JIT.
133 if (MO.isPCRelativeDisp()) {
134 std::cerr << "SparcV8CodeEmitter: PC-relative disp unhandled\n";
135 abort();
136 } else if (MO.isRegister()) {
137 rv = MO.getReg();
138 } else if (MO.isImmediate()) {
139 rv = MO.getImmedValue();
140 } else if (MO.isGlobalAddress()) {
141 GlobalValue *GV = MO.getGlobal();
Brian Gaeke1d656452004-12-03 06:57:14 +0000142 std::cerr << "Unhandled global value: " << GV << "\n";
143 abort();
Misha Brukmand8e6e7f2004-10-19 19:49:42 +0000144 } else if (MO.isMachineBasicBlock()) {
145 const BasicBlock *BB = MO.getMachineBasicBlock()->getBasicBlock();
146 unsigned* CurrPC = (unsigned*)(intptr_t)MCE.getCurrentPCValue();
147 BBRefs.push_back(std::make_pair(BB, std::make_pair(CurrPC, &MI)));
148 } else if (MO.isExternalSymbol()) {
149 } else if (MO.isConstantPoolIndex()) {
150 unsigned index = MO.getConstantPoolIndex();
151 rv = MCE.getConstantPoolEntryAddress(index);
152 } else if (MO.isFrameIndex()) {
153 std::cerr << "SparcV8CodeEmitter: error: Frame index unhandled!\n";
154 abort();
155 } else {
156 std::cerr << "ERROR: Unknown type of MachineOperand: " << MO << "\n";
157 abort();
158 }
159
160 // Adjust for special meaning of operands in some instructions
161 unsigned Opcode = MI.getOpcode();
162 if (Opcode == V8::SETHIi && !MO.isRegister() && !MO.isImmediate()) {
163 rv &= 0x03ff;
164 } else if (Opcode == V8::ORri &&!MO.isRegister() &&!MO.isImmediate()) {
165 rv = (rv >> 10) & 0x03fffff;
166 }
167
168 return rv;
Brian Gaekee785e532004-02-25 19:28:19 +0000169}
170
171void *SparcV8JITInfo::getJITStubForFunction(Function *F,
172 MachineCodeEmitter &MCE) {
Misha Brukmand8e6e7f2004-10-19 19:49:42 +0000173 std::cerr << "SparcV8JITInfo::getJITStubForFunction not implemented!\n";
174 abort();
Brian Gaekee785e532004-02-25 19:28:19 +0000175 return 0;
176}
177
Misha Brukmand8e6e7f2004-10-19 19:49:42 +0000178void SparcV8JITInfo::replaceMachineCodeForFunction(void *Old, void *New) {
179 std::cerr << "SparcV8JITInfo::replaceMachineCodeForFunction not implemented!";
180 abort();
Brian Gaekee785e532004-02-25 19:28:19 +0000181}
182
Chris Lattner02d608b2005-10-24 04:51:35 +0000183#include "SparcV8GenCodeEmitter.inc"