blob: 00a7e7c62682f71b6669f886aa8d6d3f22717d8e [file] [log] [blame]
Misha Brukmana9f7f6e2003-05-30 20:17:33 +00001//===-- SparcV9CodeEmitter.cpp - --------===//
2//
3//
4//===----------------------------------------------------------------------===//
5
Misha Brukmanf86aaa82003-06-02 04:12:39 +00006#include "llvm/Constants.h"
7#include "llvm/Function.h"
8#include "llvm/GlobalVariable.h"
Misha Brukman3de36f52003-05-27 20:07:58 +00009#include "llvm/PassManager.h"
10#include "llvm/CodeGen/MachineCodeEmitter.h"
Misha Brukmana2196c12003-06-04 20:01:13 +000011#include "llvm/CodeGen/MachineConstantPool.h"
Misha Brukmanf86aaa82003-06-02 04:12:39 +000012#include "llvm/CodeGen/MachineFunctionInfo.h"
Misha Brukman3de36f52003-05-27 20:07:58 +000013#include "llvm/CodeGen/MachineFunctionPass.h"
14#include "llvm/CodeGen/MachineInstr.h"
Misha Brukmana9f7f6e2003-05-30 20:17:33 +000015#include "llvm/Target/TargetMachine.h"
Misha Brukmanf86aaa82003-06-02 04:12:39 +000016#include "llvm/Target/TargetData.h"
17#include "Support/hash_set"
Misha Brukman3de36f52003-05-27 20:07:58 +000018#include "SparcInternals.h"
Misha Brukman0cc640e2003-05-27 21:45:05 +000019#include "SparcV9CodeEmitter.h"
Misha Brukman3de36f52003-05-27 20:07:58 +000020
21bool UltraSparc::addPassesToEmitMachineCode(PassManager &PM,
22 MachineCodeEmitter &MCE) {
23 //PM.add(new SparcV9CodeEmitter(MCE));
24 //MachineCodeEmitter *M = MachineCodeEmitter::createDebugMachineCodeEmitter();
Misha Brukmanf86aaa82003-06-02 04:12:39 +000025 MachineCodeEmitter *M = MachineCodeEmitter::createFilePrinterEmitter(MCE);
Misha Brukmana2196c12003-06-04 20:01:13 +000026 PM.add(new SparcV9CodeEmitter(*this, *M));
Misha Brukmandcbe7122003-05-31 06:26:06 +000027 PM.add(createMachineCodeDestructionPass()); // Free stuff no longer needed
Misha Brukman3de36f52003-05-27 20:07:58 +000028 return false;
29}
30
Misha Brukmanf86aaa82003-06-02 04:12:39 +000031namespace {
32 class JITResolver {
Misha Brukmana2196c12003-06-04 20:01:13 +000033 SparcV9CodeEmitter &SparcV9;
Misha Brukmanf86aaa82003-06-02 04:12:39 +000034 MachineCodeEmitter &MCE;
35
36 // LazyCodeGenMap - Keep track of call sites for functions that are to be
37 // lazily resolved.
Misha Brukmana2196c12003-06-04 20:01:13 +000038 std::map<uint64_t, Function*> LazyCodeGenMap;
Misha Brukmanf86aaa82003-06-02 04:12:39 +000039
40 // LazyResolverMap - Keep track of the lazy resolver created for a
41 // particular function so that we can reuse them if necessary.
Misha Brukmana2196c12003-06-04 20:01:13 +000042 std::map<Function*, uint64_t> LazyResolverMap;
Misha Brukmanf86aaa82003-06-02 04:12:39 +000043 public:
Misha Brukmana2196c12003-06-04 20:01:13 +000044 JITResolver(SparcV9CodeEmitter &V9,
45 MachineCodeEmitter &mce) : SparcV9(V9), MCE(mce) {}
46 uint64_t getLazyResolver(Function *F);
47 uint64_t addFunctionReference(uint64_t Address, Function *F);
48
49 // Utility functions for accessing data from static callback
50 uint64_t getCurrentPCValue() {
51 return MCE.getCurrentPCValue();
52 }
53 unsigned getBinaryCodeForInstr(MachineInstr &MI) {
54 return SparcV9.getBinaryCodeForInstr(MI);
55 }
56
Misha Brukmanf86aaa82003-06-02 04:12:39 +000057 private:
Misha Brukmana2196c12003-06-04 20:01:13 +000058 uint64_t emitStubForFunction(Function *F);
Misha Brukmanf86aaa82003-06-02 04:12:39 +000059 static void CompilationCallback();
Misha Brukmana2196c12003-06-04 20:01:13 +000060 uint64_t resolveFunctionReference(uint64_t RetAddr);
Misha Brukmanf86aaa82003-06-02 04:12:39 +000061 };
62
63 JITResolver *TheJITResolver;
64}
65
66/// addFunctionReference - This method is called when we need to emit the
67/// address of a function that has not yet been emitted, so we don't know the
68/// address. Instead, we emit a call to the CompilationCallback method, and
69/// keep track of where we are.
70///
Misha Brukmana2196c12003-06-04 20:01:13 +000071uint64_t JITResolver::addFunctionReference(uint64_t Address, Function *F) {
Misha Brukmanf86aaa82003-06-02 04:12:39 +000072 LazyCodeGenMap[Address] = F;
73 return (intptr_t)&JITResolver::CompilationCallback;
74}
75
Misha Brukmana2196c12003-06-04 20:01:13 +000076uint64_t JITResolver::resolveFunctionReference(uint64_t RetAddr) {
77 std::map<uint64_t, Function*>::iterator I = LazyCodeGenMap.find(RetAddr);
Misha Brukmanf86aaa82003-06-02 04:12:39 +000078 assert(I != LazyCodeGenMap.end() && "Not in map!");
79 Function *F = I->second;
80 LazyCodeGenMap.erase(I);
81 return MCE.forceCompilationOf(F);
82}
83
Misha Brukmana2196c12003-06-04 20:01:13 +000084uint64_t JITResolver::getLazyResolver(Function *F) {
85 std::map<Function*, uint64_t>::iterator I = LazyResolverMap.lower_bound(F);
Misha Brukmanf86aaa82003-06-02 04:12:39 +000086 if (I != LazyResolverMap.end() && I->first == F) return I->second;
87
88//std::cerr << "Getting lazy resolver for : " << ((Value*)F)->getName() << "\n";
89
Misha Brukmana2196c12003-06-04 20:01:13 +000090 uint64_t Stub = emitStubForFunction(F);
Misha Brukmanf86aaa82003-06-02 04:12:39 +000091 LazyResolverMap.insert(I, std::make_pair(F, Stub));
92 return Stub;
93}
94
95void JITResolver::CompilationCallback() {
96 uint64_t *StackPtr = (uint64_t*)__builtin_frame_address(0);
97 uint64_t RetAddr = (uint64_t)(intptr_t)__builtin_return_address(0);
98
Misha Brukmanf86aaa82003-06-02 04:12:39 +000099 std::cerr << "In callback! Addr=0x" << std::hex << RetAddr
Misha Brukmana2196c12003-06-04 20:01:13 +0000100 << " SP=0x" << (uint64_t)(intptr_t)StackPtr << std::dec << "\n";
Misha Brukmanf86aaa82003-06-02 04:12:39 +0000101
Misha Brukmana2196c12003-06-04 20:01:13 +0000102 int64_t NewVal = (int64_t)TheJITResolver->resolveFunctionReference(RetAddr);
Misha Brukmanf86aaa82003-06-02 04:12:39 +0000103
104 // Rewrite the call target... so that we don't fault every time we execute
105 // the call.
Misha Brukmana2196c12003-06-04 20:01:13 +0000106 int64_t RealCallTarget = (int64_t)
107 ((NewVal - TheJITResolver->getCurrentPCValue()) >> 4);
108 MachineInstr *MI = BuildMI(V9::CALL, 1);
109 MI->addSignExtImmOperand(RealCallTarget);
110 // FIXME: this could be in the wrong byte order!!
111 *((unsigned*)(intptr_t)RetAddr) = TheJITResolver->getBinaryCodeForInstr(*MI);
112 delete MI;
Misha Brukmanf86aaa82003-06-02 04:12:39 +0000113
114 // Change the return address to reexecute the call instruction...
115 StackPtr[1] -= 4;
Misha Brukmanf86aaa82003-06-02 04:12:39 +0000116}
117
118/// emitStubForFunction - This method is used by the JIT when it needs to emit
119/// the address of a function for a function whose code has not yet been
120/// generated. In order to do this, it generates a stub which jumps to the lazy
121/// function compiler, which will eventually get fixed to call the function
122/// directly.
123///
Misha Brukmana2196c12003-06-04 20:01:13 +0000124uint64_t JITResolver::emitStubForFunction(Function *F) {
Misha Brukmanf86aaa82003-06-02 04:12:39 +0000125#if 0
126 MCE.startFunctionStub(*F, 6);
127 MCE.emitByte(0xE8); // Call with 32 bit pc-rel destination...
128
Misha Brukmana2196c12003-06-04 20:01:13 +0000129 uint64_t Address = addFunctionReference(MCE.getCurrentPCValue(), F);
Misha Brukmanf86aaa82003-06-02 04:12:39 +0000130 MCE.emitWord(Address-MCE.getCurrentPCValue()-4);
131
132 MCE.emitByte(0xCD); // Interrupt - Just a marker identifying the stub!
133 return (intptr_t)MCE.finishFunctionStub(*F);
134#endif
Misha Brukmana2196c12003-06-04 20:01:13 +0000135 MCE.startFunctionStub(*F, 6);
136
137 int64_t CurrPC = MCE.getCurrentPCValue();
138 int64_t Addr = (int64_t)addFunctionReference(CurrPC, F);
139 int64_t CallTarget = (Addr-CurrPC) >> 2;
140 MachineInstr *Call = BuildMI(V9::CALL, 1);
141 Call->addSignExtImmOperand(CallTarget);
142 SparcV9.emitWord(SparcV9.getBinaryCodeForInstr(*Call));
143 delete Call;
144
145 MachineInstr *Nop = BuildMI(V9::NOP, 0);
146 SparcV9.emitWord(SparcV9.getBinaryCodeForInstr(*Nop));
147 delete Nop;
148
149 SparcV9.emitWord(0xDEADBEEF); // marker so that we know it's really a stub
150 return (intptr_t)MCE.finishFunctionStub(*F);
Misha Brukmanf86aaa82003-06-02 04:12:39 +0000151}
152
153
Misha Brukmana2196c12003-06-04 20:01:13 +0000154SparcV9CodeEmitter::SparcV9CodeEmitter(TargetMachine &tm,
155 MachineCodeEmitter &M): TM(tm), MCE(M)
156{
157 TheJITResolver = new JITResolver(*this, M);
158}
159
160SparcV9CodeEmitter::~SparcV9CodeEmitter() {
161 delete TheJITResolver;
162}
163
164void SparcV9CodeEmitter::emitWord(unsigned Val) {
Misha Brukman3de36f52003-05-27 20:07:58 +0000165 // Output the constant in big endian byte order...
166 unsigned byteVal;
Misha Brukmana2196c12003-06-04 20:01:13 +0000167 for (int i = 3; i >= 0; --i) {
Misha Brukman3de36f52003-05-27 20:07:58 +0000168 byteVal = Val >> 8*i;
Misha Brukmana2196c12003-06-04 20:01:13 +0000169 MCE.emitByte(byteVal & 255);
Misha Brukmana9f7f6e2003-05-30 20:17:33 +0000170 }
Misha Brukmana9f7f6e2003-05-30 20:17:33 +0000171}
172
173unsigned getRealRegNum(unsigned fakeReg, unsigned regClass) {
174 switch (regClass) {
175 case UltraSparcRegInfo::IntRegType: {
176 // Sparc manual, p31
177 static const unsigned IntRegMap[] = {
178 // "o0", "o1", "o2", "o3", "o4", "o5", "o7",
179 8, 9, 10, 11, 12, 13, 15,
180 // "l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7",
181 16, 17, 18, 19, 20, 21, 22, 23,
182 // "i0", "i1", "i2", "i3", "i4", "i5",
183 24, 25, 26, 27, 28, 29,
184 // "i6", "i7",
185 30, 31,
186 // "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7",
187 0, 1, 2, 3, 4, 5, 6, 7,
188 // "o6"
189 14
190 };
191
192 return IntRegMap[fakeReg];
193 break;
194 }
195 case UltraSparcRegInfo::FPSingleRegType: {
196 return fakeReg;
197 }
198 case UltraSparcRegInfo::FPDoubleRegType: {
199 return fakeReg;
200 }
201 case UltraSparcRegInfo::FloatCCRegType: {
202 return fakeReg;
203
204 }
205 case UltraSparcRegInfo::IntCCRegType: {
206 return fakeReg;
207 }
208 default:
209 assert(0 && "Invalid unified register number in getRegType");
210 return fakeReg;
Misha Brukman3de36f52003-05-27 20:07:58 +0000211 }
212}
213
Misha Brukmana9f7f6e2003-05-30 20:17:33 +0000214int64_t SparcV9CodeEmitter::getMachineOpValue(MachineInstr &MI,
215 MachineOperand &MO) {
Brian Gaekec3eaa892003-06-02 02:13:26 +0000216 int64_t rv = 0; // Return value; defaults to 0 for unhandled cases
217 // or things that get fixed up later by the JIT.
218
Misha Brukmaneaaf8ad2003-06-02 05:24:46 +0000219 if (MO.isVirtualRegister()) {
220 std::cerr << "ERROR: virtual register found in machine code.\n";
221 abort();
222 } else if (MO.isPCRelativeDisp()) {
Misha Brukmana2196c12003-06-04 20:01:13 +0000223 std::cerr << "PCRelativeDisp: ";
Misha Brukmaneaaf8ad2003-06-02 05:24:46 +0000224 Value *V = MO.getVRegValue();
225 if (BasicBlock *BB = dyn_cast<BasicBlock>(V)) {
226 std::cerr << "Saving reference to BB (VReg)\n";
Misha Brukmana2196c12003-06-04 20:01:13 +0000227 unsigned* CurrPC = (unsigned*)(intptr_t)MCE.getCurrentPCValue();
Misha Brukmaneaaf8ad2003-06-02 05:24:46 +0000228 BBRefs.push_back(std::make_pair(BB, std::make_pair(CurrPC, &MI)));
Misha Brukmana2196c12003-06-04 20:01:13 +0000229 } else if (const Constant *C = dyn_cast<Constant>(V)) {
230 if (ConstantMap.find(C) != ConstantMap.end()) {
231 rv = (int64_t)MCE.getConstantPoolEntryAddress(ConstantMap[C]);
232 std::cerr << "const: 0x" << std::hex << rv
233 << "\n" << std::dec;
234 } else {
Misha Brukmaneaaf8ad2003-06-02 05:24:46 +0000235 std::cerr << "ERROR: constant not in map:" << MO << "\n";
236 abort();
237 }
Misha Brukmana2196c12003-06-04 20:01:13 +0000238 } else if (GlobalValue *GV = dyn_cast<GlobalValue>(V)) {
239 // same as MO.isGlobalAddress()
240 std::cerr << "GlobalValue: ";
241 // external function calls, etc.?
242 if (Function *F = dyn_cast<Function>(GV)) {
243 std::cerr << "Function: ";
244 if (F->isExternal()) {
245 // Sparc backend broken: this MO should be `ExternalSymbol'
246 rv = (int64_t)MCE.getGlobalValueAddress(F->getName());
247 } else {
248 rv = (int64_t)MCE.getGlobalValueAddress(F);
249 }
250 if (rv == 0) {
251 std::cerr << "not yet generated\n";
252 // Function has not yet been code generated!
253 TheJITResolver->addFunctionReference(MCE.getCurrentPCValue(), F);
254 // Delayed resolution...
255 rv = TheJITResolver->getLazyResolver(F);
256 } else {
257 std::cerr << "already generated: 0x" << std::hex << rv << "\n"
258 << std::dec;
259 }
260 } else {
261 std::cerr << "not a function: " << *GV << "\n";
262 abort();
263 }
264 // The real target of the call is Addr = PC + (rv * 4)
265 // So undo that: give the instruction (Addr - PC) / 4
266 if (MI.getOpcode() == V9::CALL) {
267 int64_t CurrPC = MCE.getCurrentPCValue();
268 std::cerr << "rv addr: 0x" << std::hex << rv << "\n";
269 std::cerr << "curr PC: 0x" << CurrPC << "\n";
270 rv = (rv - CurrPC) >> 2;
271 if (rv >= (1<<29) || rv <= -(1<<29)) {
272 std::cerr << "addr out of bounds for the 30-bit call: " << rv << "\n";
273 abort();
274 }
275 std::cerr << "returning addr: 0x" << rv << "\n" << std::dec;
276 }
Misha Brukmaneaaf8ad2003-06-02 05:24:46 +0000277 } else {
278 std::cerr << "ERROR: PC relative disp unhandled:" << MO << "\n";
279 abort();
280 }
281 } else if (MO.isPhysicalRegister()) {
Misha Brukmana9f7f6e2003-05-30 20:17:33 +0000282 // This is necessary because the Sparc doesn't actually lay out registers
283 // in the real fashion -- it skips those that it chooses not to allocate,
284 // i.e. those that are the SP, etc.
285 unsigned fakeReg = MO.getReg(), realReg, regClass, regType;
Misha Brukmana2196c12003-06-04 20:01:13 +0000286 regType = TM.getRegInfo().getRegType(fakeReg);
Misha Brukmana9f7f6e2003-05-30 20:17:33 +0000287 // At least map fakeReg into its class
Misha Brukmana2196c12003-06-04 20:01:13 +0000288 fakeReg = TM.getRegInfo().getClassRegNum(fakeReg, regClass);
Misha Brukmana9f7f6e2003-05-30 20:17:33 +0000289 // Find the real register number for use in an instruction
290 realReg = getRealRegNum(fakeReg, regClass);
Misha Brukmanf86aaa82003-06-02 04:12:39 +0000291 std::cerr << "Reg[" << std::dec << fakeReg << "] = " << realReg << "\n";
Brian Gaekec3eaa892003-06-02 02:13:26 +0000292 rv = realReg;
Misha Brukman3de36f52003-05-27 20:07:58 +0000293 } else if (MO.isImmediate()) {
Brian Gaekec3eaa892003-06-02 02:13:26 +0000294 rv = MO.getImmedValue();
Misha Brukmana2196c12003-06-04 20:01:13 +0000295 std::cerr << "immed: " << rv << "\n";
Misha Brukmaneaaf8ad2003-06-02 05:24:46 +0000296 } else if (MO.isGlobalAddress()) {
Misha Brukmana2196c12003-06-04 20:01:13 +0000297 std::cerr << "GlobalAddress: not PC-relative\n";
Misha Brukmanf86aaa82003-06-02 04:12:39 +0000298 rv = (int64_t)
299 (intptr_t)getGlobalAddress(cast<GlobalValue>(MO.getVRegValue()),
Misha Brukmaneaaf8ad2003-06-02 05:24:46 +0000300 MI, MO.isPCRelative());
Misha Brukmana9f7f6e2003-05-30 20:17:33 +0000301 } else if (MO.isMachineBasicBlock()) {
Misha Brukmaneaaf8ad2003-06-02 05:24:46 +0000302 // Duplicate code of the above case for VirtualRegister, BasicBlock...
303 // It should really hit this case, but Sparc backend uses VRegs instead
Misha Brukmanf86aaa82003-06-02 04:12:39 +0000304 std::cerr << "Saving reference to MBB\n";
Misha Brukmaneaaf8ad2003-06-02 05:24:46 +0000305 BasicBlock *BB = MO.getMachineBasicBlock()->getBasicBlock();
Misha Brukmana2196c12003-06-04 20:01:13 +0000306 unsigned* CurrPC = (unsigned*)(intptr_t)MCE.getCurrentPCValue();
Misha Brukmaneaaf8ad2003-06-02 05:24:46 +0000307 BBRefs.push_back(std::make_pair(BB, std::make_pair(CurrPC, &MI)));
Misha Brukmana9f7f6e2003-05-30 20:17:33 +0000308 } else if (MO.isExternalSymbol()) {
Misha Brukmaneaaf8ad2003-06-02 05:24:46 +0000309 // Sparc backend doesn't generate this (yet...)
310 std::cerr << "ERROR: External symbol unhandled: " << MO << "\n";
311 abort();
312 } else if (MO.isFrameIndex()) {
313 // Sparc backend doesn't generate this (yet...)
314 int FrameIndex = MO.getFrameIndex();
315 std::cerr << "ERROR: Frame index unhandled.\n";
316 abort();
317 } else if (MO.isConstantPoolIndex()) {
318 // Sparc backend doesn't generate this (yet...)
319 std::cerr << "ERROR: Constant Pool index unhandled.\n";
320 abort();
Misha Brukman3de36f52003-05-27 20:07:58 +0000321 } else {
Misha Brukmana9f7f6e2003-05-30 20:17:33 +0000322 std::cerr << "ERROR: Unknown type of MachineOperand: " << MO << "\n";
Misha Brukmaneaaf8ad2003-06-02 05:24:46 +0000323 abort();
Brian Gaekec3eaa892003-06-02 02:13:26 +0000324 }
325
326 // Finally, deal with the various bitfield-extracting functions that
327 // are used in SPARC assembly. (Some of these make no sense in combination
328 // with some of the above; we'll trust that the instruction selector
329 // will not produce nonsense, and not check for valid combinations here.)
330 if (MO.opLoBits32()) { // %lo(val)
331 return rv & 0x03ff;
332 } else if (MO.opHiBits32()) { // %lm(val)
333 return (rv >> 10) & 0x03fffff;
334 } else if (MO.opLoBits64()) { // %hm(val)
335 return (rv >> 32) & 0x03ff;
336 } else if (MO.opHiBits64()) { // %hh(val)
337 return rv >> 42;
338 } else { // (unadorned) val
339 return rv;
Misha Brukman3de36f52003-05-27 20:07:58 +0000340 }
341}
342
343unsigned SparcV9CodeEmitter::getValueBit(int64_t Val, unsigned bit) {
344 Val >>= bit;
345 return (Val & 1);
346}
347
Misha Brukman3de36f52003-05-27 20:07:58 +0000348bool SparcV9CodeEmitter::runOnMachineFunction(MachineFunction &MF) {
Misha Brukmana2196c12003-06-04 20:01:13 +0000349 MCE.startFunction(MF);
Misha Brukmanf86aaa82003-06-02 04:12:39 +0000350 std::cerr << "Starting function " << MF.getFunction()->getName()
351 << ", address: " << "0x" << std::hex
Misha Brukmana2196c12003-06-04 20:01:13 +0000352 << (long)MCE.getCurrentPCValue() << "\n";
Misha Brukmanf86aaa82003-06-02 04:12:39 +0000353
Misha Brukmana2196c12003-06-04 20:01:13 +0000354 // The Sparc backend does not use MachineConstantPool;
355 // instead, it has its own constant pool implementation.
356 // We create a new MachineConstantPool here to be compatible with the emitter.
357 MachineConstantPool MCP;
Misha Brukmanf86aaa82003-06-02 04:12:39 +0000358 const hash_set<const Constant*> &pool = MF.getInfo()->getConstantPoolValues();
359 for (hash_set<const Constant*>::const_iterator I = pool.begin(),
360 E = pool.end(); I != E; ++I)
361 {
Misha Brukmana2196c12003-06-04 20:01:13 +0000362 Constant *C = (Constant*)*I;
363 unsigned idx = MCP.getConstantPoolIndex(C);
364 std::cerr << "Mapping constant 0x" << (intptr_t)C << " to " << idx << "\n";
365 ConstantMap[C] = idx;
Misha Brukmanf86aaa82003-06-02 04:12:39 +0000366 }
Misha Brukmana2196c12003-06-04 20:01:13 +0000367 MCE.emitConstantPool(&MCP);
Misha Brukmanf86aaa82003-06-02 04:12:39 +0000368
Misha Brukman3de36f52003-05-27 20:07:58 +0000369 for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I)
370 emitBasicBlock(*I);
Misha Brukmana2196c12003-06-04 20:01:13 +0000371 MCE.finishFunction(MF);
Misha Brukmanf86aaa82003-06-02 04:12:39 +0000372
373 std::cerr << "Finishing function " << MF.getFunction()->getName() << "\n";
374 ConstantMap.clear();
375 for (unsigned i = 0, e = BBRefs.size(); i != e; ++i) {
376 long Location = BBLocations[BBRefs[i].first];
377 unsigned *Ref = BBRefs[i].second.first;
378 MachineInstr *MI = BBRefs[i].second.second;
379 std::cerr << "Fixup @" << std::hex << Ref << " to " << Location
380 << " in instr: " << std::dec << *MI << "\n";
381 }
382
383 // Resolve branches to BasicBlocks for the entire function
384 for (unsigned i = 0, e = BBRefs.size(); i != e; ++i) {
385 long Location = BBLocations[BBRefs[i].first];
386 unsigned *Ref = BBRefs[i].second.first;
387 MachineInstr *MI = BBRefs[i].second.second;
388 std::cerr << "attempting to resolve BB: " << i << "\n";
389 for (unsigned ii = 0, ee = MI->getNumOperands(); ii != ee; ++ii) {
390 MachineOperand &op = MI->getOperand(ii);
391 if (op.isPCRelativeDisp()) {
392 // the instruction's branch target is made such that it branches to
393 // PC + (br target * 4), so undo that arithmetic here:
394 // Location is the target of the branch
395 // Ref is the location of the instruction, and hence the PC
396 unsigned branchTarget = (Location - (long)Ref) >> 2;
397 // Save the flags.
398 bool loBits32=false, hiBits32=false, loBits64=false, hiBits64=false;
399 if (op.opLoBits32()) { loBits32=true; }
400 if (op.opHiBits32()) { hiBits32=true; }
401 if (op.opLoBits64()) { loBits64=true; }
402 if (op.opHiBits64()) { hiBits64=true; }
403 MI->SetMachineOperandConst(ii, MachineOperand::MO_SignExtendedImmed,
404 branchTarget);
405 if (loBits32) { MI->setOperandLo32(ii); }
406 else if (hiBits32) { MI->setOperandHi32(ii); }
407 else if (loBits64) { MI->setOperandLo64(ii); }
408 else if (hiBits64) { MI->setOperandHi64(ii); }
409 std::cerr << "Rewrote BB ref: ";
410 unsigned fixedInstr = SparcV9CodeEmitter::getBinaryCodeForInstr(*MI);
411 *Ref = fixedInstr;
412 break;
413 }
414 }
415 }
416 BBRefs.clear();
417 BBLocations.clear();
418
Misha Brukman3de36f52003-05-27 20:07:58 +0000419 return false;
420}
421
422void SparcV9CodeEmitter::emitBasicBlock(MachineBasicBlock &MBB) {
Misha Brukman0d603452003-05-27 22:41:44 +0000423 currBB = MBB.getBasicBlock();
Misha Brukmana2196c12003-06-04 20:01:13 +0000424 BBLocations[currBB] = MCE.getCurrentPCValue();
Misha Brukman3de36f52003-05-27 20:07:58 +0000425 for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end(); I != E; ++I)
Misha Brukmana2196c12003-06-04 20:01:13 +0000426 emitWord(getBinaryCodeForInstr(**I));
Misha Brukman3de36f52003-05-27 20:07:58 +0000427}
428
Misha Brukmanf86aaa82003-06-02 04:12:39 +0000429void* SparcV9CodeEmitter::getGlobalAddress(GlobalValue *V, MachineInstr &MI,
430 bool isPCRelative)
431{
432 if (isPCRelative) { // must be a call, this is a major hack!
433 // Try looking up the function to see if it is already compiled!
Misha Brukmana2196c12003-06-04 20:01:13 +0000434 if (void *Addr = (void*)(intptr_t)MCE.getGlobalValueAddress(V)) {
435 intptr_t CurByte = MCE.getCurrentPCValue();
Misha Brukmanf86aaa82003-06-02 04:12:39 +0000436 // The real target of the call is Addr = PC + (target * 4)
437 // CurByte is the PC, Addr we just received
438 return (void*) (((long)Addr - (long)CurByte) >> 2);
439 } else {
440 if (Function *F = dyn_cast<Function>(V)) {
441 // Function has not yet been code generated!
Misha Brukmana2196c12003-06-04 20:01:13 +0000442 TheJITResolver->addFunctionReference(MCE.getCurrentPCValue(),
Misha Brukmanf86aaa82003-06-02 04:12:39 +0000443 cast<Function>(V));
444 // Delayed resolution...
Misha Brukmaneaaf8ad2003-06-02 05:24:46 +0000445 return
446 (void*)(intptr_t)TheJITResolver->getLazyResolver(cast<Function>(V));
Misha Brukmanf86aaa82003-06-02 04:12:39 +0000447
448 } else if (Constant *C = ConstantPointerRef::get(V)) {
449 if (ConstantMap.find(C) != ConstantMap.end()) {
Misha Brukmana2196c12003-06-04 20:01:13 +0000450 return (void*)
451 (intptr_t)MCE.getConstantPoolEntryAddress(ConstantMap[C]);
Misha Brukmanf86aaa82003-06-02 04:12:39 +0000452 } else {
453 std::cerr << "Constant: 0x" << std::hex << &*C << std::dec
454 << ", " << *V << " not found in ConstantMap!\n";
455 abort();
456 }
Misha Brukmanf86aaa82003-06-02 04:12:39 +0000457 } else {
458 std::cerr << "Unhandled global: " << *V << "\n";
459 abort();
460 }
461 }
462 } else {
Misha Brukmana2196c12003-06-04 20:01:13 +0000463 return (void*)(intptr_t)MCE.getGlobalValueAddress(V);
Misha Brukmanf86aaa82003-06-02 04:12:39 +0000464 }
465}
466
467
Misha Brukman3de36f52003-05-27 20:07:58 +0000468#include "SparcV9CodeEmitter.inc"
Misha Brukmanf86aaa82003-06-02 04:12:39 +0000469