diff --git a/bindings/python/README.txt b/bindings/python/README.txt new file mode 100644 index 00000000000..e69de29bb2d diff --git a/bindings/python/llvm/__init__.py b/bindings/python/llvm/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/bindings/python/llvm/common.py b/bindings/python/llvm/common.py new file mode 100644 index 00000000000..7818ff41a4e --- /dev/null +++ b/bindings/python/llvm/common.py @@ -0,0 +1,37 @@ +#===- common.py - Python LLVM Bindings -----------------------*- python -*--===# +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +#===------------------------------------------------------------------------===# + +from ctypes import cdll + +import ctypes.util +import platform + +__all__ = [ + "find_library", + "get_library", +] + +def find_library(): + # FIXME should probably have build system define absolute path of shared + # library at install time. + for lib in ["LLVM-3.1svn", "LLVM"]: + result = ctypes.util.find_library(lib) + if result: + return result + + # FIXME This is a local hack to ease development. + return "/usr/local/llvm/lib/libLLVM-3.1svn.so" + +def get_library(): + """Obtain a reference to the llvm library.""" + lib = find_library() + if not lib: + raise Exception("LLVM shared library not found!") + + return cdll.LoadLibrary(lib) diff --git a/bindings/python/llvm/core.py b/bindings/python/llvm/core.py new file mode 100644 index 00000000000..5a3bd51cfa5 --- /dev/null +++ b/bindings/python/llvm/core.py @@ -0,0 +1,61 @@ +#===- core.py - Python LLVM Bindings -------------------------*- python -*--===# +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +#===------------------------------------------------------------------------===# + +from .common import get_library + +from ctypes import POINTER +from ctypes import byref +from ctypes import c_char_p +from ctypes import c_void_p + +__all__ = [ + "lib", + "MemoryBufferRef", +] + +lib = get_library() + +class MemoryBuffer(object): + """Represents an opaque memory buffer.""" + + def __init__(self, filename=None): + """Create a new memory buffer. + + Currently, we support creating from the contents of a file at the + specified filename. + """ + if filename is None: + raise Exception("filename argument must be defined") + + memory = c_void_p(None) + out = c_char_p(None) + + result = lib.LLVMCreateMemoryBufferWithContentsOfFile(filename, + byref(memory), byref(out)) + + if result: + raise Exception("Could not create memory buffer: %s" % out.value) + + self._memory = memory + + def __del__(self): + lib.LLVMDisposeMemoryBuffer(self._memory) + + def from_param(self): + return self._memory + + +def register_library(library): + library.LLVMCreateMemoryBufferWithContentsOfFile.argtypes = [c_char_p, + POINTER(c_void_p), POINTER(c_char_p)] + library.LLVMCreateMemoryBufferWithContentsOfFile.restype = bool + + library.LLVMDisposeMemoryBuffer.argtypes = [c_void_p] + +register_library(lib) diff --git a/bindings/python/llvm/object.py b/bindings/python/llvm/object.py new file mode 100644 index 00000000000..a55a5cb64e1 --- /dev/null +++ b/bindings/python/llvm/object.py @@ -0,0 +1,243 @@ +#===- object.py - Python Object Bindings --------------------*- python -*--===# +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +#===------------------------------------------------------------------------===# + +from ctypes import c_char_p +from ctypes import c_uint64 +from ctypes import c_void_p + +from .common import get_library +from .core import MemoryBuffer + +__all__ = [ + "lib", + "ObjectFile", + "Relocation", + "Section", + "Symbol", +] + +class ObjectFile(object): + """Represents an object/binary file.""" + + def __init__(self, filename=None, contents=None): + """Construct an instance from a filename or binary data. + + filename must be a path to a file that can be opened with open(). + contents can be either a native Python buffer type (like str) or a + llvm.core.MemoryBuffer instance. + """ + if contents: + assert isinstance(contents, MemoryBuffer) + + if filename is not None: + contents = MemoryBuffer(filename=filename) + + self._memory = contents + self._obj = lib.LLVMCreateObjectFile(contents) + + def __del__(self): + lib.LLVMDisposeObjectFile(self._obj) + + def get_sections(self): + """Obtain the sections in this object file. + + This is an iterator for llvm.object.Section instances. + """ + pass + + def get_symbols(self): + """Obtain the symbols in this object file. + + This is an iterator for llvm.object.Symbol instances. + """ + +class Section(object): + """Represents a section in an object file.""" + + def __init__(self, obj=None): + """Construct a new section instance. + + Section instances can currently only be created from an ObjectFile + instance. Therefore, this constructor should not be used outside of + this module. + """ + pass + + def __del__(self): + pass + + @property + def name(self): + pass + + @property + def size(self): + pass + + @property + def contents(self): + pass + + @property + def address(self): + pass + + # TODO consider exposing more Pythonic interface, like __contains__ + def has_symbol(self, symbol): + pass + + def get_relocations(self): + pass + +class Symbol(object): + def __init__(self): + pass + + @property + def name(self): + pass + + @property + def address(self): + pass + + @property + def file_offset(self): + pass + + @property + def size(self): + pass + +class Relocation(object): + def __init__(self): + pass + + @property + def address(self): + pass + + @property + def offset(self): + pass + + @property + def symbol(self): + pass + + @property + def type(self): + pass + + @property + def type_name(self): + pass + + @property + def value_string(self): + pass + +ObjectFileRef = c_void_p +SectionIteratorRef = c_void_p +SymbolIteratorRef = c_void_p +RelocationIteratorRef = c_void_p + +def register_library(library): + """Register function prototypes with LLVM library instance.""" + + # Object.h functions + library.LLVMCreateObjectFile.argtypes = [MemoryBuffer] + library.LLVMCreateObjectFile.restype = ObjectFileRef + + library.LLVMDisposeObjectFile.argtypes = [ObjectFileRef] + + library.LLVMGetSections.argtypes = [ObjectFileRef] + library.LLVMGetSections.restype = SectionIteratorRef + + library.LLVMDisposeSectionIterator.argtypes = [SectionIteratorRef] + + library.LLVMIsSectionIteratorAtEnd.argtypes = [ObjectFileRef, + SectionIteratorRef] + library.LLVMIsSectionIteratorAtEnd.restype = bool + + library.LLVMMoveToNextSection.argtypes = [SectionIteratorRef] + + library.LLVMMoveToContainingSection.argtypes = [SectionIteratorRef, + SymbolIteratorRef] + + library.LLVMGetSymbols.argtypes = [ObjectFileRef] + library.LLVMGetSymbols.restype = SymbolIteratorRef + + library.LLVMDisposeSymbolIterator.argtypes = [SymbolIteratorRef] + + library.LLVMIsSymbolIteratorAtEnd.argtypes = [ObjectFileRef, + SymbolIteratorRef] + library.LLVMIsSymbolIteratorAtEnd.restype = bool + + library.LLVMMoveToNextSymbol.argtypes = [SymbolIteratorRef] + + library.LLVMGetSectionName.argtypes = [SectionIteratorRef] + library.LLVMGetSectionName.restype = c_char_p + + library.LLVMGetSectionSize.argtypes = [SectionIteratorRef] + library.LLVMGetSectionSize.restype = c_uint64 + + library.LLVMGetSectionContents.argtypes = [SectionIteratorRef] + library.LLVMGetSectionContents.restype = c_char_p + + library.LLVMGetSectionAddress.argtypes = [SectionIteratorRef] + library.LLVMGetSectionAddress.restype = c_uint64 + + library.LLVMGetSectionContainsSymbol.argtypes = [SectionIteratorRef, + SymbolIteratorRef] + library.LLVMGetSectionContainsSymbol.restype = bool + + library.LLVMGetRelocations.argtypes = [SectionIteratorRef] + library.LLVMGetRelocations.restype = RelocationIteratorRef + + library.LLVMDisposeRelocationIterator.argtypes = [RelocationIteratorRef] + + library.LLVMIsRelocationIteratorAtEnd.argtypes = [SectionIteratorRef, + RelocationIteratorRef] + library.LLVMIsRelocationIteratorAtEnd.restype = bool + + library.LLVMMoveToNextRelocation.argtypes = [RelocationIteratorRef] + + library.LLVMGetSymbolName.argtypes = [SymbolIteratorRef] + library.LLVMGetSymbolName.restype = c_char_p + + library.LLVMGetSymbolAddress.argtypes = [SymbolIteratorRef] + library.LLVMGetSymbolAddress.restype = c_uint64 + + library.LLVMGetSymbolFileOffset.argtypes = [SymbolIteratorRef] + library.LLVMGetSymbolFileOffset.restype = c_uint64 + + library.LLVMGetSymbolSize.argtypes = [SymbolIteratorRef] + library.LLVMGetSymbolSize.restype = c_uint64 + + library.LLVMGetRelocationAddress.argtypes = [SymbolIteratorRef] + library.LLVMGetRelocationAddress.restype = c_uint64 + + library.LLVMGetRelocationOffset.argtypes = [RelocationIteratorRef] + library.LLVMGetRelocationOffset.restype = c_uint64 + + library.LLVMGetRelocationSymbol.argtypes = [RelocationIteratorRef] + library.LLVMGetRelocationSymbol.restype = SymbolIteratorRef + + library.LLVMGetRelocationType.argtypes = [RelocationIteratorRef] + library.LLVMGetRelocationType.restype = c_uint64 + + library.LLVMGetRelocationTypeName.argtypes = [RelocationIteratorRef] + library.LLVMGetRelocationTypeName.restype = c_char_p + + library.LLVMGetRelocationValueString.argtypes = [RelocationIteratorRef] + library.LLVMGetRelocationValueString.restype = c_char_p + +lib = get_library() +register_library(lib) diff --git a/bindings/python/tests/test_core.py b/bindings/python/tests/test_core.py new file mode 100644 index 00000000000..8c4e9337053 --- /dev/null +++ b/bindings/python/tests/test_core.py @@ -0,0 +1,11 @@ +from llvm.common import find_library +from llvm.core import MemoryBuffer + +import unittest + +class TestCore(unittest.TestCase): + def test_memory_buffer_create_from_file(self): + source = find_library() + self.assertIsNotNone(source) + + mb = MemoryBuffer(filename=source) diff --git a/bindings/python/tests/test_object.py b/bindings/python/tests/test_object.py new file mode 100644 index 00000000000..afb02019672 --- /dev/null +++ b/bindings/python/tests/test_object.py @@ -0,0 +1,9 @@ +from llvm.common import find_library +from llvm.object import ObjectFile + +import unittest + +class TestObjectFile(unittest.TestCase): + def test_create_from_file(self): + source = find_library() + of = ObjectFile(filename=source)