This code rotted - change it to call abort() until someone wants
[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
24 namespace llvm {
25
26 namespace {
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
71 /// 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 ///
77 bool SparcV8TargetMachine::addPassesToEmitMachineCode(FunctionPassManager &PM,
78                                                       MachineCodeEmitter &MCE) {
79   // Keep as `true' until this is a functional JIT to allow llvm-gcc to build
80   return true;
81   
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
89 bool 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
125 void SparcV8CodeEmitter::emitBasicBlock(MachineBasicBlock &MBB) {
126   for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end(); I != E; ++I)
127     emitWord(getBinaryCodeForInstr(*I));
128 }
129
130 int64_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();
143     std::cerr << "Unhandled global value: " << GV << "\n";
144     abort();
145   } 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;
170 }
171
172 void *SparcV8JITInfo::getJITStubForFunction(Function *F,
173                                             MachineCodeEmitter &MCE) {
174   std::cerr << "SparcV8JITInfo::getJITStubForFunction not implemented!\n";
175   abort();
176   return 0;
177 }
178
179 void SparcV8JITInfo::replaceMachineCodeForFunction(void *Old, void *New) {
180   std::cerr << "SparcV8JITInfo::replaceMachineCodeForFunction not implemented!";
181   abort();
182 }
183
184 #include "SparcV8GenCodeEmitter.inc"
185
186 } // end llvm namespace