Skip to content

Commit

Permalink
Add support for reference types proposal
Browse files Browse the repository at this point in the history
  • Loading branch information
aheejin committed Dec 13, 2019
1 parent fbce98c commit 3e90ff5
Show file tree
Hide file tree
Showing 88 changed files with 10,737 additions and 2,145 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ 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.
- `local.tee`'s C/Binaryen.js API now takes an additional type parameter for its
local type, like `local.get`. This is required to handle subtypes.
- Added load_splat SIMD instructions
Expand Down
6 changes: 4 additions & 2 deletions check.py
Original file line number Diff line number Diff line change
Expand Up @@ -152,8 +152,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
# HACK Remove this condition after nullref is implemented in V8
if 'reference_types.wast' 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
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']])


# 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 @@ -467,6 +469,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
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
97 changes: 76 additions & 21 deletions src/binaryen-c.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,6 @@ using namespace wasm;

// Literal utilities

static_assert(sizeof(BinaryenLiteral) == sizeof(Literal),
"Binaryen C API literal must match wasm.h");

BinaryenLiteral toBinaryenLiteral(Literal x) {
BinaryenLiteral ret;
ret.type = x.type;
Expand All @@ -64,15 +61,15 @@ 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::none:
case Type::unreachable:
case Type::nullref:
break;
case Type::funcref:
ret.func = x.func.c_str();
break;
default:
WASM_UNREACHABLE("unexpected type");
}
return ret;
Expand All @@ -90,10 +87,7 @@ 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::none:
case Type::unreachable:
default:
WASM_UNREACHABLE("unexpected type");
}
WASM_UNREACHABLE("invalid type");
Expand Down Expand Up @@ -209,10 +203,7 @@ 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::none:
case Type::unreachable:
default:
WASM_UNREACHABLE("unexpected type");
}
}
Expand Down Expand Up @@ -265,7 +256,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 +390,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 @@ -1328,17 +1330,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 @@ -1693,6 +1700,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 anyref) {
auto* ret = Builder(*(Module*)module).makeRefIsNull((Expression*)anyref);
if (tracing) {
traceExpression(ret, "BinaryenRefIsNull", anyref);
}
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 @@ -2962,6 +2995,28 @@ BinaryenExpressionRef BinaryenPushGetValue(BinaryenExpressionRef expr) {
assert(expression->is<Push>());
return static_cast<Push*>(expression)->value;
}
// RefIsNull
BinaryenExpressionRef BinaryenRefIsNullGetAnyref(BinaryenExpressionRef expr) {
if (tracing) {
std::cout << " BinaryenRefIsNullGetAnyref(expressions["
<< expressions[expr] << "]);\n";
}

auto* expression = (Expression*)expr;
assert(expression->is<RefIsNull>());
return static_cast<RefIsNull*>(expression)->anyref;
}
// 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 @@ -223,6 +228,7 @@ struct BinaryenLiteral {
double f64;
uint8_t v128[16];
};
const char* func;
};

BINARYEN_API struct BinaryenLiteral BinaryenLiteralInt32(int32_t x);
Expand Down Expand Up @@ -690,7 +696,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 @@ -795,6 +802,11 @@ BinaryenMemoryFill(BinaryenModuleRef module,
BinaryenExpressionRef dest,
BinaryenExpressionRef value,
BinaryenExpressionRef size);
BINARYEN_API BinaryenExpressionRef BinaryenRefNull(BinaryenModuleRef module);
BINARYEN_API BinaryenExpressionRef
BinaryenRefIsNull(BinaryenModuleRef module, BinaryenExpressionRef anyref);
BINARYEN_API BinaryenExpressionRef BinaryenRefFunc(BinaryenModuleRef module,
const char* func);
BINARYEN_API BinaryenExpressionRef BinaryenTry(BinaryenModuleRef module,
BinaryenExpressionRef body,
BinaryenExpressionRef catchBody);
Expand Down Expand Up @@ -1033,6 +1045,11 @@ BinaryenMemoryFillGetValue(BinaryenExpressionRef expr);
BINARYEN_API BinaryenExpressionRef
BinaryenMemoryFillGetSize(BinaryenExpressionRef expr);

BINARYEN_API BinaryenExpressionRef
BinaryenRefIsNullGetAnyref(BinaryenExpressionRef expr);

BINARYEN_API const char* BinaryenRefFuncGetFunc(BinaryenExpressionRef expr);

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

0 comments on commit 3e90ff5

Please sign in to comment.