Rename isGVNonLazyPtr to isIndirectSym to reflect how it will be used.
[oota-llvm.git] / lib / Target / ARM / ARMJITInfo.cpp
index 2f04d0b4e8ada77a1e308f89490f4e91f6a5c906..3ce311784da55a82ced0dc017c6350703073108d 100644 (file)
@@ -111,20 +111,16 @@ extern "C" void ARMCompilationCallbackC(intptr_t StubAddr) {
   // stub with:
   //   ldr pc, [pc,#-4]
   //   <addr>
-  bool ok = sys::Memory::setRangeWritable ((void*)StubAddr, 8);
-  if (!ok)
-    {
-      cerr << "ERROR: Unable to mark stub writable\n";
-      abort();
-    }
-  *(intptr_t *)StubAddr = 0xe51ff004;
+  if (!sys::Memory::setRangeWritable((void*)StubAddr, 8)) {
+    cerr << "ERROR: Unable to mark stub writable\n";
+    abort();
+  }
+  *(intptr_t *)StubAddr = 0xe51ff004;  // ldr pc, [pc, #-4]
   *(intptr_t *)(StubAddr+4) = NewVal;
-  ok = sys::Memory::setRangeExecutable ((void*)StubAddr, 8);
-  if (!ok)
-    {
-      cerr << "ERROR: Unable to mark stub executable\n";
-      abort();
-    }
+  if (!sys::Memory::setRangeExecutable((void*)StubAddr, 8)) {
+    cerr << "ERROR: Unable to mark stub executable\n";
+    abort();
+  }
 }
 
 TargetJITInfo::LazyResolverFn
@@ -133,51 +129,64 @@ ARMJITInfo::getLazyResolverFunction(JITCompilerFn F) {
   return ARMCompilationCallback;
 }
 
+void *ARMJITInfo::emitGlobalValueIndirectSym(const GlobalValue *GV, void *Ptr,
+                                             MachineCodeEmitter &MCE) {
+  MCE.startGVStub(GV, 4, 4);
+  MCE.emitWordLE((intptr_t)Ptr);
+  return MCE.finishGVStub(GV);
+}
+
 void *ARMJITInfo::emitFunctionStub(const Function* F, void *Fn,
                                    MachineCodeEmitter &MCE) {
-  unsigned addr = (intptr_t)Fn;
   // If this is just a call to an external function, emit a branch instead of a
   // call.  The code is the same except for one bit of the last instruction.
   if (Fn != (void*)(intptr_t)ARMCompilationCallback) {
-    // branch to the corresponding function addr
-    // the stub is 8-byte size and 4-aligned
-    MCE.startFunctionStub(F, 8, 4);
-    MCE.emitWordLE(0xe51ff004); // LDR PC, [PC,#-4]
-    MCE.emitWordLE(addr);       // addr of function
+    // Branch to the corresponding function addr.
+    // The stub is 8-byte size and 4-aligned.
+    MCE.startGVStub(F, 8, 4);
+    intptr_t Addr = (intptr_t)MCE.getCurrentPCValue();
+    MCE.emitWordLE(0xe51ff004);    // ldr pc, [pc, #-4]
+    MCE.emitWordLE((intptr_t)Fn);  // addr of function
+    sys::Memory::InvalidateInstructionCache((void*)Addr, 8);
   } else {
     // The compilation callback will overwrite the first two words of this
     // stub with indirect branch instructions targeting the compiled code. 
     // This stub sets the return address to restart the stub, so that
     // the new branch will be invoked when we come back.
     //
-    // branch and link to the compilation callback.
-    // the stub is 16-byte size and 4-byte aligned.
-    MCE.startFunctionStub(F, 16, 4);
+    // Branch and link to the compilation callback.
+    // The stub is 16-byte size and 4-byte aligned.
+    MCE.startGVStub(F, 16, 4);
+    intptr_t Addr = (intptr_t)MCE.getCurrentPCValue();
     // Save LR so the callback can determine which stub called it.
     // The compilation callback is responsible for popping this prior
     // to returning.
-    MCE.emitWordLE(0xe92d4000); // PUSH {lr}
-    // Set the return address to go back to the start of this stub
-    MCE.emitWordLE(0xe24fe00c); // SUB LR, PC, #12
-    // Invoke the compilation callback
-    MCE.emitWordLE(0xe51ff004); // LDR PC, [PC,#-4]
-    // The address of the compilation callback
+    MCE.emitWordLE(0xe92d4000); // push {lr}
+    // Set the return address to go back to the start of this stub.
+    MCE.emitWordLE(0xe24fe00c); // sub lr, pc, #12
+    // Invoke the compilation callback.
+    MCE.emitWordLE(0xe51ff004); // ldr pc, [pc, #-4]
+    // The address of the compilation callback.
     MCE.emitWordLE((intptr_t)ARMCompilationCallback);
+    sys::Memory::InvalidateInstructionCache((void*)Addr, 16);
   }
 
-  return MCE.finishFunctionStub(F);
+  return MCE.finishGVStub(F);
 }
 
-intptr_t ARMJITInfo::resolveRelocationAddr(MachineRelocation *MR) const {
+intptr_t ARMJITInfo::resolveRelocDestAddr(MachineRelocation *MR) const {
   ARM::RelocationType RT = (ARM::RelocationType)MR->getRelocationType();
-  if (RT == ARM::reloc_arm_cp_entry)
+  if (RT == ARM::reloc_arm_pic_jt)
+    // Destination address - jump table base.
+    return (intptr_t)(MR->getResultPointer()) - MR->getConstantVal();
+  else if (RT == ARM::reloc_arm_jt_base)
+    // Jump table base address.
+    return getJumpTableBaseAddr(MR->getJumpTableIndex());
+  else if (RT == ARM::reloc_arm_cp_entry)
+    // Constant pool entry address.
     return getConstantPoolEntryAddr(MR->getConstantPoolIndex());
   else if (RT == ARM::reloc_arm_machine_cp_entry) {
-    const MachineConstantPoolEntry &MCPE = (*MCPEs)[MR->getConstantVal()];
-    assert(MCPE.isMachineConstantPoolEntry() &&
-           "Expecting a machine constant pool entry!");
-    ARMConstantPoolValue *ACPV =
-      static_cast<ARMConstantPoolValue*>(MCPE.Val.MachineCPVal);
+    ARMConstantPoolValue *ACPV = (ARMConstantPoolValue*)MR->getConstantVal();
     assert((!ACPV->hasModifier() && !ACPV->mustAddCurrentAddress()) &&
            "Can't handle this machine constant pool entry yet!");
     intptr_t Addr = (intptr_t)(MR->getResultPointer());
@@ -194,9 +203,7 @@ void ARMJITInfo::relocate(void *Function, MachineRelocation *MR,
                           unsigned NumRelocs, unsigned char* GOTBase) {
   for (unsigned i = 0; i != NumRelocs; ++i, ++MR) {
     void *RelocPos = (char*)Function + MR->getMachineCodeOffset();
-    // If this is a constpool relocation, get the address of the
-    // constpool_entry instruction.
-    intptr_t ResultPtr = resolveRelocationAddr(MR);
+    intptr_t ResultPtr = resolveRelocDestAddr(MR);
     switch ((ARM::RelocationType)MR->getRelocationType()) {
     case ARM::reloc_arm_cp_entry:
     case ARM::reloc_arm_relative: {
@@ -218,10 +225,11 @@ void ARMJITInfo::relocate(void *Function, MachineRelocation *MR,
       *((unsigned*)RelocPos) |= 0xF << 16;
       break;
     }
+    case ARM::reloc_arm_pic_jt:
     case ARM::reloc_arm_machine_cp_entry:
     case ARM::reloc_arm_absolute: {
       // These addresses have already been resolved.
-      *((unsigned*)RelocPos) += (unsigned)ResultPtr;
+      *((unsigned*)RelocPos) |= (unsigned)ResultPtr;
       break;
     }
     case ARM::reloc_arm_branch: {
@@ -230,12 +238,18 @@ void ARMJITInfo::relocate(void *Function, MachineRelocation *MR,
       // byte offset, which must be inside the range -33554432 and +33554428.
       // Then, we set the signed_immed_24 field of the instruction to bits
       // [25:2] of the byte offset. More details ARM-ARM p. A4-11.
-      ResultPtr = ResultPtr-(intptr_t)RelocPos-8;
+      ResultPtr = ResultPtr - (intptr_t)RelocPos - 8;
       ResultPtr = (ResultPtr & 0x03FFFFFC) >> 2;
       assert(ResultPtr >= -33554432 && ResultPtr <= 33554428);
       *((unsigned*)RelocPos) |= ResultPtr;
       break;
     }
+    case ARM::reloc_arm_jt_base: {
+      // JT base - (instruction addr + 8)
+      ResultPtr = ResultPtr - (intptr_t)RelocPos - 8;
+      *((unsigned*)RelocPos) |= ResultPtr;
+      break;
+    }
     }
   }
 }