1Pull in r199977 from upstream llvm trunk (by Venkatraman Govindaraju): 2 3 [SparcV9] Add support for JIT in Sparc64. 4 With this change, all supported tests in test/ExecutionEngine pass in sparcv9. 5 6Introduced here: http://svnweb.freebsd.org/changeset/base/262261 7 8Index: lib/Target/Sparc/SparcJITInfo.cpp 9=================================================================== 10--- lib/Target/Sparc/SparcJITInfo.cpp 11+++ lib/Target/Sparc/SparcJITInfo.cpp 12@@ -12,8 +12,9 @@ 13 //===----------------------------------------------------------------------===// 14 #define DEBUG_TYPE "jit" 15 #include "SparcJITInfo.h" 16+#include "Sparc.h" 17 #include "SparcRelocations.h" 18- 19+#include "llvm/ADT/SmallVector.h" 20 #include "llvm/CodeGen/JITCodeEmitter.h" 21 #include "llvm/Support/Memory.h" 22 23@@ -35,18 +36,17 @@ extern "C" { 24 "SparcCompilationCallback:\n" 25 // Save current register window. 26 "\tsave %sp, -192, %sp\n" 27- // stubaddr+4 is in %g1. 28+ // stubaddr is in %g1. 29 "\tcall SparcCompilationCallbackC\n" 30- "\t sub %g1, 4, %o0\n" 31+ "\t mov %g1, %o0\n" 32 // restore original register window and 33 // copy %o0 to %g1 34- "\t restore %o0, 0, %g1\n" 35+ "\trestore %o0, 0, %g1\n" 36 // call the new stub 37 "\tjmp %g1\n" 38 "\t nop\n" 39 "\t.size SparcCompilationCallback, .-SparcCompilationCallback" 40 ); 41- 42 #else 43 void SparcCompilationCallback() { 44 llvm_unreachable( 45@@ -55,33 +55,120 @@ extern "C" { 46 #endif 47 } 48 49-#define HI(Val) (((unsigned)(Val)) >> 10) 50-#define LO(Val) (((unsigned)(Val)) & 0x3FF) 51 52 #define SETHI_INST(imm, rd) (0x01000000 | ((rd) << 25) | ((imm) & 0x3FFFFF)) 53 #define JMP_INST(rs1, imm, rd) (0x80000000 | ((rd) << 25) | (0x38 << 19) \ 54 | ((rs1) << 14) | (1 << 13) | ((imm) & 0x1FFF)) 55 #define NOP_INST SETHI_INST(0, 0) 56+#define OR_INST_I(rs1, imm, rd) (0x80000000 | ((rd) << 25) | (0x02 << 19) \ 57+ | ((rs1) << 14) | (1 << 13) | ((imm) & 0x1FFF)) 58+#define OR_INST_R(rs1, rs2, rd) (0x80000000 | ((rd) << 25) | (0x02 << 19) \ 59+ | ((rs1) << 14) | (0 << 13) | ((rs2) & 0x1F)) 60+#define RDPC_INST(rd) (0x80000000 | ((rd) << 25) | (0x28 << 19) \ 61+ | (5 << 14)) 62+#define LDX_INST(rs1, imm, rd) (0xC0000000 | ((rd) << 25) | (0x0B << 19) \ 63+ | ((rs1) << 14) | (1 << 13) | ((imm) & 0x1FFF)) 64+#define SLLX_INST(rs1, imm, rd) (0x80000000 | ((rd) << 25) | (0x25 << 19) \ 65+ | ((rs1) << 14) | (3 << 12) | ((imm) & 0x3F)) 66+#define SUB_INST(rs1, imm, rd) (0x80000000 | ((rd) << 25) | (0x04 << 19) \ 67+ | ((rs1) << 14) | (1 << 13) | ((imm) & 0x1FFF)) 68+#define XOR_INST(rs1, imm, rd) (0x80000000 | ((rd) << 25) | (0x03 << 19) \ 69+ | ((rs1) << 14) | (1 << 13) | ((imm) & 0x1FFF)) 70+#define BA_INST(tgt) (0x10800000 | ((tgt) & 0x3FFFFF)) 71 72+// Emit instructions to jump to Addr and store the starting address of 73+// the instructions emitted in the scratch register. 74+static void emitInstrForIndirectJump(intptr_t Addr, 75+ unsigned scratch, 76+ SmallVectorImpl<uint32_t> &Insts) { 77+ 78+ if (isInt<13>(Addr)) { 79+ // Emit: jmpl %g0+Addr, <scratch> 80+ // nop 81+ Insts.push_back(JMP_INST(0, LO10(Addr), scratch)); 82+ Insts.push_back(NOP_INST); 83+ return; 84+ } 85+ 86+ if (isUInt<32>(Addr)) { 87+ // Emit: sethi %hi(Addr), scratch 88+ // jmpl scratch+%lo(Addr), scratch 89+ // sub scratch, 4, scratch 90+ Insts.push_back(SETHI_INST(HI22(Addr), scratch)); 91+ Insts.push_back(JMP_INST(scratch, LO10(Addr), scratch)); 92+ Insts.push_back(SUB_INST(scratch, 4, scratch)); 93+ return; 94+ } 95+ 96+ if (Addr < 0 && isInt<33>(Addr)) { 97+ // Emit: sethi %hix(Addr), scratch) 98+ // xor scratch, %lox(Addr), scratch 99+ // jmpl scratch+0, scratch 100+ // sub scratch, 8, scratch 101+ Insts.push_back(SETHI_INST(HIX22(Addr), scratch)); 102+ Insts.push_back(XOR_INST(scratch, LOX10(Addr), scratch)); 103+ Insts.push_back(JMP_INST(scratch, 0, scratch)); 104+ Insts.push_back(SUB_INST(scratch, 8, scratch)); 105+ return; 106+ } 107+ 108+ // Emit: rd %pc, scratch 109+ // ldx [scratch+16], scratch 110+ // jmpl scratch+0, scratch 111+ // sub scratch, 8, scratch 112+ // <Addr: 8 byte> 113+ Insts.push_back(RDPC_INST(scratch)); 114+ Insts.push_back(LDX_INST(scratch, 16, scratch)); 115+ Insts.push_back(JMP_INST(scratch, 0, scratch)); 116+ Insts.push_back(SUB_INST(scratch, 8, scratch)); 117+ Insts.push_back((uint32_t)(((int64_t)Addr) >> 32) & 0xffffffff); 118+ Insts.push_back((uint32_t)(Addr & 0xffffffff)); 119+ 120+ // Instruction sequence without rdpc instruction 121+ // 7 instruction and 2 scratch register 122+ // Emit: sethi %hh(Addr), scratch 123+ // or scratch, %hm(Addr), scratch 124+ // sllx scratch, 32, scratch 125+ // sethi %hi(Addr), scratch2 126+ // or scratch, scratch2, scratch 127+ // jmpl scratch+%lo(Addr), scratch 128+ // sub scratch, 20, scratch 129+ // Insts.push_back(SETHI_INST(HH22(Addr), scratch)); 130+ // Insts.push_back(OR_INST_I(scratch, HM10(Addr), scratch)); 131+ // Insts.push_back(SLLX_INST(scratch, 32, scratch)); 132+ // Insts.push_back(SETHI_INST(HI22(Addr), scratch2)); 133+ // Insts.push_back(OR_INST_R(scratch, scratch2, scratch)); 134+ // Insts.push_back(JMP_INST(scratch, LO10(Addr), scratch)); 135+ // Insts.push_back(SUB_INST(scratch, 20, scratch)); 136+} 137+ 138 extern "C" void *SparcCompilationCallbackC(intptr_t StubAddr) { 139 // Get the address of the compiled code for this function. 140 intptr_t NewVal = (intptr_t) JITCompilerFunction((void*) StubAddr); 141 142 // Rewrite the function stub so that we don't end up here every time we 143- // execute the call. We're replacing the first three instructions of the 144- // stub with code that jumps to the compiled function: 145- // sethi %hi(NewVal), %g1 146- // jmp %g1+%lo(NewVal) 147- // nop 148+ // execute the call. We're replacing the stub instructions with code 149+ // that jumps to the compiled function: 150 151- *(intptr_t *)(StubAddr) = SETHI_INST(HI(NewVal), 1); 152- *(intptr_t *)(StubAddr + 4) = JMP_INST(1, LO(NewVal), 0); 153- *(intptr_t *)(StubAddr + 8) = NOP_INST; 154+ SmallVector<uint32_t, 8> Insts; 155+ intptr_t diff = (NewVal - StubAddr) >> 2; 156+ if (isInt<22>(diff)) { 157+ // Use branch instruction to jump 158+ Insts.push_back(BA_INST(diff)); 159+ Insts.push_back(NOP_INST); 160+ } else { 161+ // Otherwise, use indirect jump to the compiled function 162+ emitInstrForIndirectJump(NewVal, 1, Insts); 163+ } 164 165- sys::Memory::InvalidateInstructionCache((void*) StubAddr, 12); 166+ for (unsigned i = 0, e = Insts.size(); i != e; ++i) 167+ *(uint32_t *)(StubAddr + i*4) = Insts[i]; 168+ 169+ sys::Memory::InvalidateInstructionCache((void*) StubAddr, Insts.size() * 4); 170 return (void*)StubAddr; 171 } 172 173+ 174 void SparcJITInfo::replaceMachineCodeForFunction(void *Old, void *New) { 175 assert(0 && "FIXME: Implement SparcJITInfo::replaceMachineCodeForFunction"); 176 } 177@@ -88,10 +175,10 @@ void SparcJITInfo::replaceMachineCodeForFunction(v 178 179 180 TargetJITInfo::StubLayout SparcJITInfo::getStubLayout() { 181- // The stub contains 3 4-byte instructions, aligned at 4 bytes. See 182- // emitFunctionStub for details. 183- 184- StubLayout Result = { 3*4, 4 }; 185+ // The stub contains maximum of 4 4-byte instructions and 8 bytes for address, 186+ // aligned at 32 bytes. 187+ // See emitFunctionStub and emitInstrForIndirectJump for details. 188+ StubLayout Result = { 4*4 + 8, 32 }; 189 return Result; 190 } 191 192@@ -98,32 +185,41 @@ TargetJITInfo::StubLayout SparcJITInfo::getStubLay 193 void *SparcJITInfo::emitFunctionStub(const Function *F, void *Fn, 194 JITCodeEmitter &JCE) 195 { 196- JCE.emitAlignment(4); 197+ JCE.emitAlignment(32); 198 void *Addr = (void*) (JCE.getCurrentPCValue()); 199- if (!sys::Memory::setRangeWritable(Addr, 12)) 200- llvm_unreachable("ERROR: Unable to mark stub writable."); 201 202+ intptr_t CurrentAddr = (intptr_t)Addr; 203 intptr_t EmittedAddr; 204- if (Fn != (void*)(intptr_t)SparcCompilationCallback) 205+ SmallVector<uint32_t, 8> Insts; 206+ if (Fn != (void*)(intptr_t)SparcCompilationCallback) { 207 EmittedAddr = (intptr_t)Fn; 208- else 209+ intptr_t diff = (EmittedAddr - CurrentAddr) >> 2; 210+ if (isInt<22>(diff)) { 211+ Insts.push_back(BA_INST(diff)); 212+ Insts.push_back(NOP_INST); 213+ } 214+ } else { 215 EmittedAddr = (intptr_t)SparcCompilationCallback; 216+ } 217 218- // sethi %hi(EmittedAddr), %g1 219- // jmp %g1+%lo(EmittedAddr), %g1 220- // nop 221+ if (Insts.size() == 0) 222+ emitInstrForIndirectJump(EmittedAddr, 1, Insts); 223 224- JCE.emitWordBE(SETHI_INST(HI(EmittedAddr), 1)); 225- JCE.emitWordBE(JMP_INST(1, LO(EmittedAddr), 1)); 226- JCE.emitWordBE(NOP_INST); 227 228- sys::Memory::InvalidateInstructionCache(Addr, 12); 229- if (!sys::Memory::setRangeExecutable(Addr, 12)) 230+ if (!sys::Memory::setRangeWritable(Addr, 4 * Insts.size())) 231+ llvm_unreachable("ERROR: Unable to mark stub writable."); 232+ 233+ for (unsigned i = 0, e = Insts.size(); i != e; ++i) 234+ JCE.emitWordBE(Insts[i]); 235+ 236+ sys::Memory::InvalidateInstructionCache(Addr, 4 * Insts.size()); 237+ if (!sys::Memory::setRangeExecutable(Addr, 4 * Insts.size())) 238 llvm_unreachable("ERROR: Unable to mark stub executable."); 239 240 return Addr; 241 } 242 243+ 244 TargetJITInfo::LazyResolverFn 245 SparcJITInfo::getLazyResolverFunction(JITCompilerFn F) { 246 JITCompilerFunction = F; 247@@ -159,6 +255,27 @@ void SparcJITInfo::relocate(void *Function, Machin 248 case SP::reloc_sparc_pc19: 249 ResultPtr = ((ResultPtr - (intptr_t)RelocPos) >> 2) & 0x7ffff; 250 break; 251+ 252+ case SP::reloc_sparc_h44: 253+ ResultPtr = (ResultPtr >> 22) & 0x3fffff; 254+ break; 255+ 256+ case SP::reloc_sparc_m44: 257+ ResultPtr = (ResultPtr >> 12) & 0x3ff; 258+ break; 259+ 260+ case SP::reloc_sparc_l44: 261+ ResultPtr = (ResultPtr & 0xfff); 262+ break; 263+ 264+ case SP::reloc_sparc_hh: 265+ ResultPtr = (((int64_t)ResultPtr) >> 42) & 0x3fffff; 266+ break; 267+ 268+ case SP::reloc_sparc_hm: 269+ ResultPtr = (((int64_t)ResultPtr) >> 32) & 0x3ff; 270+ break; 271+ 272 } 273 *((unsigned*) RelocPos) |= (unsigned) ResultPtr; 274 } 275Index: lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp 276=================================================================== 277--- lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp 278+++ lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp 279@@ -68,9 +68,13 @@ static MCCodeGenInfo *createSparcMCCodeGenInfo(Str 280 CodeGenOpt::Level OL) { 281 MCCodeGenInfo *X = new MCCodeGenInfo(); 282 283- // The default 32-bit code model is abs32/pic32. 284- if (CM == CodeModel::Default) 285- CM = RM == Reloc::PIC_ ? CodeModel::Medium : CodeModel::Small; 286+ // The default 32-bit code model is abs32/pic32 and the default 32-bit 287+ // code model for JIT is abs32. 288+ switch (CM) { 289+ default: break; 290+ case CodeModel::Default: 291+ case CodeModel::JITDefault: CM = CodeModel::Small; break; 292+ } 293 294 X->InitMCCodeGenInfo(RM, CM, OL); 295 return X; 296@@ -81,9 +85,17 @@ static MCCodeGenInfo *createSparcV9MCCodeGenInfo(S 297 CodeGenOpt::Level OL) { 298 MCCodeGenInfo *X = new MCCodeGenInfo(); 299 300- // The default 64-bit code model is abs44/pic32. 301- if (CM == CodeModel::Default) 302- CM = CodeModel::Medium; 303+ // The default 64-bit code model is abs44/pic32 and the default 64-bit 304+ // code model for JIT is abs64. 305+ switch (CM) { 306+ default: break; 307+ case CodeModel::Default: 308+ CM = RM == Reloc::PIC_ ? CodeModel::Small : CodeModel::Medium; 309+ break; 310+ case CodeModel::JITDefault: 311+ CM = CodeModel::Large; 312+ break; 313+ } 314 315 X->InitMCCodeGenInfo(RM, CM, OL); 316 return X; 317Index: lib/Target/Sparc/SparcISelLowering.cpp 318=================================================================== 319--- lib/Target/Sparc/SparcISelLowering.cpp 320+++ lib/Target/Sparc/SparcISelLowering.cpp 321@@ -1810,7 +1810,6 @@ SDValue SparcTargetLowering::makeAddress(SDValue O 322 switch(getTargetMachine().getCodeModel()) { 323 default: 324 llvm_unreachable("Unsupported absolute code model"); 325- case CodeModel::JITDefault: 326 case CodeModel::Small: 327 // abs32. 328 return makeHiLoPair(Op, SPII::MO_HI, SPII::MO_LO, DAG); 329Index: lib/Target/Sparc/SparcCodeEmitter.cpp 330=================================================================== 331--- lib/Target/Sparc/SparcCodeEmitter.cpp 332+++ lib/Target/Sparc/SparcCodeEmitter.cpp 333@@ -207,11 +207,11 @@ unsigned SparcCodeEmitter::getRelocation(const Mac 334 case SPII::MO_NO_FLAG: break; 335 case SPII::MO_LO: return SP::reloc_sparc_lo; 336 case SPII::MO_HI: return SP::reloc_sparc_hi; 337- case SPII::MO_H44: 338- case SPII::MO_M44: 339- case SPII::MO_L44: 340- case SPII::MO_HH: 341- case SPII::MO_HM: assert(0 && "FIXME: Implement Medium/Large code model."); 342+ case SPII::MO_H44: return SP::reloc_sparc_h44; 343+ case SPII::MO_M44: return SP::reloc_sparc_m44; 344+ case SPII::MO_L44: return SP::reloc_sparc_l44; 345+ case SPII::MO_HH: return SP::reloc_sparc_hh; 346+ case SPII::MO_HM: return SP::reloc_sparc_hm; 347 } 348 349 unsigned Opc = MI.getOpcode(); 350Index: lib/Target/Sparc/SparcRelocations.h 351=================================================================== 352--- lib/Target/Sparc/SparcRelocations.h 353+++ lib/Target/Sparc/SparcRelocations.h 354@@ -33,7 +33,22 @@ namespace llvm { 355 reloc_sparc_pc22 = 4, 356 357 // reloc_sparc_pc22 - pc rel. 19 bits for branch with icc/xcc 358- reloc_sparc_pc19 = 5 359+ reloc_sparc_pc19 = 5, 360+ 361+ // reloc_sparc_h44 - 43-22 bits 362+ reloc_sparc_h44 = 6, 363+ 364+ // reloc_sparc_m44 - 21-12 bits 365+ reloc_sparc_m44 = 7, 366+ 367+ // reloc_sparc_l44 - lower 12 bits 368+ reloc_sparc_l44 = 8, 369+ 370+ // reloc_sparc_hh - 63-42 bits 371+ reloc_sparc_hh = 9, 372+ 373+ // reloc_sparc_hm - 41-32 bits 374+ reloc_sparc_hm = 10 375 }; 376 } 377 } 378