LLVM API Documentation
00001 //===-- AlphaJITInfo.cpp - Implement the JIT interfaces for the Alpha ---===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file was developed by the LLVM research group and is distributed under 00006 // the University of Illinois Open Source 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/CodeGen/MachineCodeEmitter.h" 00018 #include "llvm/Config/alloca.h" 00019 #include "llvm/Support/Debug.h" 00020 #include <cstdlib> 00021 #include <iostream> 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 DEBUG(std::cerr << "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 // DEBUG(std::cerr << "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 DEBUG(std::cerr << "Came from a stub, rewriting\n"); 00091 EmitBranchToAt(CameFromStub, Target); 00092 } else { 00093 DEBUG(std::cerr << "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 std::cerr << "Cannot call AlphaCompilationCallback() on a non-Alpha arch!\n"; 00189 abort(); 00190 } 00191 #endif 00192 } 00193 00194 void *AlphaJITInfo::emitFunctionStub(void *Fn, MachineCodeEmitter &MCE) { 00195 //assert(Fn == AlphaCompilationCallback && "Where are you going?\n"); 00196 //Do things in a stupid slow way! 00197 MCE.startFunctionStub(19*4); 00198 void* Addr = (void*)(intptr_t)MCE.getCurrentPCValue(); 00199 for (int x = 0; x < 19; ++ x) 00200 MCE.emitWord(0); 00201 EmitBranchToAt(Addr, Fn); 00202 DEBUG(std::cerr << "Emitting Stub to " << Fn << " at [" << Addr << "]\n"); 00203 return MCE.finishFunctionStub(0); 00204 } 00205 00206 TargetJITInfo::LazyResolverFn 00207 AlphaJITInfo::getLazyResolverFunction(JITCompilerFn F) { 00208 JITCompilerFunction = F; 00209 // setZerothGOTEntry((void*)AlphaCompilationCallback); 00210 return AlphaCompilationCallback; 00211 } 00212 00213 //These describe LDAx 00214 static const int IMM_LOW = -32768; 00215 static const int IMM_HIGH = 32767; 00216 static const int IMM_MULT = 65536; 00217 00218 static long getUpper16(long l) 00219 { 00220 long y = l / IMM_MULT; 00221 if (l % IMM_MULT > IMM_HIGH) 00222 ++y; 00223 if (l % IMM_MULT < IMM_LOW) 00224 --y; 00225 assert((short)y == y && "displacement out of range"); 00226 return y; 00227 } 00228 00229 static long getLower16(long l) 00230 { 00231 long h = getUpper16(l); 00232 long y = l - h * IMM_MULT; 00233 assert(y == (short)y && "Displacement out of range"); 00234 return y; 00235 } 00236 00237 void AlphaJITInfo::relocate(void *Function, MachineRelocation *MR, 00238 unsigned NumRelocs, unsigned char* GOTBase) { 00239 //because gpdist are paired and relative to the pc of the first inst, 00240 //we need to have some state 00241 00242 static std::map<std::pair<void*, int>, void*> gpdistmap; 00243 00244 for (unsigned i = 0; i != NumRelocs; ++i, ++MR) { 00245 unsigned *RelocPos = (unsigned*)Function + MR->getMachineCodeOffset()/4; 00246 long idx = 0; 00247 bool doCommon = true; 00248 switch ((Alpha::RelocationType)MR->getRelocationType()) { 00249 default: assert(0 && "Unknown relocation type!"); 00250 case Alpha::reloc_literal: 00251 //This is a LDQl 00252 idx = MR->getGOTIndex(); 00253 DEBUG(std::cerr << "Literal relocation to slot " << idx); 00254 idx = (idx - GOToffset) * 8; 00255 DEBUG(std::cerr << " offset " << idx << "\n"); 00256 break; 00257 case Alpha::reloc_gprellow: 00258 idx = (unsigned char*)MR->getResultPointer() - &GOTBase[GOToffset * 8]; 00259 idx = getLower16(idx); 00260 DEBUG(std::cerr << "gprellow relocation offset " << idx << "\n"); 00261 DEBUG(std::cerr << " Pointer is " << (void*)MR->getResultPointer() 00262 << " GOT is " << (void*)&GOTBase[GOToffset * 8] << "\n"); 00263 break; 00264 case Alpha::reloc_gprelhigh: 00265 idx = (unsigned char*)MR->getResultPointer() - &GOTBase[GOToffset * 8]; 00266 idx = getUpper16(idx); 00267 DEBUG(std::cerr << "gprelhigh relocation offset " << idx << "\n"); 00268 DEBUG(std::cerr << " Pointer is " << (void*)MR->getResultPointer() 00269 << " GOT is " << (void*)&GOTBase[GOToffset * 8] << "\n"); 00270 break; 00271 case Alpha::reloc_gpdist: 00272 switch (*RelocPos >> 26) { 00273 case 0x09: //LDAH 00274 idx = &GOTBase[GOToffset * 8] - (unsigned char*)RelocPos; 00275 idx = getUpper16(idx); 00276 DEBUG(std::cerr << "LDAH: " << idx << "\n"); 00277 //add the relocation to the map 00278 gpdistmap[std::make_pair(Function, MR->getConstantVal())] = RelocPos; 00279 break; 00280 case 0x08: //LDA 00281 assert(gpdistmap[std::make_pair(Function, MR->getConstantVal())] && 00282 "LDAg without seeing LDAHg"); 00283 idx = &GOTBase[GOToffset * 8] - 00284 (unsigned char*)gpdistmap[std::make_pair(Function, MR->getConstantVal())]; 00285 idx = getLower16(idx); 00286 DEBUG(std::cerr << "LDA: " << idx << "\n"); 00287 break; 00288 default: 00289 assert(0 && "Cannot handle gpdist yet"); 00290 } 00291 break; 00292 case Alpha::reloc_bsr: { 00293 idx = (((unsigned char*)MR->getResultPointer() - 00294 (unsigned char*)RelocPos) >> 2) + 1; //skip first 2 inst of fun 00295 *RelocPos |= (idx & ((1 << 21)-1)); 00296 doCommon = false; 00297 break; 00298 } 00299 } 00300 if (doCommon) { 00301 short x = (short)idx; 00302 assert(x == idx); 00303 *(short*)RelocPos = x; 00304 } 00305 } 00306 }