LLVM API Documentation
00001 //===-- AlphaJITInfo.cpp - Implement the JIT interfaces for the Alpha ---===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file implements the JIT interfaces for the Alpha target. 00011 // 00012 //===----------------------------------------------------------------------===// 00013 00014 #define DEBUG_TYPE "jit" 00015 #include "AlphaJITInfo.h" 00016 #include "AlphaRelocations.h" 00017 #include "llvm/Function.h" 00018 #include "llvm/CodeGen/MachineCodeEmitter.h" 00019 #include "llvm/Config/alloca.h" 00020 #include "llvm/Support/Debug.h" 00021 #include <cstdlib> 00022 #include <map> 00023 using namespace llvm; 00024 00025 #define BUILD_OFormatI(Op, RA, LIT, FUN, RC) \ 00026 ((Op << 26) | (RA << 21) | (LIT << 13) | (1 << 12) | (FUN << 5) | (RC)) 00027 #define BUILD_OFormat(Op, RA, RB, FUN, RC) \ 00028 ((Op << 26) | (RA << 21) | (RB << 16) | (FUN << 5) | (RC)) 00029 00030 #define BUILD_LDA(RD, RS, IMM16) \ 00031 ((0x08 << 26) | ((RD) << 21) | ((RS) << 16) | ((IMM16) & 65535)) 00032 #define BUILD_LDAH(RD, RS, IMM16) \ 00033 ((0x09 << 26) | ((RD) << 21) | ((RS) << 16) | ((IMM16) & 65535)) 00034 00035 #define BUILD_LDQ(RD, RS, IMM16) \ 00036 ((0x29 << 26) | ((RD) << 21) | ((RS) << 16) | ((IMM16) & 0xFFFF)) 00037 00038 #define BUILD_JMP(RD, RS, IMM16) \ 00039 ((0x1A << 26) | ((RD) << 21) | ((RS) << 16) | (0x00 << 14) | ((IMM16) & 0x3FFF)) 00040 #define BUILD_JSR(RD, RS, IMM16) \ 00041 ((0x1A << 26) | ((RD) << 21) | ((RS) << 16) | (0x01 << 14) | ((IMM16) & 0x3FFF)) 00042 00043 #define BUILD_SLLi(RD, RS, IMM8) \ 00044 (BUILD_OFormatI(0x12, RS, IMM8, 0x39, RD)) 00045 00046 #define BUILD_ORi(RD, RS, IMM8) \ 00047 (BUILD_OFormatI(0x11, RS, IMM8, 0x20, RD)) 00048 00049 #define BUILD_OR(RD, RS, RT) \ 00050 (BUILD_OFormat(0x11, RS, RT, 0x20, RD)) 00051 00052 00053 00054 static void EmitBranchToAt(void *At, void *To) { 00055 unsigned long Fn = (unsigned long)To; 00056 00057 unsigned *AtI = (unsigned*)At; 00058 00059 AtI[0] = BUILD_OR(0, 27, 27); 00060 00061 DOUT << "Stub targeting " << To << "\n"; 00062 00063 for (int x = 1; x <= 8; ++x) { 00064 AtI[2*x - 1] = BUILD_SLLi(27,27,8); 00065 unsigned d = (Fn >> (64 - 8 * x)) & 0x00FF; 00066 //DOUT << "outputing " << hex << d << dec << "\n"; 00067 AtI[2*x] = BUILD_ORi(27, 27, d); 00068 } 00069 AtI[17] = BUILD_JMP(31,27,0); //jump, preserving ra, and setting pv 00070 AtI[18] = 0x00FFFFFF; //mark this as a stub 00071 } 00072 00073 void AlphaJITInfo::replaceMachineCodeForFunction(void *Old, void *New) { 00074 //FIXME 00075 assert(0); 00076 } 00077 00078 static TargetJITInfo::JITCompilerFn JITCompilerFunction; 00079 //static AlphaJITInfo* AlphaJTI; 00080 00081 extern "C" { 00082 #ifdef __alpha 00083 00084 void AlphaCompilationCallbackC(long* oldpv, void* CameFromStub) 00085 { 00086 void* Target = JITCompilerFunction(CameFromStub); 00087 00088 //rewrite the stub to an unconditional branch 00089 if (((unsigned*)CameFromStub)[18] == 0x00FFFFFF) { 00090 DOUT << "Came from a stub, rewriting\n"; 00091 EmitBranchToAt(CameFromStub, Target); 00092 } else { 00093 DOUT << "confused, didn't come from stub at " << CameFromStub 00094 << " old jump vector " << oldpv 00095 << " new jump vector " << Target << "\n"; 00096 } 00097 00098 //Change pv to new Target 00099 *oldpv = (long)Target; 00100 } 00101 00102 void AlphaCompilationCallback(void); 00103 00104 asm( 00105 ".text\n" 00106 ".globl AlphaComilationCallbackC\n" 00107 ".align 4\n" 00108 ".globl AlphaCompilationCallback\n" 00109 ".ent AlphaCompilationCallback\n" 00110 "AlphaCompilationCallback:\n" 00111 // //get JIT's GOT 00112 "ldgp $29, 0($27)\n" 00113 //Save args, callee saved, and perhaps others? 00114 //args: $16-$21 $f16-$f21 (12) 00115 //callee: $9-$14 $f2-$f9 (14) 00116 //others: fp:$15 ra:$26 pv:$27 (3) 00117 "lda $30, -232($30)\n" 00118 "stq $16, 0($30)\n" 00119 "stq $17, 8($30)\n" 00120 "stq $18, 16($30)\n" 00121 "stq $19, 24($30)\n" 00122 "stq $20, 32($30)\n" 00123 "stq $21, 40($30)\n" 00124 "stt $f16, 48($30)\n" 00125 "stt $f17, 56($30)\n" 00126 "stt $f18, 64($30)\n" 00127 "stt $f19, 72($30)\n" 00128 "stt $f20, 80($30)\n" 00129 "stt $f21, 88($30)\n" 00130 "stq $9, 96($30)\n" 00131 "stq $10, 104($30)\n" 00132 "stq $11, 112($30)\n" 00133 "stq $12, 120($30)\n" 00134 "stq $13, 128($30)\n" 00135 "stq $14, 136($30)\n" 00136 "stt $f2, 144($30)\n" 00137 "stt $f3, 152($30)\n" 00138 "stt $f4, 160($30)\n" 00139 "stt $f5, 168($30)\n" 00140 "stt $f6, 176($30)\n" 00141 "stt $f7, 184($30)\n" 00142 "stt $f8, 192($30)\n" 00143 "stt $f9, 200($30)\n" 00144 "stq $15, 208($30)\n" 00145 "stq $26, 216($30)\n" 00146 "stq $27, 224($30)\n" 00147 00148 "addq $30, 224, $16\n" //pass the addr of saved pv as the first arg 00149 "bis $0, $0, $17\n" //pass the roughly stub addr in second arg 00150 "jsr $26, AlphaCompilationCallbackC\n" //call without saving ra 00151 00152 "ldq $16, 0($30)\n" 00153 "ldq $17, 8($30)\n" 00154 "ldq $18, 16($30)\n" 00155 "ldq $19, 24($30)\n" 00156 "ldq $20, 32($30)\n" 00157 "ldq $21, 40($30)\n" 00158 "ldt $f16, 48($30)\n" 00159 "ldt $f17, 56($30)\n" 00160 "ldt $f18, 64($30)\n" 00161 "ldt $f19, 72($30)\n" 00162 "ldt $f20, 80($30)\n" 00163 "ldt $f21, 88($30)\n" 00164 "ldq $9, 96($30)\n" 00165 "ldq $10, 104($30)\n" 00166 "ldq $11, 112($30)\n" 00167 "ldq $12, 120($30)\n" 00168 "ldq $13, 128($30)\n" 00169 "ldq $14, 136($30)\n" 00170 "ldt $f2, 144($30)\n" 00171 "ldt $f3, 152($30)\n" 00172 "ldt $f4, 160($30)\n" 00173 "ldt $f5, 168($30)\n" 00174 "ldt $f6, 176($30)\n" 00175 "ldt $f7, 184($30)\n" 00176 "ldt $f8, 192($30)\n" 00177 "ldt $f9, 200($30)\n" 00178 "ldq $15, 208($30)\n" 00179 "ldq $26, 216($30)\n" 00180 "ldq $27, 224($30)\n" //this was updated in the callback with the target 00181 00182 "lda $30, 232($30)\n" //restore sp 00183 "jmp $31, ($27)\n" //jump to the new function 00184 ".end AlphaCompilationCallback\n" 00185 ); 00186 #else 00187 void AlphaCompilationCallback() { 00188 cerr << "Cannot call AlphaCompilationCallback() on a non-Alpha arch!\n"; 00189 abort(); 00190 } 00191 #endif 00192 } 00193 00194 void *AlphaJITInfo::emitFunctionStub(const Function* F, void *Fn, 00195 MachineCodeEmitter &MCE) { 00196 //assert(Fn == AlphaCompilationCallback && "Where are you going?\n"); 00197 //Do things in a stupid slow way! 00198 MCE.startFunctionStub(F, 19*4); 00199 void* Addr = (void*)(intptr_t)MCE.getCurrentPCValue(); 00200 for (int x = 0; x < 19; ++ x) 00201 MCE.emitWordLE(0); 00202 EmitBranchToAt(Addr, Fn); 00203 DOUT << "Emitting Stub to " << Fn << " at [" << Addr << "]\n"; 00204 return MCE.finishFunctionStub(F); 00205 } 00206 00207 TargetJITInfo::LazyResolverFn 00208 AlphaJITInfo::getLazyResolverFunction(JITCompilerFn F) { 00209 JITCompilerFunction = F; 00210 // setZerothGOTEntry((void*)AlphaCompilationCallback); 00211 return AlphaCompilationCallback; 00212 } 00213 00214 //These describe LDAx 00215 static const int IMM_LOW = -32768; 00216 static const int IMM_HIGH = 32767; 00217 static const int IMM_MULT = 65536; 00218 00219 static long getUpper16(long l) 00220 { 00221 long y = l / IMM_MULT; 00222 if (l % IMM_MULT > IMM_HIGH) 00223 ++y; 00224 if (l % IMM_MULT < IMM_LOW) 00225 --y; 00226 assert((short)y == y && "displacement out of range"); 00227 return y; 00228 } 00229 00230 static long getLower16(long l) 00231 { 00232 long h = getUpper16(l); 00233 long y = l - h * IMM_MULT; 00234 assert(y == (short)y && "Displacement out of range"); 00235 return y; 00236 } 00237 00238 void AlphaJITInfo::relocate(void *Function, MachineRelocation *MR, 00239 unsigned NumRelocs, unsigned char* GOTBase) { 00240 //because gpdist are paired and relative to the pc of the first inst, 00241 //we need to have some state 00242 00243 static std::map<std::pair<void*, int>, void*> gpdistmap; 00244 00245 for (unsigned i = 0; i != NumRelocs; ++i, ++MR) { 00246 unsigned *RelocPos = (unsigned*)Function + MR->getMachineCodeOffset()/4; 00247 long idx = 0; 00248 bool doCommon = true; 00249 switch ((Alpha::RelocationType)MR->getRelocationType()) { 00250 default: assert(0 && "Unknown relocation type!"); 00251 case Alpha::reloc_literal: 00252 //This is a LDQl 00253 idx = MR->getGOTIndex(); 00254 DOUT << "Literal relocation to slot " << idx; 00255 idx = (idx - GOToffset) * 8; 00256 DOUT << " offset " << idx << "\n"; 00257 break; 00258 case Alpha::reloc_gprellow: 00259 idx = (unsigned char*)MR->getResultPointer() - &GOTBase[GOToffset * 8]; 00260 idx = getLower16(idx); 00261 DOUT << "gprellow relocation offset " << idx << "\n"; 00262 DOUT << " Pointer is " << (void*)MR->getResultPointer() 00263 << " GOT is " << (void*)&GOTBase[GOToffset * 8] << "\n"; 00264 break; 00265 case Alpha::reloc_gprelhigh: 00266 idx = (unsigned char*)MR->getResultPointer() - &GOTBase[GOToffset * 8]; 00267 idx = getUpper16(idx); 00268 DOUT << "gprelhigh relocation offset " << idx << "\n"; 00269 DOUT << " Pointer is " << (void*)MR->getResultPointer() 00270 << " GOT is " << (void*)&GOTBase[GOToffset * 8] << "\n"; 00271 break; 00272 case Alpha::reloc_gpdist: 00273 switch (*RelocPos >> 26) { 00274 case 0x09: //LDAH 00275 idx = &GOTBase[GOToffset * 8] - (unsigned char*)RelocPos; 00276 idx = getUpper16(idx); 00277 DOUT << "LDAH: " << idx << "\n"; 00278 //add the relocation to the map 00279 gpdistmap[std::make_pair(Function, MR->getConstantVal())] = RelocPos; 00280 break; 00281 case 0x08: //LDA 00282 assert(gpdistmap[std::make_pair(Function, MR->getConstantVal())] && 00283 "LDAg without seeing LDAHg"); 00284 idx = &GOTBase[GOToffset * 8] - 00285 (unsigned char*)gpdistmap[std::make_pair(Function, MR->getConstantVal())]; 00286 idx = getLower16(idx); 00287 DOUT << "LDA: " << idx << "\n"; 00288 break; 00289 default: 00290 assert(0 && "Cannot handle gpdist yet"); 00291 } 00292 break; 00293 case Alpha::reloc_bsr: { 00294 idx = (((unsigned char*)MR->getResultPointer() - 00295 (unsigned char*)RelocPos) >> 2) + 1; //skip first 2 inst of fun 00296 *RelocPos |= (idx & ((1 << 21)-1)); 00297 doCommon = false; 00298 break; 00299 } 00300 } 00301 if (doCommon) { 00302 short x = (short)idx; 00303 assert(x == idx); 00304 *(short*)RelocPos = x; 00305 } 00306 } 00307 }