mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-09-08 23:55:03 +00:00
[llvm.py] Initial skeleton for Python LLVM bindings
This contains a semi-functional skeleton for the implementation of the LLVM bindings for Python. The API for the Object.h interface is roughly designed but not implemented. MemoryBufferRef is implemented and actually appears to work! The ObjectFile unit test fails with a segmentation fault because the LLVM library isn't being properly initialized. The build system doesn't know about this code yet, so no alerts should fire. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@152397 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
1fabd9f85e
commit
5ae04279e0
0
bindings/python/README.txt
Normal file
0
bindings/python/README.txt
Normal file
0
bindings/python/llvm/__init__.py
Normal file
0
bindings/python/llvm/__init__.py
Normal file
37
bindings/python/llvm/common.py
Normal file
37
bindings/python/llvm/common.py
Normal file
@ -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)
|
61
bindings/python/llvm/core.py
Normal file
61
bindings/python/llvm/core.py
Normal file
@ -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)
|
243
bindings/python/llvm/object.py
Normal file
243
bindings/python/llvm/object.py
Normal file
@ -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)
|
11
bindings/python/tests/test_core.py
Normal file
11
bindings/python/tests/test_core.py
Normal file
@ -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)
|
9
bindings/python/tests/test_object.py
Normal file
9
bindings/python/tests/test_object.py
Normal file
@ -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)
|
Loading…
Reference in New Issue
Block a user