- Refactor the code that resolve basic block references to a TargetJITInfo
authorEvan Cheng <evan.cheng@apple.com>
Tue, 25 Jul 2006 20:40:54 +0000 (20:40 +0000)
committerEvan Cheng <evan.cheng@apple.com>
Tue, 25 Jul 2006 20:40:54 +0000 (20:40 +0000)
  method.
- Added synchronizeICache() to TargetJITInfo. It is called after each block
  of code is emitted to flush the icache. This ensures correct execution
  on targets that have separate dcache and icache.
- Added PPC / Mac OS X specific code to do icache flushing.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@29276 91177308-0d34-0410-b5e6-96231b3b80d8

16 files changed:
include/llvm/Target/TargetJITInfo.h
lib/ExecutionEngine/JIT/JITEmitter.cpp
lib/Target/Alpha/Alpha.h
lib/Target/Alpha/AlphaCodeEmitter.cpp
lib/Target/Alpha/AlphaJITInfo.cpp
lib/Target/Alpha/AlphaJITInfo.h
lib/Target/Alpha/AlphaTargetMachine.cpp
lib/Target/PowerPC/PPCCodeEmitter.cpp
lib/Target/PowerPC/PPCJITInfo.cpp
lib/Target/PowerPC/PPCJITInfo.h
lib/Target/X86/X86.h
lib/Target/X86/X86CodeEmitter.cpp
lib/Target/X86/X86ELFWriter.cpp
lib/Target/X86/X86JITInfo.cpp
lib/Target/X86/X86JITInfo.h
lib/Target/X86/X86TargetMachine.cpp

index 9f083f6e591b1e373982ff354b559a2790db1700..dee5a9537575d78f0cf6b292ed41476ef1d2c63b 100644 (file)
 #define LLVM_TARGET_TARGETJITINFO_H
 
 #include <cassert>
+#include <vector>
 
 namespace llvm {
   class Function;
   class FunctionPassManager;
+  class MachineBasicBlock;
   class MachineCodeEmitter;
   class MachineRelocation;
 
@@ -81,6 +83,20 @@ namespace llvm {
       assert(NumRelocs == 0 && "This target does not have relocations!");
     }
 
+    /// resolveBBRefs - Resolve branches to BasicBlocks for the JIT emitted
+    /// function.
+    virtual void resolveBBRefs(MachineCodeEmitter &MCE) {}
+
+    /// synchronizeICache - On some targets, the JIT emitted code must be
+    /// explicitly refetched to ensure correct execution.
+    virtual void synchronizeICache(const void *Addr, size_t len) {}
+
+    /// addBBRef - Add a BasicBlock reference to be resolved after the function
+    /// is emitted.
+    void addBBRef(MachineBasicBlock *BB, intptr_t PC) {
+      BBRefs.push_back(std::make_pair(BB, PC));
+    }
+
     /// needsGOT - Allows a target to specify that it would like the
     // JIT to manage a GOT for it.
     bool needsGOT() const { return useGOT; }
@@ -88,6 +104,9 @@ namespace llvm {
   protected:
     bool useGOT;
 
+    // Tracks which instruction references which BasicBlock
+    std::vector<std::pair<MachineBasicBlock*, intptr_t> > BBRefs;
+    
   };
 } // End llvm namespace
 
index 5e130167279a2d954b270c9b795a12513c1c7414..ecde6cfeca8a9dcf25ec991fe7933ccaefc26707 100644 (file)
@@ -542,6 +542,10 @@ void *JITResolver::getFunctionStub(Function *F) {
     TheJIT->updateGlobalMapping(F, Stub);
   }
 
+  // Invalidate the icache if necessary.
+  TheJIT->getJITInfo().
+    synchronizeICache(Stub, MCE.getCurrentPCValue()-(intptr_t)Stub);
+
   DEBUG(std::cerr << "JIT: Stub emitted at [" << Stub << "] for function '"
                   << F->getName() << "'\n");
 
@@ -559,6 +563,11 @@ void *JITResolver::getExternalFunctionStub(void *FnAddr) {
   if (Stub) return Stub;
 
   Stub = TheJIT->getJITInfo().emitFunctionStub(FnAddr, MCE);
+
+  // Invalidate the icache if necessary.
+  TheJIT->getJITInfo().
+    synchronizeICache(Stub, MCE.getCurrentPCValue()-(intptr_t)Stub);
+
   DEBUG(std::cerr << "JIT: Stub emitted at [" << Stub
         << "] for external function at '" << FnAddr << "'\n");
   return Stub;
@@ -747,7 +756,7 @@ void JITEmitter::startFunction(MachineFunction &F) {
   // About to start emitting the machine code for the function.
   emitAlignment(std::max(F.getFunction()->getAlignment(), 8U));
   TheJIT->updateGlobalMapping(F.getFunction(), CurBufferPtr);
-  
+
   MBBLocations.clear();
 }
 
@@ -825,6 +834,12 @@ bool JITEmitter::finishFunction(MachineFunction &F) {
     }
   }
 
+  // Resolve BasicaBlock references.
+  TheJIT->getJITInfo().resolveBBRefs(*this);
+
+  // Invalidate the icache if necessary.
+  TheJIT->getJITInfo().synchronizeICache(FnStart, FnEnd-FnStart);
+
   DEBUG(std::cerr << "JIT: Finished CodeGen of [" << (void*)FnStart
                   << "] Function: " << F.getFunction()->getName()
                   << ": " << (FnEnd-FnStart) << " bytes of text, "
index 8884af224d4c7117a8b6611e341e6bbbe7199373..6dc412b815e0fc2095a4968a143a99477abbbe38 100644 (file)
@@ -19,6 +19,7 @@
 
 namespace llvm {
 
+  class AlphaTargetMachine;
   class FunctionPass;
   class TargetMachine;
   class MachineCodeEmitter;
@@ -28,7 +29,8 @@ namespace llvm {
   FunctionPass *createAlphaCodePrinterPass(std::ostream &OS,
                                              TargetMachine &TM);
   FunctionPass *createAlphaPatternInstructionSelector(TargetMachine &TM);
-  FunctionPass *createAlphaCodeEmitterPass(MachineCodeEmitter &MCE);
+  FunctionPass *createAlphaCodeEmitterPass(AlphaTargetMachine &TM,
+                                           MachineCodeEmitter &MCE);
 } // end namespace llvm;
 
 // Defines symbolic names for Alpha registers.  This defines a mapping from
index d8cf7df45f387b988fd10544fa98a49672c72764..7a3c550d83d8591e734df3e59218bbc763108e1c 100644 (file)
@@ -34,17 +34,19 @@ namespace {
 namespace {
   class AlphaCodeEmitter : public MachineFunctionPass {
     const AlphaInstrInfo  *II;
+    TargetMachine &TM;
     MachineCodeEmitter  &MCE;
-    std::vector<std::pair<MachineBasicBlock *, unsigned*> > BBRefs;
 
     /// getMachineOpValue - evaluates the MachineOperand of a given MachineInstr
     ///
     int getMachineOpValue(MachineInstr &MI, MachineOperand &MO);
 
   public:
-    explicit AlphaCodeEmitter(MachineCodeEmitter &mce) : II(0), MCE(mce) {}
-    AlphaCodeEmitter(MachineCodeEmitter &mce, const AlphaInstrInfo& ii)
-        : II(&ii), MCE(mce) {}
+    explicit AlphaCodeEmitter(TargetMachine &tm, MachineCodeEmitter &mce)
+      : II(0), TM(tm), MCE(mce) {}
+    AlphaCodeEmitter(TargetMachine &tm, MachineCodeEmitter &mce,
+                     const AlphaInstrInfo& ii)
+      : II(&ii), TM(tm), MCE(mce) {}
 
     bool runOnMachineFunction(MachineFunction &MF);
 
@@ -68,34 +70,20 @@ namespace {
 
 /// createAlphaCodeEmitterPass - Return a pass that emits the collected Alpha code
 /// to the specified MCE object.
-FunctionPass *llvm::createAlphaCodeEmitterPass(MachineCodeEmitter &MCE) {
-  return new AlphaCodeEmitter(MCE);
+FunctionPass *llvm::createAlphaCodeEmitterPass(AlphaTargetMachine &TM,
+                                               MachineCodeEmitter &MCE) {
+  return new AlphaCodeEmitter(TM, MCE);
 }
 
 bool AlphaCodeEmitter::runOnMachineFunction(MachineFunction &MF) {
   II = ((AlphaTargetMachine&)MF.getTarget()).getInstrInfo();
 
   do {
-    BBRefs.clear();
-    
     MCE.startFunction(MF);
     for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I)
       emitBasicBlock(*I);
   } while (MCE.finishFunction(MF));
 
-  // Resolve all forward branches now...
-  for (unsigned i = 0, e = BBRefs.size(); i != e; ++i) {
-    unsigned* Location =
-      (unsigned*)MCE.getMachineBasicBlockAddress(BBRefs[i].first);
-    unsigned* Ref = (unsigned*)BBRefs[i].second;
-    intptr_t BranchTargetDisp = 
-      (((unsigned char*)Location  - (unsigned char*)Ref) >> 2) - 1;
-    DEBUG(std::cerr << "Fixup @ " << (void*)Ref << " to " << (void*)Location
-          << " Disp " << BranchTargetDisp 
-          << " using " <<  (BranchTargetDisp & ((1 << 22)-1)) << "\n");
-    *Ref |= (BranchTargetDisp & ((1 << 21)-1));
-  }
-  BBRefs.clear();
   return false;
 }
 
@@ -227,8 +215,8 @@ int AlphaCodeEmitter::getMachineOpValue(MachineInstr &MI, MachineOperand &MO) {
                                           Reloc, MO.getConstantPoolIndex(),
                                           Offset));
   } else if (MO.isMachineBasicBlock()) {
-    unsigned* CurrPC = (unsigned*)(intptr_t)MCE.getCurrentPCValue();
-    BBRefs.push_back(std::make_pair(MO.getMachineBasicBlock(), CurrPC));
+    TM.getJITInfo()->addBBRef(MO.getMachineBasicBlock(),
+                              MCE.getCurrentPCValue());
   }else {
     std::cerr << "ERROR: Unknown type of MachineOperand: " << MO << "\n";
     abort();
index 81f5e743aa2af30249eaf553ce35ef6898dcafe2..8dc5a479603c4caab414041b95cc8742d34da464 100644 (file)
@@ -304,3 +304,19 @@ void AlphaJITInfo::relocate(void *Function, MachineRelocation *MR,
     }
   }
 }
+
+void AlphaJITInfo::resolveBBRefs(MachineCodeEmitter &MCE) {
+  // Resolve all forward branches now...
+  for (unsigned i = 0, e = BBRefs.size(); i != e; ++i) {
+    unsigned* Location =
+      (unsigned*)MCE.getMachineBasicBlockAddress(BBRefs[i].first);
+    unsigned* Ref = (unsigned*)BBRefs[i].second;
+    intptr_t BranchTargetDisp = 
+      (((unsigned char*)Location  - (unsigned char*)Ref) >> 2) - 1;
+    DEBUG(std::cerr << "Fixup @ " << (void*)Ref << " to " << (void*)Location
+          << " Disp " << BranchTargetDisp 
+          << " using " <<  (BranchTargetDisp & ((1 << 22)-1)) << "\n");
+    *Ref |= (BranchTargetDisp & ((1 << 21)-1));
+  }
+  BBRefs.clear();
+}
index 252b05c7786f153810c2f22c72e6e5eb27f727da..68663f2cd1d99bc2bdb5f5463be2215626c0fbd9 100644 (file)
@@ -47,6 +47,7 @@ namespace llvm {
     ///
     virtual void replaceMachineCodeForFunction(void *Old, void *New);
 
+    virtual void resolveBBRefs(MachineCodeEmitter &MCE);
   private:
     static const unsigned GOToffset = 4096;
 
index df94d6fa348b4c10be13f5918f6c192591e587d3..427094c9553a0ff5572b0d6dba2e58da14d0f349 100644 (file)
@@ -138,7 +138,7 @@ void AlphaJITInfo::addPassesToJITCompile(FunctionPassManager &PM) {
 
 bool AlphaTargetMachine::addPassesToEmitMachineCode(FunctionPassManager &PM,
                                                     MachineCodeEmitter &MCE) {
-  PM.add(createAlphaCodeEmitterPass(MCE));
+  PM.add(createAlphaCodeEmitterPass(*this, MCE));
   // Delete machine code for this function
   PM.add(createMachineCodeDeleter());
   return false;
index 76dc349b50c7b87948ad1742a32f652d4ac7ba49..73b0436fd18cf5365debbf8fdb7a04eebe2ed735 100644 (file)
@@ -32,9 +32,6 @@ namespace {
     TargetMachine &TM;
     MachineCodeEmitter &MCE;
 
-    // Tracks which instruction references which BasicBlock
-    std::vector<std::pair<MachineBasicBlock*, unsigned*> > BBRefs;
-    
     /// getMachineOpValue - evaluates the MachineOperand of a given MachineInstr
     ///
     int getMachineOpValue(MachineInstr &MI, MachineOperand &MO);
@@ -80,39 +77,20 @@ bool PPCTargetMachine::addPassesToEmitMachineCode(FunctionPassManager &PM,
   return false;
 }
 
+#ifdef __APPLE__ 
+extern "C" void sys_icache_invalidate(const void *Addr, size_t len);
+#endif
+
 bool PPCCodeEmitter::runOnMachineFunction(MachineFunction &MF) {
   assert((MF.getTarget().getRelocationModel() != Reloc::Default ||
           MF.getTarget().getRelocationModel() != Reloc::Static) &&
          "JIT relocation model must be set to static or default!");
   do {
-    BBRefs.clear();
-
     MCE.startFunction(MF);
     for (MachineFunction::iterator BB = MF.begin(), E = MF.end(); BB != E; ++BB)
       emitBasicBlock(*BB);
   } while (MCE.finishFunction(MF));
 
-  // Resolve branches to BasicBlocks for the entire function
-  for (unsigned i = 0, e = BBRefs.size(); i != e; ++i) {
-    intptr_t Location = MCE.getMachineBasicBlockAddress(BBRefs[i].first);
-    unsigned *Ref = BBRefs[i].second;
-    DEBUG(std::cerr << "Fixup @ " << (void*)Ref << " to " << (void*)Location
-                    << "\n");
-    unsigned Instr = *Ref;
-    intptr_t BranchTargetDisp = (Location - (intptr_t)Ref) >> 2;
-
-    switch (Instr >> 26) {
-    default: assert(0 && "Unknown branch user!");
-    case 18:  // This is B or BL
-      *Ref |= (BranchTargetDisp & ((1 << 24)-1)) << 2;
-      break;
-    case 16:  // This is BLT,BLE,BEQ,BGE,BGT,BNE, or other bcx instruction
-      *Ref |= (BranchTargetDisp & ((1 << 14)-1)) << 2;
-      break;
-    }
-  }
-  BBRefs.clear();
-
   return false;
 }
 
@@ -203,7 +181,7 @@ int PPCCodeEmitter::getMachineOpValue(MachineInstr &MI, MachineOperand &MO) {
                                           Reloc, MO.getSymbolName(), 0));
   } else if (MO.isMachineBasicBlock()) {
     unsigned* CurrPC = (unsigned*)(intptr_t)MCE.getCurrentPCValue();
-    BBRefs.push_back(std::make_pair(MO.getMachineBasicBlock(), CurrPC));
+    TM.getJITInfo()->addBBRef(MO.getMachineBasicBlock(), (intptr_t)CurrPC);
   } else if (MO.isConstantPoolIndex() || MO.isJumpTableIndex()) {
     if (MO.isConstantPoolIndex())
       rv = MCE.getConstantPoolEntryAddress(MO.getConstantPoolIndex());
index 1d4760affaf0df6c0d88a93c123210227bf7afe7..0c6044c928a6411712b868e40f65e99ef1316ba3 100644 (file)
@@ -16,7 +16,9 @@
 #include "PPCRelocations.h"
 #include "llvm/CodeGen/MachineCodeEmitter.h"
 #include "llvm/Config/alloca.h"
+#include "llvm/Support/Debug.h"
 #include <set>
+#include <iostream>
 using namespace llvm;
 
 static TargetJITInfo::JITCompilerFn JITCompilerFunction;
@@ -243,3 +245,36 @@ void PPCJITInfo::relocate(void *Function, MachineRelocation *MR,
 void PPCJITInfo::replaceMachineCodeForFunction(void *Old, void *New) {
   EmitBranchToAt(Old, New, false);
 }
+
+void PPCJITInfo::resolveBBRefs(MachineCodeEmitter &MCE) {
+  // Resolve branches to BasicBlocks for the entire function
+  for (unsigned i = 0, e = BBRefs.size(); i != e; ++i) {
+    intptr_t Location = MCE.getMachineBasicBlockAddress(BBRefs[i].first);
+    unsigned *Ref = (unsigned *)BBRefs[i].second;
+    DEBUG(std::cerr << "Fixup @ " << (void*)Ref << " to " << (void*)Location
+                    << "\n");
+    unsigned Instr = *Ref;
+    intptr_t BranchTargetDisp = (Location - (intptr_t)Ref) >> 2;
+
+    switch (Instr >> 26) {
+    default: assert(0 && "Unknown branch user!");
+    case 18:  // This is B or BL
+      *Ref |= (BranchTargetDisp & ((1 << 24)-1)) << 2;
+      break;
+    case 16:  // This is BLT,BLE,BEQ,BGE,BGT,BNE, or other bcx instruction
+      *Ref |= (BranchTargetDisp & ((1 << 14)-1)) << 2;
+      break;
+    }
+  }
+  BBRefs.clear();
+}
+
+#ifdef __APPLE__ 
+extern "C" void sys_icache_invalidate(const void *Addr, size_t len);
+#endif
+
+void PPCJITInfo::synchronizeICache(const void *Addr, size_t Len) {
+#ifdef __APPLE__
+  sys_icache_invalidate(Addr, Len);
+#endif
+}
index 245cf9ad9023508114982ff754e207d56c6a65e3..292539f3ec9d930d42d04c7e714f08570ef09a93 100644 (file)
@@ -42,6 +42,9 @@ namespace llvm {
     /// code.
     ///
     virtual void replaceMachineCodeForFunction(void *Old, void *New);
+
+    virtual void resolveBBRefs(MachineCodeEmitter &MCE);
+    virtual void synchronizeICache(const void *Addr, size_t Len);
   };
 }
 
index 8d2805ccc203b47d54cc3a7cb3e5ab8dfe32d041..e6deda620e24384ebdad7e8969c8e6e931e06e63 100644 (file)
@@ -44,7 +44,8 @@ FunctionPass *createX86CodePrinterPass(std::ostream &o, X86TargetMachine &tm);
 
 /// createX86CodeEmitterPass - Return a pass that emits the collected X86 code
 /// to the specified MCE object.
-FunctionPass *createX86CodeEmitterPass(MachineCodeEmitter &MCE);
+FunctionPass *createX86CodeEmitterPass(X86TargetMachine &TM,
+                                       MachineCodeEmitter &MCE);
 
 /// addX86ELFObjectWriterPass - Add passes to the FPM that output the generated
 /// code as an ELF object file.
index 9179890b39bc2d72041f28d0227e829b81fef80a..31b4bdf1852889eaa570777db2361ae5688a4657 100644 (file)
@@ -35,12 +35,14 @@ namespace {
 namespace {
   class VISIBILITY_HIDDEN Emitter : public MachineFunctionPass {
     const X86InstrInfo  *II;
+    TargetMachine &TM;
     MachineCodeEmitter  &MCE;
-    std::vector<std::pair<MachineBasicBlock *, unsigned> > BBRefs;
   public:
-    explicit Emitter(MachineCodeEmitter &mce) : II(0), MCE(mce) {}
-    Emitter(MachineCodeEmitter &mce, const X86InstrInfo& ii)
-        : II(&ii), MCE(mce) {}
+    explicit Emitter(TargetMachine &tm, MachineCodeEmitter &mce)
+      : II(0), TM(tm), MCE(mce) {}
+    Emitter(TargetMachine &tm, MachineCodeEmitter &mce,
+            const X86InstrInfo& ii)
+      : II(&ii), TM(tm), MCE(mce) {}
 
     bool runOnMachineFunction(MachineFunction &MF);
 
@@ -71,8 +73,9 @@ namespace {
 
 /// createX86CodeEmitterPass - Return a pass that emits the collected X86 code
 /// to the specified MCE object.
-FunctionPass *llvm::createX86CodeEmitterPass(MachineCodeEmitter &MCE) {
-  return new Emitter(MCE);
+FunctionPass *llvm::createX86CodeEmitterPass(X86TargetMachine &TM,
+                                             MachineCodeEmitter &MCE) {
+  return new Emitter(TM, MCE);
 }
 
 bool Emitter::runOnMachineFunction(MachineFunction &MF) {
@@ -82,8 +85,6 @@ bool Emitter::runOnMachineFunction(MachineFunction &MF) {
   II = ((X86TargetMachine&)MF.getTarget()).getInstrInfo();
 
   do {
-    BBRefs.clear();
-
     MCE.startFunction(MF);
     for (MachineFunction::iterator MBB = MF.begin(), E = MF.end(); 
          MBB != E; ++MBB) {
@@ -94,13 +95,6 @@ bool Emitter::runOnMachineFunction(MachineFunction &MF) {
     }
   } while (MCE.finishFunction(MF));
 
-  // Resolve all forward branches now.
-  for (unsigned i = 0, e = BBRefs.size(); i != e; ++i) {
-    unsigned Location = MCE.getMachineBasicBlockAddress(BBRefs[i].first);
-    unsigned Ref = BBRefs[i].second;
-    *((unsigned*)(intptr_t)Ref) = Location-Ref-4;
-  }
-  BBRefs.clear();
   return false;
 }
 
@@ -117,7 +111,7 @@ void Emitter::emitPCRelativeValue(unsigned Address) {
 void Emitter::emitPCRelativeBlockAddress(MachineBasicBlock *MBB) {
   // Remember where this reference was and where it is to so we can
   // deal with it later.
-  BBRefs.push_back(std::make_pair(MBB, MCE.getCurrentPCValue()));
+  TM.getJITInfo()->addBBRef(MBB, MCE.getCurrentPCValue());
   MCE.emitWordLE(0);
 }
 
index 0a3a027f1d4ce302946f1a7a17d61bda9de38f87..46c46420301bcc7ca74e83fdb65dc675542d06a6 100644 (file)
@@ -35,5 +35,5 @@ void llvm::addX86ELFObjectWriterPass(PassManager &FPM,
                                      std::ostream &O, X86TargetMachine &TM) {
   X86ELFWriter *EW = new X86ELFWriter(O, TM);
   FPM.add(EW);
-  FPM.add(createX86CodeEmitterPass(EW->getMachineCodeEmitter()));
+  FPM.add(createX86CodeEmitterPass(TM, EW->getMachineCodeEmitter()));
 }
index 9bb2a7252331a98fdf1aedfa1abf1a0f79b77edf..9fd8029962d9c333ccb750abaafc197733118413 100644 (file)
@@ -203,3 +203,13 @@ void X86JITInfo::relocate(void *Function, MachineRelocation *MR,
     }
   }
 }
+
+void X86JITInfo::resolveBBRefs(MachineCodeEmitter &MCE) {
+  // Resolve all forward branches now.
+  for (unsigned i = 0, e = BBRefs.size(); i != e; ++i) {
+    unsigned Location = MCE.getMachineBasicBlockAddress(BBRefs[i].first);
+    intptr_t Ref = BBRefs[i].second;
+    *((unsigned*)Ref) = Location-Ref-4;
+  }
+  BBRefs.clear();
+}
index 02e54af11af7b139da0a0d1430bb2003d93e7be0..f9e437e41b12f78ed0b8521905094d439edebc10 100644 (file)
@@ -51,6 +51,8 @@ namespace llvm {
     /// referenced global symbols.
     virtual void relocate(void *Function, MachineRelocation *MR,
                           unsigned NumRelocs, unsigned char* GOTBase);
+
+    virtual void resolveBBRefs(MachineCodeEmitter &MCE);
   };
 }
 
index 2c3c5306847cda4a966630448621b5053582d3a6..e4b6a941a4668b09f54f5973cb35744596506d37 100644 (file)
@@ -194,7 +194,7 @@ void X86JITInfo::addPassesToJITCompile(FunctionPassManager &PM) {
 
 bool X86TargetMachine::addPassesToEmitMachineCode(FunctionPassManager &PM,
                                                   MachineCodeEmitter &MCE) {
-  PM.add(createX86CodeEmitterPass(MCE));
+  PM.add(createX86CodeEmitterPass(*this, MCE));
   // Delete machine code for this function
   PM.add(createMachineCodeDeleter());
   return false;