[llvm-commits] CVS: reopt/lib/TraceJIT/Makefile TraceJIT.cpp TraceJIT.h TraceJITEmitter.cpp TraceJITIntercept.cpp
Brian Gaeke
gaeke at cs.uiuc.edu
Wed May 26 16:29:02 PDT 2004
Changes in directory reopt/lib/TraceJIT:
Makefile added (r1.1)
TraceJIT.cpp added (r1.1)
TraceJIT.h added (r1.1)
TraceJITEmitter.cpp added (r1.1)
TraceJITIntercept.cpp added (r1.1)
---
Log message:
Import TraceJIT: a new ExecutionEngine based on the JIT, designed to
reoptimize TraceFunctions at runtime.
---
Diffs of the changes: (+689 -0)
Index: reopt/lib/TraceJIT/Makefile
diff -c /dev/null reopt/lib/TraceJIT/Makefile:1.1
*** /dev/null Wed May 26 16:25:23 2004
--- reopt/lib/TraceJIT/Makefile Wed May 26 16:25:13 2004
***************
*** 0 ****
--- 1,12 ----
+ ##===- lib/TraceJIT/Makefile -------------------------------*- Makefile -*-===##
+ #
+ # The LLVM Compiler Infrastructure
+ #
+ # This file was developed by the LLVM research group and is distributed under
+ # the University of Illinois Open Source License. See LICENSE.TXT for details.
+ #
+ ##===----------------------------------------------------------------------===##
+ LEVEL = ../..
+ LIBRARYNAME = tracejit
+
+ include $(LEVEL)/Makefile.common
Index: reopt/lib/TraceJIT/TraceJIT.cpp
diff -c /dev/null reopt/lib/TraceJIT/TraceJIT.cpp:1.1
*** /dev/null Wed May 26 16:25:23 2004
--- reopt/lib/TraceJIT/TraceJIT.cpp Wed May 26 16:25:13 2004
***************
*** 0 ****
--- 1,268 ----
+ //===-- TraceJIT.cpp - LLVM Just in Time Compiler -------------------------===//
+ //
+ // The LLVM Compiler Infrastructure
+ //
+ // This file was developed by the LLVM research group and is distributed under
+ // the University of Illinois Open Source License. See LICENSE.TXT for details.
+ //
+ //===----------------------------------------------------------------------===//
+ //
+ // This tool implements a just-in-time compiler for LLVM, allowing direct
+ // execution of LLVM bytecode in an efficient manner.
+ //
+ //===----------------------------------------------------------------------===//
+
+ #include "TraceJIT.h"
+ #include "../LightWtProfiling/ReoptimizerInternal.h"
+ #include "reopt/TraceToFunction.h"
+ #include "reopt/UnpackTraceFunction.h"
+ #include "llvm/CodeGen/MachineCodeEmitter.h"
+ #include "llvm/CodeGen/MachineFunction.h"
+ #include "llvm/DerivedTypes.h"
+ #include "llvm/ExecutionEngine/GenericValue.h"
+ #include "llvm/Function.h"
+ #include "llvm/GlobalVariable.h"
+ #include "llvm/Module.h"
+ #include "llvm/ModuleProvider.h"
+ #include "llvm/Analysis/Verifier.h"
+ #include "llvm/Assembly/PrintModulePass.h"
+ #include "llvm/CodeGen/Passes.h"
+ #include "llvm/Target/TargetMachine.h"
+ #include "llvm/Target/TargetMachineImpls.h"
+ #include "llvm/Target/TargetJITInfo.h"
+ #include "Support/CommandLine.h"
+ #include "Support/DynamicLinker.h"
+ #include "Support/Debug.h"
+ using namespace llvm;
+
+ namespace llvm {
+ extern bool SaveStateToModule;
+ extern bool SaveRegAllocState;
+ extern MachineCodeEmitter *createTraceJITEmitter (TraceJIT *JIT);
+ } // end namespace llvm
+
+ void TraceJIT::addPassesToReoptimizeTrace (FunctionPassManager &PM) {
+ // Verify that the generated function's bytecode is good, then compile it
+ // down to machine code. Then, "unpack" it back into its matrix function.
+ // FIXME: Register allocation hints also need to be added to the PassManager,
+ // so that we do not get clobbered by the overhead of adding copies in
+ // UnpackTraceFunction.
+ DEBUG (PM.add (new PrintFunctionPass ("Function created from trace:\n",
+ &std::cerr)));
+ DEBUG (PM.add (createVerifierPass ()));
+ TJI.addPassesToJITCompile (PM);
+ DEBUG (PM.add (createMachineFunctionPrinterPass (&std::cerr,
+ "Before unpacking:\n")));
+ PM.add (UTF);
+ DEBUG (PM.add (createMachineFunctionPrinterPass (&std::cerr,
+ "After unpacking:\n")));
+
+ // Force the SPARCv9 register allocator to save its state into a global
+ // variable where UTF can read it.
+ SaveRegAllocState = true;
+ SaveStateToModule = false;
+ }
+
+ TraceJIT::TraceJIT(ModuleProvider *MP, TargetMachine &tm, TargetJITInfo &tji)
+ : ExecutionEngine(MP), TM(tm), TJI(tji), PM(MP) {
+ setTargetData(TM.getTargetData());
+
+ // Initialize MCE & trace-function unpacker
+ MCE = createTraceJITEmitter (this);
+ UTF = new UnpackTraceFunction (&TM);
+
+ PM.add (new TargetData (getTargetData ()));
+
+ // Compile LLVM Code down to machine code in the intermediate representation
+ addPassesToReoptimizeTrace (PM);
+
+ // Turn the machine code intermediate representation into bytes in memory that
+ // may be executed.
+ if (TM.addPassesToEmitMachineCode(PM, *MCE)) {
+ std::cerr << "Target '" << TM.getName()
+ << "' doesn't support machine code emission!\n";
+ abort();
+ }
+ }
+
+ TraceJIT::~TraceJIT() {
+ delete MCE;
+ delete &TM;
+ }
+
+ /// run - Start execution with the specified function and arguments.
+ ///
+ GenericValue TraceJIT::runFunction(Function *F,
+ const std::vector<GenericValue> &ArgValues) {
+ assert (F && "Function *F was null at entry to run()");
+ GenericValue rv;
+
+ if (ArgValues.size() == 3) {
+ int (*PF)(int, char **, const char **) =
+ (int(*)(int, char **, const char **))getPointerToFunction(F);
+ assert(PF && "Pointer to fn's code was null after getPointerToFunction");
+
+ // Call the function.
+ int ExitCode = PF(ArgValues[0].IntVal, (char **) GVTOP (ArgValues[1]),
+ (const char **) GVTOP (ArgValues[2]));
+
+ rv.IntVal = ExitCode;
+ } else {
+ // FIXME: This code should handle a couple of common cases efficiently, but
+ // it should also implement the general case by code-gening a new anonymous
+ // nullary function to call.
+ assert(ArgValues.size() == 1);
+ void (*PF)(int) = (void(*)(int))getPointerToFunction(F);
+ assert(PF && "Pointer to fn's code was null after getPointerToFunction");
+ PF(ArgValues[0].IntVal);
+ }
+
+ return rv;
+ }
+
+ /// runJITOnFunction - Run the FunctionPassManager full of
+ /// just-in-time compilation passes on F, hopefully filling in
+ /// GlobalAddress[F] with the address of F's machine code.
+ ///
+ void TraceJIT::runJITOnFunction(Function *F) {
+ static bool isAlreadyCodeGenerating = false;
+ assert(!isAlreadyCodeGenerating && "Error: Recursive compilation detected!");
+
+ // TraceJIT the function
+ isAlreadyCodeGenerating = true;
+ PM.run(*F);
+ isAlreadyCodeGenerating = false;
+
+ // If the function referred to a global variable that had not yet been
+ // emitted, it allocates memory for the global, but doesn't emit it yet. Emit
+ // all of these globals now.
+ while (!PendingGlobals.empty()) {
+ const GlobalVariable *GV = PendingGlobals.back();
+ PendingGlobals.pop_back();
+ EmitGlobalVariable(GV);
+ }
+ }
+
+ /// getPointerToFunction - This method is used to get the address of the
+ /// specified function, compiling it if neccesary.
+ ///
+ void *TraceJIT::getPointerToFunction(Function *F) {
+ if (void *Addr = getPointerToGlobalIfAvailable(F))
+ return Addr; // Check if function already code gen'd
+
+ // Make sure we read in the function if it exists in this Module
+ try {
+ MP->materializeFunction(F);
+ } catch (...) {
+ std::cerr << "Error parsing bytecode file!\n";
+ abort();
+ }
+
+ // First try to see if we can dig it out of the executable.
+ void *Addr = getPointerToNamedFunction(F->getName());
+ if (Addr) {
+ addGlobalMapping(F, Addr);
+ return Addr;
+ }
+
+ if (!F->isExternal()) {
+ // Try to compile it
+ runJITOnFunction(F);
+ Addr = getPointerToGlobalIfAvailable(F);
+ }
+
+ assert(Addr && "Can't find function");
+ return Addr;
+ }
+
+ // getPointerToFunctionOrStub - If the specified function has been
+ // code-gen'd, return a pointer to the function. If not, compile it, or use
+ // a stub to implement lazy compilation if available.
+ //
+ void *TraceJIT::getPointerToFunctionOrStub(Function *F) {
+ // If we have already code generated the function, just return the address.
+ if (void *Addr = getPointerToGlobalIfAvailable(F))
+ return Addr;
+
+ // Otherwise, codegen the function.
+ return getPointerToFunction(F);
+ }
+
+ /// getOrEmitGlobalVariable - Return the address of the specified global
+ /// variable, possibly emitting it to memory if needed. This is used by the
+ /// Emitter.
+ void *TraceJIT::getOrEmitGlobalVariable(const GlobalVariable *GV) {
+ void *Ptr = getPointerToGlobalIfAvailable(GV);
+ if (Ptr) return Ptr;
+
+ // If the global is external, just remember the address.
+ if (GV->isExternal()) {
+ Ptr = GetAddressOfSymbol(GV->getName().c_str());
+ if (Ptr == 0) {
+ std::cerr << "Could not resolve external global address: "
+ << GV->getName() << "\n";
+ abort();
+ }
+ } else {
+ // If the global hasn't been emitted to memory yet, allocate space. We will
+ // actually initialize the global after current function has finished
+ // compilation.
+ Ptr =new char[getTargetData().getTypeSize(GV->getType()->getElementType())];
+ PendingGlobals.push_back(GV);
+ }
+ addGlobalMapping(GV, Ptr);
+ return Ptr;
+ }
+
+
+ /// recompileAndRelinkFunction - This method is used to force a function
+ /// which has already been compiled, to be compiled again, possibly
+ /// after it has been modified. Then the entry to the old copy is overwritten
+ /// with a branch to the new copy. If there was no old copy, this acts
+ /// just like TraceJIT::getPointerToFunction().
+ ///
+ void *TraceJIT::recompileAndRelinkFunction(Function *F) {
+ void *OldAddr = getPointerToGlobalIfAvailable(F);
+
+ // If it's not already compiled there is no reason to patch it up.
+ if (OldAddr == 0) { return getPointerToFunction(F); }
+
+ // Delete the old function mapping.
+ addGlobalMapping(F, 0);
+
+ // Recodegen the function
+ runJITOnFunction(F);
+
+ // Update state, forward the old function to the new function.
+ void *Addr = getPointerToGlobalIfAvailable(F);
+ assert(Addr && "Code generation didn't add function to GlobalAddress table!");
+ TJI.replaceMachineCodeForFunction(OldAddr, Addr);
+ return Addr;
+ }
+
+ /// create - Create and return a new SparcV9 TraceJIT compiler, or 0 if
+ /// there is an error.
+ ///
+ TraceJIT *TraceJIT::create(ModuleProvider *MP, IntrinsicLowering *IL) {
+ // Allocate a SparcV9 target.
+ TargetMachine *Target = allocateSparcV9TargetMachine(*MP->getModule(), IL);
+ assert(Target && "Could not allocate target machine!");
+
+ // If the target supports TraceJIT code generation, return a new TraceJIT now.
+ if (TargetJITInfo *TJ = Target->getJITInfo())
+ return new TraceJIT(MP, *Target, *TJ);
+
+ // Fail...
+ return 0;
+ }
+
+ uint64_t TraceJIT::compileTraceFunction (TraceFunction *TF) {
+ // Pass out-of-band information to UTF.
+ UTF->setTraceFunction (TF);
+
+ // Compile & unpack the TraceFunction.
+ uint64_t traceStartAddr = (uint64_t) getPointerToFunction (TF->TraceFn);
+ assert (traceStartAddr && "Address of code for TraceFn was NULL after JIT?!");
+ return traceStartAddr;
+ }
+
Index: reopt/lib/TraceJIT/TraceJIT.h
diff -c /dev/null reopt/lib/TraceJIT/TraceJIT.h:1.1
*** /dev/null Wed May 26 16:25:23 2004
--- reopt/lib/TraceJIT/TraceJIT.h Wed May 26 16:25:13 2004
***************
*** 0 ****
--- 1,106 ----
+ //===-- TraceJIT.h - Class definition for the TraceJIT ----------*- C++ -*-===//
+ //
+ // The LLVM Compiler Infrastructure
+ //
+ // This file was developed by the LLVM research group and is distributed under
+ // the University of Illinois Open Source License. See LICENSE.TXT for details.
+ //
+ //===----------------------------------------------------------------------===//
+ //
+ // This file defines the top-level TraceJIT data structure.
+ //
+ //===----------------------------------------------------------------------===//
+
+ #ifndef TRACEJIT_H
+ #define TRACEJIT_H
+
+ #include "llvm/ExecutionEngine/ExecutionEngine.h"
+ #include "llvm/PassManager.h"
+ #include <map>
+
+ namespace llvm {
+
+ class Function;
+ class GlobalValue;
+ class Constant;
+ class TargetMachine;
+ class TargetJITInfo;
+ class MachineCodeEmitter;
+ class TraceFunction;
+ class UnpackTraceFunction;
+
+ class TraceJIT : public ExecutionEngine {
+ TargetMachine &TM; // The current target we are compiling to
+ TargetJITInfo &TJI; // The TargetJITInfo for the current target
+
+ FunctionPassManager PM; // Passes to compile a TraceFunction
+ MachineCodeEmitter *MCE; // Optimized trace code emitter
+ UnpackTraceFunction *UTF; // TraceFunction unpacker
+
+ /// PendingGlobals - Global variables which have had memory allocated for them
+ /// while a function was code generated, but which have not been initialized
+ /// yet.
+ std::vector<const GlobalVariable*> PendingGlobals;
+
+ TraceJIT(ModuleProvider *MP, TargetMachine &tm, TargetJITInfo &tji);
+ public:
+ ~TraceJIT();
+
+ /// create - Create an return a new TraceJIT compiler if there is one available
+ /// for the current target. Otherwise, return null. If the TraceJIT is created
+ /// successfully, it takes responsibility for deleting the specified
+ /// IntrinsicLowering implementation.
+ ///
+ static TraceJIT *create(ModuleProvider *MP, IntrinsicLowering *IL = 0);
+
+ /// run - Start execution with the specified function and arguments.
+ ///
+ virtual GenericValue runFunction(Function *F,
+ const std::vector<GenericValue> &ArgValues);
+
+ /// getPointerToNamedFunction - This method returns the address of the
+ /// specified function by using the dlsym function call. As such it is only
+ /// useful for resolving library symbols, not code generated symbols.
+ ///
+ void *getPointerToNamedFunction(const std::string &Name);
+
+ // CompilationCallback - Invoked the first time that a call site is found,
+ // which causes lazy compilation of the target function.
+ //
+ static void CompilationCallback();
+
+ /// getPointerToFunction - This returns the address of the specified function,
+ /// compiling it if necessary.
+ ///
+ void *getPointerToFunction(Function *F);
+
+ /// getOrEmitGlobalVariable - Return the address of the specified global
+ /// variable, possibly emitting it to memory if needed. This is used by the
+ /// Emitter.
+ void *getOrEmitGlobalVariable(const GlobalVariable *GV);
+
+ /// getPointerToFunctionOrStub - If the specified function has been
+ /// code-gen'd, return a pointer to the function. If not, compile it, or use
+ /// a stub to implement lazy compilation if available.
+ ///
+ void *getPointerToFunctionOrStub(Function *F);
+
+ /// recompileAndRelinkFunction - This method is used to force a function
+ /// which has already been compiled, to be compiled again, possibly
+ /// after it has been modified. Then the entry to the old copy is overwritten
+ /// with a branch to the new copy. If there was no old copy, this acts
+ /// just like TraceJIT::getPointerToFunction().
+ ///
+ void *recompileAndRelinkFunction(Function *F);
+
+ uint64_t compileTraceFunction (TraceFunction *TF);
+
+ MachineCodeEmitter *getEmitter() { return MCE; }
+ private:
+ void addPassesToReoptimizeTrace (FunctionPassManager &PM);
+ void runJITOnFunction (Function *F);
+ };
+
+ } // End llvm namespace
+
+ #endif
Index: reopt/lib/TraceJIT/TraceJITEmitter.cpp
diff -c /dev/null reopt/lib/TraceJIT/TraceJITEmitter.cpp:1.1
*** /dev/null Wed May 26 16:25:23 2004
--- reopt/lib/TraceJIT/TraceJITEmitter.cpp Wed May 26 16:25:13 2004
***************
*** 0 ****
--- 1,212 ----
+ //===-- TraceJITEmitter.cpp - Write machine code to executable memory -----===//
+ //
+ // The LLVM Compiler Infrastructure
+ //
+ // This file was developed by the LLVM research group and is distributed under
+ // the University of Illinois Open Source License. See LICENSE.TXT for details.
+ //
+ //===----------------------------------------------------------------------===//
+ //
+ // The trace reoptimizer uses this MachineCodeEmitter to output
+ // optimized machine code to memory, so that it can be executed instead of
+ // the corresponding unoptimized code.
+ //
+ // Currently, it uses the same executable memory segment that the
+ // TraceCache would use, but the TraceCache is unaware of it, so they can
+ // not be used together.
+ //
+ //===----------------------------------------------------------------------===//
+
+ #include "TraceJIT.h"
+ #include "reopt/ScratchMemory.h"
+ #include "reopt/VirtualMem.h"
+ #include "reopt/InstrUtils.h"
+ #include "../LightWtProfiling/ReoptimizerInternal.h"
+ #include "llvm/Constant.h"
+ #include "llvm/Module.h"
+ #include "llvm/CodeGen/MachineCodeEmitter.h"
+ #include "llvm/CodeGen/MachineFunction.h"
+ #include "llvm/CodeGen/MachineConstantPool.h"
+ #include "llvm/Target/TargetData.h"
+ #include "Support/Debug.h"
+ #include "Support/DynamicLinker.h"
+ using namespace llvm;
+
+ namespace {
+ /// TraceJITEmitter - The trace reoptimizer's MachineCodeEmitter,
+ /// which is used to output functions to memory for execution.
+ ///
+ class TraceJITEmitter : public MachineCodeEmitter {
+ TraceJIT *TheJIT;
+
+ // CurBlock - The start of the current block of memory. CurByte - The
+ // current byte being emitted to.
+ uint64_t CurBlock, CurByte;
+ uint64_t FunctionBase, CurFunctionPtr;
+
+ // ConstantPoolAddresses - Contains the location for each entry in the
+ // constant pool.
+ std::vector<void*> ConstantPoolAddresses;
+ public:
+ TraceJITEmitter (TraceJIT *JIT_) : TheJIT (JIT_) {
+ // Re-use the existing DummyFunction area for code emission in the
+ // Reoptimizer. No memory is reserved for stubs.
+ FunctionBase = (uint64_t) OptimizedTraceTextArea;
+ // Allocate functions forward from the function base.
+ CurFunctionPtr = FunctionBase;
+ }
+
+ virtual void startFunction(MachineFunction &F);
+ virtual void finishFunction(MachineFunction &F);
+ virtual void emitConstantPool(MachineConstantPool *MCP);
+ virtual void startFunctionStub(const Function &F, unsigned StubSize) {
+ abort ();
+ }
+ virtual void* finishFunctionStub(const Function &F) {
+ abort ();
+ }
+ virtual void emitByte(unsigned char B);
+ virtual void emitWord(unsigned W);
+ virtual void emitWordAt(unsigned W, unsigned *Ptr);
+
+ virtual uint64_t getGlobalValueAddress(GlobalValue *V);
+ virtual uint64_t getGlobalValueAddress(const std::string &Name);
+ virtual uint64_t getConstantPoolEntryAddress(unsigned Entry);
+ virtual uint64_t getCurrentPCValue();
+
+ // forceCompilationOf - Force the compilation of the specified function, and
+ // return its address, because we REALLY need the address now.
+ //
+ // FIXME: This is JIT specific!
+ //
+ virtual uint64_t forceCompilationOf(Function *F);
+ };
+ } // end anonymous namespace
+
+ namespace llvm {
+
+ MachineCodeEmitter *createTraceJITEmitter(TraceJIT *JIT) {
+ return new TraceJITEmitter(JIT);
+ }
+
+ } // end namespace llvm
+
+ void TraceJITEmitter::startFunction(MachineFunction &F) {
+ // Round up to a 64-bit word boundary.
+ CurBlock = (CurFunctionPtr + 7) & ~7;
+ CurByte = CurBlock;
+
+ // Remember where we started generating this function.
+ TheJIT->addGlobalMapping(F.getFunction(), (void*)CurBlock);
+ }
+
+ void TraceJITEmitter::finishFunction(MachineFunction &F) {
+ assert(CurByte > CurFunctionPtr);
+ CurFunctionPtr = CurByte;
+
+ ConstantPoolAddresses.clear();
+
+ DEBUG(std::cerr << "Finished CodeGen of [" << (void*)CurBlock
+ << "] Function: " << F.getFunction()->getName()
+ << ": " << CurByte-CurBlock << " bytes of text\n");
+ }
+
+ void TraceJITEmitter::emitConstantPool(MachineConstantPool *MCP) {
+ const std::vector<Constant*> &Constants = MCP->getConstants();
+ if (Constants.empty()) return;
+
+ std::vector<unsigned> ConstantOffset;
+ ConstantOffset.reserve(Constants.size());
+
+ // Calculate how much space we will need for all the constants, and the offset
+ // each one will live in.
+ unsigned TotalSize = 0;
+ for (unsigned i = 0, e = Constants.size(); i != e; ++i) {
+ const Type *Ty = Constants[i]->getType();
+ unsigned Size = TheJIT->getTargetData().getTypeSize(Ty);
+ unsigned Alignment = TheJIT->getTargetData().getTypeAlignment(Ty);
+ // Make sure to take into account the alignment requirements of the type.
+ TotalSize = (TotalSize + Alignment-1) & ~(Alignment-1);
+
+ // Remember the offset this element lives at.
+ ConstantOffset.push_back(TotalSize);
+ TotalSize += Size; // Reserve space for the constant.
+ }
+
+ // Now that we know how much memory to allocate, do so.
+ char *Pool = new char[TotalSize];
+
+ // Actually output all of the constants, and remember their addresses.
+ for (unsigned i = 0, e = Constants.size(); i != e; ++i) {
+ void *Addr = Pool + ConstantOffset[i];
+ TheJIT->InitializeMemory(Constants[i], Addr);
+ ConstantPoolAddresses.push_back(Addr);
+ }
+ }
+
+ void TraceJITEmitter::emitByte(unsigned char B) {
+ std::cerr << "TraceJITEmitter: attempt to emit a single byte: 0x"
+ << std::hex << (unsigned)B << std::dec << " at cursor: "
+ << CurByte << "\n";
+ abort ();
+ // *CurByte = W;
+ ++CurByte;
+ }
+
+ void TraceJITEmitter::emitWord(unsigned W) {
+ // This won't work if the endianness of the host and target don't agree! (For
+ // a JIT this can't happen though. :)
+ DEBUG (std::cerr << "TraceJITEmitter: emitting word 0x" << std::hex << W
+ << " at cursor: " << CurByte << std::dec << "\n");
+ vm->writeInstToVM (CurByte, W); // does: *(unsigned*)CurByte = W;
+ doFlush (CurByte - sizeof (unsigned), (uint64_t) CurByte + sizeof (unsigned));
+ CurByte += sizeof(unsigned);
+ }
+
+ void TraceJITEmitter::emitWordAt(unsigned W, unsigned *Ptr) {
+ DEBUG (std::cerr << "TraceJITEmitter: emitting word 0x" << std::hex << W
+ << std::dec << " at pointer: " << Ptr << "\n");
+ vm->writeInstToVM ((uint64_t) Ptr, W); // does: *Ptr = W;
+ doFlush ((uint64_t) Ptr - sizeof (unsigned),
+ (uint64_t) Ptr + sizeof (unsigned));
+ }
+
+ uint64_t TraceJITEmitter::getGlobalValueAddress(GlobalValue *V) {
+ // Try looking up the function to see if it is already compiled, if not return
+ // 0.
+ if (isa<Function>(V)) {
+ if (V->hasName ()) {
+ uint64_t where = (uint64_t) GetAddressOfSymbol (V->getName ());
+ if (where)
+ return where;
+ }
+ return (uint64_t)TheJIT->getPointerToGlobalIfAvailable(V);
+ } else {
+ return (uint64_t)TheJIT->getOrEmitGlobalVariable(cast<GlobalVariable>(V));
+ }
+ }
+
+ uint64_t TraceJITEmitter::getGlobalValueAddress(const std::string &Name) {
+ return (uint64_t)TheJIT->getPointerToNamedFunction(Name);
+ }
+
+ // getConstantPoolEntryAddress - Return the address of the 'ConstantNum' entry
+ // in the constant pool that was last emitted with the 'emitConstantPool'
+ // method.
+ //
+ uint64_t TraceJITEmitter::getConstantPoolEntryAddress(unsigned ConstantNum) {
+ assert(ConstantNum < ConstantPoolAddresses.size() &&
+ "Invalid ConstantPoolIndex!");
+ return (uint64_t)ConstantPoolAddresses[ConstantNum];
+ }
+
+ // getCurrentPCValue - This returns the address that the next emitted byte
+ // will be output to.
+ //
+ uint64_t TraceJITEmitter::getCurrentPCValue() {
+ return CurByte;
+ }
+
+ uint64_t TraceJITEmitter::forceCompilationOf(Function *F) {
+ return (uint64_t)TheJIT->getPointerToFunction(F);
+ }
Index: reopt/lib/TraceJIT/TraceJITIntercept.cpp
diff -c /dev/null reopt/lib/TraceJIT/TraceJITIntercept.cpp:1.1
*** /dev/null Wed May 26 16:25:23 2004
--- reopt/lib/TraceJIT/TraceJITIntercept.cpp Wed May 26 16:25:13 2004
***************
*** 0 ****
--- 1,91 ----
+ //===-- Intercept.cpp - System function interception routines -------------===//
+ //
+ // The LLVM Compiler Infrastructure
+ //
+ // This file was developed by the LLVM research group and is distributed under
+ // the University of Illinois Open Source License. See LICENSE.TXT for details.
+ //
+ //===----------------------------------------------------------------------===//
+ //
+ // If a function call occurs to an external function, the TraceJIT is designed to use
+ // the dynamic loader interface to find a function to call. This is useful for
+ // calling system calls and library functions that are not available in LLVM.
+ // Some system calls, however, need to be handled specially. For this reason,
+ // we intercept some of them here and use our own stubs to handle them.
+ //
+ //===----------------------------------------------------------------------===//
+
+ #include "TraceJIT.h"
+ #include "Support/DynamicLinker.h"
+ #include <iostream>
+ #include <sys/stat.h>
+ using namespace llvm;
+
+ // AtExitHandlers - List of functions to call when the program exits,
+ // registered with the atexit() library function.
+ static std::vector<void (*)()> AtExitHandlers;
+
+ /// runAtExitHandlers - Run any functions registered by the program's
+ /// calls to atexit(3), which we intercept and store in
+ /// AtExitHandlers.
+ ///
+ static void runAtExitHandlers() {
+ while (!AtExitHandlers.empty()) {
+ void (*Fn)() = AtExitHandlers.back();
+ AtExitHandlers.pop_back();
+ Fn();
+ }
+ }
+
+ //===----------------------------------------------------------------------===//
+ // Function stubs that are invoked instead of certain library calls
+ //===----------------------------------------------------------------------===//
+
+ // Force the following functions to be linked in to anything that uses the
+ // TraceJIT. This is a hack designed to work around the all-too-clever Glibc
+ // strategy of making these functions work differently when inlined vs. when
+ // not inlined, and hiding their real definitions in a separate archive file
+ // that the dynamic linker can't see. For more info, search for
+ // 'libc_nonshared.a' on Google, or read http://llvm.cs.uiuc.edu/PR274.
+ #if defined(__linux__)
+ void *FunctionPointers[] = {
+ (void *) stat,
+ (void *) fstat,
+ (void *) lstat,
+ (void *) stat64,
+ (void *) fstat64,
+ (void *) lstat64,
+ (void *) atexit,
+ (void *) mknod
+ };
+ #endif // __linux__
+
+ // NoopFn - Used if we have nothing else to call...
+ static void NoopFn() {}
+
+ // jit_exit - Used to intercept the "exit" library call.
+ static void jit_exit(int Status) {
+ runAtExitHandlers(); // Run atexit handlers...
+ exit(Status);
+ }
+
+ // jit_atexit - Used to intercept the "atexit" library call.
+ static int jit_atexit(void (*Fn)(void)) {
+ AtExitHandlers.push_back(Fn); // Take note of atexit handler...
+ return 0; // Always successful
+ }
+
+ //===----------------------------------------------------------------------===//
+ //
+ /// getPointerToNamedFunction - This method returns the address of the specified
+ /// function by using the dynamic loader interface. As such it is only useful
+ /// for resolving library symbols, not code generated symbols.
+ ///
+ void *TraceJIT::getPointerToNamedFunction(const std::string &Name) {
+ // Check to see if this is one of the functions we want to intercept...
+ if (Name == "exit") return (void*)&jit_exit;
+ if (Name == "atexit") return (void*)&jit_atexit;
+
+ // Try to look it up in the process image.
+ return GetAddressOfSymbol(Name);
+ }
More information about the llvm-commits
mailing list