ARMJITInfo.cpp revision 59324297650c12a8dccf1a7ad650a9e895fdc17e
1148b6a419fbb20e2224a1b92c499d51513b9bc27Evan Cheng//===-- ARMJITInfo.cpp - Implement the JIT interfaces for the ARM target --===//
2148b6a419fbb20e2224a1b92c499d51513b9bc27Evan Cheng//
3148b6a419fbb20e2224a1b92c499d51513b9bc27Evan Cheng//                     The LLVM Compiler Infrastructure
4148b6a419fbb20e2224a1b92c499d51513b9bc27Evan Cheng//
54ee451de366474b9c228b4e5fa573795a715216dChris Lattner// This file is distributed under the University of Illinois Open Source
64ee451de366474b9c228b4e5fa573795a715216dChris Lattner// License. See LICENSE.TXT for details.
7148b6a419fbb20e2224a1b92c499d51513b9bc27Evan Cheng//
8148b6a419fbb20e2224a1b92c499d51513b9bc27Evan Cheng//===----------------------------------------------------------------------===//
9148b6a419fbb20e2224a1b92c499d51513b9bc27Evan Cheng//
10148b6a419fbb20e2224a1b92c499d51513b9bc27Evan Cheng// This file implements the JIT interfaces for the ARM target.
11148b6a419fbb20e2224a1b92c499d51513b9bc27Evan Cheng//
12148b6a419fbb20e2224a1b92c499d51513b9bc27Evan Cheng//===----------------------------------------------------------------------===//
13148b6a419fbb20e2224a1b92c499d51513b9bc27Evan Cheng
14148b6a419fbb20e2224a1b92c499d51513b9bc27Evan Cheng#define DEBUG_TYPE "jit"
15148b6a419fbb20e2224a1b92c499d51513b9bc27Evan Cheng#include "ARMJITInfo.h"
16acf2077ca497980a066e8e7bb81ceec0de82d5daCraig Topper#include "ARM.h"
1725e04788bfddc54dde7bed65302146b46089a166Evan Cheng#include "ARMConstantPoolValue.h"
18148b6a419fbb20e2224a1b92c499d51513b9bc27Evan Cheng#include "ARMRelocations.h"
19148b6a419fbb20e2224a1b92c499d51513b9bc27Evan Cheng#include "ARMSubtarget.h"
2051cc3c13eac78da242f0518fc42580e48dd5304fNicolas Geoffray#include "llvm/Function.h"
21a3f99f90338d89354384ca25f53ca4450a1a9d18Bruno Cardoso Lopes#include "llvm/CodeGen/JITCodeEmitter.h"
22588920b9a5f7004e330e3597872908b4d57e9355Evan Cheng#include "llvm/Support/Debug.h"
23ab7c09b6b6f4516a631fd6788918c237c83939afTorok Edwin#include "llvm/Support/ErrorHandling.h"
24ce63ffb52f249b62cdf2d250c128007b13f27e71Daniel Dunbar#include "llvm/Support/raw_ostream.h"
253cc52ea33c0b96d1682f14fc45c45b57df0f39b6Michael J. Spencer#include "llvm/Support/Memory.h"
26148b6a419fbb20e2224a1b92c499d51513b9bc27Evan Cheng#include <cstdlib>
27148b6a419fbb20e2224a1b92c499d51513b9bc27Evan Chengusing namespace llvm;
28148b6a419fbb20e2224a1b92c499d51513b9bc27Evan Cheng
29148b6a419fbb20e2224a1b92c499d51513b9bc27Evan Chengvoid ARMJITInfo::replaceMachineCodeForFunction(void *Old, void *New) {
3075361b69f3f327842b9dad69fa7f28ae3b688412Chris Lattner  report_fatal_error("ARMJITInfo::replaceMachineCodeForFunction");
31148b6a419fbb20e2224a1b92c499d51513b9bc27Evan Cheng}
32148b6a419fbb20e2224a1b92c499d51513b9bc27Evan Cheng
33148b6a419fbb20e2224a1b92c499d51513b9bc27Evan Cheng/// JITCompilerFunction - This contains the address of the JIT function used to
34148b6a419fbb20e2224a1b92c499d51513b9bc27Evan Cheng/// compile a function lazily.
35148b6a419fbb20e2224a1b92c499d51513b9bc27Evan Chengstatic TargetJITInfo::JITCompilerFn JITCompilerFunction;
36148b6a419fbb20e2224a1b92c499d51513b9bc27Evan Cheng
3795ce1178e40d232cbf8d134030c3dcc8474c704dEvan Cheng// Get the ASMPREFIX for the current host.  This is often '_'.
3895ce1178e40d232cbf8d134030c3dcc8474c704dEvan Cheng#ifndef __USER_LABEL_PREFIX__
3995ce1178e40d232cbf8d134030c3dcc8474c704dEvan Cheng#define __USER_LABEL_PREFIX__
4095ce1178e40d232cbf8d134030c3dcc8474c704dEvan Cheng#endif
4195ce1178e40d232cbf8d134030c3dcc8474c704dEvan Cheng#define GETASMPREFIX2(X) #X
4295ce1178e40d232cbf8d134030c3dcc8474c704dEvan Cheng#define GETASMPREFIX(X) GETASMPREFIX2(X)
4395ce1178e40d232cbf8d134030c3dcc8474c704dEvan Cheng#define ASMPREFIX GETASMPREFIX(__USER_LABEL_PREFIX__)
4495ce1178e40d232cbf8d134030c3dcc8474c704dEvan Cheng
45148b6a419fbb20e2224a1b92c499d51513b9bc27Evan Cheng// CompilationCallback stub - We can't use a C function with inline assembly in
46692df93de427356d3ab7bb0438a3c998f28186eaBob Wilson// it, because the prolog/epilog inserted by GCC won't work for us. (We need
47932a32d2512353478d16c4101582adff404a55a5Jim Grosbach// to preserve more context and manipulate the stack directly).  Instead,
48764ab52dd80310a205c9888bf166d09dab858f90Jim Grosbach// write our own wrapper, which does things our way, so we have complete
49932a32d2512353478d16c4101582adff404a55a5Jim Grosbach// control over register saving and restoring.
50148b6a419fbb20e2224a1b92c499d51513b9bc27Evan Chengextern "C" {
51148b6a419fbb20e2224a1b92c499d51513b9bc27Evan Cheng#if defined(__arm__)
52a9ad04191cb56c42944b17980b8b2bb2afe11ab2Dan Gohman  void ARMCompilationCallback();
53148b6a419fbb20e2224a1b92c499d51513b9bc27Evan Cheng  asm(
54148b6a419fbb20e2224a1b92c499d51513b9bc27Evan Cheng    ".text\n"
55148b6a419fbb20e2224a1b92c499d51513b9bc27Evan Cheng    ".align 2\n"
5695ce1178e40d232cbf8d134030c3dcc8474c704dEvan Cheng    ".globl " ASMPREFIX "ARMCompilationCallback\n"
5795ce1178e40d232cbf8d134030c3dcc8474c704dEvan Cheng    ASMPREFIX "ARMCompilationCallback:\n"
58932a32d2512353478d16c4101582adff404a55a5Jim Grosbach    // Save caller saved registers since they may contain stuff
59932a32d2512353478d16c4101582adff404a55a5Jim Grosbach    // for the real target function right now. We have to act as if this
60932a32d2512353478d16c4101582adff404a55a5Jim Grosbach    // whole compilation callback doesn't exist as far as the caller is
61932a32d2512353478d16c4101582adff404a55a5Jim Grosbach    // concerned, so we can't just preserve the callee saved regs.
62a9ab95b38b0aec44e26a3b36a6b37498dc2acddeJim Grosbach    "stmdb sp!, {r0, r1, r2, r3, lr}\n"
63901a8b7c6b2525889282add0d902ce46e111e0c2Xerxes Ranby#if (defined(__VFP_FP__) && !defined(__SOFTFP__))
642bbb22b8ef571cc11e0c0bb0a0f13670b5ef5cffBob Wilson    "vstmdb sp!, {d0, d1, d2, d3, d4, d5, d6, d7}\n"
6528f312949e27e6e218ba25d8ca07ed58a96a4bd1Evan Cheng#endif
66932a32d2512353478d16c4101582adff404a55a5Jim Grosbach    // The LR contains the address of the stub function on entry.
67932a32d2512353478d16c4101582adff404a55a5Jim Grosbach    // pass it as the argument to the C part of the callback
68932a32d2512353478d16c4101582adff404a55a5Jim Grosbach    "mov  r0, lr\n"
69932a32d2512353478d16c4101582adff404a55a5Jim Grosbach    "sub  sp, sp, #4\n"
70932a32d2512353478d16c4101582adff404a55a5Jim Grosbach    // Call the C portion of the callback
71932a32d2512353478d16c4101582adff404a55a5Jim Grosbach    "bl   " ASMPREFIX "ARMCompilationCallbackC\n"
72932a32d2512353478d16c4101582adff404a55a5Jim Grosbach    "add  sp, sp, #4\n"
73932a32d2512353478d16c4101582adff404a55a5Jim Grosbach    // Restoring the LR to the return address of the function that invoked
74932a32d2512353478d16c4101582adff404a55a5Jim Grosbach    // the stub and de-allocating the stack space for it requires us to
75932a32d2512353478d16c4101582adff404a55a5Jim Grosbach    // swap the two saved LR values on the stack, as they're backwards
76932a32d2512353478d16c4101582adff404a55a5Jim Grosbach    // for what we need since the pop instruction has a pre-determined
77932a32d2512353478d16c4101582adff404a55a5Jim Grosbach    // order for the registers.
78932a32d2512353478d16c4101582adff404a55a5Jim Grosbach    //      +--------+
79932a32d2512353478d16c4101582adff404a55a5Jim Grosbach    //   0  | LR     | Original return address
80764ab52dd80310a205c9888bf166d09dab858f90Jim Grosbach    //      +--------+
81932a32d2512353478d16c4101582adff404a55a5Jim Grosbach    //   1  | LR     | Stub address (start of stub)
82932a32d2512353478d16c4101582adff404a55a5Jim Grosbach    // 2-5  | R3..R0 | Saved registers (we need to preserve all regs)
8328f312949e27e6e218ba25d8ca07ed58a96a4bd1Evan Cheng    // 6-20 | D0..D7 | Saved VFP registers
84764ab52dd80310a205c9888bf166d09dab858f90Jim Grosbach    //      +--------+
85932a32d2512353478d16c4101582adff404a55a5Jim Grosbach    //
86901a8b7c6b2525889282add0d902ce46e111e0c2Xerxes Ranby#if (defined(__VFP_FP__) && !defined(__SOFTFP__))
8728f312949e27e6e218ba25d8ca07ed58a96a4bd1Evan Cheng    // Restore VFP caller-saved registers.
882bbb22b8ef571cc11e0c0bb0a0f13670b5ef5cffBob Wilson    "vldmia sp!, {d0, d1, d2, d3, d4, d5, d6, d7}\n"
8928f312949e27e6e218ba25d8ca07ed58a96a4bd1Evan Cheng#endif
9028f312949e27e6e218ba25d8ca07ed58a96a4bd1Evan Cheng    //
91932a32d2512353478d16c4101582adff404a55a5Jim Grosbach    //      We need to exchange the values in slots 0 and 1 so we can
92932a32d2512353478d16c4101582adff404a55a5Jim Grosbach    //      return to the address in slot 1 with the address in slot 0
93932a32d2512353478d16c4101582adff404a55a5Jim Grosbach    //      restored to the LR.
94932a32d2512353478d16c4101582adff404a55a5Jim Grosbach    "ldr  r0, [sp,#20]\n"
95932a32d2512353478d16c4101582adff404a55a5Jim Grosbach    "ldr  r1, [sp,#16]\n"
96932a32d2512353478d16c4101582adff404a55a5Jim Grosbach    "str  r1, [sp,#20]\n"
97932a32d2512353478d16c4101582adff404a55a5Jim Grosbach    "str  r0, [sp,#16]\n"
98932a32d2512353478d16c4101582adff404a55a5Jim Grosbach    // Return to the (newly modified) stub to invoke the real function.
99932a32d2512353478d16c4101582adff404a55a5Jim Grosbach    // The above twiddling of the saved return addresses allows us to
10092e7195e433435eeb93d5f88de146878b76abb21Bob Wilson    // deallocate everything, including the LR the stub saved, with two
10192e7195e433435eeb93d5f88de146878b76abb21Bob Wilson    // updating load instructions.
102692df93de427356d3ab7bb0438a3c998f28186eaBob Wilson    "ldmia  sp!, {r0, r1, r2, r3, lr}\n"
103692df93de427356d3ab7bb0438a3c998f28186eaBob Wilson    "ldr    pc, [sp], #4\n"
10495ce1178e40d232cbf8d134030c3dcc8474c704dEvan Cheng      );
10595ce1178e40d232cbf8d134030c3dcc8474c704dEvan Cheng#else  // Not an ARM host
106148b6a419fbb20e2224a1b92c499d51513b9bc27Evan Cheng  void ARMCompilationCallback() {
107c23197a26f34f559ea9797de51e187087c039c42Torok Edwin    llvm_unreachable("Cannot call ARMCompilationCallback() on a non-ARM arch!");
108148b6a419fbb20e2224a1b92c499d51513b9bc27Evan Cheng  }
109148b6a419fbb20e2224a1b92c499d51513b9bc27Evan Cheng#endif
110148b6a419fbb20e2224a1b92c499d51513b9bc27Evan Cheng}
111148b6a419fbb20e2224a1b92c499d51513b9bc27Evan Cheng
112764ab52dd80310a205c9888bf166d09dab858f90Jim Grosbach/// ARMCompilationCallbackC - This is the target-specific function invoked
113764ab52dd80310a205c9888bf166d09dab858f90Jim Grosbach/// by the function stub when we did not know the real target of a call.
114764ab52dd80310a205c9888bf166d09dab858f90Jim Grosbach/// This function must locate the start of the stub or call site and pass
115932a32d2512353478d16c4101582adff404a55a5Jim Grosbach/// it into the JIT compiler function.
116932a32d2512353478d16c4101582adff404a55a5Jim Grosbachextern "C" void ARMCompilationCallbackC(intptr_t StubAddr) {
117932a32d2512353478d16c4101582adff404a55a5Jim Grosbach  // Get the address of the compiled code for this function.
118932a32d2512353478d16c4101582adff404a55a5Jim Grosbach  intptr_t NewVal = (intptr_t)JITCompilerFunction((void*)StubAddr);
119148b6a419fbb20e2224a1b92c499d51513b9bc27Evan Cheng
120148b6a419fbb20e2224a1b92c499d51513b9bc27Evan Cheng  // Rewrite the call target... so that we don't end up here every time we
121932a32d2512353478d16c4101582adff404a55a5Jim Grosbach  // execute the call. We're replacing the first two instructions of the
122932a32d2512353478d16c4101582adff404a55a5Jim Grosbach  // stub with:
123932a32d2512353478d16c4101582adff404a55a5Jim Grosbach  //   ldr pc, [pc,#-4]
124932a32d2512353478d16c4101582adff404a55a5Jim Grosbach  //   <addr>
125ae166410b992e7eb8652aba1c9010c043a8f6016Evan Cheng  if (!sys::Memory::setRangeWritable((void*)StubAddr, 8)) {
126c23197a26f34f559ea9797de51e187087c039c42Torok Edwin    llvm_unreachable("ERROR: Unable to mark stub writable");
127ae166410b992e7eb8652aba1c9010c043a8f6016Evan Cheng  }
128ae166410b992e7eb8652aba1c9010c043a8f6016Evan Cheng  *(intptr_t *)StubAddr = 0xe51ff004;  // ldr pc, [pc, #-4]
129932a32d2512353478d16c4101582adff404a55a5Jim Grosbach  *(intptr_t *)(StubAddr+4) = NewVal;
130ae166410b992e7eb8652aba1c9010c043a8f6016Evan Cheng  if (!sys::Memory::setRangeExecutable((void*)StubAddr, 8)) {
131c23197a26f34f559ea9797de51e187087c039c42Torok Edwin    llvm_unreachable("ERROR: Unable to mark stub executable");
132ae166410b992e7eb8652aba1c9010c043a8f6016Evan Cheng  }
133148b6a419fbb20e2224a1b92c499d51513b9bc27Evan Cheng}
134148b6a419fbb20e2224a1b92c499d51513b9bc27Evan Cheng
135148b6a419fbb20e2224a1b92c499d51513b9bc27Evan ChengTargetJITInfo::LazyResolverFn
136148b6a419fbb20e2224a1b92c499d51513b9bc27Evan ChengARMJITInfo::getLazyResolverFunction(JITCompilerFn F) {
137148b6a419fbb20e2224a1b92c499d51513b9bc27Evan Cheng  JITCompilerFunction = F;
138148b6a419fbb20e2224a1b92c499d51513b9bc27Evan Cheng  return ARMCompilationCallback;
139148b6a419fbb20e2224a1b92c499d51513b9bc27Evan Cheng}
140148b6a419fbb20e2224a1b92c499d51513b9bc27Evan Cheng
1419ed2f80910160bbf8051d91cd74c82d4619885b4Evan Chengvoid *ARMJITInfo::emitGlobalValueIndirectSym(const GlobalValue *GV, void *Ptr,
142a3f99f90338d89354384ca25f53ca4450a1a9d18Bruno Cardoso Lopes                                             JITCodeEmitter &JCE) {
14332d7e6ebde29faeea75ecb718b4281414b0eea0bJeffrey Yasskin  uint8_t Buffer[4];
14432d7e6ebde29faeea75ecb718b4281414b0eea0bJeffrey Yasskin  uint8_t *Cur = Buffer;
14532d7e6ebde29faeea75ecb718b4281414b0eea0bJeffrey Yasskin  MachineCodeEmitter::emitWordLEInto(Cur, (intptr_t)Ptr);
14632d7e6ebde29faeea75ecb718b4281414b0eea0bJeffrey Yasskin  void *PtrAddr = JCE.allocIndirectGV(
14732d7e6ebde29faeea75ecb718b4281414b0eea0bJeffrey Yasskin      GV, Buffer, sizeof(Buffer), /*Alignment=*/4);
148588920b9a5f7004e330e3597872908b4d57e9355Evan Cheng  addIndirectSymAddr(Ptr, (intptr_t)PtrAddr);
149588920b9a5f7004e330e3597872908b4d57e9355Evan Cheng  return PtrAddr;
150e96a490d7a0e224961d37f60f85e8556a64ed2b1Evan Cheng}
151e96a490d7a0e224961d37f60f85e8556a64ed2b1Evan Cheng
152108c838093704650378b194fe9afc5ebb9e91455Jeffrey YasskinTargetJITInfo::StubLayout ARMJITInfo::getStubLayout() {
153108c838093704650378b194fe9afc5ebb9e91455Jeffrey Yasskin  // The stub contains up to 3 4-byte instructions, aligned at 4 bytes, and a
154108c838093704650378b194fe9afc5ebb9e91455Jeffrey Yasskin  // 4-byte address.  See emitFunctionStub for details.
155108c838093704650378b194fe9afc5ebb9e91455Jeffrey Yasskin  StubLayout Result = {16, 4};
156108c838093704650378b194fe9afc5ebb9e91455Jeffrey Yasskin  return Result;
157108c838093704650378b194fe9afc5ebb9e91455Jeffrey Yasskin}
158108c838093704650378b194fe9afc5ebb9e91455Jeffrey Yasskin
15951cc3c13eac78da242f0518fc42580e48dd5304fNicolas Geoffrayvoid *ARMJITInfo::emitFunctionStub(const Function* F, void *Fn,
160a3f99f90338d89354384ca25f53ca4450a1a9d18Bruno Cardoso Lopes                                   JITCodeEmitter &JCE) {
161108c838093704650378b194fe9afc5ebb9e91455Jeffrey Yasskin  void *Addr;
162148b6a419fbb20e2224a1b92c499d51513b9bc27Evan Cheng  // If this is just a call to an external function, emit a branch instead of a
163148b6a419fbb20e2224a1b92c499d51513b9bc27Evan Cheng  // call.  The code is the same except for one bit of the last instruction.
164148b6a419fbb20e2224a1b92c499d51513b9bc27Evan Cheng  if (Fn != (void*)(intptr_t)ARMCompilationCallback) {
165e96a490d7a0e224961d37f60f85e8556a64ed2b1Evan Cheng    // Branch to the corresponding function addr.
166588920b9a5f7004e330e3597872908b4d57e9355Evan Cheng    if (IsPIC) {
167108c838093704650378b194fe9afc5ebb9e91455Jeffrey Yasskin      // The stub is 16-byte size and 4-aligned.
168588920b9a5f7004e330e3597872908b4d57e9355Evan Cheng      intptr_t LazyPtr = getIndirectSymAddr(Fn);
169588920b9a5f7004e330e3597872908b4d57e9355Evan Cheng      if (!LazyPtr) {
170588920b9a5f7004e330e3597872908b4d57e9355Evan Cheng        // In PIC mode, the function stub is loading a lazy-ptr.
17159324297650c12a8dccf1a7ad650a9e895fdc17eRoman Divacky        LazyPtr= (intptr_t)emitGlobalValueIndirectSym((const GlobalValue*)F, Fn, JCE);
172ce63ffb52f249b62cdf2d250c128007b13f27e71Daniel Dunbar        DEBUG(if (F)
173764ab52dd80310a205c9888bf166d09dab858f90Jim Grosbach                errs() << "JIT: Indirect symbol emitted at [" << LazyPtr
174ce63ffb52f249b62cdf2d250c128007b13f27e71Daniel Dunbar                       << "] for GV '" << F->getName() << "'\n";
175ce63ffb52f249b62cdf2d250c128007b13f27e71Daniel Dunbar              else
176ce63ffb52f249b62cdf2d250c128007b13f27e71Daniel Dunbar                errs() << "JIT: Stub emitted at [" << LazyPtr
177ce63ffb52f249b62cdf2d250c128007b13f27e71Daniel Dunbar                       << "] for external function at '" << Fn << "'\n");
178588920b9a5f7004e330e3597872908b4d57e9355Evan Cheng      }
179108c838093704650378b194fe9afc5ebb9e91455Jeffrey Yasskin      JCE.emitAlignment(4);
180108c838093704650378b194fe9afc5ebb9e91455Jeffrey Yasskin      Addr = (void*)JCE.getCurrentPCValue();
181108c838093704650378b194fe9afc5ebb9e91455Jeffrey Yasskin      if (!sys::Memory::setRangeWritable(Addr, 16)) {
18204cedd3c8f6c7d00e06f63a49aaef05d1d4a726fEvan Cheng        llvm_unreachable("ERROR: Unable to mark stub writable");
18304cedd3c8f6c7d00e06f63a49aaef05d1d4a726fEvan Cheng      }
1840dde97156ce75d14498185e34c5d20c66a0c38d1Eric Christopher      JCE.emitWordLE(0xe59fc004);            // ldr ip, [pc, #+4]
185a3f99f90338d89354384ca25f53ca4450a1a9d18Bruno Cardoso Lopes      JCE.emitWordLE(0xe08fc00c);            // L_func$scv: add ip, pc, ip
186a3f99f90338d89354384ca25f53ca4450a1a9d18Bruno Cardoso Lopes      JCE.emitWordLE(0xe59cf000);            // ldr pc, [ip]
187108c838093704650378b194fe9afc5ebb9e91455Jeffrey Yasskin      JCE.emitWordLE(LazyPtr - (intptr_t(Addr)+4+8));  // func - (L_func$scv+8)
188108c838093704650378b194fe9afc5ebb9e91455Jeffrey Yasskin      sys::Memory::InvalidateInstructionCache(Addr, 16);
189108c838093704650378b194fe9afc5ebb9e91455Jeffrey Yasskin      if (!sys::Memory::setRangeExecutable(Addr, 16)) {
19004cedd3c8f6c7d00e06f63a49aaef05d1d4a726fEvan Cheng        llvm_unreachable("ERROR: Unable to mark stub executable");
19104cedd3c8f6c7d00e06f63a49aaef05d1d4a726fEvan Cheng      }
192588920b9a5f7004e330e3597872908b4d57e9355Evan Cheng    } else {
193588920b9a5f7004e330e3597872908b4d57e9355Evan Cheng      // The stub is 8-byte size and 4-aligned.
194108c838093704650378b194fe9afc5ebb9e91455Jeffrey Yasskin      JCE.emitAlignment(4);
195108c838093704650378b194fe9afc5ebb9e91455Jeffrey Yasskin      Addr = (void*)JCE.getCurrentPCValue();
196108c838093704650378b194fe9afc5ebb9e91455Jeffrey Yasskin      if (!sys::Memory::setRangeWritable(Addr, 8)) {
19704cedd3c8f6c7d00e06f63a49aaef05d1d4a726fEvan Cheng        llvm_unreachable("ERROR: Unable to mark stub writable");
19804cedd3c8f6c7d00e06f63a49aaef05d1d4a726fEvan Cheng      }
199a3f99f90338d89354384ca25f53ca4450a1a9d18Bruno Cardoso Lopes      JCE.emitWordLE(0xe51ff004);    // ldr pc, [pc, #-4]
200a3f99f90338d89354384ca25f53ca4450a1a9d18Bruno Cardoso Lopes      JCE.emitWordLE((intptr_t)Fn);  // addr of function
201108c838093704650378b194fe9afc5ebb9e91455Jeffrey Yasskin      sys::Memory::InvalidateInstructionCache(Addr, 8);
202108c838093704650378b194fe9afc5ebb9e91455Jeffrey Yasskin      if (!sys::Memory::setRangeExecutable(Addr, 8)) {
20304cedd3c8f6c7d00e06f63a49aaef05d1d4a726fEvan Cheng        llvm_unreachable("ERROR: Unable to mark stub executable");
20404cedd3c8f6c7d00e06f63a49aaef05d1d4a726fEvan Cheng      }
205588920b9a5f7004e330e3597872908b4d57e9355Evan Cheng    }
206148b6a419fbb20e2224a1b92c499d51513b9bc27Evan Cheng  } else {
207932a32d2512353478d16c4101582adff404a55a5Jim Grosbach    // The compilation callback will overwrite the first two words of this
208764ab52dd80310a205c9888bf166d09dab858f90Jim Grosbach    // stub with indirect branch instructions targeting the compiled code.
209932a32d2512353478d16c4101582adff404a55a5Jim Grosbach    // This stub sets the return address to restart the stub, so that
210932a32d2512353478d16c4101582adff404a55a5Jim Grosbach    // the new branch will be invoked when we come back.
211932a32d2512353478d16c4101582adff404a55a5Jim Grosbach    //
212e96a490d7a0e224961d37f60f85e8556a64ed2b1Evan Cheng    // Branch and link to the compilation callback.
213e96a490d7a0e224961d37f60f85e8556a64ed2b1Evan Cheng    // The stub is 16-byte size and 4-byte aligned.
214108c838093704650378b194fe9afc5ebb9e91455Jeffrey Yasskin    JCE.emitAlignment(4);
215108c838093704650378b194fe9afc5ebb9e91455Jeffrey Yasskin    Addr = (void*)JCE.getCurrentPCValue();
216108c838093704650378b194fe9afc5ebb9e91455Jeffrey Yasskin    if (!sys::Memory::setRangeWritable(Addr, 16)) {
21704cedd3c8f6c7d00e06f63a49aaef05d1d4a726fEvan Cheng      llvm_unreachable("ERROR: Unable to mark stub writable");
21804cedd3c8f6c7d00e06f63a49aaef05d1d4a726fEvan Cheng    }
219932a32d2512353478d16c4101582adff404a55a5Jim Grosbach    // Save LR so the callback can determine which stub called it.
220932a32d2512353478d16c4101582adff404a55a5Jim Grosbach    // The compilation callback is responsible for popping this prior
221932a32d2512353478d16c4101582adff404a55a5Jim Grosbach    // to returning.
222a3f99f90338d89354384ca25f53ca4450a1a9d18Bruno Cardoso Lopes    JCE.emitWordLE(0xe92d4000); // push {lr}
223ae166410b992e7eb8652aba1c9010c043a8f6016Evan Cheng    // Set the return address to go back to the start of this stub.
224a3f99f90338d89354384ca25f53ca4450a1a9d18Bruno Cardoso Lopes    JCE.emitWordLE(0xe24fe00c); // sub lr, pc, #12
225ae166410b992e7eb8652aba1c9010c043a8f6016Evan Cheng    // Invoke the compilation callback.
226a3f99f90338d89354384ca25f53ca4450a1a9d18Bruno Cardoso Lopes    JCE.emitWordLE(0xe51ff004); // ldr pc, [pc, #-4]
227ae166410b992e7eb8652aba1c9010c043a8f6016Evan Cheng    // The address of the compilation callback.
228a3f99f90338d89354384ca25f53ca4450a1a9d18Bruno Cardoso Lopes    JCE.emitWordLE((intptr_t)ARMCompilationCallback);
229108c838093704650378b194fe9afc5ebb9e91455Jeffrey Yasskin    sys::Memory::InvalidateInstructionCache(Addr, 16);
230108c838093704650378b194fe9afc5ebb9e91455Jeffrey Yasskin    if (!sys::Memory::setRangeExecutable(Addr, 16)) {
23104cedd3c8f6c7d00e06f63a49aaef05d1d4a726fEvan Cheng      llvm_unreachable("ERROR: Unable to mark stub executable");
23204cedd3c8f6c7d00e06f63a49aaef05d1d4a726fEvan Cheng    }
233148b6a419fbb20e2224a1b92c499d51513b9bc27Evan Cheng  }
234148b6a419fbb20e2224a1b92c499d51513b9bc27Evan Cheng
235108c838093704650378b194fe9afc5ebb9e91455Jeffrey Yasskin  return Addr;
236148b6a419fbb20e2224a1b92c499d51513b9bc27Evan Cheng}
237148b6a419fbb20e2224a1b92c499d51513b9bc27Evan Cheng
2384df60f5491ff35c8a48c2cf14e18a33c9793b3bbEvan Chengintptr_t ARMJITInfo::resolveRelocDestAddr(MachineRelocation *MR) const {
23925e04788bfddc54dde7bed65302146b46089a166Evan Cheng  ARM::RelocationType RT = (ARM::RelocationType)MR->getRelocationType();
240580c0dfaed1caaf241dfb8c02c11f89d6431ee50Evan Cheng  switch (RT) {
241580c0dfaed1caaf241dfb8c02c11f89d6431ee50Evan Cheng  default:
242580c0dfaed1caaf241dfb8c02c11f89d6431ee50Evan Cheng    return (intptr_t)(MR->getResultPointer());
243580c0dfaed1caaf241dfb8c02c11f89d6431ee50Evan Cheng  case ARM::reloc_arm_pic_jt:
244437c1738ef0ca451b710c31c87166f6abfd04ec7Evan Cheng    // Destination address - jump table base.
245437c1738ef0ca451b710c31c87166f6abfd04ec7Evan Cheng    return (intptr_t)(MR->getResultPointer()) - MR->getConstantVal();
246580c0dfaed1caaf241dfb8c02c11f89d6431ee50Evan Cheng  case ARM::reloc_arm_jt_base:
247437c1738ef0ca451b710c31c87166f6abfd04ec7Evan Cheng    // Jump table base address.
2484df60f5491ff35c8a48c2cf14e18a33c9793b3bbEvan Cheng    return getJumpTableBaseAddr(MR->getJumpTableIndex());
249580c0dfaed1caaf241dfb8c02c11f89d6431ee50Evan Cheng  case ARM::reloc_arm_cp_entry:
250580c0dfaed1caaf241dfb8c02c11f89d6431ee50Evan Cheng  case ARM::reloc_arm_vfp_cp_entry:
251437c1738ef0ca451b710c31c87166f6abfd04ec7Evan Cheng    // Constant pool entry address.
25225e04788bfddc54dde7bed65302146b46089a166Evan Cheng    return getConstantPoolEntryAddr(MR->getConstantPoolIndex());
253580c0dfaed1caaf241dfb8c02c11f89d6431ee50Evan Cheng  case ARM::reloc_arm_machine_cp_entry: {
254413a89f3187581ee94d01cafe167f1deff16493dEvan Cheng    ARMConstantPoolValue *ACPV = (ARMConstantPoolValue*)MR->getConstantVal();
25525e04788bfddc54dde7bed65302146b46089a166Evan Cheng    assert((!ACPV->hasModifier() && !ACPV->mustAddCurrentAddress()) &&
25625e04788bfddc54dde7bed65302146b46089a166Evan Cheng           "Can't handle this machine constant pool entry yet!");
25725e04788bfddc54dde7bed65302146b46089a166Evan Cheng    intptr_t Addr = (intptr_t)(MR->getResultPointer());
25825e04788bfddc54dde7bed65302146b46089a166Evan Cheng    Addr -= getPCLabelAddr(ACPV->getLabelId()) + ACPV->getPCAdjustment();
25925e04788bfddc54dde7bed65302146b46089a166Evan Cheng    return Addr;
26025e04788bfddc54dde7bed65302146b46089a166Evan Cheng  }
261580c0dfaed1caaf241dfb8c02c11f89d6431ee50Evan Cheng  }
26225e04788bfddc54dde7bed65302146b46089a166Evan Cheng}
26325e04788bfddc54dde7bed65302146b46089a166Evan Cheng
264148b6a419fbb20e2224a1b92c499d51513b9bc27Evan Cheng/// relocate - Before the JIT can run a block of code that has been emitted,
265148b6a419fbb20e2224a1b92c499d51513b9bc27Evan Cheng/// it must rewrite the code to contain the actual addresses of any
266148b6a419fbb20e2224a1b92c499d51513b9bc27Evan Cheng/// referenced global symbols.
267148b6a419fbb20e2224a1b92c499d51513b9bc27Evan Chengvoid ARMJITInfo::relocate(void *Function, MachineRelocation *MR,
268148b6a419fbb20e2224a1b92c499d51513b9bc27Evan Cheng                          unsigned NumRelocs, unsigned char* GOTBase) {
2690ff94f7fcc95112331ee0f4f3d31c90acb9f2952Evan Cheng  for (unsigned i = 0; i != NumRelocs; ++i, ++MR) {
2700ff94f7fcc95112331ee0f4f3d31c90acb9f2952Evan Cheng    void *RelocPos = (char*)Function + MR->getMachineCodeOffset();
2714df60f5491ff35c8a48c2cf14e18a33c9793b3bbEvan Cheng    intptr_t ResultPtr = resolveRelocDestAddr(MR);
2720ff94f7fcc95112331ee0f4f3d31c90acb9f2952Evan Cheng    switch ((ARM::RelocationType)MR->getRelocationType()) {
2730f282439be688babbbf6d54151ddf9a7ebbf3637Evan Cheng    case ARM::reloc_arm_cp_entry:
274580c0dfaed1caaf241dfb8c02c11f89d6431ee50Evan Cheng    case ARM::reloc_arm_vfp_cp_entry:
2750ff94f7fcc95112331ee0f4f3d31c90acb9f2952Evan Cheng    case ARM::reloc_arm_relative: {
276d05c04c1692d4630e43fd4f22bba37edbe701258Raul Herbster      // It is necessary to calculate the correct PC relative value. We
277d05c04c1692d4630e43fd4f22bba37edbe701258Raul Herbster      // subtract the base addr from the target addr to form a byte offset.
278580c0dfaed1caaf241dfb8c02c11f89d6431ee50Evan Cheng      ResultPtr = ResultPtr - (intptr_t)RelocPos - 8;
279d05c04c1692d4630e43fd4f22bba37edbe701258Raul Herbster      // If the result is positive, set bit U(23) to 1.
280d05c04c1692d4630e43fd4f22bba37edbe701258Raul Herbster      if (ResultPtr >= 0)
281580c0dfaed1caaf241dfb8c02c11f89d6431ee50Evan Cheng        *((intptr_t*)RelocPos) |= 1 << ARMII::U_BitShift;
282d05c04c1692d4630e43fd4f22bba37edbe701258Raul Herbster      else {
283580c0dfaed1caaf241dfb8c02c11f89d6431ee50Evan Cheng        // Otherwise, obtain the absolute value and set bit U(23) to 0.
284cb5798285aa3a3cd93448beda6264152c761e8e3Evan Cheng        *((intptr_t*)RelocPos) &= ~(1 << ARMII::U_BitShift);
285580c0dfaed1caaf241dfb8c02c11f89d6431ee50Evan Cheng        ResultPtr = - ResultPtr;
286d05c04c1692d4630e43fd4f22bba37edbe701258Raul Herbster      }
28725e04788bfddc54dde7bed65302146b46089a166Evan Cheng      // Set the immed value calculated.
288580c0dfaed1caaf241dfb8c02c11f89d6431ee50Evan Cheng      // VFP immediate offset is multiplied by 4.
289580c0dfaed1caaf241dfb8c02c11f89d6431ee50Evan Cheng      if (MR->getRelocationType() == ARM::reloc_arm_vfp_cp_entry)
290580c0dfaed1caaf241dfb8c02c11f89d6431ee50Evan Cheng        ResultPtr = ResultPtr >> 2;
291580c0dfaed1caaf241dfb8c02c11f89d6431ee50Evan Cheng      *((intptr_t*)RelocPos) |= ResultPtr;
292df1c637ac4b6f6587c037be55cafed665c732d8fEric Christopher      // Set register Rn to PC (which is register 15 on all architectures).
293df1c637ac4b6f6587c037be55cafed665c732d8fEric Christopher      // FIXME: This avoids the need for register info in the JIT class.
294df1c637ac4b6f6587c037be55cafed665c732d8fEric Christopher      *((intptr_t*)RelocPos) |= 15 << ARMII::RegRnShift;
2950ff94f7fcc95112331ee0f4f3d31c90acb9f2952Evan Cheng      break;
2960ff94f7fcc95112331ee0f4f3d31c90acb9f2952Evan Cheng    }
297437c1738ef0ca451b710c31c87166f6abfd04ec7Evan Cheng    case ARM::reloc_arm_pic_jt:
29825e04788bfddc54dde7bed65302146b46089a166Evan Cheng    case ARM::reloc_arm_machine_cp_entry:
2990f282439be688babbbf6d54151ddf9a7ebbf3637Evan Cheng    case ARM::reloc_arm_absolute: {
30025e04788bfddc54dde7bed65302146b46089a166Evan Cheng      // These addresses have already been resolved.
301580c0dfaed1caaf241dfb8c02c11f89d6431ee50Evan Cheng      *((intptr_t*)RelocPos) |= (intptr_t)ResultPtr;
3020f282439be688babbbf6d54151ddf9a7ebbf3637Evan Cheng      break;
3030f282439be688babbbf6d54151ddf9a7ebbf3637Evan Cheng    }
3040ff94f7fcc95112331ee0f4f3d31c90acb9f2952Evan Cheng    case ARM::reloc_arm_branch: {
305d05c04c1692d4630e43fd4f22bba37edbe701258Raul Herbster      // It is necessary to calculate the correct value of signed_immed_24
306d05c04c1692d4630e43fd4f22bba37edbe701258Raul Herbster      // field. We subtract the base addr from the target addr to form a
307d05c04c1692d4630e43fd4f22bba37edbe701258Raul Herbster      // byte offset, which must be inside the range -33554432 and +33554428.
308d05c04c1692d4630e43fd4f22bba37edbe701258Raul Herbster      // Then, we set the signed_immed_24 field of the instruction to bits
309d05c04c1692d4630e43fd4f22bba37edbe701258Raul Herbster      // [25:2] of the byte offset. More details ARM-ARM p. A4-11.
3104df60f5491ff35c8a48c2cf14e18a33c9793b3bbEvan Cheng      ResultPtr = ResultPtr - (intptr_t)RelocPos - 8;
311d05c04c1692d4630e43fd4f22bba37edbe701258Raul Herbster      ResultPtr = (ResultPtr & 0x03FFFFFC) >> 2;
312d05c04c1692d4630e43fd4f22bba37edbe701258Raul Herbster      assert(ResultPtr >= -33554432 && ResultPtr <= 33554428);
313580c0dfaed1caaf241dfb8c02c11f89d6431ee50Evan Cheng      *((intptr_t*)RelocPos) |= ResultPtr;
3140ff94f7fcc95112331ee0f4f3d31c90acb9f2952Evan Cheng      break;
3150ff94f7fcc95112331ee0f4f3d31c90acb9f2952Evan Cheng    }
3164df60f5491ff35c8a48c2cf14e18a33c9793b3bbEvan Cheng    case ARM::reloc_arm_jt_base: {
3174df60f5491ff35c8a48c2cf14e18a33c9793b3bbEvan Cheng      // JT base - (instruction addr + 8)
3184df60f5491ff35c8a48c2cf14e18a33c9793b3bbEvan Cheng      ResultPtr = ResultPtr - (intptr_t)RelocPos - 8;
319580c0dfaed1caaf241dfb8c02c11f89d6431ee50Evan Cheng      *((intptr_t*)RelocPos) |= ResultPtr;
3204df60f5491ff35c8a48c2cf14e18a33c9793b3bbEvan Cheng      break;
3214df60f5491ff35c8a48c2cf14e18a33c9793b3bbEvan Cheng    }
322f86399be0c2cd095ebaa80dcc0180dab45ec263cZonr Chang    case ARM::reloc_arm_movw: {
323f86399be0c2cd095ebaa80dcc0180dab45ec263cZonr Chang      ResultPtr = ResultPtr & 0xFFFF;
324f86399be0c2cd095ebaa80dcc0180dab45ec263cZonr Chang      *((intptr_t*)RelocPos) |= ResultPtr & 0xFFF;
325f86399be0c2cd095ebaa80dcc0180dab45ec263cZonr Chang      *((intptr_t*)RelocPos) |= ((ResultPtr >> 12) & 0xF) << 16;
326f86399be0c2cd095ebaa80dcc0180dab45ec263cZonr Chang      break;
327f86399be0c2cd095ebaa80dcc0180dab45ec263cZonr Chang    }
328f86399be0c2cd095ebaa80dcc0180dab45ec263cZonr Chang    case ARM::reloc_arm_movt: {
329f86399be0c2cd095ebaa80dcc0180dab45ec263cZonr Chang      ResultPtr = (ResultPtr >> 16) & 0xFFFF;
330f86399be0c2cd095ebaa80dcc0180dab45ec263cZonr Chang      *((intptr_t*)RelocPos) |= ResultPtr & 0xFFF;
331f86399be0c2cd095ebaa80dcc0180dab45ec263cZonr Chang      *((intptr_t*)RelocPos) |= ((ResultPtr >> 12) & 0xF) << 16;
332f86399be0c2cd095ebaa80dcc0180dab45ec263cZonr Chang      break;
333f86399be0c2cd095ebaa80dcc0180dab45ec263cZonr Chang    }
3340ff94f7fcc95112331ee0f4f3d31c90acb9f2952Evan Cheng    }
3350ff94f7fcc95112331ee0f4f3d31c90acb9f2952Evan Cheng  }
336148b6a419fbb20e2224a1b92c499d51513b9bc27Evan Cheng}
337