diff --git a/src/dune b/src/dune index 1249f71d..b4109357 100644 --- a/src/dune +++ b/src/dune @@ -24,6 +24,7 @@ heap_type signature_type struct_type + type_builder ocaml_helpers) (flags :standard -O2 -Wall -Wextra)) (js_of_ocaml @@ -46,4 +47,5 @@ packed_type.js heap_type.js signature_type.js + type_builder.js struct_type.js))) diff --git a/src/expression.c b/src/expression.c index 69d9d568..7f0f25cf 100644 --- a/src/expression.c +++ b/src/expression.c @@ -124,6 +124,38 @@ caml_binaryen_call_indirect__bytecode(value * argv) { return caml_binaryen_call_indirect(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]); } +CAMLprim value +caml_binaryen_call_ref(value _module, value _target, value _params, value _ty) { + CAMLparam4(_module, _target, _params, _ty); + BinaryenModuleRef module = BinaryenModuleRef_val(_module); + BinaryenExpressionRef target = BinaryenExpressionRef_val(_target); + _params = array_of_list(_params); + int paramsLen = array_length(_params); + BinaryenExpressionRef params[paramsLen]; + for (int i = 0; i < paramsLen; i++) { + params[i] = BinaryenExpressionRef_val(Field(_params, i)); + } + BinaryenType ty = BinaryenType_val(_ty); + BinaryenExpressionRef exp = BinaryenCallRef(module, target, params, paramsLen, ty); + CAMLreturn(alloc_BinaryenExpressionRef(exp)); +} + +CAMLprim value +caml_binaryen_return_call_ref(value _module, value _target, value _params, value _ty) { + CAMLparam4(_module, _target, _params, _ty); + BinaryenModuleRef module = BinaryenModuleRef_val(_module); + BinaryenExpressionRef target = BinaryenExpressionRef_val(_target); + _params = array_of_list(_params); + int paramsLen = array_length(_params); + BinaryenExpressionRef params[paramsLen]; + for (int i = 0; i < paramsLen; i++) { + params[i] = BinaryenExpressionRef_val(Field(_params, i)); + } + BinaryenType ty = BinaryenType_val(_ty); + BinaryenExpressionRef exp = BinaryenReturnCallRef(module, target, params, paramsLen, ty); + CAMLreturn(alloc_BinaryenExpressionRef(exp)); +} + CAMLprim value caml_binaryen_return_call(value _module, value _name, value _params, value _retty) { CAMLparam4(_module, _name, _params, _retty); @@ -459,6 +491,38 @@ caml_binaryen_i31_get(value _module, value _val, value _signed) { CAMLreturn(alloc_BinaryenExpressionRef(exp)); } +CAMLprim value +caml_binaryen_ref_test(value _module, value _ref, value _castType) { + CAMLparam3(_module, _ref, _castType); + BinaryenModuleRef module = BinaryenModuleRef_val(_module); + BinaryenExpressionRef ref = BinaryenExpressionRef_val(_ref); + BinaryenType castType = BinaryenType_val(_castType); + BinaryenExpressionRef exp = BinaryenRefTest(module, ref, castType); + CAMLreturn(alloc_BinaryenExpressionRef(exp)); +} + +CAMLprim value +caml_binaryen_ref_cast(value _module, value _ref, value _castType) { + CAMLparam3(_module, _ref, _castType); + BinaryenModuleRef module = BinaryenModuleRef_val(_module); + BinaryenExpressionRef ref = BinaryenExpressionRef_val(_ref); + BinaryenType castType = BinaryenType_val(_castType); + BinaryenExpressionRef exp = BinaryenRefCast(module, ref, castType); + CAMLreturn(alloc_BinaryenExpressionRef(exp)); +} + +CAMLprim value +caml_binaryen_br_on(value _module, value _op, value _name, value _ref, value _castType) { + CAMLparam5(_module, _op, _name, _ref, _castType); + BinaryenModuleRef module = BinaryenModuleRef_val(_module); + BinaryenOp op = BinaryenOp_val(_op); + char* name = Safe_String_val(_name); + BinaryenExpressionRef ref = BinaryenExpressionRef_val(_ref); + BinaryenType castType = BinaryenType_val(_castType); + BinaryenExpressionRef exp = BinaryenBrOn(module, op, name, ref, castType); + CAMLreturn(alloc_BinaryenExpressionRef(exp)); +} + CAMLprim value caml_binaryen_expression_id_invalid(value unit) { CAMLparam1(unit); @@ -1328,6 +1392,90 @@ caml_binaryen_call_indirect_set_return(value _exp, value _isReturn) { CAMLreturn(Val_unit); } +CAMLprim value +caml_binaryen_call_ref_get_target(value _exp) { + CAMLparam1(_exp); + BinaryenExpressionRef exp = BinaryenExpressionRef_val(_exp); + BinaryenExpressionRef target = BinaryenCallRefGetTarget(exp); + CAMLreturn(alloc_BinaryenExpressionRef(target)); +} + +CAMLprim value +caml_binaryen_call_ref_set_target(value _exp, value _target) { + CAMLparam2(_exp, _target); + BinaryenExpressionRef exp = BinaryenExpressionRef_val(_exp); + BinaryenExpressionRef target = BinaryenExpressionRef_val(_target); + BinaryenCallRefSetTarget(exp, target); + CAMLreturn(Val_unit); +} + +CAMLprim value +caml_binaryen_call_ref_get_num_operands(value _exp) { + CAMLparam1(_exp); + BinaryenExpressionRef exp = BinaryenExpressionRef_val(_exp); + CAMLreturn(Val_int(BinaryenCallRefGetNumOperands(exp))); +} + +CAMLprim value +caml_binaryen_call_ref_get_operand_at(value _exp, value _index) { + CAMLparam2(_exp, _index); + BinaryenExpressionRef exp = BinaryenExpressionRef_val(_exp); + BinaryenIndex index = Int_val(_index); + CAMLreturn(alloc_BinaryenExpressionRef(BinaryenCallRefGetOperandAt(exp, index))); +} + +CAMLprim value +caml_binaryen_call_ref_set_operand_at(value _exp, value _index, value _operand) { + CAMLparam3(_exp, _index, _operand); + BinaryenExpressionRef exp = BinaryenExpressionRef_val(_exp); + BinaryenIndex index = Int_val(_index); + BinaryenExpressionRef operand = BinaryenExpressionRef_val(_operand); + BinaryenCallRefSetOperandAt(exp, index, operand); + CAMLreturn(Val_unit); +} + +CAMLprim value +caml_binaryen_call_ref_append_operand(value _exp, value _operand) { + CAMLparam2(_exp, _operand); + BinaryenExpressionRef exp = BinaryenExpressionRef_val(_exp); + BinaryenExpressionRef operand = BinaryenExpressionRef_val(_operand); + CAMLreturn(Val_int(BinaryenCallRefAppendOperand(exp, operand))); +} + +CAMLprim value +caml_binaryen_call_ref_insert_operand_at(value _exp, value _index, value _operand) { + CAMLparam3(_exp, _index, _operand); + BinaryenExpressionRef exp = BinaryenExpressionRef_val(_exp); + BinaryenIndex index = Int_val(_index); + BinaryenExpressionRef operand = BinaryenExpressionRef_val(_operand); + BinaryenCallRefInsertOperandAt(exp, index, operand); + CAMLreturn(Val_unit); +} + +CAMLprim value +caml_binaryen_call_ref_remove_operand_at(value _exp, value _index) { + CAMLparam2(_exp, _index); + BinaryenExpressionRef exp = BinaryenExpressionRef_val(_exp); + BinaryenIndex index = Int_val(_index); + CAMLreturn(alloc_BinaryenExpressionRef(BinaryenCallRefRemoveOperandAt(exp, index))); +} + +CAMLprim value +caml_binaryen_call_ref_is_return(value _exp) { + CAMLparam1(_exp); + BinaryenExpressionRef exp = BinaryenExpressionRef_val(_exp); + CAMLreturn(Val_bool(BinaryenCallRefIsReturn(exp))); +} + +CAMLprim value +caml_binaryen_call_ref_set_return(value _exp, value _isReturn) { + CAMLparam2(_exp, _isReturn); + BinaryenExpressionRef exp = BinaryenExpressionRef_val(_exp); + int isReturn = Bool_val(_isReturn); + BinaryenCallRefSetReturn(exp, isReturn); + CAMLreturn(Val_unit); +} + CAMLprim value caml_binaryen_local_set_get_value(value _exp) { CAMLparam1(_exp); @@ -1883,6 +2031,203 @@ caml_binaryen_ref_eq(value _module, value _left, value _right) { CAMLreturn(alloc_BinaryenExpressionRef(exp)); } +// Struct operations + +CAMLprim value +caml_binaryen_struct_new(value _module, value _operands, value _type) { + CAMLparam3(_module, _operands, _type); + BinaryenModuleRef module = BinaryenModuleRef_val(_module); + BinaryenHeapType type = BinaryenHeapType_val(_type); + if (Is_some(_operands)) { + _operands = array_of_list(Some_val(_operands)); + int operandsLen = array_length(_operands); + BinaryenExpressionRef operands[operandsLen]; + for (int i = 0; i < operandsLen; i++) { + operands[i] = BinaryenExpressionRef_val(Field(_operands, i)); + } + BinaryenExpressionRef exp = BinaryenStructNew(module, operands, operandsLen, type); + CAMLreturn(alloc_BinaryenExpressionRef(exp)); + } else { + BinaryenExpressionRef exp = BinaryenStructNew(module, NULL, 0, type); + CAMLreturn(alloc_BinaryenExpressionRef(exp)); + } +} + +CAMLprim value +caml_binaryen_struct_get(value _module, value _index, value _ref, value _type, value _signed) { + CAMLparam5(_module, _index, _ref, _type, _signed); + BinaryenModuleRef module = BinaryenModuleRef_val(_module); + BinaryenIndex index = Int_val(_index); + BinaryenExpressionRef ref = BinaryenExpressionRef_val(_ref); + BinaryenType type = BinaryenType_val(_type); + bool signed_ = Bool_val(_signed); + BinaryenExpressionRef exp = BinaryenStructGet(module, index, ref, type, signed_); + CAMLreturn(alloc_BinaryenExpressionRef(exp)); +} + +CAMLprim value +caml_binaryen_struct_set(value _module, value _index, value _ref, value _value) { + CAMLparam4(_module, _index, _ref, _value); + BinaryenModuleRef module = BinaryenModuleRef_val(_module); + BinaryenIndex index = Int_val(_index); + BinaryenExpressionRef ref = BinaryenExpressionRef_val(_ref); + BinaryenExpressionRef value_ = BinaryenExpressionRef_val(_value); + BinaryenExpressionRef exp = BinaryenStructSet(module, index, ref, value_); + CAMLreturn(alloc_BinaryenExpressionRef(exp)); +} + +// Array operations + +CAMLprim value +caml_binaryen_array_new(value _module, value _type, value _size, value _init) { + CAMLparam4(_module, _type, _size, _init); + BinaryenModuleRef module = BinaryenModuleRef_val(_module); + BinaryenHeapType type = BinaryenHeapType_val(_type); + BinaryenExpressionRef size = BinaryenExpressionRef_val(_size); + BinaryenExpressionRef init = BinaryenExpressionRef_val(_init); + BinaryenExpressionRef exp = BinaryenArrayNew(module, type, size, init); + CAMLreturn(alloc_BinaryenExpressionRef(exp)); +} + +CAMLprim value +caml_binaryen_array_new_data(value _module, value _type, value _name, value _offset, value _size) { + CAMLparam5(_module, _type, _name, _offset, _size); + BinaryenModuleRef module = BinaryenModuleRef_val(_module); + BinaryenHeapType type = BinaryenHeapType_val(_type); + char* name = Safe_String_val(_name); + BinaryenExpressionRef offset = BinaryenExpressionRef_val(_offset); + BinaryenExpressionRef size = BinaryenExpressionRef_val(_size); + BinaryenExpressionRef exp = BinaryenArrayNewData(module, type, name, offset, size); + CAMLreturn(alloc_BinaryenExpressionRef(exp)); +} + +CAMLprim value +caml_binaryen_array_new_elem(value _module, value _type, value _seg, value _offset, value _size) { + CAMLparam5(_module, _type, _seg, _offset, _size); + BinaryenModuleRef module = BinaryenModuleRef_val(_module); + BinaryenHeapType type = BinaryenHeapType_val(_type); + char* seg = Safe_String_val(_seg); + BinaryenExpressionRef offset = BinaryenExpressionRef_val(_offset); + BinaryenExpressionRef size = BinaryenExpressionRef_val(_size); + BinaryenExpressionRef exp = BinaryenArrayNewElem(module, type, seg, offset, size); + CAMLreturn(alloc_BinaryenExpressionRef(exp)); +} + +CAMLprim value +caml_binaryen_array_new_fixed(value _module, value _type, value _values) { + CAMLparam3(_module, _type, _values); + BinaryenModuleRef module = BinaryenModuleRef_val(_module); + BinaryenHeapType type = BinaryenHeapType_val(_type); + _values = array_of_list(_values); + int valuesLen = array_length(_values); + BinaryenExpressionRef values[valuesLen]; + for (int i = 0; i < valuesLen; i++) { + values[i] = BinaryenExpressionRef_val(Field(_values, i)); + } + BinaryenExpressionRef exp = BinaryenArrayNewFixed(module, type, values, valuesLen); + CAMLreturn(alloc_BinaryenExpressionRef(exp)); +} + +CAMLprim value +caml_binaryen_array_get(value _module, value _ref, value _index, value _type, value _signed) { + CAMLparam5(_module, _ref, _index, _type, _signed); + BinaryenModuleRef module = BinaryenModuleRef_val(_module); + BinaryenExpressionRef ref = BinaryenExpressionRef_val(_ref); + BinaryenExpressionRef index = BinaryenExpressionRef_val(_index); + BinaryenType type = BinaryenType_val(_type); + bool signed_ = Bool_val(_signed); + BinaryenExpressionRef exp = BinaryenArrayGet(module, ref, index, type, signed_); + CAMLreturn(alloc_BinaryenExpressionRef(exp)); +} + +CAMLprim value +caml_binaryen_array_set(value _module, value _ref, value _index, value _value) { + CAMLparam4(_module, _ref, _index, _value); + BinaryenModuleRef module = BinaryenModuleRef_val(_module); + BinaryenExpressionRef ref = BinaryenExpressionRef_val(_ref); + BinaryenExpressionRef index = BinaryenExpressionRef_val(_index); + BinaryenExpressionRef value_ = BinaryenExpressionRef_val(_value); + BinaryenExpressionRef exp = BinaryenArraySet(module, ref, index, value_); + CAMLreturn(alloc_BinaryenExpressionRef(exp)); +} + +CAMLprim value +caml_binaryen_array_len(value _module, value _ref) { + CAMLparam2(_module, _ref); + BinaryenModuleRef module = BinaryenModuleRef_val(_module); + BinaryenExpressionRef ref = BinaryenExpressionRef_val(_ref); + BinaryenExpressionRef exp = BinaryenArrayLen(module, ref); + CAMLreturn(alloc_BinaryenExpressionRef(exp)); +} + +CAMLprim value +caml_binaryen_array_copy(value _module, value _destRef, value _destIndex, value _srcRef, value _srcIndex, value _length) { + CAMLparam5(_module, _destRef, _destIndex, _srcRef, _srcIndex); + CAMLxparam1(_length); + BinaryenModuleRef module = BinaryenModuleRef_val(_module); + BinaryenExpressionRef destRef = BinaryenExpressionRef_val(_destRef); + BinaryenExpressionRef destIndex = BinaryenExpressionRef_val(_destIndex); + BinaryenExpressionRef srcRef = BinaryenExpressionRef_val(_srcRef); + BinaryenExpressionRef srcIndex = BinaryenExpressionRef_val(_srcIndex); + BinaryenExpressionRef length = BinaryenExpressionRef_val(_length); + BinaryenExpressionRef exp = BinaryenArrayCopy(module, destRef, destIndex, srcRef, srcIndex, length); + CAMLreturn(alloc_BinaryenExpressionRef(exp)); +} +CAMLprim value +caml_binaryen_array_copy__bytecode(value * argv) { + return caml_binaryen_array_copy(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]); +} + +CAMLprim value +caml_binaryen_array_fill(value _module, value _ref, value _index, value _value, value _size) { + CAMLparam5(_module, _ref, _index, _value, _size); + BinaryenModuleRef module = BinaryenModuleRef_val(_module); + BinaryenExpressionRef ref = BinaryenExpressionRef_val(_ref); + BinaryenExpressionRef index = BinaryenExpressionRef_val(_index); + BinaryenExpressionRef val = BinaryenExpressionRef_val(_value); + BinaryenExpressionRef size = BinaryenExpressionRef_val(_size); + BinaryenExpressionRef exp = BinaryenArrayFill(module, ref, index, val, size); + CAMLreturn(alloc_BinaryenExpressionRef(exp)); +} + +CAMLprim value +caml_binaryen_array_init_data(value _module, value _name, value _ref, value _index, value _offset, value _size) { + CAMLparam5(_module, _name, _ref, _index, _offset); + CAMLxparam1(_size); + BinaryenModuleRef module = BinaryenModuleRef_val(_module); + char* name = Safe_String_val(_name); + BinaryenExpressionRef ref = BinaryenExpressionRef_val(_ref); + BinaryenExpressionRef index = BinaryenExpressionRef_val(_index); + BinaryenExpressionRef offset = BinaryenExpressionRef_val(_offset); + BinaryenExpressionRef size = BinaryenExpressionRef_val(_size); + BinaryenExpressionRef exp = BinaryenArrayInitData(module, name, ref, index, offset, size); + CAMLreturn(alloc_BinaryenExpressionRef(exp)); +} + +CAMLprim value +caml_binaryen_array_init_data__bytecode(value * argv) { + return caml_binaryen_array_init_data(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]); +} + +CAMLprim value +caml_binaryen_array_init_elem(value _module, value _seg, value _ref, value _index, value _offset, value _size) { + CAMLparam5(_module, _seg, _ref, _index, _offset); + CAMLxparam1(_size); + BinaryenModuleRef module = BinaryenModuleRef_val(_module); + char* seg = Safe_String_val(_seg); + BinaryenExpressionRef ref = BinaryenExpressionRef_val(_ref); + BinaryenExpressionRef index = BinaryenExpressionRef_val(_index); + BinaryenExpressionRef offset = BinaryenExpressionRef_val(_offset); + BinaryenExpressionRef size = BinaryenExpressionRef_val(_size); + BinaryenExpressionRef exp = BinaryenArrayInitElem(module, seg, ref, index, offset, size); + CAMLreturn(alloc_BinaryenExpressionRef(exp)); +} + +CAMLprim value +caml_binaryen_array_init_elem__bytecode(value * argv) { + return caml_binaryen_array_init_elem(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]); +} + // Exception handling operations CAMLprim value caml_binaryen_try(value _module, value _name, value _body, value _catchTags, value _catchBodies, value _delegateTarget) { diff --git a/src/expression.js b/src/expression.js index 2fd5f650..586acebb 100644 --- a/src/expression.js +++ b/src/expression.js @@ -101,6 +101,28 @@ function caml_binaryen_call_indirect__bytecode() { ); } +//Provides: caml_binaryen_call_ref +//Requires: caml_jsstring_of_string +//Requires: caml_list_to_js_array +function caml_binaryen_call_ref(wasm_mod, target, params, typ) { + return wasm_mod.call_ref( + target, + caml_list_to_js_array(params), + typ + ); +} + +//Provides: caml_binaryen_return_call_ref +//Requires: caml_jsstring_of_string +//Requires: caml_list_to_js_array +function caml_binaryen_return_call_ref(wasm_mod, target, params, typ) { + return wasm_mod.return_call_ref( + target, + caml_list_to_js_array(params), + typ + ); +} + //Provides: caml_binaryen_return_call //Requires: caml_jsstring_of_string //Requires: caml_list_to_js_array @@ -547,6 +569,32 @@ function caml_binaryen_ref_i31(wasm_mod, typ) { return wasm_mod.ref.i31(typ); } +//Provides: caml_binaryen_ref_test +function caml_binaryen_ref_test(wasm_mod, ref, typ) { + return wasm_mod.ref.test(ref, typ); +} + +//Provides: caml_binaryen_ref_cast +function caml_binaryen_ref_cast(wasm_mod, ref, typ) { + return wasm_mod.ref.cast(ref, typ); +} + +//Provides: caml_binaryen_br_on +//Requires: caml_jsstring_of_string +//Requires: Binaryen +function caml_binaryen_br_on(wasm_mod, op, name, ref, typ) { + switch (op) { + case Binaryen.BrOnNull: + return wasm_mod.br_on_null(caml_jsstring_of_string(name), ref); + case Binaryen.BrOnNonNull: + return wasm_mod.br_on_non_null(caml_jsstring_of_string(name), ref); + case Binaryen.BrOnCast: + return wasm_mod.br_on_cast(caml_jsstring_of_string(name), ref, typ); + case Binaryen.BrOnCastFail: + return wasm_mod.br_on_cast_fail(caml_jsstring_of_string(name), ref, typ); + } +} + //Provides: caml_binaryen_i31_get function caml_binaryen_i31_get(wasm_mod, typ, signed) { if (signed) { @@ -1296,6 +1344,68 @@ function caml_binaryen_call_indirect_set_return(exp, isReturn) { return Binaryen.CallIndirect.setReturn(exp, caml_js_from_bool(isReturn)); } +//Provides: caml_binaryen_call_ref_get_target +//Requires: Binaryen +function caml_binaryen_call_ref_get_target(exp) { + return Binaryen.CallRef.getTarget(exp); +} + +//Provides: caml_binaryen_call_ref_set_target +//Requires: Binaryen +function caml_binaryen_call_ref_set_target(exp, target) { + return Binaryen.CallRef.setTarget(exp, target); +} + +//Provides: caml_binaryen_call_ref_get_num_operands +//Requires: Binaryen +function caml_binaryen_call_ref_get_num_operands(exp) { + return Binaryen.CallRef.getNumOperands(exp); +} + +//Provides: caml_binaryen_call_ref_get_operand_at +//Requires: Binaryen +function caml_binaryen_call_ref_get_operand_at(exp, index) { + return Binaryen.CallRef.getOperandAt(exp, index); +} + +//Provides: caml_binaryen_call_ref_set_operand_at +//Requires: Binaryen +function caml_binaryen_call_ref_set_operand_at(exp, index, operand) { + return Binaryen.CallRef.setOperandAt(exp, index, operand); +} + +//Provides: caml_binaryen_call_ref_append_operand +//Requires: Binaryen +function caml_binaryen_call_ref_append_operand(exp, operand) { + return Binaryen.CallRef.appendOperand(exp, operand); +} + +//Provides: caml_binaryen_call_ref_insert_operand_at +//Requires: Binaryen +function caml_binaryen_call_ref_insert_operand_at(exp, index, operand) { + return Binaryen.CallRef.insertOperandAt(exp, index, operand); +} + +//Provides: caml_binaryen_call_ref_remove_operand_at +//Requires: Binaryen +function caml_binaryen_call_ref_remove_operand_at(exp, index) { + return Binaryen.CallRef.removeOperandAt(exp, index); +} + +//Provides: caml_binaryen_call_ref_is_return +//Requires: Binaryen +//Requires: caml_js_to_bool +function caml_binaryen_call_ref_is_return(exp) { + return caml_js_to_bool(Binaryen.CallRef.isReturn(exp)); +} + +//Provides: caml_binaryen_call_ref_set_return +//Requires: Binaryen +//Requires: caml_js_from_bool +function caml_binaryen_call_ref_set_return(exp, isReturn) { + return Binaryen.CallRef.setReturn(exp, caml_js_from_bool(isReturn)); +} + //Provides: caml_binaryen_local_set_get_value //Requires: Binaryen function caml_binaryen_local_set_get_value(exp) { @@ -1704,7 +1814,135 @@ function caml_binaryen_ref_func(wasm_mod, name, typ) { //Provides: caml_binaryen_ref_eq function caml_binaryen_ref_eq(wasm_mod, left, right) { - return wasm_mod.ref.func(left, right); + return wasm_mod.ref.eq(left, right); +} + +// Struct operations + +//Provides: caml_binaryen_struct_new +//Requires: caml_list_to_js_array +function caml_binaryen_struct_new(wasm_mod, operands, type) { + return wasm_mod.struct.new( + operands ? caml_list_to_js_array(operands[1]) : null, + type + ); +} + +//Provides: caml_binaryen_struct_get +//Requires: caml_js_from_bool +function caml_binaryen_struct_get(wasm_mod, index, ref, type, signed) { + return wasm_mod.struct.get(index, ref, type, caml_js_from_bool(signed)); +} + +//Provides: caml_binaryen_struct_set +function caml_binaryen_struct_set(wasm_mod, index, ref, value) { + return wasm_mod.struct.set(index, ref, value); +} + +// Array operations + +//Provides: caml_binaryen_array_new +function caml_binaryen_array_new(wasm_mod, type, size, init) { + return wasm_mod.array.new(type, size, init); +} + +//Provides: caml_binaryen_array_new_data +//Requires: caml_jsstring_of_string +function caml_binaryen_array_new_data(wasm_mod, type, name, offset, size) { + return wasm_mod.array.new_data( + type, + caml_jsstring_of_string(name), + offset, + size + ); +} + +//Provides: caml_binaryen_array_new_elem +//Requires: caml_jsstring_of_string +function caml_binaryen_array_new_elem(wasm_mod, type, name, offset, size) { + return wasm_mod.array.new_elem( + type, + caml_jsstring_of_string(name), + offset, + size + ); +} + +//Provides: caml_binaryen_array_new_fixed +//Requires: caml_list_to_js_array +function caml_binaryen_array_new_fixed(wasm_mod, type, values) { + return wasm_mod.array.new_fixed(type, caml_list_to_js_array(values)); +} + +//Provides: caml_binaryen_array_get +//Requires: caml_js_from_bool +function caml_binaryen_array_get(wasm_mod, ref, index, type, signed) { + return wasm_mod.array.get(ref, index, type, caml_js_from_bool(signed)); +} + +//Provides: caml_binaryen_array_set +function caml_binaryen_array_set(wasm_mod, ref, index, value) { + return wasm_mod.array.set(ref, index, value); +} + +//Provides: caml_binaryen_array_len +function caml_binaryen_array_len(wasm_mod, ref) { + return wasm_mod.array.len(ref); +} + +//Provides: caml_binaryen_array_fill +function caml_binaryen_array_fill(wasm_mod, ref, index, value, size) { + return wasm_mod.array.fill(ref, index, value, size); +} + +//Provides: caml_binaryen_array_copy +function caml_binaryen_array_copy( + wasm_mod, + destRef, + destIndex, + srcRef, + srcIndex, + length +) { + return wasm_mod.array.copy(destRef, destIndex, srcRef, srcIndex, length); +} + +//Provides: caml_binaryen_array_init_data +//Requires: caml_jsstring_of_string +function caml_binaryen_array_init_data(wasm_mod, name, ref, index, offset, size) { + return wasm_mod.array.init_data(caml_jsstring_of_string(name), ref, index, offset, size); +} + +//Provides: caml_binaryen_array_init_data__bytecode +//Requires: caml_binaryen_array_init_data +function caml_binaryen_array_init_data__bytecode() { + return caml_binaryen_array_init_data( + arguments[0], + arguments[1], + arguments[2], + arguments[3], + arguments[4], + arguments[5] + ); +} + +//Provides: caml_binaryen_array_init_elem +//Requires: caml_jsstring_of_string +function caml_binaryen_array_init_elem(wasm_mod, name, ref, index, offset, size) { + return wasm_mod.array.init_elem(caml_jsstring_of_string(name), ref, index, offset, size); +} + +//Provides: caml_binaryen_array_copy__bytecode +//Requires: caml_binaryen_array_copy +function caml_binaryen_array_copy__bytecode() { + return caml_binaryen_array_copy( + arguments[0], + arguments[1], + arguments[2], + arguments[3], + arguments[4], + arguments[5] + ); } // Exception handling operations diff --git a/src/expression.ml b/src/expression.ml index 9328e31a..9780b83b 100644 --- a/src/expression.ml +++ b/src/expression.ml @@ -583,6 +583,44 @@ module Call_indirect = struct = "caml_binaryen_call_indirect_set_return" end +module Call_ref = struct + external make : Module.t -> t -> t list -> Type.t -> t + = "caml_binaryen_call_ref" + + (** Module, function value, params, type. *) + let make mod_ target params typ = make mod_ target params typ + + external make_return : Module.t -> t -> t list -> Type.t -> t + = "caml_binaryen_return_call_ref" + + (** Module, function value, params, type. *) + let make_return mod_ target params typ = make_return mod_ target params typ + + external get_target : t -> t = "caml_binaryen_call_ref_get_target" + external set_target : t -> t -> unit = "caml_binaryen_call_ref_set_target" + + external get_num_operands : t -> int + = "caml_binaryen_call_ref_get_num_operands" + + external get_operand_at : t -> int -> t + = "caml_binaryen_call_ref_get_operand_at" + + external set_operand_at : t -> int -> t -> unit + = "caml_binaryen_call_ref_set_operand_at" + + external append_operand : t -> t -> int + = "caml_binaryen_call_ref_append_operand" + + external insert_operand_at : t -> int -> t -> unit + = "caml_binaryen_call_ref_insert_operand_at" + + external remove_operand_at : t -> int -> t + = "caml_binaryen_call_ref_remove_operand_at" + + external is_return : t -> bool = "caml_binaryen_call_ref_is_return" + external set_return : t -> bool -> unit = "caml_binaryen_call_ref_set_return" +end + module Local_get = struct external make : Module.t -> int -> Type.t -> t = "caml_binaryen_local_get" (** Module, slot, type. *) @@ -830,6 +868,74 @@ module Ref = struct external eq : Module.t -> t -> t -> t = "caml_binaryen_ref_eq" (** Module, left, right *) + + external test : Module.t -> t -> Type.t -> t = "caml_binaryen_ref_test" + (** Module, value, type *) + + external cast : Module.t -> t -> Type.t -> t = "caml_binaryen_ref_cast" + (** Module, value, type *) +end + +module BrOn = struct + external make : Module.t -> Op.t -> string -> t -> Type.t -> t + = "caml_binaryen_br_on" + (** Module, op, label, value, type *) +end + +module Struct = struct + external new_ : Module.t -> t list option -> Heap_type.t -> t + = "caml_binaryen_struct_new" + (** Mdoule, operands, type *) + + external get : Module.t -> int -> t -> Type.t -> bool -> t + = "caml_binaryen_struct_get" + (** Module, index, struct, type, signed *) + + external set : Module.t -> int -> t -> t -> t = "caml_binaryen_struct_set" + (** Module, index, struct, value *) +end + +module Array = struct + external new_ : Module.t -> Heap_type.t -> t -> t -> t + = "caml_binaryen_array_new" + (** Module, type, size, init *) + + external new_data : Module.t -> Heap_type.t -> string -> t -> t -> t + = "caml_binaryen_array_new_data" + (** Module, type, data name, offset, size *) + + external new_elem : Module.t -> Heap_type.t -> string -> t -> t -> t + = "caml_binaryen_array_new_elem" + (** Module, type, seg, offset, size *) + + external new_fixed : Module.t -> Heap_type.t -> t list -> t + = "caml_binaryen_array_new_fixed" + (** Module, type, values *) + + external get : Module.t -> t -> t -> Type.t -> bool -> t + = "caml_binaryen_array_get" + (** Module, array, index, type, signed *) + + external set : Module.t -> t -> t -> t -> t = "caml_binaryen_array_set" + (** Module, array, index, value *) + + external len : Module.t -> t -> t = "caml_binaryen_array_len" + (** Module, array *) + + external fill : Module.t -> t -> t -> t -> t -> t = "caml_binaryen_array_fill" + (** Module, array, index, value, offset *) + + external copy : Module.t -> t -> t -> t -> t -> t -> t + = "caml_binaryen_array_copy__bytecode" "caml_binaryen_array_copy" + (** Module, dest, dest index, src, src index, length *) + + external init_data : Module.t -> string -> t -> t -> t -> t -> t + = "caml_binaryen_array_init_data__bytecode" "caml_binaryen_array_init_data" + (** Module, name, ref, index, offset, size *) + + external init_elem : Module.t -> string -> t -> t -> t -> t -> t + = "caml_binaryen_array_init_elem__bytecode" "caml_binaryen_array_init_elem" + (** Module, seg, ref, index, offset, size *) end (** Bindings for `try_table` instruction. *) diff --git a/src/expression.mli b/src/expression.mli index 3b70645a..775cb27d 100644 --- a/src/expression.mli +++ b/src/expression.mli @@ -161,6 +161,21 @@ module Call_indirect : sig val set_return : t -> bool -> unit end +module Call_ref : sig + val make : Module.t -> t -> t list -> Type.t -> t + val make_return : Module.t -> t -> t list -> Type.t -> t + val get_target : t -> t + val set_target : t -> t -> unit + val get_num_operands : t -> int + val get_operand_at : t -> int -> t + val set_operand_at : t -> int -> t -> unit + val append_operand : t -> t -> int + val insert_operand_at : t -> int -> t -> unit + val remove_operand_at : t -> int -> t + val is_return : t -> bool + val set_return : t -> bool -> unit +end + module Local_get : sig val make : Module.t -> int -> Type.t -> t end @@ -348,6 +363,63 @@ module Ref : sig val eq : Module.t -> t -> t -> t (** Module, left, right *) + + val test : Module.t -> t -> Type.t -> t + (** Module, value, type *) + + val cast : Module.t -> t -> Type.t -> t + (** Module, value, type *) +end + +module BrOn : sig + val make : Module.t -> Op.t -> string -> t -> Type.t -> t + (** Module, op, label, value, type *) +end + +module Struct : sig + val new_ : Module.t -> t list option -> Heap_type.t -> t + (** Mdoule, operands, type *) + + val get : Module.t -> int -> t -> Type.t -> bool -> t + (** Module, index, struct, type, signed *) + + val set : Module.t -> int -> t -> t -> t + (** Module, index, struct, value *) +end + +module Array : sig + val new_ : Module.t -> Heap_type.t -> t -> t -> t + (** Module, type, size, init *) + + val new_data : Module.t -> Heap_type.t -> string -> t -> t -> t + (** Module, type, data name, offset, size *) + + val new_elem : Module.t -> Heap_type.t -> string -> t -> t -> t + (** Module, type, seg, offset, size *) + + val new_fixed : Module.t -> Heap_type.t -> t list -> t + (** Module, type, values *) + + val get : Module.t -> t -> t -> Type.t -> bool -> t + (** Module, array, index, type, signed *) + + val set : Module.t -> t -> t -> t -> t + (** Module, array, index, value *) + + val len : Module.t -> t -> t + (** Module, array *) + + val fill : Module.t -> t -> t -> t -> t -> t + (** Module, array, index, value, offset *) + + val copy : Module.t -> t -> t -> t -> t -> t -> t + (** Module, dest, dest index, src, src index, length *) + + val init_data : Module.t -> string -> t -> t -> t -> t -> t + (** Module, name, ref, index, offset, size *) + + val init_elem : Module.t -> string -> t -> t -> t -> t -> t + (** Module, seg, ref, index, offset, size *) end (** Bindings for `try` instruction. *) diff --git a/src/heap_type.c b/src/heap_type.c index 711e4ff8..b4a78bc6 100644 --- a/src/heap_type.c +++ b/src/heap_type.c @@ -148,3 +148,22 @@ caml_binaryen_type_get_heap_type(value _ty) { BinaryenHeapType heapTy = BinaryenTypeGetHeapType(ty); CAMLreturn(alloc_BinaryenHeapType(heapTy)); } + +CAMLprim value caml_binaryen_module_set_type_name(value _module, value _heapType, value _name) { + CAMLparam3(_module, _heapType, _name); + BinaryenModuleRef module = BinaryenModuleRef_val(_module); + BinaryenHeapType heapType = BinaryenHeapType_val(_heapType); + const char* name = String_val(_name); + BinaryenModuleSetTypeName(module, heapType, name); + CAMLreturn(Val_unit); +} + +CAMLprim value caml_binaryen_module_set_field_name(value _module, value _heapType, value _index, value _name) { + CAMLparam4(_module, _heapType, _index, _name); + BinaryenModuleRef module = BinaryenModuleRef_val(_module); + BinaryenHeapType heapType = BinaryenHeapType_val(_heapType); + BinaryenIndex index = Int_val(_index); + const char* name = String_val(_name); + BinaryenModuleSetFieldName(module, heapType, index, name); + CAMLreturn(Val_unit); +} \ No newline at end of file diff --git a/src/heap_type.js b/src/heap_type.js index b14ac2c7..acf0a30b 100644 --- a/src/heap_type.js +++ b/src/heap_type.js @@ -111,3 +111,15 @@ function caml_binaryen_heap_type_is_sub_type(left, right) { function caml_binaryen_type_get_heap_type(typ) { return Binaryen._BinaryenTypeGetHeapType(typ); } + +//Provides: caml_binaryen_module_set_type_name +//Requires: caml_jsstring_of_string +function caml_binaryen_module_set_type_name(wasm_mod, heapType, name) { + wasm_mod.setTypeName(heapType, caml_jsstring_of_string(name)); +} + +//Provides: caml_binaryen_module_set_field_name +//Requires: caml_jsstring_of_string +function caml_binaryen_module_set_field_name(wasm_mod, heapType, index, name) { + wasm_mod.setFieldName(heapType, index, caml_jsstring_of_string(name)); +} \ No newline at end of file diff --git a/src/heap_type.ml b/src/heap_type.ml index 44271e44..36ca38af 100644 --- a/src/heap_type.ml +++ b/src/heap_type.ml @@ -17,4 +17,13 @@ external is_struct : t -> bool = "caml_binaryen_heap_type_is_struct" external is_array : t -> bool = "caml_binaryen_heap_type_is_array" external is_bottom : t -> bool = "caml_binaryen_heap_type_is_bottom" external get_bottom : t -> t = "caml_binaryen_heap_type_get_bottom" -external is_sub_type : t -> bool = "caml_binaryen_heap_type_is_sub_type" +external is_sub_type : t -> t -> bool = "caml_binaryen_heap_type_is_sub_type" + +external set_type_name : Module.t -> t -> string -> unit + = "caml_binaryen_module_set_type_name" +(** Sets the textual name of a compound `heapType`. Has no effect if the type + already has a canonical name. *) + +external set_field_name : Module.t -> t -> int -> string -> unit + = "caml_binaryen_module_set_field_name" +(** Sets the field name of a struct `heapType` at index `index`. *) diff --git a/src/heap_type.mli b/src/heap_type.mli index ff28fa8f..471d1aa9 100644 --- a/src/heap_type.mli +++ b/src/heap_type.mli @@ -17,4 +17,11 @@ val is_struct : t -> bool val is_array : t -> bool val is_bottom : t -> bool val get_bottom : t -> t -val is_sub_type : t -> bool +val is_sub_type : t -> t -> bool + +val set_type_name : Module.t -> t -> string -> unit +(** Sets the textual name of a compound `heapType`. Has no effect if the type + already has a canonical name. *) + +val set_field_name : Module.t -> t -> int -> string -> unit +(** Sets the field name of a struct `heapType` at index `index`. *) diff --git a/src/ocaml_helpers.c b/src/ocaml_helpers.c index d8af8bb6..be2568dc 100644 --- a/src/ocaml_helpers.c +++ b/src/ocaml_helpers.c @@ -3,6 +3,7 @@ #include #include #include +#include #include "ocaml_helpers.h" @@ -102,6 +103,14 @@ value alloc_BinaryenElementSegmentRef(BinaryenElementSegmentRef elem) return v; } +/* Allocating an OCaml custom block to hold the given TypeBuilderRef */ +value alloc_TypeBuilderRef(TypeBuilderRef builder) +{ + value v = caml_alloc_custom(&binaryen_ops, sizeof(TypeBuilderRef), 0, 1); + TypeBuilderRef_val(v) = builder; + return v; +} + CAMLprim value array_of_list(value list) { CAMLparam1(list); diff --git a/src/ocaml_helpers.h b/src/ocaml_helpers.h index 939ba09e..5c32738c 100644 --- a/src/ocaml_helpers.h +++ b/src/ocaml_helpers.h @@ -23,6 +23,7 @@ static struct custom_operations binaryen_ops = { #define BinaryenModuleRef_val(v) (*((BinaryenModuleRef*) Data_custom_val(v))) #define BinaryenType_val(v) (*((BinaryenType*) Data_custom_val(v))) +#define BinaryenPackedType_val(v) Int_val(v) #define BinaryenHeapType_val(v) (*((BinaryenHeapType*) Data_custom_val(v))) #define BinaryenExpressionRef_val(v) (*((BinaryenExpressionRef*) Data_custom_val(v))) #define BinaryenOp_val(v) (*((BinaryenOp*) Data_custom_val(v))) @@ -33,6 +34,7 @@ static struct custom_operations binaryen_ops = { #define BinaryenExportRef_val(v) (*((BinaryenExportRef*) Data_custom_val(v))) #define BinaryenTableRef_val(v) (*((BinaryenTableRef*) Data_custom_val(v))) #define BinaryenElementSegmentRef_val(v) (*((BinaryenElementSegmentRef*) Data_custom_val(v))) +#define TypeBuilderRef_val(v) (*((TypeBuilderRef*) Data_custom_val(v))) #define Val_none Val_int(0) #define Some_val(v) Field(v, 0) @@ -78,6 +80,9 @@ value alloc_BinaryenTableRef(BinaryenTableRef table); /* Allocating an OCaml custom block to hold the given BinaryenElementSegmentRef */ value alloc_BinaryenElementSegmentRef(BinaryenElementSegmentRef elem); +/* Allocating an OCaml custom block to hold the given TypeBuilderRef */ +value alloc_TypeBuilderRef(TypeBuilderRef builder); + CAMLprim value array_of_list(value list); diff --git a/src/type.c b/src/type.c index 43855ec5..e8303ca5 100644 --- a/src/type.c +++ b/src/type.c @@ -147,14 +147,16 @@ caml_binaryen_type_create(value tys) { CAMLprim value caml_binaryen_type_expand(value _ty) { CAMLparam1(_ty); + CAMLlocal2(typeArray, field); BinaryenType ty = BinaryenType_val(_ty); int arity = BinaryenTypeArity(ty); BinaryenType* buf = malloc(sizeof(BinaryenType) * arity); BinaryenTypeExpand(ty, buf); - value typeArray = caml_alloc(arity, 0); + typeArray = caml_alloc(arity, 0); for (int i = 0; i < arity; i++) { - Field(typeArray, i) = alloc_BinaryenType(buf[i]); + field = alloc_BinaryenType(buf[i]); + Store_field(typeArray, i, field); } free(buf); @@ -176,4 +178,4 @@ caml_binaryen_type_from_heap_type(value _ty, value _nullable) { bool nullable = Bool_val(_nullable); BinaryenType ty = BinaryenTypeFromHeapType(heapTy, nullable); CAMLreturn(alloc_BinaryenType(ty)); -} +} \ No newline at end of file diff --git a/src/type.js b/src/type.js index ffbbcab5..9100766b 100644 --- a/src/type.js +++ b/src/type.js @@ -130,4 +130,4 @@ function caml_binaryen_type_is_nullable(typ) { //Requires: Binaryen function caml_binaryen_type_from_heap_type(typ, nullable) { return Binaryen._BinaryenTypeFromHeapType(typ, nullable); -} +} \ No newline at end of file diff --git a/src/type.ml b/src/type.ml index 119be8cc..8090acb6 100644 --- a/src/type.ml +++ b/src/type.ml @@ -75,5 +75,8 @@ let auto = auto () external create : t array -> t = "caml_binaryen_type_create" external expand : t -> t array = "caml_binaryen_type_expand" external is_nullable : t -> bool = "caml_binaryen_type_is_nullable" -external from_heap_type : Heap_type.t -> t = "caml_binaryen_type_from_heap_type" + +external from_heap_type : Heap_type.t -> bool -> t + = "caml_binaryen_type_from_heap_type" + external get_heap_type : t -> Heap_type.t = "caml_binaryen_type_get_heap_type" diff --git a/src/type.mli b/src/type.mli index 874ddb37..868ac579 100644 --- a/src/type.mli +++ b/src/type.mli @@ -21,5 +21,5 @@ val auto : t val create : t array -> t val expand : t -> t array val is_nullable : t -> bool -val from_heap_type : Heap_type.t -> t +val from_heap_type : Heap_type.t -> bool -> t val get_heap_type : t -> Heap_type.t diff --git a/src/type_builder.c b/src/type_builder.c new file mode 100644 index 00000000..886c9891 --- /dev/null +++ b/src/type_builder.c @@ -0,0 +1,180 @@ +#define CAML_NAME_SPACE +#include +#include +#include +#include + +#include "binaryen-c.h" +#include "ocaml_helpers.h" + +CAMLprim value +caml_type_builder_create(value _size) { + CAMLparam1(_size); + BinaryenIndex size = Int_val(_size); + CAMLreturn(alloc_TypeBuilderRef(TypeBuilderCreate(size))); +} + +CAMLprim value +caml_type_builder_grow(value _builder, value _count) { + CAMLparam2(_builder, _count); + TypeBuilderRef builder = TypeBuilderRef_val(_builder); + BinaryenIndex count = Int_val(_count); + TypeBuilderGrow(builder, count); + CAMLreturn(Val_unit); +} + +CAMLprim value +caml_type_builder_get_size(value _builder) { + CAMLparam1(_builder); + TypeBuilderRef builder = TypeBuilderRef_val(_builder); + CAMLreturn(Val_int(TypeBuilderGetSize(builder))); +} + +CAMLprim value +caml_type_builder_set_signature_type(value _builder, value _index, value _paramTypes, value _resultTypes) { + CAMLparam4(_builder, _index, _paramTypes, _resultTypes); + TypeBuilderRef builder = TypeBuilderRef_val(_builder); + BinaryenIndex index = Int_val(_index); + BinaryenType paramTypes = BinaryenType_val(_paramTypes); + BinaryenType resultTypes = BinaryenType_val(_resultTypes); + TypeBuilderSetSignatureType(builder, index, paramTypes, resultTypes); + CAMLreturn(Val_unit); +} + +CAMLprim value +caml_type_builder_set_struct_type(value _builder, value _index, value _fieldTypes, value _fieldPackedTypes, value _fieldMutables, value _numFields) { + CAMLparam5(_builder, _index, _fieldTypes, _fieldPackedTypes, _fieldMutables); + CAMLxparam1(_numFields); + TypeBuilderRef builder = TypeBuilderRef_val(_builder); + BinaryenIndex index = Int_val(_index); + _fieldTypes = array_of_list(_fieldTypes); + int fieldTypesLen = array_length(_fieldTypes); + BinaryenType fieldTypes[fieldTypesLen]; + for (int i = 0; i < fieldTypesLen; i++) { + fieldTypes[i] = BinaryenType_val(Field(_fieldTypes, i)); + } + _fieldPackedTypes = array_of_list(_fieldPackedTypes); + int fieldPackedTypesLen = array_length(_fieldPackedTypes); + BinaryenPackedType fieldPackedTypes[fieldPackedTypesLen]; + for (int i = 0; i < fieldPackedTypesLen; i++) { + fieldPackedTypes[i] = BinaryenPackedType_val(Field(_fieldPackedTypes, i)); + } + _fieldMutables = array_of_list(_fieldMutables); + int fieldMutablesLen = array_length(_fieldMutables); + bool fieldMutables[fieldMutablesLen]; + for (int i = 0; i < fieldMutablesLen; i++) { + fieldMutables[i] = Bool_val(Field(_fieldMutables, i)); + } + int numFields = Int_val(_numFields); + TypeBuilderSetStructType(builder, index, fieldTypes, fieldPackedTypes, fieldMutables, numFields); + CAMLreturn(Val_unit); +} +CAMLprim value +caml_type_builder_set_struct_type__bytecode(value * argv) { + return caml_type_builder_set_struct_type(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]); +} + +CAMLprim value +caml_type_builder_set_array_type(value _builder, value _index, value _elementType, value _elementPackedType, value _elementMutable) { + CAMLparam5(_builder, _index, _elementType, _elementPackedType, _elementMutable); + TypeBuilderRef builder = TypeBuilderRef_val(_builder); + BinaryenIndex index = Int_val(_index); + BinaryenType elementType = BinaryenType_val(_elementType); + BinaryenPackedType elementPackedType = BinaryenPackedType_val(_elementPackedType); + bool elementMutable = Bool_val(_elementMutable); + TypeBuilderSetArrayType(builder, index, elementType, elementPackedType, elementMutable); + CAMLreturn(Val_unit); +} + +CAMLprim value +caml_type_builder_get_temp_heap_type(value _builder, value _index) { + CAMLparam2(_builder, _index); + TypeBuilderRef builder = TypeBuilderRef_val(_builder); + BinaryenIndex index = Int_val(_index); + CAMLreturn(alloc_BinaryenHeapType(TypeBuilderGetTempHeapType(builder, index))); +} + +CAMLprim value +caml_type_builder_get_temp_tuple_type(value _builder, value _types) { + CAMLparam2(_builder, _types); + TypeBuilderRef builder = TypeBuilderRef_val(_builder); + _types = array_of_list(_types); + int typesLen = array_length(_types); + BinaryenType types[typesLen]; + for (int i = 0; i < typesLen; i++) { + types[i] = BinaryenType_val(Field(_types, i)); + } + CAMLreturn(alloc_BinaryenType(TypeBuilderGetTempTupleType(builder, types, typesLen))); +} + +CAMLprim value +caml_type_builder_get_temp_ref_type(value _builder, value _heapType, value _nullable) { + CAMLparam3(_builder, _heapType, _nullable); + TypeBuilderRef builder = TypeBuilderRef_val(_builder); + BinaryenHeapType heapType = BinaryenHeapType_val(_heapType); + bool nullable = Bool_val(_nullable); + CAMLreturn(alloc_BinaryenType(TypeBuilderGetTempRefType(builder, heapType, nullable))); +} + +CAMLprim value +caml_type_builder_set_sub_type(value _builder, value _index, value _superType) { + CAMLparam3(_builder, _index, _superType); + TypeBuilderRef builder = TypeBuilderRef_val(_builder); + BinaryenIndex index = Int_val(_index); + BinaryenHeapType superType = BinaryenHeapType_val(_superType); + TypeBuilderSetSubType(builder, index, superType); + CAMLreturn(Val_unit); +} + +CAMLprim value +caml_type_builder_set_open(value _builder, value _index) { + CAMLparam2(_builder, _index); + TypeBuilderRef builder = TypeBuilderRef_val(_builder); + BinaryenIndex index = Int_val(_index); + TypeBuilderSetOpen(builder, index); + CAMLreturn(Val_unit); +} + +CAMLprim value +caml_type_builder_create_rec_group(value _builder, value _index, value _length) { + CAMLparam3(_builder, _index, _length); + TypeBuilderRef builder = TypeBuilderRef_val(_builder); + BinaryenIndex index = Int_val(_index); + BinaryenIndex length = Int_val(_length); + TypeBuilderCreateRecGroup(builder, index, length); + CAMLreturn(Val_unit); +} + +CAMLprim value +caml_conv_heap_type(BinaryenHeapType heapType) { + return alloc_BinaryenHeapType(heapType); +} + +CAMLprim value caml_type_builder_build_and_dispose(value _builder) { + CAMLparam1(_builder); + CAMLlocal5(arr, ok, error, tuple, field); + TypeBuilderRef builder = TypeBuilderRef_val(_builder); + BinaryenIndex size = TypeBuilderGetSize(builder); + BinaryenHeapType heapTypes[size + 1]; + BinaryenIndex errorIndex; + TypeBuilderErrorReason errorReason; + bool success = + TypeBuilderBuildAndDispose(builder, heapTypes, &errorIndex, &errorReason); + if (success) { + arr = caml_alloc(size, 0); + for (mlsize_t i = 0; i < (mlsize_t)size; i++) { + field = alloc_BinaryenHeapType(heapTypes[i]); + Store_field(arr, i, field); + } + ok = caml_alloc_small(1, 0); + Store_field(ok, 0, arr); + CAMLreturn(ok); + } else { + error = caml_alloc_small(1, 1); + tuple = caml_alloc_small(2, 0); + Field(tuple, 0) = Val_int(errorIndex); + Field(tuple, 1) = Val_int(errorReason); + Store_field(error, 0, tuple); + CAMLreturn(error); + } +} \ No newline at end of file diff --git a/src/type_builder.js b/src/type_builder.js new file mode 100644 index 00000000..2e587d7f --- /dev/null +++ b/src/type_builder.js @@ -0,0 +1,116 @@ +//Provides: caml_type_builder_create +//Requires: Binaryen +function caml_type_builder_create(size) { + return new Binaryen.TypeBuilder(size); +} + +//Provides: caml_type_builder_grow +function caml_type_builder_grow(builder, count) { + builder.grow(count); +} + +//Provides: caml_type_builder_get_size +function caml_type_builder_get_size(builder) { + return builder.getSize(); +} + +//Provides: caml_type_builder_set_signature_type +function caml_type_builder_set_signature_type( + builder, + index, + paramTypes, + resultTypes +) { + builder.setSignatureType(index, paramTypes, resultTypes); +} + +//Provides: caml_type_builder_set_struct_type +//Requires: caml_list_to_js_array +//Requires: caml_js_from_bool +function caml_type_builder_set_struct_type( + builder, + index, + fieldTypes, + fieldPackedTypes, + fieldMutables, + numFields +) { + var types = caml_list_to_js_array(fieldTypes); + var packedTypes = caml_list_to_js_array(fieldPackedTypes); + var mutables = caml_list_to_js_array(fieldMutables); + var fields = types.map(function (type, idx) { + return { + type, + packedType: packedTypes[idx], + mutable: caml_js_from_bool(mutables[idx]), + }; + }); + builder.setStructType(index, fields); +} +//Provides: caml_type_builder_set_struct_type__bytecode +//Requires: caml_type_builder_set_struct_type +function caml_type_builder_set_struct_type__bytecode() { + return caml_type_builder_set_struct_type( + arguments[0], + arguments[1], + arguments[2], + arguments[3], + arguments[4], + arguments[5] + ); +} + +//Provides: caml_type_builder_set_array_type +function caml_type_builder_set_array_type( + builder, + index, + elementType, + elementPackedType, + elementMutable +) { + builder.setArrayType(index, elementType, elementPackedType, elementMutable); +} + +//Provides: caml_type_builder_get_temp_heap_type +function caml_type_builder_get_temp_heap_type(builder, index) { + return builder.getTempHeapType(index); +} + +//Provides: caml_type_builder_get_temp_tuple_type +//Requires: caml_list_to_js_array +function caml_type_builder_get_temp_tuple_type(builder, types) { + var tupleTypes = caml_list_to_js_array(types); + return builder.getTempTupleType(tupleTypes); +} + +//Provides: caml_type_builder_get_temp_ref_type +//Requires: caml_js_from_bool +function caml_type_builder_get_temp_ref_type(builder, heapType, nullable) { + return builder.getTempRefType(heapType, caml_js_from_bool(nullable)); +} + +//Provides: caml_type_builder_set_sub_type +function caml_type_builder_set_sub_type(builder, index, superType) { + builder.setSubType(index, superType); +} + +//Provides: caml_type_builder_set_open +function caml_type_builder_set_open(builder, index) { + builder.setOpen(index); +} + +//Provides: caml_type_builder_create_rec_group +function caml_type_builder_create_rec_group(builder, index, length) { + builder.createRecGroup(index, length); +} + +//Provides: caml_type_builder_build_and_dispose +//Requires: caml_js_to_array +function caml_type_builder_build_and_dispose(builder) { + try { + var types = builder.buildAndDispose(); + return [0, caml_js_to_array(types)]; + } catch (e) { + return [1, [0, e.index, e.reason]]; + } +} diff --git a/src/type_builder.ml b/src/type_builder.ml new file mode 100644 index 00000000..1a41f101 --- /dev/null +++ b/src/type_builder.ml @@ -0,0 +1,67 @@ +type t + +type struct_field = { + type_ : Type.t; + packed_type : Packed_type.t; + mutable_ : bool; +} + +(* Source: https://github.com/WebAssembly/binaryen/blob/64ba23996a10e229d46e41eb37736a55af87f79a/src/binaryen-c.h#L3618 *) +type error = + | SelfSupertype of int + | InvalidSupertype of int + | ForwardSupertypeReference of int + | ForwardChildReference of int + +external make : int -> t = "caml_type_builder_create" +external grow : t -> int -> unit = "caml_type_builder_grow" +external size : t -> int = "caml_type_builder_get_size" + +external set_signature_type : t -> int -> Type.t -> Type.t -> unit + = "caml_type_builder_set_signature_type" + +external set_struct_type : + t -> int -> Type.t list -> Packed_type.t list -> bool list -> int -> unit + = "caml_type_builder_set_struct_type__bytecode" + "caml_type_builder_set_struct_type" + +let set_struct_type builder index fields = + let split_fields fields = + List.fold_right + (fun { type_; packed_type; mutable_ } (types, packed_types, mutables) -> + (type_ :: types, packed_type :: packed_types, mutable_ :: mutables)) + fields ([], [], []) + in + let types, packed_types, mutables = split_fields fields in + set_struct_type builder index types packed_types mutables (List.length types) + +external set_array_type : t -> int -> Type.t -> Packed_type.t -> bool -> unit + = "caml_type_builder_set_array_type" + +external get_temp_heap_type : t -> int -> Heap_type.t + = "caml_type_builder_get_temp_heap_type" + +external get_temp_tuple_type : t -> Type.t list -> Type.t + = "caml_type_builder_get_temp_tuple_type" + +external get_temp_ref_type : t -> Heap_type.t -> bool -> Type.t + = "caml_type_builder_get_temp_ref_type" + +external set_sub_type : t -> int -> Heap_type.t -> unit + = "caml_type_builder_set_sub_type" + +external set_open : t -> int -> unit = "caml_type_builder_set_open" + +external create_rec_group : t -> int -> int -> unit + = "caml_type_builder_create_rec_group" + +external build_and_dispose : t -> (Heap_type.t array, int * int) result + = "caml_type_builder_build_and_dispose" + +let build_and_dispose builder = + match build_and_dispose builder with + | Ok types -> Ok (Array.to_list types) + | Error (idx, 0) -> Error (SelfSupertype idx) + | Error (idx, 1) -> Error (InvalidSupertype idx) + | Error (idx, 2) -> Error (ForwardSupertypeReference idx) + | Error (idx, _) -> Error (ForwardChildReference idx) diff --git a/src/type_builder.mli b/src/type_builder.mli new file mode 100644 index 00000000..f76dfbb1 --- /dev/null +++ b/src/type_builder.mli @@ -0,0 +1,28 @@ +type t + +type struct_field = { + type_ : Type.t; + packed_type : Packed_type.t; + mutable_ : bool; +} + +(* Source: https://github.com/WebAssembly/binaryen/blob/64ba23996a10e229d46e41eb37736a55af87f79a/src/binaryen-c.h#L3618 *) +type error = + | SelfSupertype of int + | InvalidSupertype of int + | ForwardSupertypeReference of int + | ForwardChildReference of int + +val make : int -> t +val grow : t -> int -> unit +val size : t -> int +val set_signature_type : t -> int -> Type.t -> Type.t -> unit +val set_struct_type : t -> int -> struct_field list -> unit +val set_array_type : t -> int -> Type.t -> Packed_type.t -> bool -> unit +val get_temp_heap_type : t -> int -> Heap_type.t +val get_temp_tuple_type : t -> Type.t list -> Type.t +val get_temp_ref_type : t -> Heap_type.t -> bool -> Type.t +val set_sub_type : t -> int -> Heap_type.t -> unit +val set_open : t -> int -> unit +val create_rec_group : t -> int -> int -> unit +val build_and_dispose : t -> (Heap_type.t list, error) result diff --git a/test/test.expected b/test/test.expected index 0a35f066..642a51c0 100644 --- a/test/test.expected +++ b/test/test.expected @@ -7,12 +7,16 @@ (i32.const 0) ) (module - (type $0 (func (param i32))) - (type $1 (func (param i32 i32) (result i32))) - (type $2 (func)) - (type $3 (func (param anyref i32 i32) (result i32))) - (type $4 (func (param anyref) (result i32))) - (import "future-wasi" "write" (func $write (type $3) (param anyref i32 i32) (result i32))) + (type $List (struct (field $head i31ref) (field $tail (ref null $List)))) + (type $1 (array (mut i8))) + (type $2 (func (param i32))) + (type $3 (func (param i32 i32) (result i32))) + (type $4 (func)) + (type $5 (func (param anyref i32 i32) (result i32))) + (type $6 (func (param anyref) (result i32))) + (type $7 (func (param anyref) (result anyref anyref))) + (type $8 (func (result (ref $1) (ref $List)))) + (import "future-wasi" "write" (func $write (type $5) (param anyref i32 i32) (result i32))) (global $max_int64 i64 (i64.const 9223372036854775807)) (global $max_int64_mut (mut i64) (i64.const 9223372036854775807)) (global $test_float64_bits f64 (f64.const 1.23)) @@ -21,14 +25,15 @@ (data $world "world") (table $table 1 1 funcref) (elem $elem (i32.const 0) $adder) - (tag $foo (type $0) (param i32)) - (tag $bar (type $0) (param i32)) + (tag $foo (type $2) (param i32)) + (tag $bar (type $2) (param i32)) (export "adder" (func $adder)) (export "memory" (memory $0)) (export "hello" (func $hello)) (export "try" (func $try)) + (export "gc" (func $gc)) (start $start) - (func $adder (type $1) (param $0 i32) (param $1 i32) (result i32) + (func $adder (type $3) (param $0 i32) (param $1 i32) (result i32) (block $add (result i32) (if (i32.const 0) @@ -48,7 +53,7 @@ ) ) ) - (func $start (type $2) + (func $start (type $4) (block $start (memory.init $world (i32.const 2048) @@ -56,7 +61,7 @@ (i32.const 5) ) (drop - (call_indirect $table (type $1) + (call_indirect $table (type $3) (i32.const 3) (i32.const 5) (i32.const 0) @@ -64,14 +69,14 @@ ) ) ) - (func $hello (type $4) (param $0 anyref) (result i32) + (func $hello (type $6) (param $0 anyref) (result i32) (call $write (local.get $0) (i32.const 0) (i32.const 1) ) ) - (func $try (type $2) + (func $try (type $4) (block $blk (drop (try $tc1 (result i32) @@ -139,27 +144,76 @@ ) ) ) + (func $gc (type $7) (param $0 anyref) (result anyref anyref) + (local $1 (ref $1)) + (local $2 (ref $List)) + (block $gc_block (type $8) (result (ref $1) (ref $List)) + (local.set $1 + (array.new_fixed $1 2 + (i32.const 0) + (i32.const 255) + ) + ) + (array.set $1 + (local.get $1) + (i32.const 1) + (i32.const 42) + ) + (local.set $2 + (struct.new $List + (ref.cast i31ref + (local.get $0) + ) + (struct.new $List + (ref.i31 + (i32.const 1) + ) + (struct.new $List + (ref.i31 + (i32.const 2) + ) + (struct.new $List + (ref.i31 + (i32.const 3) + ) + (ref.null none) + ) + ) + ) + ) + ) + (tuple.make 2 + (local.get $1) + (local.get $2) + ) + ) + ) ) (module - (type $0 (func (param i32))) - (type $1 (func)) - (type $2 (func (param i32 i32) (result i32))) - (type $3 (func (param anyref i32 i32) (result i32))) - (type $4 (func (param anyref) (result i32))) - (import "future-wasi" "write" (func $write (type $3) (param anyref i32 i32) (result i32))) + (type $List (struct (field $head i31ref) (field $tail (ref null $List)))) + (type $1 (array (mut i8))) + (type $2 (func (param i32))) + (type $3 (func)) + (type $4 (func (param i32 i32) (result i32))) + (type $5 (func (param anyref i32 i32) (result i32))) + (type $6 (func (param anyref) (result i32))) + (type $7 (func (param anyref) (result anyref anyref))) + (type $8 (func (result (ref (exact $1)) (ref (exact $List))))) + (import "future-wasi" "write" (func $write (type $5) (param anyref i32 i32) (result i32))) (memory $0 1) (data $hello (i32.const 0) "hello") (data $world "world") (table $table 1 1 funcref) (elem $elem (i32.const 0) $adder) - (tag $foo (type $0) (param i32)) - (tag $bar (type $0) (param i32)) + (tag $foo (type $2) (param i32)) + (tag $bar (type $2) (param i32)) (export "adder" (func $adder)) (export "memory" (memory $0)) (export "hello" (func $hello)) (export "try" (func $try)) + (export "gc" (func $gc)) (start $start) - (func $adder (type $2) (param $0 i32) (param $1 i32) (result i32) + (func $adder (type $4) (param $0 i32) (param $1 i32) (result i32) (i32.add (select (local.get $0) @@ -171,7 +225,7 @@ (local.get $1) ) ) - (func $start (type $1) + (func $start (type $3) (memory.init $world (i32.const 2048) (i32.const 0) @@ -184,14 +238,14 @@ ) ) ) - (func $hello (type $4) (param $0 anyref) (result i32) + (func $hello (type $6) (param $0 anyref) (result i32) (call $write (local.get $0) (i32.const 0) (i32.const 1) ) ) - (func $try (type $1) + (func $try (type $3) (drop (try (result i32) (do @@ -231,12 +285,53 @@ ) ) ) + (func $gc (type $7) (param $0 anyref) (result anyref anyref) + (local $1 (ref (exact $1))) + (array.set $1 + (local.tee $1 + (array.new_fixed $1 2 + (i32.const 0) + (i32.const 255) + ) + ) + (i32.const 1) + (i32.const 42) + ) + (tuple.make 2 + (local.get $1) + (struct.new $List + (ref.cast i31ref + (local.get $0) + ) + (struct.new $List + (ref.i31 + (i32.const 1) + ) + (struct.new $List + (ref.i31 + (i32.const 2) + ) + (struct.new $List + (ref.i31 + (i32.const 3) + ) + (ref.null none) + ) + ) + ) + ) + ) + ) ) (module + (type $type_7 (struct (field i31ref) (field (ref null $type_7)))) + (type $type_6 (array (mut i8))) (type $type_3 (func)) (type $type_1 (func (param anyref i32 i32) (result i32))) (type $type_2 (func (param i32 i32) (result i32))) (type $type_4 (func (param anyref) (result i32))) + (type $type_5 (func (param anyref) (result anyref anyref))) + (type $type_8 (func (result anyref anyref))) (import "future-wasi" "write" (func $fimport$0 (type $type_1) (param anyref i32 i32) (result i32))) (memory $0 1) (data $0 (i32.const 0) "hello") @@ -247,6 +342,7 @@ (export "memory" (memory $0)) (export "hello" (func $2)) (export "try" (func $3)) + (export "gc" (func $4)) (start $1) (func $0 (type $type_2) (param $0 i32) (param $1 i32) (result i32) (i32.add @@ -286,12 +382,53 @@ ) (unreachable) ) + (func $4 (type $type_5) (param $0 anyref) (result anyref anyref) + (local $1 (ref (exact $type_6))) + (array.set $type_6 + (local.tee $1 + (array.new_fixed $type_6 2 + (i32.const 0) + (i32.const 255) + ) + ) + (i32.const 1) + (i32.const 42) + ) + (tuple.make 2 + (local.get $1) + (struct.new $type_7 + (ref.cast i31ref + (local.get $0) + ) + (struct.new $type_7 + (ref.i31 + (i32.const 1) + ) + (struct.new $type_7 + (ref.i31 + (i32.const 2) + ) + (struct.new $type_7 + (ref.i31 + (i32.const 3) + ) + (ref.null none) + ) + ) + ) + ) + ) + ) ) (module + (type $type_7 (struct (field i31ref) (field (ref null $type_7)))) + (type $type_6 (array (mut i8))) (type $type_3 (func)) (type $type_1 (func (param anyref i32 i32) (result i32))) (type $type_2 (func (param i32 i32) (result i32))) (type $type_4 (func (param anyref) (result i32))) + (type $type_5 (func (param anyref) (result anyref anyref))) + (type $type_8 (func (result anyref anyref))) (import "future-wasi" "write" (func $fimport$0 (type $type_1) (param anyref i32 i32) (result i32))) (memory $0 1) (data $0 (i32.const 0) "hello") @@ -302,6 +439,7 @@ (export "memory" (memory $0)) (export "hello" (func $2)) (export "try" (func $3)) + (export "gc" (func $4)) (start $1) (func $0 (type $type_2) (param $0 i32) (param $1 i32) (result i32) local.get $0 @@ -331,4 +469,29 @@ (func $3 (type $type_3) unreachable ) + (func $4 (type $type_5) (param $0 anyref) (result anyref anyref) + (local $1 (ref (exact $type_6))) + i32.const 0 + i32.const 255 + array.new_fixed $type_6 2 + local.tee $1 + i32.const 1 + i32.const 42 + array.set $type_6 + local.get $1 + local.get $0 + ref.cast i31ref + i32.const 1 + ref.i31 + i32.const 2 + ref.i31 + i32.const 3 + ref.i31 + ref.null none + struct.new $type_7 + struct.new $type_7 + struct.new $type_7 + struct.new $type_7 + tuple.make 2 + ) ) diff --git a/test/test.ml b/test/test.ml index 95634257..cad22181 100644 --- a/test/test.ml +++ b/test/test.ml @@ -171,13 +171,19 @@ let start = let _ = Export.add_function_export wasm_mod "adder" "adder" let _ = Table.add_table wasm_mod "table" 1 1 Type.funcref -(* TODO(#240): Re-enable after type-builder api is merged *) -(* let funcref_expr1 = Expression.Ref.func wasm_mod "adder" (Heap_type.func ()) +let adder_type = + let builder = Type_builder.make 1 in + Type_builder.set_signature_type builder 0 (params ()) results; + match Type_builder.build_and_dispose builder with + | Ok [ ty ] -> ty + | _ -> failwith "failed to build type" + +let funcref_expr1 = Expression.Ref.func wasm_mod "adder" adder_type let _ = Expression.Table.set wasm_mod "table" (Expression.Const.make wasm_mod (Literal.int32 0l)) - funcref_expr1 *) + funcref_expr1 let funcref_expr2 = Expression.Table.get wasm_mod "table" @@ -257,6 +263,19 @@ let _ = (Memory.get_segment_data wasm_mod "world") (Bytes.of_string "world")) +(* Call_ref *) +let thunk_type = + let builder = Type_builder.make 1 in + Type_builder.set_signature_type builder 0 Type.none Type.none; + match Type_builder.build_and_dispose builder with + | Ok [ ty ] -> ty + | _ -> failwith "failed to build type" + +let _ = + Expression.Call_ref.make wasm_mod + (Expression.Ref.func wasm_mod "start" thunk_type) + [] Type.none + let _ = Tag.add_tag wasm_mod "foo" Type.int32 Type.none let _ = Tag.add_tag wasm_mod "bar" Type.int32 Type.none @@ -368,6 +387,111 @@ let _ = Export.add_function_export wasm_mod "hello" "hello" let _ = Export.add_function_export wasm_mod "try" "try" let _ = Module.validate wasm_mod +(* Create a function that does gc *) +let _ = + let array_u8_type = + let builder = Type_builder.make 1 in + Type_builder.set_array_type builder 0 Type.int32 Packed_type.int8 true; + match Type_builder.build_and_dispose builder with + | Ok [ ty ] -> ty + | _ -> failwith "failed to make array type" + in + let list_type = + let builder = Type_builder.make 1 in + let temp_heap_type = Type_builder.get_temp_heap_type builder 0 in + let temp_ref_type = + Type_builder.get_temp_ref_type builder temp_heap_type true + in + Type_builder.set_struct_type builder 0 + [ + Type_builder. + { + type_ = Type.i31ref; + packed_type = Packed_type.not_packed; + mutable_ = false; + }; + Type_builder. + { + type_ = temp_ref_type; + packed_type = Packed_type.not_packed; + mutable_ = false; + }; + ]; + match Type_builder.build_and_dispose builder with + | Ok [ ty ] -> ty + | _ -> failwith "failed to make list type" + in + let i32 v = Expression.Const.make wasm_mod (Literal.int32 v) in + let i31 v = Expression.I31.make wasm_mod (i32 v) in + let cons first rest = + Expression.Struct.new_ wasm_mod (Some [ first; rest ]) list_type + in + let empty () = + Expression.Ref.null wasm_mod (Type.from_heap_type list_type true) + in + Function.add_function wasm_mod "gc" Type.anyref + (Type.create [| Type.anyref; Type.anyref |]) + [| + Type.from_heap_type array_u8_type false; + Type.from_heap_type list_type false; + |] + (Expression.Block.make wasm_mod "gc_block" + [ + Expression.Local_set.make wasm_mod 1 + (Expression.Array.new_fixed wasm_mod array_u8_type + [ i32 0l; i32 255l ]); + Expression.Array.set wasm_mod + (Expression.Local_get.make wasm_mod 1 + (Type.from_heap_type array_u8_type false)) + (i32 1l) (i32 42l); + Expression.Local_set.make wasm_mod 2 + (cons + (Expression.Ref.cast wasm_mod + (Expression.Local_get.make wasm_mod 0 Type.anyref) + Type.i31ref) + (cons (i31 1l) (cons (i31 2l) (cons (i31 3l) (empty ()))))); + Expression.Tuple_make.make wasm_mod + [ + Expression.Local_get.make wasm_mod 1 + (Type.from_heap_type array_u8_type false); + Expression.Local_get.make wasm_mod 2 + (Type.from_heap_type list_type false); + ]; + ]) + +let _ = Export.add_function_export wasm_mod "gc" "gc" +let _ = assert (Module.validate wasm_mod == 1) + +(* Test Heap_type.set_type_name and Heap_type.set_field_name *) +let list_type = + let builder = Type_builder.make 1 in + let temp_heap_type = Type_builder.get_temp_heap_type builder 0 in + let temp_ref_type = + Type_builder.get_temp_ref_type builder temp_heap_type true + in + Type_builder.set_struct_type builder 0 + [ + Type_builder. + { + type_ = Type.i31ref; + packed_type = Packed_type.not_packed; + mutable_ = false; + }; + Type_builder. + { + type_ = temp_ref_type; + packed_type = Packed_type.not_packed; + mutable_ = false; + }; + ]; + match Type_builder.build_and_dispose builder with + | Ok [ ty ] -> ty + | _ -> failwith "failed to make list type" + +let _ = Heap_type.set_type_name wasm_mod list_type "List" +let _ = Heap_type.set_field_name wasm_mod list_type 0 "head" +let _ = Heap_type.set_field_name wasm_mod list_type 1 "tail" + (* Shouldn't actually do anything since we aren't doing function renames *) let _ = Module.update_maps wasm_mod @@ -440,7 +564,7 @@ let _ = Module.Feature.all; ] -let _ = Module.validate new_mod +let _ = assert (Module.validate new_mod == 1) let _ = Module.print new_mod let _ = Module.print_stack_ir new_mod