Skip to content

Commit

Permalink
Merge branch 'main' into ci-build-wheel
Browse files Browse the repository at this point in the history
  • Loading branch information
jonathanharg committed Mar 6, 2024
2 parents 1a34583 + 9bee683 commit e8ed34a
Show file tree
Hide file tree
Showing 8 changed files with 213 additions and 17 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -74,4 +74,4 @@ jobs:
- uses: actions/upload-artifact@v4
with:
name: binaryen-py-sdist
path: dist/*.tar.gz
path: dist/*.tar.gz
1 change: 1 addition & 0 deletions binaryen/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@
from .__feature import Feature
from .__functionref import FunctionRef
from .__module import Module
from .__type_builder import TypeBuilder
from ._binaryen import ffi, lib
91 changes: 80 additions & 11 deletions binaryen/__module.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,13 @@
from .__feature import Feature
from .__functionref import FunctionRef
from ._binaryen import ffi, lib
from .internals import BinaryenHeapType, BinaryenLiteral, BinaryenOp, BinaryenType
from .internals import (
BinaryenGlobalRef,
BinaryenHeapType,
BinaryenLiteral,
BinaryenOp,
BinaryenType,
)
from .type import TypeNone

type BinaryenExportRef = Any
Expand Down Expand Up @@ -170,7 +176,7 @@ def store(
ptr.ref,
value.ref,
store_type,
memory_name,
_none_to_null(memory_name),
)
return Expression(ref)

Expand Down Expand Up @@ -226,15 +232,61 @@ def unreachable(self) -> Expression:
# TODO: TupleMake, TupleExtract, Pop, RefI31, I31Get
# TODO: CallRef, ReftTest, RefCast, BrOn
# TODO: StructNew, StructGet, StructSet
# TODO: ArrayNew, ArrayNewData

def array_new(
self, heap_type: BinaryenHeapType, size: Expression, init: Expression
):
ref = lib.BinaryenArrayNew(self.ref, heap_type, size.ref, init.ref)
return Expression(ref)

def array_new_data(
self,
heap_type: BinaryenHeapType,
name: bytes,
offset: Expression,
size: Expression,
):
ref = lib.BinaryenArrayNewData(self.ref, heap_type, name, offset.ref, size.ref)
return Expression(ref)

def array_new_fixed(self, heap_type: BinaryenHeapType, values: list[Expression]):
num_values = len(values)
value_refs = list(map(lambda x: x.ref, values))
ref = lib.BinaryenArrayNewFixed(self.ref, heap_type, value_refs, num_values)
return Expression(ref)

# TODO: ArrayGet, ArraySet, ArrayLen, ArrayGet, ArraySet, ArrayLen, ArrayCopy
def array_get(
self, ref: Expression, index: Expression, array_type: BinaryenType, signed: bool
):
ref = lib.BinaryenArrayGet(self.ref, ref.ref, index.ref, array_type, signed)
return Expression(ref)

def array_set(self, ref: Expression, index: Expression, value: Expression):
ref = lib.BinaryenArraySet(self.ref, ref.ref, index.ref, value.ref)
return Expression(ref)

def array_len(self, ref: Expression):
ref = lib.BinaryenArrayLen(self.ref, ref.ref)
return Expression(ref)

def array_copy(
self,
dest_ref: Expression,
dest_index: Expression,
src_ref: Expression,
src_index: Expression,
length: Expression,
):
ref = lib.BinaryenArrayCopy(
self.ref,
dest_ref.ref,
dest_index.ref,
src_ref.ref,
src_index.ref,
length.ref,
)
return Expression(ref)

# TODO: StringNew

def string_const(self, name: bytes) -> Expression:
Expand Down Expand Up @@ -331,7 +383,13 @@ def add_function_export(

# TODO: GetExport, RemoveExport, GetNumExports, GetExportByIndex

# TODO: AddGlobal, GetGlobal, RemoveGlobal, GetNumGlobals, GetGlobalByIndex
def add_global(
self, name: bytes, global_type: BinaryenType, mutable: bool, init: Expression
) -> BinaryenGlobalRef:
ref = lib.BinaryenAddGlobal(self.ref, name, global_type, mutable, init.ref)
return ref

# TODO: GetGlobal, RemoveGlobal, GetNumGlobals, GetGlobalByIndex

# TODO: AddTag, GetTag, RemoveTag

Expand All @@ -344,30 +402,39 @@ def set_memory(
initial: int,
maximum: int,
export_name: bytes,
segments: list[bytes],
segment_names: list[bytes],
segment_datas: list[bytes],
segment_passive: list[bool],
segment_offsets: list[Expression],
segment_sizes: list[int],
shared: bool,
memory64: bool,
name: bytes,
):
if len(segment_sizes) != len(segments):
if not (
len(segment_names)
== len(segment_datas)
== len(segment_passive)
== len(segment_offsets)
== len(segment_sizes)
):
raise RuntimeError("Segment sizes do not match")

segment_offset_refs = list(map(lambda x: x.ref, segment_offsets))
segments_char_arr = list(map(lambda x: ffi.new("char[]", x), segments))
segment_names_charptr = list(map(lambda x: ffi.new("char[]", x), segment_names))
segment_datas_charptr = list(map(lambda x: ffi.new("char[]", x), segment_datas))

lib.BinaryenSetMemory(
self.ref,
initial,
maximum,
export_name,
segments_char_arr,
segment_names_charptr,
segment_datas_charptr,
segment_passive,
segment_offset_refs,
segment_sizes,
len(segments),
len(segment_names),
shared,
memory64,
name,
Expand Down Expand Up @@ -451,5 +518,7 @@ def write_binary(self, filename: str):
# TODO: SideEffects
# TODO: CFG/Relooper
# TODO: Expression Runner
# TODO: TypeBuilder

# TODO: SetTypeName, SetFieldName

# TODO: Utilities
76 changes: 76 additions & 0 deletions binaryen/__type_builder.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
from ._binaryen import lib, ffi
from .internals import (
BinaryenExpressionId,
BinaryenType,
BinaryenPackedType,
BinaryenHeapType,
)

type_builder_errors = {
lib.TypeBuilderErrorReasonSelfSupertype(): "Self Supertype",
lib.TypeBuilderErrorReasonInvalidSupertype(): "Invalid Supertype",
lib.TypeBuilderErrorReasonForwardSupertypeReference(): "Forward Supertype Reference",
lib.TypeBuilderErrorReasonForwardChildReference(): "Forward Child Reference",
}


class TypeBuilder:
def __init__(self, size: int):
self.ref = lib.TypeBuilderCreate(size)

def grow(self, count: int):
if self.ref is None:
raise RuntimeError("Cannot access TypeBuilder after it has been built.")
lib.TypeBuilderGrow(self.ref, count)

def get_size(self) -> int:
if self.ref is None:
raise RuntimeError("Cannot access TypeBuilder after it has been built.")
return lib.TypeBuilderGetSize(self.ref)

def set_signature_type(
self, index: int, param_types: BinaryenType, result_types: BinaryenType
):
if self.ref is None:
raise RuntimeError("Cannot access TypeBuilder after it has been built.")
lib.TypeBuilderSetSignatureType(self.ref, index, param_types, result_types)

# TODO: SetStructType

def set_array_type(
self,
index: int,
element_type: BinaryenType,
element_packed_type: BinaryenPackedType,
element_mutable: bool,
):
if self.ref is None:
raise RuntimeError("Cannot access TypeBuilder after it has been built.")
lib.TypeBuilderSetArrayType(
self.ref, index, element_type, element_packed_type, element_mutable
)

# TODO: GetTempHeapType, GetTempTupleType, TempRefType, SetSubType, SetOpen, CreateRecGroup

def build(self):
if self.ref is None:
raise RuntimeError("Cannot access TypeBuilder after it has been built.")

size = self.get_size()
heap_types = ffi.new(f"BinaryenHeapType[{size}]")
error_index = ffi.new("BinaryenIndex[1]")
error_reason = ffi.new("TypeBuilderErrorReason[1]")
successful = lib.TypeBuilderBuildAndDispose(
self.ref, heap_types, error_index, error_reason
)
self.ref = None

if not successful:
raise RuntimeError(
f"TypeBuilder Error at type index {error_index[0]}: {type_builder_errors[error_reason[0]]}"
)

result: list[BinaryenHeapType] = []
for i in range(size):
result.append(heap_types[i])
return result
1 change: 1 addition & 0 deletions binaryen/internals.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,4 @@ class __BaseType:
BinaryenExternalKind = __NewType("BinaryenExternalKind", __BaseType)
BinaryenOp = __NewType("BinaryenOp", __BaseType)
BinaryenLiteral = __NewType("BinaryenLiteral", __BaseType)
BinaryenGlobalRef = __NewType("BinaryenGlobalRef", __BaseType)
48 changes: 48 additions & 0 deletions examples/array.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import binaryen
from binaryen.type import Int32, NotPacked


mod = binaryen.Module()
mod.set_feature(binaryen.Feature.GC | binaryen.Feature.ReferenceTypes)

tb = binaryen.TypeBuilder(1)
tb.set_array_type(0, Int32, NotPacked, True)
Int32ArrayHeap = tb.build()[0]
Int32Array = binaryen.type.from_heap_type(Int32ArrayHeap, True)

contents = mod.array_new(Int32ArrayHeap, mod.i32(10), mod.i32(0))
set_array = mod.local_set(0, contents.copy(mod))
array = mod.local_get(0, Int32Array)

mod.add_function(
b"indexArray",
None,
Int32,
[Int32Array],
mod.block(
None,
[
set_array,
array,
mod.Return(mod.array_len(array))
],
Int32,
),
)

mod.add_function_export(b"indexArray", b"indexArray")
mod.auto_drop()

# mod.optimize()

mod.print()
mod.write_text("array.wat")
mod.write_binary("array.wasm")


if not mod.validate():
raise RuntimeError("Invalid module!")

# Can either print with `myModule.print()` or write to file with `myModule.write_binary(__file__)`

# Run the written binary with `wasmtime addTen.wasm --invoke addTen 12`
9 changes: 5 additions & 4 deletions examples/hello_world.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import binaryen as b
from binaryen.type import NULL, Int32, TypeNone
from binaryen.type import Int32, TypeNone

mod = b.Module()
mod.add_function_import(
b"print",
b"wasi_snapshot_preview1",
b"fd_write",
b.types.create([Int32, Int32, Int32, Int32]),
b.type.create([Int32, Int32, Int32, Int32]),
Int32,
)

Expand All @@ -18,6 +18,7 @@
1,
1,
b"memory",
[b"str"],
[b"Hello Wasm!\n"],
[False],
[mod.i32(8)],
Expand All @@ -28,8 +29,8 @@
)

# Pointer to start of string and length of string
string_pointer = mod.store(4, 0, 0, mod.i32(0), mod.i32(8), Int32, NULL)
string_length = mod.store(4, 0, 2, mod.i32(4), mod.i32(12), Int32, NULL)
string_pointer = mod.store(4, 0, 0, mod.i32(0), mod.i32(8), Int32, None)
string_length = mod.store(4, 0, 2, mod.i32(4), mod.i32(12), Int32, None)
# | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |
# [ 8 ] [ 12 ] H e l l o \ W a s m ! \n \0

Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,4 @@ before-all = ["yum install wget -y", "bash ./scripts/build_libbinaryen.sh"]

[[tool.cibuildwheel.overrides]]
select = "*-musllinux*"
before-all = ["apk add wget", "bash ./scripts/build_libbinaryen.sh"]
before-all = ["apk add wget", "bash ./scripts/build_libbinaryen.sh"]

0 comments on commit e8ed34a

Please sign in to comment.