Initial JIT support for ARM by Raul Fernandes Herbster.
[oota-llvm.git] / lib / Target / ARM / ARMJITInfo.cpp
1 //===-- ARMJITInfo.cpp - Implement the JIT interfaces for the ARM target --===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file was developed by the Raul Herbster and is distributed under the 
6 // University of Illinois Open Source License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file implements the JIT interfaces for the ARM target.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #define DEBUG_TYPE "jit"
15 #include "ARMJITInfo.h"
16 #include "ARMRelocations.h"
17 #include "ARMSubtarget.h"
18 #include "llvm/CodeGen/MachineCodeEmitter.h"
19 #include "llvm/Config/alloca.h"
20 #include <cstdlib>
21 using namespace llvm;
22
23 void ARMJITInfo::replaceMachineCodeForFunction(void *Old, void *New) {
24   unsigned char *OldByte = (unsigned char *)Old;
25   *OldByte++ = 0xEA;                // Emit B opcode.
26   unsigned *OldWord = (unsigned *)OldByte;
27   unsigned NewAddr = (intptr_t)New;
28   unsigned OldAddr = (intptr_t)OldWord;
29   *OldWord = NewAddr - OldAddr - 4; // Emit PC-relative addr of New code.
30 }
31
32 /// JITCompilerFunction - This contains the address of the JIT function used to
33 /// compile a function lazily.
34 static TargetJITInfo::JITCompilerFn JITCompilerFunction;
35
36 // CompilationCallback stub - We can't use a C function with inline assembly in
37 // it, because we the prolog/epilog inserted by GCC won't work for us.  Instead,
38 // write our own wrapper, which does things our way, so we have complete control
39 // over register saving and restoring.
40 extern "C" {
41 #if defined(__arm__)
42   void ARMCompilationCallback(void);
43   asm(
44     ".text\n"
45     ".align 2\n"
46     ".globl ARMCompilationCallback\n"
47     "ARMCompilationCallback:\n"
48     // save main registers
49     "mov    ip, sp\n"
50     "stmfd  sp!, {fp, ip, lr, pc}\n"
51     "sub    fp, ip, #4\n"
52     // arguments to Compilation Callback
53     // r0 - our lr (address of the call instruction in stub plus 4)
54     // r1 - stub's lr (address of instruction that called the stub plus 4)
55     "mov    r0, fp\n"  // stub's frame
56     "mov    r1, lr\n"  // stub's lr
57     "bl     ARMCompilationCallbackC\n"
58     // restore main registers
59     "ldmfd  sp, {fp, sp, pc}\n");
60 #else // Not an ARM host
61   void ARMCompilationCallback() {
62     assert(0 && "Cannot call ARMCompilationCallback() on a non-ARM arch!\n");
63     abort();
64   }
65 #endif
66 }
67
68 /// ARMCompilationCallbackC - This is the target-specific function invoked by the
69 /// function stub when we did not know the real target of a call.  This function
70 /// must locate the start of the stub or call site and pass it into the JIT
71 /// compiler function.
72 extern "C" void ARMCompilationCallbackC(intptr_t *StackPtr, intptr_t RetAddr) {
73   intptr_t *RetAddrLoc = &StackPtr[-1];
74
75   assert(*RetAddrLoc == RetAddr &&
76          "Could not find return address on the stack!");
77 #if 0
78   DOUT << "In callback! Addr=" << (void*)RetAddr
79        << " FP=" << (void*)StackPtr
80        << ": Resolving call to function: "
81        << TheVM->getFunctionReferencedName((void*)RetAddr) << "\n";
82 #endif
83
84   // Sanity check to make sure this really is a branch and link instruction.
85   assert(((unsigned char*)RetAddr-1)[3] == 0xEB && "Not a branch and link instr!");
86
87   intptr_t NewVal = (intptr_t)JITCompilerFunction((void*)RetAddr);
88
89   // Rewrite the call target... so that we don't end up here every time we
90   // execute the call.
91   *(intptr_t *)RetAddr = (intptr_t)(NewVal-RetAddr-4);
92
93   // Change the return address to reexecute the branch and link instruction...
94   *RetAddrLoc -= 1;
95 }
96
97 TargetJITInfo::LazyResolverFn
98 ARMJITInfo::getLazyResolverFunction(JITCompilerFn F) {
99   JITCompilerFunction = F;
100   return ARMCompilationCallback;
101 }
102
103 void *ARMJITInfo::emitFunctionStub(void *Fn, MachineCodeEmitter &MCE) {
104   unsigned addr = (intptr_t)Fn-MCE.getCurrentPCValue()-4;
105   // If this is just a call to an external function, emit a branch instead of a
106   // call.  The code is the same except for one bit of the last instruction.
107   if (Fn != (void*)(intptr_t)ARMCompilationCallback) {
108     MCE.startFunctionStub(4, 2);
109     MCE.emitByte(0xEA);  // branch to the corresponding function addr 
110     MCE.emitByte((unsigned char)(addr >>  0));
111     MCE.emitByte((unsigned char)(addr >>  8));
112     MCE.emitByte((unsigned char)(addr >>  16));
113     return MCE.finishFunctionStub(0);
114   } else {
115     MCE.startFunctionStub(5, 2);
116     MCE.emitByte(0xEB);  // branch and link to the corresponding function addr
117   }
118   MCE.emitByte((unsigned char)(addr >>  0));
119   MCE.emitByte((unsigned char)(addr >>  8));
120   MCE.emitByte((unsigned char)(addr >>  16));
121
122   return MCE.finishFunctionStub(0);
123 }
124
125 /// relocate - Before the JIT can run a block of code that has been emitted,
126 /// it must rewrite the code to contain the actual addresses of any
127 /// referenced global symbols.
128 void ARMJITInfo::relocate(void *Function, MachineRelocation *MR,
129                           unsigned NumRelocs, unsigned char* GOTBase) {
130   for (unsigned i = 0; i != NumRelocs; ++i, ++MR) {
131     void *RelocPos = (char*)Function + MR->getMachineCodeOffset();
132     intptr_t ResultPtr = (intptr_t)MR->getResultPointer();
133     switch ((ARM::RelocationType)MR->getRelocationType()) {
134     case ARM::reloc_arm_relative: {
135       // PC relative relocation
136       *((unsigned*)RelocPos) += (unsigned)ResultPtr;
137       break;
138     }
139     case ARM::reloc_arm_absolute:
140       break;
141     case ARM::reloc_arm_branch: {
142       // relocation to b and bl instructions
143       ResultPtr = (ResultPtr-(intptr_t)RelocPos) >> 2;
144       *((unsigned*)RelocPos) |= ResultPtr;
145       break;
146     }
147     }
148   }
149 }