PageRenderTime 22ms CodeModel.GetById 10ms app.highlight 9ms RepoModel.GetById 1ms app.codeStats 0ms

/JIT/ConstantMirror.h

http://unladen-swallow.googlecode.com/
C++ Header | 140 lines | 76 code | 23 blank | 41 comment | 1 complexity | fb7b4e4f1a9637973a20ad04238b83cd MD5 | raw file
  1// -*- C++ -*-
  2#ifndef UTIL_CONSTANTMIRROR_H
  3#define UTIL_CONSTANTMIRROR_H
  4
  5#ifndef __cplusplus
  6#error This header expects to be included only in C++ source
  7#endif
  8
  9#include "Python.h"
 10
 11#include "JIT/PyTypeBuilder.h"
 12
 13#include "llvm/ADT/DenseMap.h"
 14#include "llvm/ADT/StringRef.h"
 15#include <string>
 16
 17struct PyGlobalLlvmData;
 18
 19namespace llvm {
 20class Constant;
 21class ExecutionEngine;
 22class PointerType;
 23class GlobalValue;
 24class GlobalVariable;
 25class LLVMContext;
 26class StructType;
 27class TargetData;
 28class Type;
 29}
 30
 31// This class helps mirror constants from the runtime into LLVM
 32// ConstantStructs and GlobalVariables.  For PyObject*s, it uses the
 33// ExecutionEngine's reverse mapping (getGlobalValueAtAddress()) to
 34// cache GlobalVariables we've already mirrored and holds a python
 35// reference to each one so that it doesn't wind up pointing to freed
 36// memory or holding an out-of-date value.  We don't cache
 37// non-PyObject*s.
 38class PyConstantMirror {
 39public:
 40    // Keeps a reference to llvm_data.
 41    // llvm_data->getExecutionEngine() has to be destroyed before this
 42    // object because it causes several CallbackVHs to self-destruct,
 43    // and they access this object.
 44    PyConstantMirror(PyGlobalLlvmData *llvm_data);
 45
 46    // GetConstantFor(x) returns an llvm::Constant representing that
 47    // object.  It recursively mirrors objects the value points to
 48    // into GlobalVariables using GetGlobalVariableFor().
 49    llvm::Constant *GetConstantFor(PyObject *obj);
 50    llvm::Constant *GetConstantFor(PyCodeObject *obj);
 51    llvm::Constant *GetConstantFor(PyTypeObject *obj);
 52    llvm::Constant *GetConstantFor(PyTupleObject *obj);
 53    llvm::Constant *GetConstantFor(PyStringObject *obj);
 54    llvm::Constant *GetConstantFor(PyUnicodeObject *obj);
 55    llvm::Constant *GetConstantFor(PyIntObject *obj);
 56    llvm::Constant *GetConstantFor(PyLongObject *obj);
 57    llvm::Constant *GetConstantFor(PyFloatObject *obj);
 58    llvm::Constant *GetConstantFor(PyComplexObject *obj);
 59    llvm::Constant *GetConstantFor(PyNumberMethods *obj);
 60    llvm::Constant *GetConstantFor(PySequenceMethods *obj);
 61    llvm::Constant *GetConstantFor(PyMappingMethods *obj);
 62    llvm::Constant *GetConstantFor(PyBufferProcs *obj);
 63
 64    // GetGlobalVariableFor(obj) returns an llvm::GlobalVariable
 65    // representing that object (or the null constant for obj==NULL),
 66    // tells the ExecutionEngine about the memory that backs it, and
 67    // attaches a Constant initializer to help optimizations.  It also
 68    // increfs the object and arranges (with a CallbackVH) to decref
 69    // it when the GlobalVariable is destroyed.  We use the
 70    // ExecutionEngine's address->GlobalValue mapping to avoid
 71    // creating two GlobalVariables for the same object.
 72    llvm::Constant *GetGlobalVariableFor(PyObject *obj);
 73
 74    // Create an LLVM global variable that is backed by the given PyCFunction
 75    // function pointer.  This currently only works for METH_ARG_RANGE
 76    // functions.  Pass the maximum number of arguments the function accepts.
 77    llvm::Constant *GetGlobalForCFunction(PyCFunction cfunc_ptr,
 78                                          int arity,
 79                                          const llvm::StringRef &name);
 80
 81    // Create an LLVM global variable that is backed by the given function
 82    // pointer.
 83    template <typename T>
 84    llvm::Constant *GetGlobalForFunctionPointer(void *func_ptr,
 85                                                const llvm::StringRef &name);
 86
 87private:
 88    friend struct PyGlobalLlvmData;
 89
 90    // GetGlobalVariableForOwned() increfs 'owner' in order to keep
 91    // 'ptr' alive until the GlobalVariable is destoryed.
 92    template<typename T>
 93    llvm::Constant *GetGlobalVariableForOwned(T *ptr, PyObject *owner);
 94
 95    llvm::Constant *ConstantFromMemory(const llvm::Type *type,
 96                                       const void *memory) const;
 97
 98    llvm::StructType *ResizeVarObjectType(const llvm::StructType *type,
 99                                          unsigned dynamic_size) const;
100
101    // Create an llvm::Function with the given address, type, and name, or a
102    // NULL function pointer.
103    llvm::Constant *CreateFunctionOrNull(void *func_ptr,
104                                         const llvm::PointerType *func_ptr_type,
105                                         const llvm::StringRef &name) const;
106
107    // If LLVM knows a global value at address ptr, return it, otherwise return
108    // NULL.
109    llvm::GlobalValue *GetGlobalValueAtAddress(void *ptr) const;
110
111    // Attempted shorthand for getting the context.
112    llvm::LLVMContext &context() const;
113
114    class RemovePyObjFromGlobalMappingsVH;
115
116    PyGlobalLlvmData &llvm_data_;
117    llvm::ExecutionEngine &engine_;
118    const llvm::TargetData &target_data_;
119    /* When this is true, the RemovePyObjFromGlobalMappingsVH doesn't
120       decref PyObjects since running their finalizers could run
121       python code after all modules and the thread state are gone. */
122    bool python_shutting_down_;
123};
124
125// C++ templates require that we keep the templated part in the header.
126template<typename T> llvm::Constant *
127PyConstantMirror::GetGlobalForFunctionPointer(void *func_ptr,
128                                              const llvm::StringRef &name)
129{
130    // Reuse an existing LLVM global if we can.
131    if (llvm::GlobalValue *found = this->GetGlobalValueAtAddress(func_ptr))
132        return found;
133
134    // Otherwise, create a new LLVM global.
135    const llvm::PointerType *func_ptr_type =
136        PyTypeBuilder<T>::get(this->context());
137    return this->CreateFunctionOrNull(func_ptr, func_ptr_type, name);
138}
139
140#endif  // UTIL_CONSTANTMIRROR_H