llvmcpy


Namellvmcpy JSON
Version 0.2.0 PyPI version JSON
download
home_pageNone
SummaryPython bindings for LLVM auto-generated from the LLVM-C API
upload_time2024-11-22 16:30:45
maintainerNone
docs_urlNone
authorNone
requires_pythonNone
licenseMIT License
keywords llvm
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # `llvmcpy`

`llvmcpy` automatically generates Python wrappers for the [LLVM-C API](http://llvm.org/docs/doxygen/html/group__LLVMC.html).

## Goal

The main goal of `llvmcpy` is to provide Python bindings for the LLVM project that are fast and require the lowest possible maintainance effort.
To achive this, we use CFFI to parse the (slightly adapted) LLVM-C API header files and automatically generate a set of classes and functions to interact with them in a Pythonic way.

This project is in an early stage, but allows you to run the following code:

```python
import sys
from llvmcpy import LLVMCPy

llvm = LLVMCPy()
buffer = llvm.create_memory_buffer_with_contents_of_file(sys.argv[1])
context = llvm.get_global_context()
module = context.parse_ir(buffer)
for function in module.iter_functions():
    for bb in function.iter_basic_blocks():
        for instruction in bb.iter_instructions():
            instruction.dump()
```

It's tested on all LLVM versions from 5 to 19 and on Python from 3.7 to 3.13.
Supporting newer versions of the LLVM-C API should be basically effortless.

To try it out, install LLVM and install `llvmcpy`:

```bash
sudo apt-get install llvm
python -m venv venv
source venv/bin/activate
pip install llvmcpy
```

## Naming of the generated classes/functions

The basic idea behind this project is to take the LLVM-C API, create a class for each data type and create a method for that class for each function in the API taking an argument of that data type as first argument.

This means that the following functions:

```c++
LLVMModuleRef LLVMCloneModule (LLVMModuleRef M)
```

Will become:

```python
class Module(object):
    def clone(self):
        # ...
```

Note the change in the case.
Use `help(Module.clone)` to see which LLVM-C API function a certain method is using.

Each class in `llvmcpy` is basically a wrapper around a pointer to an LLVM object.

If an API function doesn't take an LLVM object as a first argument, it will be part of the `llvm` module.

Additionally, we have some generated properties and generators for certain well known patterns in the API.

### Properties

For each function starting with `LLVMGet` or `LLVMSet` in the LLVM-C API, we generate a property. For example, consider the following two functions:

```c
void LLVMSetValueName (LLVMValueRef Val, const char *Name);
const char* LLVMGetValueName(LLVMValueRef Val);
```

In `llvmcpy` the `Get`/`Set` prefixes disappear, along with `Value` (the name of the class) and you can use them as properties of the `Value` class, e.g.:

```python
my_value.name = "sum"
print(my_value.name)
```

### Generators

The LLVM-C API has a recurrent pattern which allows you to navigate through the hierarchy of its class hierarchy, i.e. the pair of `LLVMGetSomething` and `LLVMGetNextSomething` functions.
`Something` can be `Function`, `BasicBlock` and so on. `llvmcpy` identifies these patterns and produces a generator method which allows you to iterate over these objects in a Pythonic way:

```python
for function in module.iter_functions():
    for bb in function.iter_basic_blocks():
        for instruction in bb.iter_instructions():
            # ...
```

## Where are my bindings?

Bindings are automatically generated in a lazy way.
Multiple installations of LLVM are supported, just set the `LLVM_CONFIG` environment variable to the `llvm-config` program in the `bin/` directory of your LLVM installation and everything should work fine.

The bindings are generated in a Python script which is stored in `$XDG_CACHE_DIR/llvmcpy/` (typically `~/.cache/llvmcpy`) in a directory whose name is obtained by hashing the full path of the output of `llvm-config --prefix` concatenated with the LLVM version number.
For example, for LLVM 19 installed in `/usr` you'll find the API bindings in `~/.cache/llvmcpy/7fea08f2e9d5108688f692e686c8528b914eda563e7069b25ef18c49ba96d7f2-19`.

To generate the bindings, a working C preprocessor must be available in the system. By default, `cpp` (the C preprocessor part of GCC) is used. If it's not available we check if `clang` is available in the LLVM installation and use it.

## License and credits

This project is developed and maintained by rev.ng Labs as part of the rev.ng project, and it's released under the MIT license.

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "llvmcpy",
    "maintainer": null,
    "docs_url": null,
    "requires_python": null,
    "maintainer_email": null,
    "keywords": "llvm",
    "author": null,
    "author_email": "Alessandro Di Federico <ale.llvmcpy@clearmind.me>",
    "download_url": "https://files.pythonhosted.org/packages/87/0e/b9916a03db73008659282bd74927915c7d65ff4afea62468135a41bf6c94/llvmcpy-0.2.0.tar.gz",
    "platform": null,
    "description": "# `llvmcpy`\n\n`llvmcpy` automatically generates Python wrappers for the [LLVM-C API](http://llvm.org/docs/doxygen/html/group__LLVMC.html).\n\n## Goal\n\nThe main goal of `llvmcpy` is to provide Python bindings for the LLVM project that are fast and require the lowest possible maintainance effort.\nTo achive this, we use CFFI to parse the (slightly adapted) LLVM-C API header files and automatically generate a set of classes and functions to interact with them in a Pythonic way.\n\nThis project is in an early stage, but allows you to run the following code:\n\n```python\nimport sys\nfrom llvmcpy import LLVMCPy\n\nllvm = LLVMCPy()\nbuffer = llvm.create_memory_buffer_with_contents_of_file(sys.argv[1])\ncontext = llvm.get_global_context()\nmodule = context.parse_ir(buffer)\nfor function in module.iter_functions():\n    for bb in function.iter_basic_blocks():\n        for instruction in bb.iter_instructions():\n            instruction.dump()\n```\n\nIt's tested on all LLVM versions from 5 to 19 and on Python from 3.7 to 3.13.\nSupporting newer versions of the LLVM-C API should be basically effortless.\n\nTo try it out, install LLVM and install `llvmcpy`:\n\n```bash\nsudo apt-get install llvm\npython -m venv venv\nsource venv/bin/activate\npip install llvmcpy\n```\n\n## Naming of the generated classes/functions\n\nThe basic idea behind this project is to take the LLVM-C API, create a class for each data type and create a method for that class for each function in the API taking an argument of that data type as first argument.\n\nThis means that the following functions:\n\n```c++\nLLVMModuleRef LLVMCloneModule (LLVMModuleRef M)\n```\n\nWill become:\n\n```python\nclass Module(object):\n    def clone(self):\n        # ...\n```\n\nNote the change in the case.\nUse `help(Module.clone)` to see which LLVM-C API function a certain method is using.\n\nEach class in `llvmcpy` is basically a wrapper around a pointer to an LLVM object.\n\nIf an API function doesn't take an LLVM object as a first argument, it will be part of the `llvm` module.\n\nAdditionally, we have some generated properties and generators for certain well known patterns in the API.\n\n### Properties\n\nFor each function starting with `LLVMGet` or `LLVMSet` in the LLVM-C API, we generate a property. For example, consider the following two functions:\n\n```c\nvoid LLVMSetValueName (LLVMValueRef Val, const char *Name);\nconst char* LLVMGetValueName(LLVMValueRef Val);\n```\n\nIn `llvmcpy` the `Get`/`Set` prefixes disappear, along with `Value` (the name of the class) and you can use them as properties of the `Value` class, e.g.:\n\n```python\nmy_value.name = \"sum\"\nprint(my_value.name)\n```\n\n### Generators\n\nThe LLVM-C API has a recurrent pattern which allows you to navigate through the hierarchy of its class hierarchy, i.e. the pair of `LLVMGetSomething` and `LLVMGetNextSomething` functions.\n`Something` can be `Function`, `BasicBlock` and so on. `llvmcpy` identifies these patterns and produces a generator method which allows you to iterate over these objects in a Pythonic way:\n\n```python\nfor function in module.iter_functions():\n    for bb in function.iter_basic_blocks():\n        for instruction in bb.iter_instructions():\n            # ...\n```\n\n## Where are my bindings?\n\nBindings are automatically generated in a lazy way.\nMultiple installations of LLVM are supported, just set the `LLVM_CONFIG` environment variable to the `llvm-config` program in the `bin/` directory of your LLVM installation and everything should work fine.\n\nThe bindings are generated in a Python script which is stored in `$XDG_CACHE_DIR/llvmcpy/` (typically `~/.cache/llvmcpy`) in a directory whose name is obtained by hashing the full path of the output of `llvm-config --prefix` concatenated with the LLVM version number.\nFor example, for LLVM 19 installed in `/usr` you'll find the API bindings in `~/.cache/llvmcpy/7fea08f2e9d5108688f692e686c8528b914eda563e7069b25ef18c49ba96d7f2-19`.\n\nTo generate the bindings, a working C preprocessor must be available in the system. By default, `cpp` (the C preprocessor part of GCC) is used. If it's not available we check if `clang` is available in the LLVM installation and use it.\n\n## License and credits\n\nThis project is developed and maintained by rev.ng Labs as part of the rev.ng project, and it's released under the MIT license.\n",
    "bugtrack_url": null,
    "license": "MIT License",
    "summary": "Python bindings for LLVM auto-generated from the LLVM-C API",
    "version": "0.2.0",
    "project_urls": {
        "Repository": "https://github.com/revng/llvmcpy"
    },
    "split_keywords": [
        "llvm"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "14bb519b3f62b7e7112391d5a4aea2d18f7876d87cd9489f858c5d6cdc97b05e",
                "md5": "272878853f3134ba8ae3f7da4ad60805",
                "sha256": "263c8879db81cceed5d15ec909184273664b80eff247b7c6c5b007096264e6b3"
            },
            "downloads": -1,
            "filename": "llvmcpy-0.2.0-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "272878853f3134ba8ae3f7da4ad60805",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": null,
            "size": 15578,
            "upload_time": "2024-11-22T16:30:43",
            "upload_time_iso_8601": "2024-11-22T16:30:43.824065Z",
            "url": "https://files.pythonhosted.org/packages/14/bb/519b3f62b7e7112391d5a4aea2d18f7876d87cd9489f858c5d6cdc97b05e/llvmcpy-0.2.0-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "870eb9916a03db73008659282bd74927915c7d65ff4afea62468135a41bf6c94",
                "md5": "2732af909f2a6101017a13dc0a7d3dc0",
                "sha256": "46d066518ea7fc879ae936b94a7dec2bdd4893efc5bc0d4d10688c99f696a3cb"
            },
            "downloads": -1,
            "filename": "llvmcpy-0.2.0.tar.gz",
            "has_sig": false,
            "md5_digest": "2732af909f2a6101017a13dc0a7d3dc0",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": null,
            "size": 16328,
            "upload_time": "2024-11-22T16:30:45",
            "upload_time_iso_8601": "2024-11-22T16:30:45.710942Z",
            "url": "https://files.pythonhosted.org/packages/87/0e/b9916a03db73008659282bd74927915c7d65ff4afea62468135a41bf6c94/llvmcpy-0.2.0.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-11-22 16:30:45",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "revng",
    "github_project": "llvmcpy",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "llvmcpy"
}
        
Elapsed time: 0.38097s