[llvm-commits] CVS: llvm/lib/Target/PowerPC/PPC32CodeEmitter.cpp

Misha Brukman brukman at cs.uiuc.edu
Wed Oct 20 18:42:13 PDT 2004



Changes in directory llvm/lib/Target/PowerPC:

PPC32CodeEmitter.cpp updated: 1.6 -> 1.7
---
Log message:

* Added basic support for JITing functions, basic blocks, instruction encoding,
  including registers, constants, and partial support for global addresses
* The JIT is disabled by default to allow building llvm-gcc, which wants to test
  running programs during configure


---
Diffs of the changes:  (+169 -20)

Index: llvm/lib/Target/PowerPC/PPC32CodeEmitter.cpp
diff -u llvm/lib/Target/PowerPC/PPC32CodeEmitter.cpp:1.6 llvm/lib/Target/PowerPC/PPC32CodeEmitter.cpp:1.7
--- llvm/lib/Target/PowerPC/PPC32CodeEmitter.cpp:1.6	Thu Oct 14 01:39:56 2004
+++ llvm/lib/Target/PowerPC/PPC32CodeEmitter.cpp	Wed Oct 20 20:42:02 2004
@@ -14,6 +14,7 @@
 
 #include "PPC32JITInfo.h"
 #include "PPC32TargetMachine.h"
+#include "llvm/Module.h"
 #include "llvm/CodeGen/MachineCodeEmitter.h"
 #include "llvm/CodeGen/MachineFunctionPass.h"
 #include "llvm/CodeGen/Passes.h"
@@ -22,12 +23,97 @@
 namespace llvm {
 
 namespace {
+  class JITResolver {
+    MachineCodeEmitter &MCE;
+
+    // LazyCodeGenMap - Keep track of call sites for functions that are to be
+    // lazily resolved.
+    std::map<unsigned, Function*> LazyCodeGenMap;
+
+    // LazyResolverMap - Keep track of the lazy resolver created for a
+    // particular function so that we can reuse them if necessary.
+    std::map<Function*, unsigned> LazyResolverMap;
+
+  public:
+    JITResolver(MachineCodeEmitter &mce) : MCE(mce) {}
+    unsigned getLazyResolver(Function *F);
+    unsigned addFunctionReference(unsigned Address, Function *F);
+    
+  private:
+    unsigned emitStubForFunction(Function *F);
+    static void CompilationCallback();
+    unsigned resolveFunctionReference(unsigned RetAddr);
+  };
+
+  static JITResolver &getResolver(MachineCodeEmitter &MCE) {
+    static JITResolver *TheJITResolver = 0;
+    if (TheJITResolver == 0)
+      TheJITResolver = new JITResolver(MCE);
+    return *TheJITResolver;
+  }
+}
+
+unsigned JITResolver::getLazyResolver(Function *F) {
+  std::map<Function*, unsigned>::iterator I = LazyResolverMap.lower_bound(F);
+  if (I != LazyResolverMap.end() && I->first == F) return I->second;
+
+  unsigned Stub = emitStubForFunction(F);
+  LazyResolverMap.insert(I, std::make_pair(F, Stub));
+  return Stub;
+}
+
+/// addFunctionReference - This method is called when we need to emit the
+/// address of a function that has not yet been emitted, so we don't know the
+/// address.  Instead, we emit a call to the CompilationCallback method, and
+/// keep track of where we are.
+///
+unsigned JITResolver::addFunctionReference(unsigned Address, Function *F) {
+  LazyCodeGenMap[Address] = F;
+  return (intptr_t)&JITResolver::CompilationCallback;
+}
+
+unsigned JITResolver::resolveFunctionReference(unsigned RetAddr) {
+  std::map<unsigned, Function*>::iterator I = LazyCodeGenMap.find(RetAddr);
+  assert(I != LazyCodeGenMap.end() && "Not in map!");
+  Function *F = I->second;
+  LazyCodeGenMap.erase(I);
+  return MCE.forceCompilationOf(F);
+}
+
+/// emitStubForFunction - This method is used by the JIT when it needs to emit
+/// the address of a function for a function whose code has not yet been
+/// generated.  In order to do this, it generates a stub which jumps to the lazy
+/// function compiler, which will eventually get fixed to call the function
+/// directly.
+///
+unsigned JITResolver::emitStubForFunction(Function *F) {
+  std::cerr << "PPC32CodeEmitter::emitStubForFunction() unimplemented!\n";
+  abort();
+  return 0;
+}
+
+void JITResolver::CompilationCallback() {
+  std::cerr << "PPC32CodeEmitter: CompilationCallback() unimplemented!";
+  abort();
+}
+
+namespace {
   class PPC32CodeEmitter : public MachineFunctionPass {
     TargetMachine &TM;
     MachineCodeEmitter &MCE;
 
+    // Tracks which instruction references which BasicBlock
+    std::vector<std::pair<const BasicBlock*,
+                          std::pair<unsigned*,MachineInstr*> > > BBRefs;
+    // Tracks where each BasicBlock starts
+    std::map<const BasicBlock*, long> BBLocations;
+
+    /// getMachineOpValue - evaluates the MachineOperand of a given MachineInstr
+    ///
     int64_t getMachineOpValue(MachineInstr &MI, MachineOperand &MO);
 
+    unsigned getAddressOfExternalFunction(Function *F);
+
   public:
     PPC32CodeEmitter(TargetMachine &T, MachineCodeEmitter &M) 
       : TM(T), MCE(M) {}
@@ -50,7 +136,9 @@
     ///
     unsigned getValueBit(int64_t Val, unsigned bit) { return (Val >> bit) & 1; }
 
-    /// getBinaryCodeForInstr - returns the assembled code for an instruction
+    /// getBinaryCodeForInstr - This function, generated by the
+    /// CodeEmitterGenerator using TableGen, produces the binary encoding for
+    /// machine instructions.
     ///
     unsigned getBinaryCodeForInstr(MachineInstr &MI);
   };
@@ -64,8 +152,13 @@
 ///
 bool PPC32TargetMachine::addPassesToEmitMachineCode(FunctionPassManager &PM,
                                                     MachineCodeEmitter &MCE) {
+  // Keep as `true' until this is a functional JIT to allow llvm-gcc to build
+  return true;
+
   // Machine code emitter pass for PowerPC
-  PM.add(new PPC32CodeEmitter(*this, MCE)); 
+  MachineCodeEmitter *M = &MCE;
+  DEBUG(M = MachineCodeEmitter::createDebugEmitter(MCE));
+  PM.add(new PPC32CodeEmitter(*this, *M)); 
   // Delete machine code for this function after emitting it
   PM.add(createMachineCodeDeleter());
   return false;
@@ -74,9 +167,36 @@
 bool PPC32CodeEmitter::runOnMachineFunction(MachineFunction &MF) {
   MCE.startFunction(MF);
   MCE.emitConstantPool(MF.getConstantPool());
-  for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I)
-    emitBasicBlock(*I);
+  for (MachineFunction::iterator BB = MF.begin(), E = MF.end(); BB != E; ++BB)
+    emitBasicBlock(*BB);
   MCE.finishFunction(MF);
+
+  // Resolve branches to BasicBlocks for the entire function
+  for (unsigned i = 0, e = BBRefs.size(); i != e; ++i) {
+    long Location = BBLocations[BBRefs[i].first];
+    unsigned *Ref = BBRefs[i].second.first;
+    MachineInstr *MI = BBRefs[i].second.second;
+    DEBUG(std::cerr << "Fixup @ " << std::hex << Ref << " to 0x" << Location
+                    << " in instr: " << std::dec << *MI);
+    for (unsigned ii = 0, ee = MI->getNumOperands(); ii != ee; ++ii) {
+      MachineOperand &op = MI->getOperand(ii);
+      if (op.isPCRelativeDisp()) {
+        // the instruction's branch target is made such that it branches to
+        // PC + (branchTarget * 4), so undo that arithmetic here:
+        // Location is the target of the branch
+        // Ref is the location of the instruction, and hence the PC
+        int64_t branchTarget = (Location - (long)Ref) >> 2;
+        MI->SetMachineOperandConst(ii, MachineOperand::MO_SignExtendedImmed,
+                                   branchTarget);
+        unsigned fixedInstr = PPC32CodeEmitter::getBinaryCodeForInstr(*MI);
+        MCE.emitWordAt(fixedInstr, Ref);
+        break;
+      }
+    }
+  }
+  BBRefs.clear();
+  BBLocations.clear();
+
   return false;
 }
 
@@ -85,27 +205,59 @@
     emitWord(getBinaryCodeForInstr(*I));
 }
 
+unsigned PPC32CodeEmitter::getAddressOfExternalFunction(Function *F) {
+  static std::map<Function*, unsigned> ExternalFn2Addr;
+  std::map<Function*, unsigned>::iterator Addr = ExternalFn2Addr.find(F);
+
+  if (Addr == ExternalFn2Addr.end())
+    ExternalFn2Addr[F] = MCE.forceCompilationOf(F);
+  return ExternalFn2Addr[F];
+}
+
 int64_t PPC32CodeEmitter::getMachineOpValue(MachineInstr &MI, 
                                             MachineOperand &MO) {
   int64_t rv = 0; // Return value; defaults to 0 for unhandled cases
                   // or things that get fixed up later by the JIT.
-  if (MO.isPCRelativeDisp()) {
-    std::cerr << "PPC32CodeEmitter: PC-relative disp unhandled\n";
-    abort();
-  } else if (MO.isRegister()) {
+  if (MO.isRegister()) {
     rv = MO.getReg();
   } else if (MO.isImmediate()) {
     rv = MO.getImmedValue();
-#if 0
   } else if (MO.isGlobalAddress()) {
+    GlobalValue *GV = MO.getGlobal();
+    intptr_t Addr = (intptr_t)MCE.getGlobalValueAddress(GV);
+    if (Addr == 0) {
+      if (Function *F = dyn_cast<Function>(GV)) {
+        if (F->isExternal())
+          rv = getAddressOfExternalFunction(F);
+        else {
+          // Function has not yet been code generated!
+          getResolver(MCE).addFunctionReference(MCE.getCurrentPCValue(), F);
+          // Delayed resolution...
+          return (intptr_t)getResolver(MCE).getLazyResolver(F);
+        }
+      } else if (GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV)) {
+        if (GVar->isExternal())
+          rv = MCE.getGlobalValueAddress(MO.getSymbolName());
+        else {
+          std::cerr << "PPC32CodeEmitter: External global addr not found: " 
+                    << *GVar;
+          abort();
+        }
+      }
+    }
+    if (MO.isPCRelative()) { // Global variable reference
+      rv = (Addr - MCE.getCurrentPCValue()) >> 2;
+    }
   } else if (MO.isMachineBasicBlock()) {
-    MachineBasicBlock *MBB = MO.getMachineBasicBlock();
-  } else if (MO.isExternalSymbol()) {
-  } else if (MO.isFrameIndex()) {
-    unsigned index = MO.getFrameIndex();
+    const BasicBlock *BB = MO.getMachineBasicBlock()->getBasicBlock();
+    unsigned* CurrPC = (unsigned*)(intptr_t)MCE.getCurrentPCValue();
+    BBRefs.push_back(std::make_pair(BB, std::make_pair(CurrPC, &MI)));
   } else if (MO.isConstantPoolIndex()) {
-    unsigned index = MO.getCosntantPoolIndex();
-#endif
+    unsigned index = MO.getConstantPoolIndex();
+    rv = MCE.getConstantPoolEntryAddress(index);
+  } else if (MO.isFrameIndex()) {
+    std::cerr << "PPC32CodeEmitter: error: Frame index unhandled!\n";
+    abort();
   } else {
     std::cerr << "ERROR: Unknown type of MachineOperand: " << MO << "\n";
     abort();
@@ -115,11 +267,8 @@
 }
 
 
-void *PPC32JITInfo::getJITStubForFunction(Function *F,
-                                          MachineCodeEmitter &MCE) {
-  std::cerr << "PPC32JITInfo::getJITStubForFunction not implemented\n";
-  abort();
-  return 0;
+void *PPC32JITInfo::getJITStubForFunction(Function *F, MachineCodeEmitter &MCE){
+  return (void*)((unsigned long)getResolver(MCE).getLazyResolver(F));
 }
 
 void PPC32JITInfo::replaceMachineCodeForFunction (void *Old, void *New) {






More information about the llvm-commits mailing list