]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - contrib/llvm/patches/patch-r262261-llvm-r199977-sparc.diff
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / contrib / llvm / patches / patch-r262261-llvm-r199977-sparc.diff
1 Pull 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
6 Introduced here: http://svnweb.freebsd.org/changeset/base/262261
7
8 Index: 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    }
275 Index: 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;
317 Index: 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);
329 Index: 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();
350 Index: 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  }