llvmpy/newbinding/include/llvm_binding/extra.h

580 lines
16 KiB
C++

#include <Python.h>
#include <llvm/ADT/SmallVector.h>
#include <llvm/Value.h>
#include <llvm/DerivedTypes.h>
#include <llvm/Function.h>
#include <llvm/Support/raw_ostream.h>
#include <llvm/Support/FormattedStream.h>
#include <llvm/Support/MemoryBuffer.h>
#include <llvm/Bitcode/ReaderWriter.h>
#include <llvm/ExecutionEngine/ExecutionEngine.h>
#include <llvm/ExecutionEngine/GenericValue.h>
#include <llvm/Linker.h>
#include <llvm/Module.h>
#include "auto_pyobject.h"
namespace extra{
using namespace llvm;
class raw_svector_ostream_helper: public raw_svector_ostream {
SmallVectorImpl<char> *SV;
public:
static
raw_svector_ostream_helper* create()
{
SmallVectorImpl<char>* sv = new SmallVector<char, 16>();
return new raw_svector_ostream_helper(sv);
}
~raw_svector_ostream_helper()
{
delete SV;
}
protected:
explicit
raw_svector_ostream_helper(SmallVectorImpl<char>* sv)
: raw_svector_ostream(*sv), SV(sv) {}
private:
// no copy
raw_svector_ostream_helper(const raw_svector_ostream_helper&);
// no assign
void operator = (const raw_svector_ostream_helper&);
};
}
static
PyObject* make_raw_ostream_for_printing(PyObject* self, PyObject* args)
{
using extra::raw_svector_ostream_helper;
using llvm::raw_svector_ostream;
if (!PyArg_ParseTuple(args, "")) {
return NULL;
}
raw_svector_ostream* RSOH = raw_svector_ostream_helper::create();
return pycapsule_new(RSOH, "llvm::raw_ostream",
"llvm::raw_svector_ostream");
}
static
PyObject* make_small_vector_from_types(PyObject* self, PyObject* args)
{
using llvm::Type;
typedef llvm::SmallVector<llvm::Type*, 8> SmallVector_Type;
SmallVector_Type* SV = new SmallVector_Type;
Py_ssize_t size = PyTuple_Size(args);
for (Py_ssize_t i = 0; i < size; ++i) {
PyObject* cap = PyTuple_GetItem(args, i);
if (!cap) {
return NULL;
}
Type* type = (Type*)PyCapsule_GetPointer(cap, "llvm::Type");
if (!type) {
return NULL;
}
SV->push_back(type);
}
return pycapsule_new(SV, "llvm::SmallVector<llvm::Type*,8>");
}
static
PyObject* make_small_vector_from_values(PyObject* self, PyObject* args)
{
using llvm::Value;
typedef llvm::SmallVector<llvm::Value*, 8> SmallVector_Value;
SmallVector_Value* SV = new SmallVector_Value;
Py_ssize_t size = PyTuple_Size(args);
for (Py_ssize_t i = 0; i < size; ++i) {
PyObject* cap = PyTuple_GetItem(args, i);
if (!cap) {
return NULL;
}
Value* value = (Value*)PyCapsule_GetPointer(cap, "llvm::Value");
if (!value) {
return NULL;
}
SV->push_back(value);
}
return pycapsule_new(SV, "llvm::SmallVector<llvm::Value*,8>");
}
static
PyObject* make_small_vector_from_unsigned(PyObject* self, PyObject* args)
{
using llvm::Value;
typedef llvm::SmallVector<unsigned, 8> SmallVector_Unsigned;
SmallVector_Unsigned* SV = new SmallVector_Unsigned;
Py_ssize_t size = PyTuple_Size(args);
for (Py_ssize_t i = 0; i < size; ++i) {
PyObject* item = PyTuple_GetItem(args, i);
if (!item) {
return NULL;
}
unsigned value = PyLong_AsUnsignedLong(item);
if (PyErr_Occurred()){
return NULL;
}
SV->push_back(value);
}
return pycapsule_new(SV, "llvm::SmallVector<unsigned,8>");
}
static PyMethodDef extra_methodtable[] = {
#define method(func) { #func, (PyCFunction)func, METH_VARARGS, NULL }
method( make_raw_ostream_for_printing ),
method( make_small_vector_from_types ),
method( make_small_vector_from_values ),
method( make_small_vector_from_unsigned ),
#undef method
{ NULL }
};
////////////
template<class iterator>
PyObject* iterator_to_pylist_deref(iterator begin, iterator end,
const char *capsuleName, const char *className)
{
PyObject* list = PyList_New(0);
for(; begin != end; ++begin) {
PyObject* cap = pycapsule_new(&*begin, capsuleName, className);
PyList_Append(list, cap);
}
return list;
}
template<class iterator>
PyObject* iterator_to_pylist(iterator begin, iterator end,
const char *capsuleName, const char *className)
{
PyObject* list = PyList_New(0);
for(; begin != end; ++begin) {
PyObject* cap = pycapsule_new(*begin, capsuleName, className);
PyList_Append(list, cap);
}
return list;
}
template<class iplist>
PyObject* iplist_to_pylist(iplist &IPL, const char * capsuleName,
const char* className){
return iterator_to_pylist_deref(IPL.begin(), IPL.end(), capsuleName,
className);
}
//static
//bool string_equal(const char *A, const char *B){
// for (; *A and *B; ++A, ++B) {
// if (*A != *B) return false;
// }
// return true;
//}
////////////
static
PyObject* Value_use_iterator_to_list(llvm::Value* val)
{
return iterator_to_pylist(val->use_begin(), val->use_end(),
"llvm::Value", "llvm::User");
}
static
PyObject* Function_getArgumentList(llvm::Function* fn)
{
return iplist_to_pylist(fn->getArgumentList(), "llvm::Value",
"llvm::Argument");
}
static
PyObject* Function_getBasicBlockList(llvm::Function* fn)
{
return iplist_to_pylist(fn->getBasicBlockList(), "llvm::Value",
"llvm::BasicBlock");
}
/*
* errout --- can be any file object
*
*/
static
llvm::ExecutionEngine* ExecutionEngine_create(
llvm::Module* M,
bool ForceInterpreter = false,
PyObject* errout = 0,
llvm::CodeGenOpt::Level OptLevel = llvm::CodeGenOpt::Default,
bool GVsWithCode = true)
{
using namespace llvm;
std::string ErrorStr;
ExecutionEngine *ee = ExecutionEngine::create(M, ForceInterpreter,
&ErrorStr, OptLevel,
GVsWithCode);
PyFile_WriteString(ErrorStr.c_str(), errout);
return ee;
}
/*
* errout --- can be any file object
*
*/
static
llvm::ExecutionEngine* ExecutionEngine_createJIT(
llvm::Module* M,
PyObject* errout = 0,
llvm::JITMemoryManager* JMM = 0,
llvm::CodeGenOpt::Level OL = llvm::CodeGenOpt::Default,
bool GCsWithCode = true,
llvm::Reloc::Model RM = llvm::Reloc::Default,
llvm::CodeModel::Model CMM = llvm::CodeModel::JITDefault)
{
using namespace llvm;
std::string ErrorStr;
ExecutionEngine *ee = ExecutionEngine::createJIT(M, &ErrorStr, JMM, OL,
GCsWithCode, RM, CMM);
PyFile_WriteString(ErrorStr.c_str(), errout);
return ee;
}
static
llvm::GenericValue* GenericValue_CreateInt(llvm::Type* Ty, unsigned long long N,
bool IsSigned)
{
// Shamelessly copied from LLVM
llvm::GenericValue *GenVal = new llvm::GenericValue();
GenVal->IntVal = llvm::APInt(Ty->getIntegerBitWidth(), N, IsSigned);
return GenVal;
}
static
llvm::GenericValue* GenericValue_CreateFloat(float Val)
{
llvm::GenericValue *GenVal = new llvm::GenericValue();
GenVal->FloatVal = Val;
return GenVal;
}
static
llvm::GenericValue* GenericValue_CreateDouble(double Val)
{
llvm::GenericValue *GenVal = new llvm::GenericValue();
GenVal->DoubleVal = Val;
return GenVal;
}
static
llvm::GenericValue* GenericValue_CreatePointer(void * Ptr)
{
llvm::GenericValue *GenVal = new llvm::GenericValue();
GenVal->PointerVal = Ptr;
return GenVal;
}
static
unsigned GenericValue_ValueIntWidth(llvm::GenericValue *GenValRef)
{
return GenValRef->IntVal.getBitWidth();
}
static
unsigned long long GenericValue_ToUnsignedInt(llvm::GenericValue* GenVal)
{
return GenVal->IntVal.getZExtValue();
}
static
long long GenericValue_ToSignedInt(llvm::GenericValue* GenVal)
{
return GenVal->IntVal.getSExtValue();
}
static
void* GenericValue_ToPointer(llvm::GenericValue* GenVal)
{
return GenVal->PointerVal;
}
static
double GenericValue_ToFloat(llvm::GenericValue* GenVal, llvm::Type* Ty)
{
switch (Ty->getTypeID()) {
case llvm::Type::FloatTyID:
return GenVal->FloatVal;
default:
// Behavior undefined if type is not a float or a double
return GenVal->DoubleVal;
}
}
static
PyObject* ExecutionEngine_RunFunction(llvm::ExecutionEngine* EE,
llvm::Function* Fn, PyObject* Args)
{
using namespace llvm;
const char * GVN = "llvm::GenericValue";
if (!PyTuple_Check(Args)) {
PyErr_SetString(PyExc_TypeError, "Expect a tuple of args.");
return NULL;
}
std::vector<GenericValue> vec_args;
Py_ssize_t nargs = PyTuple_Size(Args);
vec_args.reserve(nargs);
for (Py_ssize_t i = 0; i < nargs; ++i) {
PyObject* obj = PyTuple_GetItem(Args, i);
if (!obj) {
PyErr_SetString(PyExc_RuntimeError, "Failed to index into args?");
return NULL;
}
GenericValue* gv = static_cast<GenericValue*>(
PyCapsule_GetPointer(obj, GVN));
if (!gv) {
return NULL;
}
vec_args.push_back(*gv);
}
GenericValue ret = EE->runFunction(Fn, vec_args);
return pycapsule_new(new GenericValue(ret), GVN);
}
static
PyObject* EngineBuilder_setErrorStr(llvm::EngineBuilder* eb, PyObject* fileobj)
{
if (!PyFile_Check(fileobj)) {
PyErr_SetString(PyExc_TypeError, "Expecting a file object.");
return NULL;
}
std::string buffer;
eb->setErrorStr(&buffer);
if (-1 == PyFile_WriteString(buffer.c_str(), fileobj)) {
return NULL;
}
return pycapsule_new(eb, "llvm::EngineBuilder");
}
static
PyObject* EngineBuilder_setMAttrs(llvm::EngineBuilder* eb,
PyObject* strlist)
{
if (!PyList_Check(strlist)) {
PyErr_SetString(PyExc_TypeError, "Expecting a list of string.");
return NULL;
}
std::vector<const char*> tmp;
const Py_ssize_t N = PyList_Size(strlist);
tmp.reserve(N);
for (Py_ssize_t i = 0; i < N; ++i) {
const char * elem = PyString_AsString(PyList_GetItem(strlist, i));
if (!elem) {
return NULL;
}
tmp.push_back(elem);
}
eb->setMAttrs(tmp);
return pycapsule_new(eb, "llvm::EngineBuilder");
}
static
PyObject* EngineBuilder_selectTarget(llvm::EngineBuilder* eb,
const llvm::Triple& TargetTriple,
llvm::StringRef MArch,
llvm::StringRef MCPU,
PyObject* strlist)
{
const Py_ssize_t N = PySequence_Size(strlist);
llvm::SmallVector<std::string, 8> MAttrs;
MAttrs.reserve(N);
for (Py_ssize_t i = 0; i < N; ++i) {
PyObject* str = PySequence_GetItem(strlist, i);
const char * cp = PyString_AsString(str);
if (!cp) {
Py_DECREF(str);
return NULL;
}
MAttrs.push_back(cp);
Py_DECREF(str);
}
eb->selectTarget(TargetTriple, MArch, MCPU, MAttrs);
return pycapsule_new(eb, "llvm::EngineBuilder");
}
static
PyObject* llvm_ParseBitCodeFile(llvm::StringRef Buf, llvm::LLVMContext& Ctx,
PyObject* FObj=NULL)
{
using namespace llvm;
MemoryBuffer* MB = MemoryBuffer::getMemBuffer(Buf);
Module* M;
if (FObj) {
std::string ErrStr;
M = ParseBitcodeFile(MB, Ctx, &ErrStr);
if (-1 == PyFile_WriteString(ErrStr.c_str(), FObj)) {
return NULL;
}
} else {
M = ParseBitcodeFile(MB, Ctx);
}
delete MB;
return pycapsule_new(M, "llvm::Module");
}
static
PyObject* llvm_WriteBitcodeToFile(const llvm::Module *M, PyObject* FObj)
{
using namespace llvm;
llvm::SmallVector<char, 32> sv;
llvm::raw_svector_ostream rso(sv);
llvm::WriteBitcodeToFile(M, rso);
rso.flush();
StringRef ref = rso.str();
PyObject* buf = PyString_FromStringAndSize(ref.data(), ref.size());
if (-1 == PyFile_WriteObject(buf, FObj, Py_PRINT_RAW)){
return NULL;
}
Py_RETURN_NONE;
}
static
PyObject* llvm_getBitcodeTargetTriple(llvm::StringRef Buf,
llvm::LLVMContext& Ctx,
PyObject* FObj = NULL)
{
using namespace llvm;
MemoryBuffer* MB = MemoryBuffer::getMemBuffer(Buf);
std::string Triple;
if (FObj) {
std::string ErrStr;
Triple = getBitcodeTargetTriple(MB, Ctx, &ErrStr);
if (-1 == PyFile_WriteString(ErrStr.c_str(), FObj)) {
return NULL;
}
} else {
Triple = getBitcodeTargetTriple(MB, Ctx);
}
delete MB;
return PyString_FromString(Triple.c_str());
}
static
PyObject* TargetMachine_addPassesToEmitFile(
llvm::TargetMachine *TM,
llvm::PassManagerBase & PM,
PyObject* Out,
llvm::TargetMachine::CodeGenFileType FTy,
bool disableVerify=true)
{
using namespace llvm;
llvm::SmallVector<char, 32> sv;
raw_svector_ostream rso(sv);
formatted_raw_ostream fso(rso);
fso.flush();
bool status = TM->addPassesToEmitFile(PM, fso, FTy, disableVerify);
if (status) {
StringRef sr = rso.str();
PyObject* buf = PyString_FromStringAndSize(sr.data(), sr.size());
if (!buf) {
return NULL;
}
if ( -1 == PyFile_WriteObject(buf, Out, Py_PRINT_RAW) ){
return NULL;
}
Py_RETURN_TRUE;
} else {
Py_RETURN_FALSE;
}
}
static
PyObject* Linker_LinkInModule(llvm::Linker* Linker,
llvm::Module* Mod,
PyObject* ErrMsg)
{
std::string errmsg;
bool failed = Linker->LinkInModule(Mod, &errmsg);
if (not failed) {
Py_RETURN_FALSE;
} else {
if (-1 == PyFile_WriteString(errmsg.c_str(), ErrMsg)) {
return NULL;
}
Py_RETURN_TRUE;
}
}
static
PyObject* Linker_LinkModules(llvm::Module* Dest,
llvm::Module* Src,
unsigned Mode,
PyObject* ErrMsg)
{
std::string errmsg;
bool failed = llvm::Linker::LinkModules(Dest, Src, Mode, &errmsg);
if (not failed) {
Py_RETURN_FALSE;
} else {
if (-1 == PyFile_WriteString(errmsg.c_str(), ErrMsg)) {
return NULL;
}
Py_RETURN_TRUE;
}
}
static
PyObject* StructType_setBody(llvm::StructType* Self,
PyObject* Elems,
bool isPacked=false)
{
using namespace llvm;
std::vector<Type*> elements;
Py_ssize_t N = PySequence_Size(Elems);
elements.reserve(N);
for (Py_ssize_t i=0; i < N; ++i) {
auto_pyobject obj = PySequence_GetItem(Elems, i);
auto_pyobject capsule = PyObject_GetAttrString(*obj, "_ptr");
if (!capsule) {
return NULL;
}
void * ptr = PyCapsule_GetPointer(*capsule, "llvm::Type");
if (!ptr) {
return NULL;
}
Type* type = static_cast<Type*>(ptr);
elements.push_back(type);
}
Self->setBody(elements, isPacked);
Py_RETURN_NONE;
}
static
PyObject* Module_list_globals(llvm::Module* Mod)
{
return iplist_to_pylist(Mod->getGlobalList(),
"llvm::Value", "llvm::GlobalVariable");
}
static
PyObject* Module_list_functions(llvm::Module* Mod)
{
return iplist_to_pylist(Mod->getFunctionList(),
"llvm::Value", "llvm::Function");
}