diff --git a/llvmpy/.gitignore b/llvmpy/.gitignore new file mode 100644 index 0000000..ab608aa --- /dev/null +++ b/llvmpy/.gitignore @@ -0,0 +1,4 @@ +api.cpp +api/*.py +api/*/*.py + diff --git a/llvmpy/capsule.py b/llvmpy/capsule.py index d98a23d..7a7ceaf 100644 --- a/llvmpy/capsule.py +++ b/llvmpy/capsule.py @@ -102,6 +102,13 @@ def release_ownership(old): _addr2dtor[addr] = None +def obtain_ownership(cap): + cls = cap.get_class() + if cls._has_dtor(): + addr = cap.pointer + assert _addr2dtor[addr] is None + _addr2dtor[addr] = cls._delete_ + def has_ownership(cap): addr = Capsule.getPointer(cap) return _addr2dtor.get(addr) is not None diff --git a/llvmpy/include/llvm_binding/auto_pyobject.h b/llvmpy/include/llvm_binding/auto_pyobject.h index 451f2d9..368e64f 100644 --- a/llvmpy/include/llvm_binding/auto_pyobject.h +++ b/llvmpy/include/llvm_binding/auto_pyobject.h @@ -34,5 +34,4 @@ private: void operator = (const auto_pyobject&); }; -#endif AUTO_PYOBJECT_H_ - +#endif // AUTO_PYOBJECT_H_ diff --git a/llvmpy/include/llvm_binding/extra.h b/llvmpy/include/llvm_binding/extra.h index 438f52c..2bbad42 100644 --- a/llvmpy/include/llvm_binding/extra.h +++ b/llvmpy/include/llvm_binding/extra.h @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -16,6 +17,9 @@ #include #include #include +#include +#include + #include "auto_pyobject.h" @@ -774,3 +778,96 @@ PyObject* DynamicLibrary_LoadLibraryPermanently(const char * Filename, } } +class PassRegistryEnumerator : public llvm::PassRegistrationListener{ +public: + PyObject* List; +public: + PassRegistryEnumerator(PyObject* list) : List(list) { } + + inline virtual void passEnumerate(const llvm::PassInfo * pass_info){ + PyObject* passArg = PyString_FromString(pass_info->getPassArgument()); + PyObject* passName = PyString_FromString(pass_info->getPassName()); + PyList_Append(List, Py_BuildValue("(OO)", passArg, passName)); + } +}; + +static +PyObject* PassRegistry_enumerate(llvm::PassRegistry* PR) +{ + using namespace llvm; + PassRegistryEnumerator PRE(PyList_New(0)); + PR->enumerateWith(&PRE); + return PRE.List; +} + +static +PyObject* TargetRegistry_lookupTarget(const std::string &Triple, + PyObject* Error) +{ + using namespace llvm; + std::string error; + const Target* target = TargetRegistry::lookupTarget(Triple, error); + if (!target) { + PyFile_WriteString(error.c_str(), Error); + Py_RETURN_NONE; + } else { + return pycapsule_new(const_cast(target), "llvm::Target"); + } +} + + +static +PyObject* TargetRegistry_lookupTarget(const std::string &Arch, + llvm::Triple &Triple, + PyObject* Error) +{ + using namespace llvm; + std::string error; + const Target* target = TargetRegistry::lookupTarget(Arch, Triple, error); + if (!target) { + PyFile_WriteString(error.c_str(), Error); + Py_RETURN_NONE; + } else { + return pycapsule_new(const_cast(target), "llvm::Target"); + } +} + + +static +PyObject* TargetRegistry_getClosestTargetForJIT(PyObject* Error) +{ + using namespace llvm; + std::string error; + const Target* target = TargetRegistry::getClosestTargetForJIT(error); + if (!target) { + PyFile_WriteString(error.c_str(), Error); + Py_RETURN_NONE; + } else { + return pycapsule_new(const_cast(target), "llvm::Target"); + } + +} + +static +PyObject* llvm_sys_getHostCPUFeatures(PyObject* Features) +{ + using namespace llvm::sys; + using namespace llvm; + typedef StringMap::iterator iterator; + StringMap features; + bool ok = getHostCPUFeatures(features); + if (ok) { + for (iterator it = features.begin(); it != features.end(); ++it) { + const char *key = it->getKey().data(); + PyObject *val = it->getValue() ? Py_True : Py_False; + Py_INCREF(val); + if (-1 == PyDict_SetItemString(Features, key, val)) { + return NULL; + } + } + Py_RETURN_TRUE; + } else { + Py_RETURN_FALSE; + } +} + diff --git a/llvmpy/src/Analysis/Verifier.py b/llvmpy/src/Analysis/Verifier.py index 5b47740..3afa075 100644 --- a/llvmpy/src/Analysis/Verifier.py +++ b/llvmpy/src/Analysis/Verifier.py @@ -1,7 +1,7 @@ from binding import * from ..namespace import llvm from ..Module import Module -from ..Function import Function +from ..Value import Function llvm.includes.add('llvm/Analysis/Verifier.h') diff --git a/llvmpy/src/DataLayout.py b/llvmpy/src/DataLayout.py index d704723..9582d53 100644 --- a/llvmpy/src/DataLayout.py +++ b/llvmpy/src/DataLayout.py @@ -1,15 +1,17 @@ from binding import * from namespace import llvm +from Pass import ImmutablePass + +DataLayout = llvm.Class(ImmutablePass) +StructLayout = llvm.Class() + from LLVMContext import LLVMContext from ADT.StringRef import StringRef from Module import Module from Type import Type, IntegerType, StructType from ADT.SmallVector import SmallVector_Value from GlobalVariable import GlobalVariable -from Pass import ImmutablePass -DataLayout = llvm.Class(ImmutablePass) -StructLayout = llvm.Class() @DataLayout class DataLayout: @@ -93,4 +95,9 @@ class DataLayout: @StructLayout class StructLayout: - pass + getSizeInBytes = Method(cast(Uint64, int)) + getSizeInBits = Method(cast(Uint64, int)) + getAlignment = Method(cast(Unsigned, int)) + getElementContainingOffset = Method(cast(Unsigned, int), cast(int, Uint64)) + getElementOffset = Method(cast(Uint64, int), cast(int, Unsigned)) + getElementOffsetInBits = Method(cast(Uint64, int), cast(int, Unsigned)) diff --git a/llvmpy/src/ExecutionEngine/ExecutionEngine.py b/llvmpy/src/ExecutionEngine/ExecutionEngine.py index 1188de3..0bd4714 100644 --- a/llvmpy/src/ExecutionEngine/ExecutionEngine.py +++ b/llvmpy/src/ExecutionEngine/ExecutionEngine.py @@ -34,16 +34,25 @@ class ExecutionEngine: Reloc.Model, CodeModel.Model).require_only(1) - addModule = Method(Void, ptr(Module)) + addModule = Method(Void, ownedptr(Module)) getDataLayout = Method(const(ownedptr(DataLayout))) - removeModule = Method(cast(Bool, bool), ptr(Module)) + _removeModule = Method(cast(Bool, bool), ptr(Module)) + _removeModule.realname = 'removeModule' + @CustomPythonMethod + def removeModule(self, module): + if self._removeModule(module): + capsule.obtain_ownership(module._ptr) + return True + return False FindFunctionNamed = Method(ptr(Function), cast(str, ConstCharPtr)) getPointerToNamedFunction = Method(cast(VoidPtr, int), cast(str, StdString), cast(bool, Bool)).require_only(1) - runStaticConstructorsDestructors = Method(Void, cast(Bool, bool)) + runStaticConstructorsDestructors = Method(Void, + cast(Bool, bool), # is dtor + ) runStaticConstructorsDestructors |= Method(Void, ptr(Module), cast(Bool, bool)) diff --git a/llvmpy/src/GlobalVariable.py b/llvmpy/src/GlobalVariable.py index 4ee91fb..2280e24 100644 --- a/llvmpy/src/GlobalVariable.py +++ b/llvmpy/src/GlobalVariable.py @@ -4,10 +4,10 @@ from namespace import llvm from GlobalValue import GlobalValue GlobalVariable = llvm.Class(GlobalValue) -from Constant import Constant from Module import Module from Type import Type from ADT.StringRef import StringRef +from Value import Constant @GlobalVariable class GlobalVariable: diff --git a/llvmpy/src/Instruction.py b/llvmpy/src/Instruction.py index ca64072..b3fa701 100644 --- a/llvmpy/src/Instruction.py +++ b/llvmpy/src/Instruction.py @@ -1,11 +1,6 @@ from binding import * from namespace import llvm from Value import Value, MDNode, User, BasicBlock, Function -from ADT.StringRef import StringRef -from CallingConv import CallingConv -from Attributes import Attributes -from Constant import ConstantInt -from Type import Type Instruction = llvm.Class(User) @@ -68,6 +63,13 @@ SynchronizationScope = llvm.Enum('SynchronizationScope', +from ADT.StringRef import StringRef +from CallingConv import CallingConv +from Attributes import Attributes +from Constant import ConstantInt +from Type import Type + + @Instruction class Instruction: diff --git a/llvmpy/src/Pass.py b/llvmpy/src/Pass.py index 39e894b..f36856c 100644 --- a/llvmpy/src/Pass.py +++ b/llvmpy/src/Pass.py @@ -1,14 +1,14 @@ from binding import * from namespace import llvm -from ADT.StringRef import StringRef -from Module import Module -from Function import Function Pass = llvm.Class() ModulePass = llvm.Class(Pass) FunctionPass = llvm.Class(Pass) ImmutablePass = llvm.Class(ModulePass) +from ADT.StringRef import StringRef +from Module import Module +from Value import Function @Pass class Pass: @@ -16,7 +16,7 @@ class Pass: delete = Destructor() getPassName = Method(cast(StringRef, str)) - + dump = Method() @ModulePass class ModulePass: diff --git a/llvmpy/src/PassManager.py b/llvmpy/src/PassManager.py index f969192..91a98f4 100644 --- a/llvmpy/src/PassManager.py +++ b/llvmpy/src/PassManager.py @@ -2,7 +2,7 @@ from binding import * from namespace import llvm from Pass import Pass from Module import Module -from Function import Function +from Value import Function PassManagerBase = llvm.Class() PassManager = llvm.Class(PassManagerBase) diff --git a/llvmpy/src/PassRegistry.py b/llvmpy/src/PassRegistry.py new file mode 100644 index 0000000..495de51 --- /dev/null +++ b/llvmpy/src/PassRegistry.py @@ -0,0 +1,21 @@ +from binding import * +from namespace import llvm +from src.ADT.StringRef import StringRef + +PassRegistry = llvm.Class() + +from src.PassSupport import PassInfo + +@PassRegistry +class PassRegistry: + _include_ = 'llvm/PassRegistry.h' + + delete = Destructor() + + getPassRegistry = StaticMethod(ownedptr(PassRegistry)) + + getPassInfo = Method(const(ptr(PassInfo)), cast(str, StringRef)) + + # This is a custom method that wraps enumerateWith + # Returns list of tuples of (pass-arg, pass-name) + enumerate = CustomMethod('PassRegistry_enumerate', PyObjectPtr) \ No newline at end of file diff --git a/llvmpy/src/PassSupport.py b/llvmpy/src/PassSupport.py new file mode 100644 index 0000000..8dba872 --- /dev/null +++ b/llvmpy/src/PassSupport.py @@ -0,0 +1,24 @@ +from binding import * +from namespace import llvm + +PassInfo = llvm.Class() + +from src.Pass import Pass +from src.PassRegistry import PassRegistry + +@PassInfo +class PassInfo: + _include_ = 'llvm/PassSupport.h' + + createPass = Method(ptr(Pass)) + +llvm.Function('initializeCore', Void, ref(PassRegistry)) +llvm.Function('initializeScalarOpts', Void, ref(PassRegistry)) +llvm.Function('initializeVectorization', Void, ref(PassRegistry)) +llvm.Function('initializeIPO', Void, ref(PassRegistry)) +llvm.Function('initializeAnalysis', Void, ref(PassRegistry)) +llvm.Function('initializeIPA', Void, ref(PassRegistry)) +llvm.Function('initializeTransformUtils', Void, ref(PassRegistry)) +llvm.Function('initializeInstCombine', Void, ref(PassRegistry)) +llvm.Function('initializeInstrumentation', Void, ref(PassRegistry)) +llvm.Function('initializeTarget', Void, ref(PassRegistry)) diff --git a/llvmpy/src/Support/Host.py b/llvmpy/src/Support/Host.py new file mode 100644 index 0000000..8163ebe --- /dev/null +++ b/llvmpy/src/Support/Host.py @@ -0,0 +1,25 @@ +from binding import * +from src.namespace import sys + +isLittleEndianHost = sys.Function('isLittleEndianHost', + cast(Bool, bool)) + +isBigEndianHost = sys.Function('isBigEndianHost', + cast(Bool, bool)) + +getDefaultTargetTriple = sys.Function('getDefaultTargetTriple', + cast(ConstStdString, str)) + +# llvm 3.3 +#getProcessTriple = sys.Function('getProcessTriple', +# cast(ConstStdString, str)) + +getHostCPUName = sys.Function('getHostCPUName', + cast(ConstStdString, str)) + +getHostCPUFeatures = sys.CustomFunction('getHostCPUFeatures', + 'llvm_sys_getHostCPUFeatures', + PyObjectPtr, # bool: success? + PyObjectPtr, # dict: store feature map + ) + diff --git a/llvmpy/src/Support/Target.py b/llvmpy/src/Support/Target.py deleted file mode 100644 index bdaeff5..0000000 --- a/llvmpy/src/Support/Target.py +++ /dev/null @@ -1,27 +0,0 @@ -from binding import * -from ..namespace import llvm -from ..ADT.StringRef import StringRef -Target = llvm.Class() - -@Target -class Target: - _include_ = 'llvm/Support/TargetRegistry.h' - - getNext = Method(const(ptr(Target))) - - getName = Method(cast(StringRef, str)) - getShortDescription = Method(cast(StringRef, str)) - - def _has(): - return Method(cast(Bool, bool)) - - hasJIT = _has() - hasTargetMachine = _has() - hasMCAsmBackend = _has() - hasMCAsmParser = _has() - hasAsmPrinter = _has() - hasMCDisassembler = _has() - hasMCInstPrinter = _has() - hasMCCodeEmitter = _has() - hasMCObjectStreamer = _has() - hasAsmStreamer = _has() diff --git a/llvmpy/src/Support/TargetRegistry.py b/llvmpy/src/Support/TargetRegistry.py new file mode 100644 index 0000000..640364b --- /dev/null +++ b/llvmpy/src/Support/TargetRegistry.py @@ -0,0 +1,68 @@ +from binding import * +from src.namespace import llvm + +llvm.includes.add('llvm/Support/TargetRegistry.h') + +Target = llvm.Class() +TargetRegistry = llvm.Class() + +from src.ADT.Triple import Triple +from src.ADT.StringRef import StringRef +from src.Target.TargetMachine import TargetMachine +from src.Target.TargetOptions import TargetOptions +from src.Support.CodeGen import Reloc, CodeModel, CodeGenOpt + +@Target +class Target: + getNext = Method(const(ptr(Target))) + + getName = Method(cast(StringRef, str)) + getShortDescription = Method(cast(StringRef, str)) + + def _has(): + return Method(cast(Bool, bool)) + + hasJIT = _has() + hasTargetMachine = _has() + hasMCAsmBackend = _has() + hasMCAsmParser = _has() + hasAsmPrinter = _has() + hasMCDisassembler = _has() + hasMCInstPrinter = _has() + hasMCCodeEmitter = _has() + hasMCObjectStreamer = _has() + hasAsmStreamer = _has() + + createTargetMachine = Method(ptr(TargetMachine), + cast(str, StringRef), # triple + cast(str, StringRef), # cpu + cast(str, StringRef), # features + ref(TargetOptions), + Reloc.Model, # = Reloc::Default + CodeModel.Model, # = CodeModel.Default + CodeGenOpt.Level, # = CodeGenOpt.Default + ).require_only(4) + + +@TargetRegistry +class TargetRegistry: + printRegisteredTargetsForVersion = StaticMethod() + + lookupTarget = CustomStaticMethod('TargetRegistry_lookupTarget', + PyObjectPtr, # const Target* + cast(str, ConstCharPtr), # triple + PyObjectPtr, # std::string &Error + ) + + lookupTarget |= CustomStaticMethod('TargetRegistry_lookupTarget', + PyObjectPtr, # const Target* + cast(str, ConstCharPtr), # arch + ref(Triple), # triple + PyObjectPtr, # std::string &Error + ) + + getClosestTargetForJIT = CustomStaticMethod( + 'TargetRegistry_getClosestTargetForJIT', + PyObjectPtr, # const Target* + PyObjectPtr, # std::string &Error + ) diff --git a/llvmpy/src/Target/TargetLibraryInfo.py b/llvmpy/src/Target/TargetLibraryInfo.py index d98b00b..9c47814 100644 --- a/llvmpy/src/Target/TargetLibraryInfo.py +++ b/llvmpy/src/Target/TargetLibraryInfo.py @@ -1,8 +1,7 @@ from binding import * from ..namespace import llvm -from ..ADT.Triple import Triple -from ..Pass import ImmutablePass -from ..ADT.StringRef import StringRef + +from src.Pass import ImmutablePass TargetLibraryInfo = llvm.Class(ImmutablePass) @@ -54,6 +53,10 @@ LibFunc.Enum('Func', ''' # not in llvm-3.2 abs, ffs, ffsl, ffsll, fprintf, isascii, # isdigit, labs, llabs, printf, sprintf, toascii +from src.ADT.Triple import Triple +from src.ADT.StringRef import StringRef + + @TargetLibraryInfo class TargetLibraryInfo: _include_ = 'llvm/Target/TargetLibraryInfo.h' diff --git a/llvmpy/src/Target/TargetMachine.py b/llvmpy/src/Target/TargetMachine.py index e60ed5c..29960fa 100644 --- a/llvmpy/src/Target/TargetMachine.py +++ b/llvmpy/src/Target/TargetMachine.py @@ -1,17 +1,18 @@ from binding import * -from ..namespace import llvm -from ..ADT.StringRef import StringRef -from ..Support.CodeGen import CodeModel, TLSModel, CodeGenOpt, Reloc -from ..GlobalValue import GlobalValue -from ..Support.Target import Target -from ..DataLayout import DataLayout -from ..TargetTransformInfo import (ScalarTargetTransformInfo, - VectorTargetTransformInfo) -from ..PassManager import PassManagerBase -from ..Support.FormattedStream import formatted_raw_ostream +from src.namespace import llvm TargetMachine = llvm.Class() +from src.Support.TargetRegistry import Target +from src.ADT.StringRef import StringRef +from src.Support.CodeGen import CodeModel, TLSModel, CodeGenOpt, Reloc +from src.GlobalValue import GlobalValue +from src.DataLayout import DataLayout +from src.TargetTransformInfo import (ScalarTargetTransformInfo, + VectorTargetTransformInfo) +from src.PassManager import PassManagerBase +from src.Support.FormattedStream import formatted_raw_ostream + @TargetMachine class TargetMachine: _include_ = 'llvm/Target/TargetMachine.h' diff --git a/llvmpy/src/Target/TargetOptions.py b/llvmpy/src/Target/TargetOptions.py new file mode 100644 index 0000000..0e28677 --- /dev/null +++ b/llvmpy/src/Target/TargetOptions.py @@ -0,0 +1,12 @@ +from binding import * +from src.namespace import llvm + +llvm.includes.add('llvm/Target/TargetOptions.h') + +TargetOptions = llvm.Class() + +@TargetOptions +class TargetOptions: + new = Constructor() + delete = Destructor() + diff --git a/llvmpy/test_binding.py b/llvmpy/test_binding.py index e1e12e5..01e6c38 100644 --- a/llvmpy/test_binding.py +++ b/llvmpy/test_binding.py @@ -7,9 +7,10 @@ import llvmpy.capsule llvmpy.capsule.set_debug(True) +llvm.InitializeNativeTarget() +llvm.InitializeNativeTargetAsmPrinter() + def test_basic_jit_use(): - llvm.InitializeNativeTarget() - llvm.InitializeNativeTargetAsmPrinter() context = llvm.getGlobalContext() m = llvm.Module.new("modname", context) @@ -332,6 +333,42 @@ def test_intrinsic(): fn.eraseFromParent() assert 'llvm.sin.f32' not in str(m) +def test_passregistry(): + passreg = llvm.PassRegistry.getPassRegistry() + + llvm.initializeScalarOpts(passreg) + + passinfo = passreg.getPassInfo("dce") + dcepass = passinfo.createPass() + print dcepass.getPassName() + + print passreg.enumerate() + +def test_targetregistry(): + llvm.TargetRegistry.printRegisteredTargetsForVersion() + errmsg = StringIO() + + target = llvm.TargetRegistry.getClosestTargetForJIT(errmsg) + errmsg.close() + + print target.getName() + print target.getShortDescription() + assert target.hasJIT() + assert target.hasTargetMachine() + + next = target.getNext() + if next: + print next.getName() + print next.getShortDescription() + + triple = llvm.sys.getDefaultTargetTriple() + cpu = llvm.sys.getHostCPUName() + features = {} + assert not llvm.sys.getHostCPUFeatures(features), "Only for Linux and ARM?" + + targetoptions = llvm.TargetOptions.new() + tm = target.createTargetMachine(triple, cpu, "", targetoptions) + def main(): for name, value in globals().items(): if name.startswith('test_') and callable(value):