do not wrap this whole file in namespace llvm
[oota-llvm.git] / lib / Target / Sparc / SparcV8CodeEmitter.cpp
1 //===-- 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
13 #include "SparcV8.h"
14 #include "SparcV8TargetMachine.h"
15 #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>
23 using namespace llvm;
24
25 namespace {
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
70 /// 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 ///
76 bool SparcV8TargetMachine::addPassesToEmitMachineCode(FunctionPassManager &PM,
77                                                       MachineCodeEmitter &MCE) {
78   // Keep as `true' until this is a functional JIT to allow llvm-gcc to build
79   return true;
80
81   // 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
88 bool 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
124 void SparcV8CodeEmitter::emitBasicBlock(MachineBasicBlock &MBB) {
125   for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end(); I != E; ++I)
126     emitWord(getBinaryCodeForInstr(*I));
127 }
128
129 int64_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();
142     std::cerr << "Unhandled global value: " << GV << "\n";
143     abort();
144   } 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;
169 }
170
171 void *SparcV8JITInfo::getJITStubForFunction(Function *F,
172                                             MachineCodeEmitter &MCE) {
173   std::cerr << "SparcV8JITInfo::getJITStubForFunction not implemented!\n";
174   abort();
175   return 0;
176 }
177
178 void SparcV8JITInfo::replaceMachineCodeForFunction(void *Old, void *New) {
179   std::cerr << "SparcV8JITInfo::replaceMachineCodeForFunction not implemented!";
180   abort();
181 }
182
183 #include "SparcV8GenCodeEmitter.inc"