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