Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for reference types proposal #2451

Merged
merged 23 commits into from
Dec 31, 2019
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
278aba7
Refactor module element related functions (NFC)
aheejin Dec 21, 2019
e85bc4b
Add support for reference types proposal
aheejin Nov 2, 2019
0027828
Merge branch 'master' into reference_types
aheejin Dec 23, 2019
28f78e9
Add types back to switch-case
aheejin Dec 24, 2019
f935052
Merge branch 'master' into reference_types
aheejin Dec 24, 2019
2be26a2
Move Type-related functions into Type class (NFC)
aheejin Dec 25, 2019
d183d50
Address some comments
aheejin Dec 25, 2019
4dbd4da
Merge branch 'master' into reference_types
aheejin Dec 25, 2019
e7ea3d5
Merge branch 'type_method_refactor' into reference_types
aheejin Dec 25, 2019
944ae89
Move Type-related functions into Type class (NFC)
aheejin Dec 25, 2019
893ce13
Merge branch 'type_method_refactor' into reference_types
aheejin Dec 25, 2019
5a0d4b4
Address more comments
aheejin Dec 25, 2019
e94e3a1
Rename anyref to value in ref.is_null for Binaryen.js
aheejin Dec 25, 2019
fbeb640
Fix funcref exclusion when comparing execution results
aheejin Dec 25, 2019
012c293
Try to change func to Name in Literal
aheejin Dec 26, 2019
e5f5880
Delete obsolete comments about nullref
aheejin Dec 27, 2019
839084e
Fix nullref try-catch test
aheejin Dec 27, 2019
aef96d4
Update test output
aheejin Dec 27, 2019
9589c2e
Use more Type:: prefixes in new code
aheejin Dec 28, 2019
7933fba
Use more Type:: prefixes in new code
aheejin Dec 28, 2019
69dc6d8
Merge branch 'type_method_refactor' into reference_types
aheejin Dec 28, 2019
dfa6753
Fix type conversion
aheejin Dec 29, 2019
78223a9
Merge branch 'master' into reference_types
aheejin Dec 30, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ full changeset diff at the end of each section.
Current Trunk
-------------

- Reference type support is added. Supported instructions are `ref.null`,
`ref.is_null`, `ref.func`, and typed `select`. Table instructions are not
supported yet. For typed `select`, C/JS API can take an additional 'type'
parameter.

v90
---

Expand Down
17 changes: 11 additions & 6 deletions check.py
Original file line number Diff line number Diff line change
Expand Up @@ -153,8 +153,10 @@ def check():

shared.fail_if_not_identical_to_file(actual, f)

shared.binary_format_check(t, wasm_as_args=['-g']) # test with debuginfo
shared.binary_format_check(t, wasm_as_args=[], binary_suffix='.fromBinary.noDebugInfo') # test without debuginfo
# FIXME Remove this condition after nullref is implemented in V8
if 'reference-types.wast' not in t:
shared.binary_format_check(t, wasm_as_args=['-g']) # test with debuginfo
shared.binary_format_check(t, wasm_as_args=[], binary_suffix='.fromBinary.noDebugInfo') # test without debuginfo

shared.minify_check(t)

Expand Down Expand Up @@ -271,9 +273,9 @@ def run_wasm_reduce_tests():
before = os.stat('a.wasm').st_size
support.run_command(shared.WASM_REDUCE + ['a.wasm', '--command=%s b.wasm --fuzz-exec -all' % shared.WASM_OPT[0], '-t', 'b.wasm', '-w', 'c.wasm'])
after = os.stat('c.wasm').st_size
# 0.65 is a custom threshold to check if we have shrunk the output
# sufficiently
assert after < 0.7 * before, [before, after]
# This number is a custom threshold to check if we have shrunk the
# output sufficiently
assert after < 0.75 * before, [before, after]


def run_spec_tests():
Expand Down Expand Up @@ -323,7 +325,10 @@ def check_expected(actual, expected):
# some wast files cannot be split:
# * comments.wast: contains characters that are not valid utf-8,
# so our string splitting code fails there
if os.path.basename(wast) not in ['comments.wast']:

# FIXME Remove reference type tests from this list after nullref is
# implemented in V8
if os.path.basename(wast) not in ['comments.wast', 'ref_null.wast', 'ref_is_null.wast', 'ref_func.wast', 'old_select.wast']:
split_num = 0
actual = ''
for module, asserts in support.split_wast(wast):
Expand Down
6 changes: 3 additions & 3 deletions scripts/fuzz_opt.py
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ def compare_vs(self, before, after):
break

def can_run_on_feature_opts(self, feature_opts):
return all([x in feature_opts for x in ['--disable-simd']])
return all([x in feature_opts for x in ['--disable-simd', '--disable-reference-types', '--disable-exception-handling']])


# Fuzz the interpreter with --fuzz-exec. This tests everything in a single command (no
Expand Down Expand Up @@ -294,7 +294,7 @@ def run(self, wasm):
return out

def can_run_on_feature_opts(self, feature_opts):
return all([x in feature_opts for x in ['--disable-exception-handling', '--disable-simd', '--disable-threads', '--disable-bulk-memory', '--disable-nontrapping-float-to-int', '--disable-tail-call', '--disable-sign-ext']])
return all([x in feature_opts for x in ['--disable-exception-handling', '--disable-simd', '--disable-threads', '--disable-bulk-memory', '--disable-nontrapping-float-to-int', '--disable-tail-call', '--disable-sign-ext', '--disable-reference-types']])


class Asyncify(TestCaseHandler):
Expand Down Expand Up @@ -339,7 +339,7 @@ def do_asyncify(wasm):
compare(before, after_asyncify, 'Asyncify (before/after_asyncify)')

def can_run_on_feature_opts(self, feature_opts):
return all([x in feature_opts for x in ['--disable-exception-handling', '--disable-simd', '--disable-tail-call']])
return all([x in feature_opts for x in ['--disable-exception-handling', '--disable-simd', '--disable-tail-call', '--disable-reference-types']])


# The global list of all test case handlers
Expand Down
7 changes: 7 additions & 0 deletions scripts/gen-s-parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,9 @@
("f32.pop", "makePop(f32)"),
("f64.pop", "makePop(f64)"),
("v128.pop", "makePop(v128)"),
("funcref.pop", "makePop(funcref)"),
("anyref.pop", "makePop(anyref)"),
("nullref.pop", "makePop(nullref)"),
("exnref.pop", "makePop(exnref)"),
("i32.load", "makeLoad(s, i32, /*isAtomic=*/false)"),
("i64.load", "makeLoad(s, i64, /*isAtomic=*/false)"),
Expand Down Expand Up @@ -469,6 +471,11 @@
("i32x4.widen_low_i16x8_u", "makeUnary(s, UnaryOp::WidenLowUVecI16x8ToVecI32x4)"),
("i32x4.widen_high_i16x8_u", "makeUnary(s, UnaryOp::WidenHighUVecI16x8ToVecI32x4)"),
("v8x16.swizzle", "makeBinary(s, BinaryOp::SwizzleVec8x16)"),
# reference types instructions
# TODO Add table instructions
("ref.null", "makeRefNull(s)"),
("ref.is_null", "makeRefIsNull(s)"),
("ref.func", "makeRefFunc(s)"),
# exception handling instructions
("try", "makeTry(s)"),
("throw", "makeThrow(s)"),
Expand Down
2 changes: 1 addition & 1 deletion src/asm2wasm.h
Original file line number Diff line number Diff line change
Expand Up @@ -2008,7 +2008,7 @@ Function* Asm2WasmBuilder::processFunction(Ref ast) {
ret->offset = 0;
ret->align = view.bytes;
ret->ptr = processUnshifted(ast[2], view.bytes);
ret->type = getType(view.bytes, !view.integer);
ret->type = Type::getType(view.bytes, !view.integer);
return ret;
} else if (what == UNARY_PREFIX) {
if (ast[1] == PLUS) {
Expand Down
13 changes: 9 additions & 4 deletions src/asmjs/asm_v_wasm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,11 @@ AsmType wasmToAsmType(Type type) {
return ASM_INT64;
case v128:
assert(false && "v128 not implemented yet");
case funcref:
case anyref:
assert(false && "anyref is not supported by asm2wasm");
case nullref:
case exnref:
assert(false && "exnref is not supported by asm2wasm");
assert(false && "reference types are not supported by asm2wasm");
case none:
return ASM_NONE;
case unreachable:
Expand All @@ -77,10 +78,14 @@ char getSig(Type type) {
return 'd';
case v128:
return 'V';
case funcref:
return 'F';
case anyref:
return 'a';
return 'A';
case nullref:
return 'N';
case exnref:
return 'e';
return 'E';
case none:
return 'v';
case unreachable:
Expand Down
101 changes: 89 additions & 12 deletions src/binaryen-c.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,13 +64,16 @@ BinaryenLiteral toBinaryenLiteral(Literal x) {
case Type::f64:
ret.i64 = x.reinterpreti64();
break;
case Type::v128: {
case Type::v128:
memcpy(&ret.v128, x.getv128Ptr(), 16);
break;
}

case Type::anyref: // there's no anyref literals
case Type::exnref: // there's no exnref literals
case Type::funcref:
ret.func = x.getFunc().c_str();
break;
case Type::nullref:
break;
case Type::anyref:
case Type::exnref:
case Type::none:
case Type::unreachable:
WASM_UNREACHABLE("unexpected type");
Expand All @@ -90,8 +93,12 @@ Literal fromBinaryenLiteral(BinaryenLiteral x) {
return Literal(x.i64).castToF64();
case Type::v128:
return Literal(x.v128);
case Type::anyref: // there's no anyref literals
case Type::exnref: // there's no exnref literals
case Type::funcref:
return Literal::makeFuncref(x.func);
case Type::nullref:
return Literal::makeNullref();
case Type::anyref:
case Type::exnref:
case Type::none:
case Type::unreachable:
WASM_UNREACHABLE("unexpected type");
Expand Down Expand Up @@ -209,8 +216,14 @@ void printArg(std::ostream& setup, std::ostream& out, BinaryenLiteral arg) {
out << "BinaryenLiteralVec128(" << array << ")";
break;
}
case Type::anyref: // there's no anyref literals
case Type::exnref: // there's no exnref literals
case Type::funcref:
out << "BinaryenLiteralFuncref(" << arg.func << ")";
break;
case Type::nullref:
out << "BinaryenLiteralNullref()";
break;
case Type::anyref:
case Type::exnref:
case Type::none:
case Type::unreachable:
WASM_UNREACHABLE("unexpected type");
Expand Down Expand Up @@ -265,7 +278,9 @@ BinaryenType BinaryenTypeInt64(void) { return i64; }
BinaryenType BinaryenTypeFloat32(void) { return f32; }
BinaryenType BinaryenTypeFloat64(void) { return f64; }
BinaryenType BinaryenTypeVec128(void) { return v128; }
BinaryenType BinaryenTypeFuncref(void) { return funcref; }
BinaryenType BinaryenTypeAnyref(void) { return anyref; }
BinaryenType BinaryenTypeNullref(void) { return nullref; }
BinaryenType BinaryenTypeExnref(void) { return exnref; }
BinaryenType BinaryenTypeUnreachable(void) { return unreachable; }
BinaryenType BinaryenTypeAuto(void) { return uint32_t(-1); }
Expand Down Expand Up @@ -397,6 +412,15 @@ BinaryenExpressionId BinaryenMemoryCopyId(void) {
BinaryenExpressionId BinaryenMemoryFillId(void) {
return Expression::Id::MemoryFillId;
}
BinaryenExpressionId BinaryenRefNullId(void) {
return Expression::Id::RefNullId;
}
BinaryenExpressionId BinaryenRefIsNullId(void) {
return Expression::Id::RefIsNullId;
}
BinaryenExpressionId BinaryenRefFuncId(void) {
return Expression::Id::RefFuncId;
}
BinaryenExpressionId BinaryenTryId(void) { return Expression::Id::TryId; }
BinaryenExpressionId BinaryenThrowId(void) { return Expression::Id::ThrowId; }
BinaryenExpressionId BinaryenRethrowId(void) {
Expand Down Expand Up @@ -1330,17 +1354,22 @@ BinaryenExpressionRef BinaryenBinary(BinaryenModuleRef module,
BinaryenExpressionRef BinaryenSelect(BinaryenModuleRef module,
BinaryenExpressionRef condition,
BinaryenExpressionRef ifTrue,
BinaryenExpressionRef ifFalse) {
BinaryenExpressionRef ifFalse,
BinaryenType type) {
auto* ret = ((Module*)module)->allocator.alloc<Select>();

if (tracing) {
traceExpression(ret, "BinaryenSelect", condition, ifTrue, ifFalse);
traceExpression(ret, "BinaryenSelect", condition, ifTrue, ifFalse, type);
}

ret->condition = (Expression*)condition;
ret->ifTrue = (Expression*)ifTrue;
ret->ifFalse = (Expression*)ifFalse;
ret->finalize();
if (type != BinaryenTypeAuto()) {
ret->finalize(Type(type));
} else {
ret->finalize();
}
return static_cast<Expression*>(ret);
}
BinaryenExpressionRef BinaryenDrop(BinaryenModuleRef module,
Expand Down Expand Up @@ -1695,6 +1724,32 @@ BinaryenExpressionRef BinaryenPop(BinaryenModuleRef module, BinaryenType type) {
return static_cast<Expression*>(ret);
}

BinaryenExpressionRef BinaryenRefNull(BinaryenModuleRef module) {
auto* ret = Builder(*(Module*)module).makeRefNull();
if (tracing) {
traceExpression(ret, "BinaryenRefNull");
}
return static_cast<Expression*>(ret);
}

BinaryenExpressionRef BinaryenRefIsNull(BinaryenModuleRef module,
BinaryenExpressionRef value) {
auto* ret = Builder(*(Module*)module).makeRefIsNull((Expression*)value);
if (tracing) {
traceExpression(ret, "BinaryenRefIsNull", value);
}
return static_cast<Expression*>(ret);
}

BinaryenExpressionRef BinaryenRefFunc(BinaryenModuleRef module,
const char* func) {
auto* ret = Builder(*(Module*)module).makeRefFunc(func);
if (tracing) {
traceExpression(ret, "BinaryenRefFunc", StringLit(func));
}
return static_cast<Expression*>(ret);
}

BinaryenExpressionRef BinaryenTry(BinaryenModuleRef module,
BinaryenExpressionRef body,
BinaryenExpressionRef catchBody) {
Expand Down Expand Up @@ -2964,6 +3019,28 @@ BinaryenExpressionRef BinaryenPushGetValue(BinaryenExpressionRef expr) {
assert(expression->is<Push>());
return static_cast<Push*>(expression)->value;
}
// RefIsNull
BinaryenExpressionRef BinaryenRefIsNullGetValue(BinaryenExpressionRef expr) {
if (tracing) {
std::cout << " BinaryenRefIsNullGetValue(expressions[" << expressions[expr]
<< "]);\n";
}

auto* expression = (Expression*)expr;
assert(expression->is<RefIsNull>());
return static_cast<RefIsNull*>(expression)->value;
}
// RefFunc
const char* BinaryenRefFuncGetFunc(BinaryenExpressionRef expr) {
if (tracing) {
std::cout << " BinaryenRefFuncGetFunc(expressions[" << expressions[expr]
<< "]);\n";
}

auto* expression = (Expression*)expr;
assert(expression->is<RefFunc>());
return static_cast<RefFunc*>(expression)->func.c_str();
}
// Try
BinaryenExpressionRef BinaryenTryGetBody(BinaryenExpressionRef expr) {
if (tracing) {
Expand Down
19 changes: 18 additions & 1 deletion src/binaryen-c.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,9 @@ BINARYEN_API BinaryenType BinaryenTypeInt64(void);
BINARYEN_API BinaryenType BinaryenTypeFloat32(void);
BINARYEN_API BinaryenType BinaryenTypeFloat64(void);
BINARYEN_API BinaryenType BinaryenTypeVec128(void);
BINARYEN_API BinaryenType BinaryenTypeFuncref(void);
BINARYEN_API BinaryenType BinaryenTypeAnyref(void);
BINARYEN_API BinaryenType BinaryenTypeNullref(void);
BINARYEN_API BinaryenType BinaryenTypeExnref(void);
BINARYEN_API BinaryenType BinaryenTypeUnreachable(void);
// Not a real type. Used as the last parameter to BinaryenBlock to let
Expand Down Expand Up @@ -158,6 +160,9 @@ BINARYEN_API BinaryenExpressionId BinaryenMemoryInitId(void);
BINARYEN_API BinaryenExpressionId BinaryenDataDropId(void);
BINARYEN_API BinaryenExpressionId BinaryenMemoryCopyId(void);
BINARYEN_API BinaryenExpressionId BinaryenMemoryFillId(void);
BINARYEN_API BinaryenExpressionId BinaryenRefNullId(void);
BINARYEN_API BinaryenExpressionId BinaryenRefIsNullId(void);
BINARYEN_API BinaryenExpressionId BinaryenRefFuncId(void);
BINARYEN_API BinaryenExpressionId BinaryenTryId(void);
BINARYEN_API BinaryenExpressionId BinaryenThrowId(void);
BINARYEN_API BinaryenExpressionId BinaryenRethrowId(void);
Expand Down Expand Up @@ -222,6 +227,7 @@ struct BinaryenLiteral {
float f32;
double f64;
uint8_t v128[16];
const char* func;
};
};

Expand Down Expand Up @@ -692,7 +698,8 @@ BINARYEN_API BinaryenExpressionRef
BinaryenSelect(BinaryenModuleRef module,
BinaryenExpressionRef condition,
BinaryenExpressionRef ifTrue,
BinaryenExpressionRef ifFalse);
BinaryenExpressionRef ifFalse,
BinaryenType type);
BINARYEN_API BinaryenExpressionRef BinaryenDrop(BinaryenModuleRef module,
BinaryenExpressionRef value);
// Return: value can be NULL
Expand Down Expand Up @@ -797,6 +804,11 @@ BinaryenMemoryFill(BinaryenModuleRef module,
BinaryenExpressionRef dest,
BinaryenExpressionRef value,
BinaryenExpressionRef size);
BINARYEN_API BinaryenExpressionRef BinaryenRefNull(BinaryenModuleRef module);
BINARYEN_API BinaryenExpressionRef
BinaryenRefIsNull(BinaryenModuleRef module, BinaryenExpressionRef value);
BINARYEN_API BinaryenExpressionRef BinaryenRefFunc(BinaryenModuleRef module,
const char* func);
BINARYEN_API BinaryenExpressionRef BinaryenTry(BinaryenModuleRef module,
BinaryenExpressionRef body,
BinaryenExpressionRef catchBody);
Expand Down Expand Up @@ -1035,6 +1047,11 @@ BinaryenMemoryFillGetValue(BinaryenExpressionRef expr);
BINARYEN_API BinaryenExpressionRef
BinaryenMemoryFillGetSize(BinaryenExpressionRef expr);

BINARYEN_API BinaryenExpressionRef
BinaryenRefIsNullGetValue(BinaryenExpressionRef expr);

BINARYEN_API const char* BinaryenRefFuncGetFunc(BinaryenExpressionRef expr);

BINARYEN_API BinaryenExpressionRef
BinaryenTryGetBody(BinaryenExpressionRef expr);
BINARYEN_API BinaryenExpressionRef
Expand Down
Loading