LLVM API Documentation

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
SparcJITInfo.cpp
Go to the documentation of this file.
1 //===-- SparcJITInfo.cpp - Implement the Sparc JIT Interface --------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file implements the JIT interfaces for the Sparc target.
11 //
12 //===----------------------------------------------------------------------===//
13 #define DEBUG_TYPE "jit"
14 #include "SparcJITInfo.h"
15 #include "SparcRelocations.h"
16 
18 #include "llvm/Support/Memory.h"
19 
20 using namespace llvm;
21 
22 /// JITCompilerFunction - This contains the address of the JIT function used to
23 /// compile a function lazily.
25 
26 extern "C" void SparcCompilationCallback();
27 
28 extern "C" {
29 #if defined (__sparc__)
30  asm(
31  ".text\n"
32  "\t.align 4\n"
33  "\t.global SparcCompilationCallback\n"
34  "\t.type SparcCompilationCallback, #function\n"
35  "SparcCompilationCallback:\n"
36  // Save current register window.
37  "\tsave %sp, -192, %sp\n"
38  // stubaddr+4 is in %g1.
39  "\tcall SparcCompilationCallbackC\n"
40  "\t sub %g1, 4, %o0\n"
41  // restore original register window and
42  // copy %o0 to %g1
43  "\t restore %o0, 0, %g1\n"
44  // call the new stub
45  "\tjmp %g1\n"
46  "\t nop\n"
47  "\t.size SparcCompilationCallback, .-SparcCompilationCallback"
48  );
49 
50 #else
53  "Cannot call SparcCompilationCallback() on a non-sparc arch!");
54  }
55 #endif
56 }
57 
58 #define HI(Val) (((unsigned)(Val)) >> 10)
59 #define LO(Val) (((unsigned)(Val)) & 0x3FF)
60 
61 #define SETHI_INST(imm, rd) (0x01000000 | ((rd) << 25) | ((imm) & 0x3FFFFF))
62 #define JMP_INST(rs1, imm, rd) (0x80000000 | ((rd) << 25) | (0x38 << 19) \
63  | ((rs1) << 14) | (1 << 13) | ((imm) & 0x1FFF))
64 #define NOP_INST SETHI_INST(0, 0)
65 
66 extern "C" void *SparcCompilationCallbackC(intptr_t StubAddr) {
67  // Get the address of the compiled code for this function.
68  intptr_t NewVal = (intptr_t) JITCompilerFunction((void*) StubAddr);
69 
70  // Rewrite the function stub so that we don't end up here every time we
71  // execute the call. We're replacing the first three instructions of the
72  // stub with code that jumps to the compiled function:
73  // sethi %hi(NewVal), %g1
74  // jmp %g1+%lo(NewVal)
75  // nop
76 
77  *(intptr_t *)(StubAddr) = SETHI_INST(HI(NewVal), 1);
78  *(intptr_t *)(StubAddr + 4) = JMP_INST(1, LO(NewVal), 0);
79  *(intptr_t *)(StubAddr + 8) = NOP_INST;
80 
81  sys::Memory::InvalidateInstructionCache((void*) StubAddr, 12);
82  return (void*)StubAddr;
83 }
84 
85 void SparcJITInfo::replaceMachineCodeForFunction(void *Old, void *New) {
86  assert(0 && "FIXME: Implement SparcJITInfo::replaceMachineCodeForFunction");
87 }
88 
89 
91  // The stub contains 3 4-byte instructions, aligned at 4 bytes. See
92  // emitFunctionStub for details.
93 
94  StubLayout Result = { 3*4, 4 };
95  return Result;
96 }
97 
98 void *SparcJITInfo::emitFunctionStub(const Function *F, void *Fn,
99  JITCodeEmitter &JCE)
100 {
101  JCE.emitAlignment(4);
102  void *Addr = (void*) (JCE.getCurrentPCValue());
103  if (!sys::Memory::setRangeWritable(Addr, 12))
104  llvm_unreachable("ERROR: Unable to mark stub writable.");
105 
106  intptr_t EmittedAddr;
107  if (Fn != (void*)(intptr_t)SparcCompilationCallback)
108  EmittedAddr = (intptr_t)Fn;
109  else
110  EmittedAddr = (intptr_t)SparcCompilationCallback;
111 
112  // sethi %hi(EmittedAddr), %g1
113  // jmp %g1+%lo(EmittedAddr), %g1
114  // nop
115 
116  JCE.emitWordBE(SETHI_INST(HI(EmittedAddr), 1));
117  JCE.emitWordBE(JMP_INST(1, LO(EmittedAddr), 1));
118  JCE.emitWordBE(NOP_INST);
119 
121  if (!sys::Memory::setRangeExecutable(Addr, 12))
122  llvm_unreachable("ERROR: Unable to mark stub executable.");
123 
124  return Addr;
125 }
126 
131 }
132 
133 /// relocate - Before the JIT can run a block of code that has been emitted,
134 /// it must rewrite the code to contain the actual addresses of any
135 /// referenced global symbols.
137  unsigned NumRelocs, unsigned char *GOTBase) {
138  for (unsigned i = 0; i != NumRelocs; ++i, ++MR) {
139  void *RelocPos = (char*) Function + MR->getMachineCodeOffset();
140  intptr_t ResultPtr = (intptr_t) MR->getResultPointer();
141 
142  switch ((SP::RelocationType) MR->getRelocationType()) {
143  case SP::reloc_sparc_hi:
144  ResultPtr = (ResultPtr >> 10) & 0x3fffff;
145  break;
146 
147  case SP::reloc_sparc_lo:
148  ResultPtr = (ResultPtr & 0x3ff);
149  break;
150 
152  ResultPtr = ((ResultPtr - (intptr_t)RelocPos) >> 2) & 0x3fffffff;
153  break;
154 
156  ResultPtr = ((ResultPtr - (intptr_t)RelocPos) >> 2) & 0x3fffff;
157  break;
158 
160  ResultPtr = ((ResultPtr - (intptr_t)RelocPos) >> 2) & 0x7ffff;
161  break;
162  }
163  *((unsigned*) RelocPos) |= (unsigned) ResultPtr;
164  }
165 }
void emitAlignment(unsigned Alignment)
unsigned getRelocationType() const
static bool setRangeWritable(const void *Addr, size_t Size)
#define NOP_INST
F(f)
virtual StubLayout getStubLayout()
Returns the maximum size and alignment for a call stub on this target.
#define SETHI_INST(imm, rd)
void SparcCompilationCallback()
void *(* JITCompilerFn)(void *)
Definition: TargetJITInfo.h:90
static void InvalidateInstructionCache(const void *Addr, size_t Len)
#define llvm_unreachable(msg)
void(* LazyResolverFn)()
Definition: TargetJITInfo.h:83
virtual void replaceMachineCodeForFunction(void *Old, void *New)
#define LO(Val)
void emitWordBE(uint32_t W)
intptr_t getMachineCodeOffset() const
void * SparcCompilationCallbackC(intptr_t StubAddr)
#define HI(Val)
static bool setRangeExecutable(const void *Addr, size_t Size)
void * getResultPointer() const
static TargetJITInfo::JITCompilerFn JITCompilerFunction
virtual uintptr_t getCurrentPCValue() const
virtual void relocate(void *Function, MachineRelocation *MR, unsigned NumRelocs, unsigned char *GOTBase)
#define JMP_INST(rs1, imm, rd)
virtual LazyResolverFn getLazyResolverFunction(JITCompilerFn)
getLazyResolverFunction - Expose the lazy resolver to the JIT.
virtual void * emitFunctionStub(const Function *F, void *Fn, JITCodeEmitter &JCE)
Records the required size and alignment for a call stub in bytes.
Definition: TargetJITInfo.h:54