Commit 2aa4656e authored by titzer's avatar titzer Committed by Commit bot

[wasm] Binary 11: WASM AST is now postorder.

[wasm] Binary 11: br_table takes a value.
[wasm] Binary 11: Add implicit blocks to if arms.
[wasm] Binary 11: Add arities to call, return, and breaks
[wasm] Binary 11: Add experimental version.

This CL changes the encoder, decoder, and tests to use a postorder
encoding of the AST, which is more efficient in decode time and
space.

R=bradnelson@chromium.org,rossberg@chromium.org,binji@chromium.org
BUG=chromium:575167
LOG=Y

Review-Url: https://codereview.chromium.org/1830663002
Cr-Commit-Position: refs/heads/master@{#35896}
parent 7595dfd9
This diff is collapsed.
This diff is collapsed.
......@@ -89,66 +89,81 @@ struct GlobalIndexOperand {
}
};
struct Block;
struct Control;
struct BreakDepthOperand {
uint32_t arity;
uint32_t depth;
Block* target;
Control* target;
int length;
inline BreakDepthOperand(Decoder* decoder, const byte* pc) {
depth = decoder->checked_read_u32v(pc, 1, &length, "break depth");
int len1 = 0;
int len2 = 0;
arity = decoder->checked_read_u32v(pc, 1, &len1, "argument count");
depth = decoder->checked_read_u32v(pc, 1 + len1, &len2, "break depth");
length = len1 + len2;
target = nullptr;
}
};
struct BlockCountOperand {
uint32_t count;
int length;
inline BlockCountOperand(Decoder* decoder, const byte* pc) {
count = decoder->checked_read_u32v(pc, 1, &length, "block count");
}
};
struct SignatureIndexOperand {
struct CallIndirectOperand {
uint32_t arity;
uint32_t index;
FunctionSig* sig;
int length;
inline SignatureIndexOperand(Decoder* decoder, const byte* pc) {
index = decoder->checked_read_u32v(pc, 1, &length, "signature index");
inline CallIndirectOperand(Decoder* decoder, const byte* pc) {
int len1 = 0;
int len2 = 0;
arity = decoder->checked_read_u32v(pc, 1, &len1, "argument count");
index = decoder->checked_read_u32v(pc, 1 + len1, &len2, "signature index");
length = len1 + len2;
sig = nullptr;
}
};
struct FunctionIndexOperand {
struct CallFunctionOperand {
uint32_t arity;
uint32_t index;
FunctionSig* sig;
int length;
inline FunctionIndexOperand(Decoder* decoder, const byte* pc) {
index = decoder->checked_read_u32v(pc, 1, &length, "function index");
inline CallFunctionOperand(Decoder* decoder, const byte* pc) {
int len1 = 0;
int len2 = 0;
arity = decoder->checked_read_u32v(pc, 1, &len1, "argument count");
index = decoder->checked_read_u32v(pc, 1 + len1, &len2, "function index");
length = len1 + len2;
sig = nullptr;
}
};
struct ImportIndexOperand {
struct CallImportOperand {
uint32_t arity;
uint32_t index;
FunctionSig* sig;
int length;
inline ImportIndexOperand(Decoder* decoder, const byte* pc) {
index = decoder->checked_read_u32v(pc, 1, &length, "import index");
inline CallImportOperand(Decoder* decoder, const byte* pc) {
int len1 = 0;
int len2 = 0;
arity = decoder->checked_read_u32v(pc, 1, &len1, "argument count");
index = decoder->checked_read_u32v(pc, 1 + len1, &len2, "import index");
length = len1 + len2;
sig = nullptr;
}
};
struct BranchTableOperand {
uint32_t arity;
uint32_t table_count;
const byte* table;
int length;
inline BranchTableOperand(Decoder* decoder, const byte* pc) {
int varint_length;
int len1 = 0;
int len2 = 0;
arity = decoder->checked_read_u32v(pc, 1, &len1, "argument count");
table_count =
decoder->checked_read_u32v(pc, 1, &varint_length, "expected #entries");
length = varint_length + (table_count + 1) * sizeof(uint32_t);
decoder->checked_read_u32v(pc, 1 + len1, &len2, "table count");
length = len1 + len2 + (table_count + 1) * sizeof(uint32_t);
uint32_t table_start = 1 + varint_length;
uint32_t table_start = 1 + len1 + len2;
if (decoder->check(pc, table_start, (table_count + 1) * sizeof(uint32_t),
"expected <table entries>")) {
table = pc + table_start;
......@@ -177,6 +192,15 @@ struct MemoryAccessOperand {
}
};
struct ReturnArityOperand {
uint32_t arity;
int length;
inline ReturnArityOperand(Decoder* decoder, const byte* pc) {
arity = decoder->checked_read_u32v(pc, 1, &length, "return count");
}
};
typedef compiler::WasmGraphBuilder TFBuilder;
struct ModuleEnv; // forward declaration of module interface.
......
......@@ -189,6 +189,16 @@ void WasmFunctionBuilder::EmitWithVarInt(WasmOpcode opcode,
EmitVarInt(immediate);
}
void WasmFunctionBuilder::EmitI32Const(int32_t value) {
// TODO(titzer): variable-length signed and unsigned i32 constants.
if (-128 <= value && value <= 127) {
EmitWithU8(kExprI8Const, static_cast<byte>(value));
} else {
byte code[] = {WASM_I32V_5(value)};
EmitCode(code, sizeof(code));
}
}
uint32_t WasmFunctionBuilder::EmitEditableVarIntImmediate() {
// Guess that the immediate will be 1 byte. If it is more, we'll have to
// shift everything down.
......
......@@ -57,6 +57,7 @@ class WasmFunctionBuilder : public ZoneObject {
void Emit(WasmOpcode opcode);
void EmitGetLocal(uint32_t index);
void EmitSetLocal(uint32_t index);
void EmitI32Const(int32_t val);
void EmitWithU8(WasmOpcode opcode, const byte immediate);
void EmitWithU8U8(WasmOpcode opcode, const byte imm1, const byte imm2);
void EmitWithVarInt(WasmOpcode opcode, uint32_t immediate);
......
......@@ -572,11 +572,10 @@ class ModuleDecoder : public Decoder {
// Verifies the body (code) of a given function.
void VerifyFunctionBody(uint32_t func_num, ModuleEnv* menv,
WasmFunction* function) {
if (FLAG_trace_wasm_decode_time) {
if (FLAG_trace_wasm_decoder || FLAG_trace_wasm_decode_time) {
OFStream os(stdout);
os << "Verifying WASM function " << WasmFunctionName(function, menv)
<< std::endl;
os << std::endl;
}
FunctionBody body = {menv, function->sig, start_,
start_ + function->code_start_offset,
......
......@@ -294,6 +294,15 @@ void WasmJs::Install(Isolate* isolate, Handle<JSGlobalObject> global) {
InstallFunc(isolate, wasm_object, "instantiateModule", InstantiateModule);
InstallFunc(isolate, wasm_object, "instantiateModuleFromAsm",
InstantiateModuleFromAsm);
{
// Add the Wasm.experimentalVersion property.
Handle<String> name = v8_str(isolate, "experimentalVersion");
PropertyAttributes attributes =
static_cast<PropertyAttributes>(DONT_DELETE | READ_ONLY);
Handle<Smi> value = Handle<Smi>(Smi::FromInt(wasm::kWasmVersion), isolate);
JSObject::AddProperty(wasm_object, name, value, attributes);
}
}
......
This diff is collapsed.
......@@ -25,6 +25,18 @@ const char* WasmOpcodes::OpcodeName(WasmOpcode opcode) {
return "Unknown";
}
const char* WasmOpcodes::ShortOpcodeName(WasmOpcode opcode) {
switch (opcode) {
#define DECLARE_NAME_CASE(name, opcode, sig) \
case kExpr##name: \
return #name;
FOREACH_OPCODE(DECLARE_NAME_CASE)
#undef DECLARE_NAME_CASE
default:
break;
}
return "Unknown";
}
std::ostream& operator<<(std::ostream& os, const FunctionSig& sig) {
if (sig.return_count() == 0) os << "v";
......
......@@ -51,37 +51,35 @@ std::ostream& operator<<(std::ostream& os, const FunctionSig& function);
typedef Vector<const char> WasmName;
// TODO(titzer): Renumber all the opcodes to fill in holes.
// Control expressions and blocks.
#define FOREACH_CONTROL_OPCODE(V) \
V(Nop, 0x00, _) \
V(Block, 0x01, _) \
V(Loop, 0x02, _) \
V(If, 0x03, _) \
V(IfElse, 0x04, _) \
V(Else, 0x04, _) \
V(Select, 0x05, _) \
V(Br, 0x06, _) \
V(BrIf, 0x07, _) \
V(BrTable, 0x08, _) \
V(Return, 0x14, _) \
V(Unreachable, 0x15, _)
V(Return, 0x09, _) \
V(Unreachable, 0x0a, _) \
V(End, 0x0F, _)
// Constants, locals, globals, and calls.
#define FOREACH_MISC_OPCODE(V) \
V(I8Const, 0x09, _) \
V(I32Const, 0x0a, _) \
V(I64Const, 0x0b, _) \
V(F64Const, 0x0c, _) \
V(F32Const, 0x0d, _) \
V(GetLocal, 0x0e, _) \
V(SetLocal, 0x0f, _) \
V(LoadGlobal, 0x10, _) \
V(StoreGlobal, 0x11, _) \
V(CallFunction, 0x12, _) \
V(CallIndirect, 0x13, _) \
V(CallImport, 0x1F, _) \
V(DeclLocals, 0x1E, _)
V(I32Const, 0x10, _) \
V(I64Const, 0x11, _) \
V(F64Const, 0x12, _) \
V(F32Const, 0x13, _) \
V(GetLocal, 0x14, _) \
V(SetLocal, 0x15, _) \
V(CallFunction, 0x16, _) \
V(CallIndirect, 0x17, _) \
V(CallImport, 0x18, _) \
V(I8Const, 0xcb, _) \
V(LoadGlobal, 0xcc, _) \
V(StoreGlobal, 0xcd, _)
// Load memory expressions.
#define FOREACH_LOAD_MEM_OPCODE(V) \
......@@ -349,6 +347,7 @@ class WasmOpcodes {
public:
static bool IsSupported(WasmOpcode opcode);
static const char* OpcodeName(WasmOpcode opcode);
static const char* ShortOpcodeName(WasmOpcode opcode);
static FunctionSig* Signature(WasmOpcode opcode);
static int TrapReasonToMessageId(TrapReason reason);
......
......@@ -24,8 +24,8 @@
#define asu64(x) static_cast<uint64_t>(x)
#define B2(a, b) kExprBlock, 2, a, b
#define B1(a) kExprBlock, 1, a
#define B2(a, b) kExprBlock, a, b, kExprEnd
#define B1(a) kExprBlock, a, kExprEnd
// Can't bridge macro land with nested macros.
#if V8_TARGET_ARCH_MIPS
......@@ -116,7 +116,7 @@ TEST(Run_Wasm_Return_I64) {
REQUIRE(I64Return);
WasmRunner<int64_t> r(MachineType::Int64());
BUILD(r, WASM_RETURN(WASM_GET_LOCAL(0)));
BUILD(r, WASM_RETURN1(WASM_GET_LOCAL(0)));
FOR_INT64_INPUTS(i) { CHECK_EQ(*i, r.Call(*i)); }
}
......@@ -816,8 +816,8 @@ TEST(Run_WasmCallI64Parameter) {
WasmRunner<int32_t> r(&module);
BUILD(
r,
WASM_I32_CONVERT_I64(WASM_CALL_FUNCTION(
index, WASM_I64V_9(0xbcd12340000000b),
WASM_I32_CONVERT_I64(WASM_CALL_FUNCTIONN(
19, index, WASM_I64V_9(0xbcd12340000000b),
WASM_I64V_9(0xbcd12340000000c), WASM_I32V_1(0xd),
WASM_I32_CONVERT_I64(WASM_I64V_9(0xbcd12340000000e)),
WASM_I64V_9(0xbcd12340000000f), WASM_I64V_10(0xbcd1234000000010),
......@@ -1093,7 +1093,7 @@ TEST(Run_WasmCall_Int64Sub) {
// Build the caller function.
WasmRunner<int64_t> r(&module, MachineType::Int64(), MachineType::Int64());
BUILD(r, WASM_CALL_FUNCTION(index, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
BUILD(r, WASM_CALL_FUNCTION2(index, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
FOR_INT32_INPUTS(i) {
FOR_INT32_INPUTS(j) {
......@@ -1120,12 +1120,16 @@ TEST(Run_Wasm_LoadStoreI64_sx) {
byte* memory = module.AddMemoryElems<byte>(16);
WasmRunner<int64_t> r(&module);
byte code[] = {kExprI64StoreMem, ZERO_ALIGNMENT,
ZERO_OFFSET, // --
kExprI8Const, 8, // --
loads[m], ZERO_ALIGNMENT,
ZERO_OFFSET, // --
kExprI8Const, 0}; // --
byte code[] = {
kExprI8Const, 8, // --
kExprI8Const, 0, // --
loads[m], // --
ZERO_ALIGNMENT, // --
ZERO_OFFSET, // --
kExprI64StoreMem, // --
ZERO_ALIGNMENT, // --
ZERO_OFFSET // --
};
r.Build(code, code + arraysize(code));
......
......@@ -156,7 +156,7 @@ TEST(Run_CallJS_Add_jswrapped) {
WasmFunctionCompiler t(sigs.i_i(), &module);
uint32_t js_index =
module.AddJsFunction(sigs.i_i(), "(function(a) { return a + 99; })");
BUILD(t, WASM_CALL_FUNCTION(js_index, WASM_GET_LOCAL(0)));
BUILD(t, WASM_CALL_FUNCTION1(js_index, WASM_GET_LOCAL(0)));
Handle<JSFunction> jsfunc = module.WrapCode(t.CompileAndAdd());
......@@ -182,12 +182,14 @@ void RunJSSelectTest(int which) {
{
std::vector<byte> code;
ADD_CODE(code, kExprCallFunction, static_cast<byte>(js_index));
for (int i = 0; i < num_params; i++) {
ADD_CODE(code, WASM_F64(inputs.arg_d(i)));
}
ADD_CODE(code, kExprCallFunction, static_cast<byte>(num_params),
static_cast<byte>(js_index));
size_t end = code.size();
code.push_back(0);
t.Build(&code[0], &code[end]);
......@@ -370,12 +372,13 @@ void RunJSSelectAlignTest(int num_args, int num_params) {
// Build the calling code.
std::vector<byte> code;
ADD_CODE(code, kExprCallFunction, 0);
for (int i = 0; i < num_params; i++) {
ADD_CODE(code, WASM_GET_LOCAL(i));
}
ADD_CODE(code, kExprCallFunction, static_cast<byte>(num_params), 0);
size_t end = code.size();
code.push_back(0);
......
......@@ -37,25 +37,26 @@ TEST(Run_WasmModule_CallAdd_rev) {
static const byte data[] = {
WASM_MODULE_HEADER,
// sig#0 ------------------------------------------
WASM_SECTION_SIGNATURES_SIZE + 7, // Section size.
WASM_SECTION_SIGNATURES, 2, 0, kLocalI32, // void -> int
2, kLocalI32, kLocalI32, kLocalI32, // int,int -> int
WASM_SECTION_SIGNATURES_SIZE + 7, // Section size.
WASM_SECTION_SIGNATURES, 2, // --
0, kLocalI32, // void -> int
2, kLocalI32, kLocalI32, kLocalI32, // int,int -> int
// func#0 (main) ----------------------------------
WASM_SECTION_FUNCTIONS_SIZE + 24, WASM_SECTION_FUNCTIONS, 2,
WASM_SECTION_FUNCTIONS_SIZE + 25, WASM_SECTION_FUNCTIONS, 2,
kDeclFunctionExport, 0, 0, // sig index
7, 0, // body size
8, 0, // body size
0, // locals
kExprCallFunction, 1, // --
kExprI8Const, 77, // --
kExprI8Const, 22, // --
kExprCallFunction, 2, 1, // --
// func#1 -----------------------------------------
0, // no name, not exported
1, 0, // sig index
6, 0, // body size
0, // locals
kExprI32Add, // --
kExprGetLocal, 0, // --
kExprGetLocal, 1, // --
kExprI32Add, // --
};
Isolate* isolate = CcTest::InitIsolateOnce();
......@@ -93,13 +94,12 @@ TEST(Run_WasmModule_CallAdd) {
uint16_t param1 = f->AddParam(kAstI32);
uint16_t param2 = f->AddParam(kAstI32);
byte code1[] = {WASM_I32_ADD(WASM_GET_LOCAL(param1), WASM_GET_LOCAL(param2))};
uint32_t local_indices1[] = {2, 4};
f->EmitCode(code1, sizeof(code1), local_indices1, sizeof(local_indices1) / 4);
f->EmitCode(code1, sizeof(code1));
uint16_t f2_index = builder->AddFunction();
f = builder->FunctionAt(f2_index);
f->ReturnType(kAstI32);
f->Exported(1);
byte code2[] = {WASM_CALL_FUNCTION(f1_index, WASM_I8(77), WASM_I8(22))};
byte code2[] = {WASM_CALL_FUNCTION2(f1_index, WASM_I8(77), WASM_I8(22))};
f->EmitCode(code2, sizeof(code2));
WasmModuleWriter* writer = builder->Build(&zone);
TestModule(writer->WriteTo(&zone), 99);
......@@ -188,7 +188,7 @@ TEST(Run_WasmModule_Global) {
f->Exported(1);
byte code2[] = {WASM_STORE_GLOBAL(global1, WASM_I32V_1(56)),
WASM_STORE_GLOBAL(global2, WASM_I32V_1(41)),
WASM_RETURN(WASM_CALL_FUNCTION0(f1_index))};
WASM_RETURN1(WASM_CALL_FUNCTION0(f1_index))};
f->EmitCode(code2, sizeof(code2));
WasmModuleWriter* writer = builder->Build(&zone);
TestModule(writer->WriteTo(&zone), 97);
......
This diff is collapsed.
......@@ -4,6 +4,32 @@
// Flags: --expose-wasm
(function TestSwitch0() {
function asmModule() {
"use asm"
function caller() {
var ret = 0;
var x = 7;
switch (x) {
case 1: {
return 0;
}
case 7: {
ret = 5;
break;
}
default: return 0;
}
return ret|0;
}
return {caller:caller};
}
var wasm = Wasm.instantiateModuleFromAsm(asmModule.toString());
assertEquals(5, wasm.caller());
})();
(function TestSwitch() {
function asmModule() {
"use asm"
......
......@@ -23,6 +23,20 @@ function EmptyTest() {
assertWasm(11, EmptyTest);
function VoidReturnTest() {
"use asm";
function caller() {
empty();
return 19;
}
function empty() {
var x = 0;
if (x) return;
}
return {caller: caller};
}
assertWasm(19, VoidReturnTest);
function IntTest() {
"use asm";
......@@ -193,6 +207,55 @@ function TestReturnInWhileWithoutBraces() {
assertWasm(7, TestReturnInWhileWithoutBraces);
function TestBreakInIf() {
"use asm";
function caller() {
label: {
if(1) break label;
return 11;
}
return 12;
}
return {caller: caller};
}
assertWasm(12, TestBreakInIf);
function TestBreakInIfInDoWhileFalse() {
"use asm";
function caller() {
do {
if(1) break;
return 11;
} while(0);
return 12;
}
return {caller: caller};
}
assertWasm(12, TestBreakInIfInDoWhileFalse);
function TestBreakInElse() {
"use asm";
function caller() {
do {
if(0) ;
else break;
return 14;
} while(0);
return 15;
}
return {caller: caller};
}
assertWasm(15, TestBreakInElse);
function TestBreakInWhile() {
"use asm";
......@@ -209,6 +272,22 @@ function TestBreakInWhile() {
assertWasm(8, TestBreakInWhile);
function TestBreakInIfInWhile() {
"use asm";
function caller() {
while(1) {
if (1) break;
else break;
}
return 8;
}
return {caller: caller};
}
assertWasm(8, TestBreakInIfInWhile);
function TestBreakInNestedWhile() {
"use asm";
......
......@@ -37,7 +37,6 @@ function assertFunction(module, func) {
assertFalse(exp === null);
assertFalse(exp === 0);
assertEquals("function", typeof exp);
return exp;
}
......@@ -47,10 +46,10 @@ function assertFunction(module, func) {
builder.addMemory(1, 1, true);
builder.addFunction("sub", [kAstI64, kAstI64, kAstI64])
.addBody([
kExprI64Sub, // --
kExprGetLocal, 0, // --
kExprGetLocal, 1]) // --
.addBody([ // --
kExprGetLocal, 0, // --
kExprGetLocal, 1, // --
kExprI64Sub]) // --
.exportFunc()
var module = builder.instantiate();
......@@ -70,9 +69,10 @@ function assertFunction(module, func) {
builder.addMemory(1, 1, true);
builder.addFunction("sub", [kAstI32, kAstI32, kAstI32])
.addBody([
kExprI32Sub, // --
kExprGetLocal, 0, // --
kExprGetLocal, 1]) // --
kExprGetLocal, 1, // --
kExprI32Sub, // --
])
.exportFunc()
var module = builder.instantiate();
......@@ -111,9 +111,10 @@ function assertFunction(module, func) {
builder.addMemory(kPages, kPages, true);
builder.addFunction("flt", [kAstI32, kAstF64, kAstF64])
.addBody([
kExprF64Lt, // --
kExprGetLocal, 0, // --
kExprGetLocal, 1]) // --
kExprGetLocal, 1, // --
kExprF64Lt // --
]) // --
.exportFunc();
var module = builder.instantiate();
......
......@@ -34,7 +34,11 @@ function makeBinop(opcode) {
var builder = new WasmModuleBuilder();
builder.addFunction("main", [kAstI32, kAstI32, kAstI32])
.addBody([opcode, kExprGetLocal, 0, kExprGetLocal, 1])
.addBody([
kExprGetLocal, 0, // --
kExprGetLocal, 1, // --
opcode, // --
])
.exportFunc();
return builder.instantiate().exports.main;
......
......@@ -13,9 +13,10 @@ load("test/mjsunit/wasm/wasm-module-builder.js");
builder.addFunction("main", [kAstI32])
.addBody([
kExprReturn,
kExprI8Const,
kReturnValue])
kReturnValue,
kExprReturn, kArity1
])
.exportFunc();
var module = builder.instantiate();
......@@ -33,9 +34,10 @@ load("test/mjsunit/wasm/wasm-module-builder.js");
builder.addFunction("main", [kAstI32])
.addBody([
kExprReturn,
kExprI8Const,
kReturnValue])
kReturnValue,
kExprReturn, kArity1
])
.exportAs("blah")
.exportAs("foo");
......
......@@ -14,9 +14,10 @@ function testCallFFI(ffi) {
builder.addImport("fun", sig_index);
builder.addFunction("main", sig_index)
.addBody([
kExprCallImport, 0, // --
kExprGetLocal, 0, // --
kExprGetLocal, 1]) // --
kExprGetLocal, 0, // --
kExprGetLocal, 1, // --
kExprCallFunction, kArity2, 0, // --
]) // --
.exportFunc();
var module = builder.instantiate(ffi);
......
......@@ -14,9 +14,10 @@ function testCallFFI(func, check) {
builder.addImport("func", sig_index);
builder.addFunction("main", sig_index)
.addBody([
kExprCallImport, 0, // --
kExprGetLocal, 0, // --
kExprGetLocal, 1]) // --
kExprGetLocal, 0, // --
kExprGetLocal, 1, // --
kExprCallImport, kArity2, 0 // --
]) // --
.exportFunc();
var main = builder.instantiate({func: func}).exports.main;
......@@ -187,11 +188,11 @@ function testCallBinopVoid(type, func, check) {
builder.addImport("func", [kAstStmt, type, type]);
builder.addFunction("main", [kAstI32, type, type])
.addBody([
kExprBlock, 2, // --
kExprCallImport, 0, // --
kExprGetLocal, 0, // --
kExprGetLocal, 1, // --
kExprI8Const, 99]) // --
kExprGetLocal, 0, // --
kExprGetLocal, 1, // --
kExprCallImport, kArity2, 0, // --
kExprI8Const, 99 // --
]) // --
.exportFunc()
var main = builder.instantiate(ffi).exports.main;
......@@ -244,11 +245,11 @@ function testCallPrint() {
builder.addImport("print", [kAstStmt, kAstF64]);
builder.addFunction("main", [kAstStmt, kAstF64])
.addBody([
kExprBlock, 2, // --
kExprCallImport, 0, // --
kExprI8Const, 97, // --
kExprCallImport, 1, // --
kExprGetLocal, 0]) // --
kExprI8Const, 97, // --
kExprCallImport, kArity1, 0, // --
kExprGetLocal, 0, // --
kExprCallImport, kArity1, 1 // --
]) // --
.exportFunc()
var main = builder.instantiate({print: print}).exports.main;
......
......@@ -17,7 +17,6 @@ function makeFFI(func, t) {
// the different parts of the stack.
builder.addFunction("main", sig_index)
.addBody([
kExprCallImport, 0, // --
kExprGetLocal, 0, // --
kExprGetLocal, 1, // --
kExprGetLocal, 2, // --
......@@ -28,7 +27,7 @@ function makeFFI(func, t) {
kExprGetLocal, 7, // --
kExprGetLocal, 8, // --
kExprGetLocal, 9, // --
kExprCallImport, 0, // --
kExprCallImport, 10, 0, // --
kExprGetLocal, 0, // --
kExprGetLocal, 1, // --
kExprGetLocal, 2, // --
......@@ -38,7 +37,8 @@ function makeFFI(func, t) {
kExprGetLocal, 6, // --
kExprGetLocal, 7, // --
kExprGetLocal, 8, // --
kExprGetLocal, 9 // --
kExprGetLocal, 9, // --
kExprCallImport, 10, 0 // --
]) // --
.exportFunc();
......
......@@ -14,9 +14,9 @@ function testCallImport(func, check) {
builder.addImport("func", sig_index);
builder.addFunction("main", sig_index)
.addBody([
kExprCallImport, 0, // --
kExprGetLocal, 0, // --
kExprGetLocal, 1]) // --
kExprGetLocal, 1, // --
kExprCallImport, 2, 0]) // --
.exportAs("main");
var main = builder.instantiate({func: func}).exports.main;
......@@ -189,11 +189,11 @@ function testCallBinopVoid(type, func, check) {
builder.addImport("func", [kAstStmt, type, type]);
builder.addFunction("main", [kAstI32, type, type])
.addBody([
kExprBlock, 2, // --
kExprCallImport, 0, // --
kExprGetLocal, 0, // --
kExprGetLocal, 1, // --
kExprI8Const, 99])
kExprCallImport, 2, 0, // --
kExprI8Const, 99, // --
])
.exportFunc("main");
var main = builder.instantiate(ffi).exports.main;
......@@ -245,11 +245,11 @@ function testCallPrint() {
builder.addImport("print", [kAstStmt, kAstF64]);
builder.addFunction("main", [kAstStmt, kAstF64])
.addBody([
kExprBlock, 2, // --
kExprCallImport, 0, // --
kExprI8Const, 97, // --
kExprCallImport, 1, // --
kExprGetLocal, 0]) // --
kExprI8Const, 97, // --
kExprCallImport, kArity1, 0, // --
kExprGetLocal, 0, // --
kExprCallImport, kArity1, 1 // --
])
.exportFunc();
var main = builder.instantiate({print: print}).exports.main;
......@@ -270,9 +270,10 @@ function testCallImport2(foo, bar, expected) {
builder.addImport("bar", [kAstI32]);
builder.addFunction("main", [kAstI32])
.addBody([
kExprCallImport, kArity0, 0, // --
kExprCallImport, kArity0, 1, // --
kExprI32Add, // --
kExprCallImport, 0, // --
kExprCallImport, 1]) // --
]) // --
.exportFunc();
var main = builder.instantiate({foo: foo, bar: bar}).exports.main;
......
......@@ -14,18 +14,21 @@ var module = (function () {
builder.addImport("add", sig_index);
builder.addFunction("add", sig_index)
.addBody([
kExprCallImport, 0, kExprGetLocal, 0, kExprGetLocal, 1
kExprGetLocal, 0, kExprGetLocal, 1, kExprCallImport, kArity2, 0
]);
builder.addFunction("sub", sig_index)
.addBody([
kExprI32Sub, kExprGetLocal, 0, kExprGetLocal, 1
kExprGetLocal, 0, // --
kExprGetLocal, 1, // --
kExprI32Sub, // --
]);
builder.addFunction("main", [kAstI32, kAstI32, kAstI32, kAstI32])
.addBody([
kExprCallIndirect, sig_index,
kExprGetLocal, 0,
kExprGetLocal, 1,
kExprGetLocal, 2])
kExprGetLocal, 2,
kExprCallIndirect, kArity2, sig_index
])
.exportFunc()
builder.appendToFunctionTable([0, 1, 2]);
......
......@@ -15,17 +15,25 @@ function genModule(memory) {
builder.addMemory(1, 1, true);
builder.addFunction("main", [kAstI32, kAstI32])
.addBody([
kExprBlock,2,
kExprLoop,1,
kExprIf,
// main body: while(i) { if(mem[i]) return -1; i -= 4; } return 0;
kExprLoop,
kExprGetLocal,0,
kExprIf,
kExprGetLocal,0,
kExprBr, 0,
kExprIfElse,
kExprI32LoadMem,0,0,kExprGetLocal,0,
kExprBr,2, kExprI8Const, 255,
kExprSetLocal,0,
kExprI32Sub,kExprGetLocal,0,kExprI8Const,4,
kExprI8Const,0])
kExprI32LoadMem,0,0,
kExprIf,
kExprI8Const,255,
kExprReturn, kArity1,
kExprEnd,
kExprGetLocal,0,
kExprI8Const,4,
kExprI32Sub,
kExprSetLocal,0,
kExprBr, kArity1, 1,
kExprEnd,
kExprEnd,
kExprI8Const,0
])
.exportFunc();
return builder.instantiate(null, memory);
......@@ -122,12 +130,14 @@ function testOOBThrows() {
builder.addMemory(1, 1, true);
builder.addFunction("geti", [kAstI32, kAstI32, kAstI32])
.addBody([
kExprI32StoreMem, 0, 0, kExprGetLocal, 0, kExprI32LoadMem, 0, 0, kExprGetLocal, 1
kExprGetLocal, 0,
kExprGetLocal, 1,
kExprI32LoadMem, 0, 0,
kExprI32StoreMem, 0, 0
])
.exportFunc();
var module = builder.instantiate();
var offset;
function read() { return module.exports.geti(0, offset); }
......
......@@ -39,7 +39,7 @@ var builder = new WasmModuleBuilder();
builder.addImport("func", [kAstStmt]);
builder.addFunction("main", [kAstStmt])
.addBody([kExprCallImport, 0])
.addBody([kExprCallImport, kArity0, 0])
.exportAs("main");
builder.addFunction("exec_unreachable", [kAstStmt])
......@@ -49,12 +49,12 @@ builder.addFunction("exec_unreachable", [kAstStmt])
// make this function unnamed, just to test also this case
var mem_oob_func = builder.addFunction(undefined, [kAstStmt])
// access the memory at offset -1
.addBody([kExprI32LoadMem8S, 0, 0, kExprI32Const, 0x7f])
.addBody([kExprI32Const, 0x7f, kExprI32LoadMem8S, 0, 0])
.exportAs("mem_out_of_bounds");
// call the mem_out_of_bounds function, in order to have two WASM stack frames
builder.addFunction("call_mem_out_of_bounds", [kAstStmt])
.addBody([kExprCallFunction, mem_oob_func.index])
.addBody([kExprCallFunction, kArity0, mem_oob_func.index])
.exportAs("call_mem_out_of_bounds");
var module = builder.instantiate({func: STACK});
......
......@@ -14,9 +14,10 @@ function makeFFI(func) {
builder.addImport("func", sig_index);
builder.addFunction("main", sig_index)
.addBody([
kExprCallImport, 0, // --
kExprGetLocal, 0, // --
kExprGetLocal, 1]) // --
kExprGetLocal, 0, // --
kExprGetLocal, 1, // --
kExprCallImport, kArity2, 0, // --
])
.exportFunc()
return builder.instantiate({func: func}).exports.main;
......
......@@ -79,7 +79,7 @@ assertFails([kAstI32, kAstI32, kAstF32, kAstF64], [kExprGetLocal, 0]);
builder.addMemory(12, 12, true);
var func = builder.addFunction("", [kAstStmt])
.addBody([kExprI32StoreMem, 0, 0, kExprI8Const, 0, kExprI8Const, 77]);
.addBody([kExprI8Const, 0, kExprI8Const, 77, kExprI32StoreMem, 0, 0]);
builder.addStart(func.index);
......@@ -102,7 +102,7 @@ assertFails([kAstI32, kAstI32, kAstF32, kAstF64], [kExprGetLocal, 0]);
builder.addImport("foo", sig_index);
var func = builder.addFunction("", sig_index)
.addBody([kExprCallImport, 0]);
.addBody([kExprCallImport, kArity0, 0]);
builder.addStart(func.index);
......
......@@ -25,7 +25,7 @@ var debug = false;
var module = new WasmModuleBuilder();
var index = module.addImport("print", [kAstStmt, kAstI32]);
module.addFunction("foo", [kAstStmt])
.addBody([kExprCallImport, index, kExprI8Const, 13])
.addBody([kExprI8Const, 13, kExprCallImport, kArity1, index])
.exportAs("main");
var buffer = module.toBuffer(debug);
......@@ -38,7 +38,7 @@ var debug = false;
var module = new WasmModuleBuilder();
module.addFunction(undefined, [kAstI32, kAstI32])
.addLocals({i32_count: 1})
.addBody([kExprSetLocal, 1, kExprGetLocal, 0])
.addBody([kExprGetLocal, 0, kExprSetLocal, 1])
.exportAs("main");
var buffer = module.toBuffer(debug);
......@@ -60,7 +60,7 @@ var debug = false;
var module = new WasmModuleBuilder();
module.addFunction(undefined, [p.type, p.type])
.addLocals(p.locals)
.addBody([kExprSetLocal, 1, kExprGetLocal, 0])
.addBody([kExprGetLocal, 0, kExprSetLocal, 1])
.exportAs("main");
var buffer = module.toBuffer(debug);
......@@ -73,9 +73,9 @@ var debug = false;
(function CallTest() {
var module = new WasmModuleBuilder();
module.addFunction("add", [kAstI32, kAstI32, kAstI32])
.addBody([kExprI32Add, kExprGetLocal, 0, kExprGetLocal, 1]);
.addBody([kExprGetLocal, 0, kExprGetLocal, 1, kExprI32Add]);
module.addFunction("main", [kAstI32, kAstI32, kAstI32])
.addBody([kExprCallFunction, 0, kExprGetLocal, 0, kExprGetLocal, 1])
.addBody([kExprGetLocal, 0, kExprGetLocal, 1, kExprCallFunction, kArity2, 0])
.exportAs("main");
var instance = module.instantiate();
......@@ -86,10 +86,10 @@ var debug = false;
(function IndirectCallTest() {
var module = new WasmModuleBuilder();
module.addFunction("add", [kAstI32, kAstI32, kAstI32])
.addBody([kExprI32Add, kExprGetLocal, 0, kExprGetLocal, 1]);
.addBody([kExprGetLocal, 0, kExprGetLocal, 1, kExprI32Add]);
module.addFunction("main", [kAstI32, kAstI32, kAstI32, kAstI32])
.addBody([kExprCallIndirect, 0, kExprGetLocal,
0, kExprGetLocal, 1, kExprGetLocal, 2])
.addBody([kExprGetLocal,
0, kExprGetLocal, 1, kExprGetLocal, 2, kExprCallIndirect, kArity2, 0])
.exportAs("main");
module.appendToFunctionTable([0]);
......@@ -103,7 +103,7 @@ var debug = false;
var module = new WasmModuleBuilder();
module.addMemory(1, 1, false);
module.addFunction("load", [kAstI32, kAstI32])
.addBody([kExprI32LoadMem, 0, 0, kExprGetLocal, 0])
.addBody([kExprGetLocal, 0, kExprI32LoadMem, 0, 0])
.exportAs("load");
module.addDataSegment(0, [9, 9, 9, 9], true);
......@@ -143,7 +143,7 @@ var debug = false;
var module = new WasmModuleBuilder();
var index = module.addImportWithModule("mod", "print", [kAstStmt, kAstI32]);
module.addFunction("foo", [kAstStmt])
.addBody([kExprCallImport, index, kExprI8Const, 19])
.addBody([kExprI8Const, 19, kExprCallImport, kArity1, index])
.exportAs("main");
var buffer = module.toBuffer(debug);
......
......@@ -25,7 +25,7 @@ try {
var data = bytes(
0, kAstI32, // signature
kDeclNoLocals, // --
kExprBlock, 2, kExprNop, kExprNop // body
kExprBlock, kExprNop, kExprNop, kExprEnd // body
);
Wasm.verifyFunction(data);
......
......@@ -65,6 +65,11 @@ var kDeclFunctionSignatures = 0x0a;
var kDeclFunctionBodies = 0x0b;
var kDeclNames = 0x0c;
var kArity0 = 0;
var kArity1 = 1;
var kArity2 = 2;
var kArity3 = 3;
var section_names = [
"memory", "signatures", "functions", "globals", "data_segments",
"function_table", "end", "start_function", "import_table", "export_table",
......@@ -88,26 +93,27 @@ var kExprNop = 0x00;
var kExprBlock = 0x01;
var kExprLoop = 0x02;
var kExprIf = 0x03;
var kExprIfElse = 0x04;
var kExprElse = 0x04;
var kExprSelect = 0x05;
var kExprBr = 0x06;
var kExprBrIf = 0x07;
var kExprTableSwitch = 0x08;
var kExprReturn = 0x14;
var kExprUnreachable = 0x15;
var kExprBrTable = 0x08;
var kExprReturn = 0x09;
var kExprUnreachable = 0x0a;
var kExprEnd = 0x0f;
var kExprI8Const = 0x09;
var kExprI32Const = 0x0a;
var kExprI64Const = 0x0b;
var kExprF64Const = 0x0c;
var kExprF32Const = 0x0d;
var kExprGetLocal = 0x0e;
var kExprSetLocal = 0x0f;
var kExprLoadGlobal = 0x10;
var kExprStoreGlobal = 0x11;
var kExprCallFunction = 0x12;
var kExprCallIndirect = 0x13;
var kExprCallImport = 0x1F;
var kExprI32Const = 0x10;
var kExprI64Const = 0x11;
var kExprF64Const = 0x12;
var kExprF32Const = 0x13;
var kExprGetLocal = 0x14;
var kExprSetLocal = 0x15;
var kExprCallFunction = 0x16;
var kExprCallIndirect = 0x17;
var kExprCallImport = 0x18;
var kExprI8Const = 0xcb;
var kExprLoadGlobal = 0xcc;
var kExprStoreGlobal = 0xcd;
var kExprI32LoadMem8S = 0x20;
var kExprI32LoadMem8U = 0x21;
......
......@@ -10,3 +10,4 @@ assertEquals("function", typeof Wasm.verifyModule);
assertEquals("function", typeof Wasm.verifyFunction);
assertEquals("function", typeof Wasm.instantiateModule);
assertEquals("function", typeof Wasm.instantiateModuleFromAsm);
assertFalse(undefined == Wasm.experimentalVersion);
This diff is collapsed.
......@@ -184,7 +184,7 @@ TEST_F(WasmLoopAssignmentAnalyzerTest, Loop2) {
WASM_STORE_MEM(MachineType::Float32(), WASM_ZERO, WASM_GET_LOCAL(kSum)),
WASM_GET_LOCAL(kIter))};
BitVector* assigned = Analyze(code + 2, code + arraysize(code));
BitVector* assigned = Analyze(code + 1, code + arraysize(code));
for (int j = 0; j < assigned->length(); j++) {
bool expected = j == kIter || j == kSum;
CHECK_EQ(expected, assigned->Contains(j));
......
......@@ -58,46 +58,46 @@ TEST_F(WasmMacroGenTest, Statements) {
EXPECT_SIZE(7, WASM_STORE_MEM(MachineType::Int32(), WASM_ZERO, WASM_ZERO));
EXPECT_SIZE(4, WASM_IF(WASM_ZERO, WASM_NOP));
EXPECT_SIZE(5, WASM_IF(WASM_ZERO, WASM_NOP));
EXPECT_SIZE(5, WASM_IF_ELSE(WASM_ZERO, WASM_NOP, WASM_NOP));
EXPECT_SIZE(7, WASM_IF_ELSE(WASM_ZERO, WASM_NOP, WASM_NOP));
EXPECT_SIZE(5, WASM_SELECT(WASM_ZERO, WASM_NOP, WASM_NOP));
EXPECT_SIZE(3, WASM_BR(0));
EXPECT_SIZE(4, WASM_BR(0));
EXPECT_SIZE(5, WASM_BR_IF(0, WASM_ZERO));
EXPECT_SIZE(3, WASM_BLOCK(1, WASM_NOP));
EXPECT_SIZE(4, WASM_BLOCK(2, WASM_NOP, WASM_NOP));
EXPECT_SIZE(5, WASM_BLOCK(3, WASM_NOP, WASM_NOP, WASM_NOP));
EXPECT_SIZE(5, WASM_INFINITE_LOOP);
EXPECT_SIZE(6, WASM_INFINITE_LOOP);
EXPECT_SIZE(3, WASM_LOOP(1, WASM_NOP));
EXPECT_SIZE(4, WASM_LOOP(2, WASM_NOP, WASM_NOP));
EXPECT_SIZE(5, WASM_LOOP(3, WASM_NOP, WASM_NOP, WASM_NOP));
EXPECT_SIZE(5, WASM_LOOP(1, WASM_BR(0)));
EXPECT_SIZE(6, WASM_LOOP(1, WASM_BR(0)));
EXPECT_SIZE(7, WASM_LOOP(1, WASM_BR_IF(0, WASM_ZERO)));
EXPECT_SIZE(1, WASM_RETURN0);
EXPECT_SIZE(3, WASM_RETURN(WASM_ZERO));
EXPECT_SIZE(5, WASM_RETURN(WASM_ZERO, WASM_ZERO));
EXPECT_SIZE(2, WASM_RETURN0);
EXPECT_SIZE(4, WASM_RETURN1(WASM_ZERO));
EXPECT_SIZE(1, WASM_UNREACHABLE);
}
TEST_F(WasmMacroGenTest, MacroStatements) {
EXPECT_SIZE(8, WASM_WHILE(WASM_I8(0), WASM_NOP));
EXPECT_SIZE(10, WASM_WHILE(WASM_I8(0), WASM_NOP));
EXPECT_SIZE(7, WASM_INC_LOCAL(0));
EXPECT_SIZE(7, WASM_INC_LOCAL_BY(0, 3));
EXPECT_SIZE(3, WASM_BREAK(0));
EXPECT_SIZE(3, WASM_CONTINUE(0));
EXPECT_SIZE(4, WASM_BREAK(0));
EXPECT_SIZE(4, WASM_CONTINUE(0));
}
TEST_F(WasmMacroGenTest, BrTable) {
EXPECT_SIZE(8, WASM_BR_TABLE(WASM_ZERO, 1, BR_TARGET(1)));
EXPECT_SIZE(9, WASM_BR_TABLE(WASM_ZERO, 1, BR_TARGET(1)));
EXPECT_SIZE(11, WASM_BR_TABLEV(WASM_ZERO, WASM_ZERO, 1, BR_TARGET(1)));
}
......@@ -114,8 +114,8 @@ TEST_F(WasmMacroGenTest, Expressions) {
EXPECT_SIZE(3, WASM_NOT(WASM_ZERO));
EXPECT_SIZE(4, WASM_BRV(1, WASM_ZERO));
EXPECT_SIZE(6, WASM_BRV_IF(1, WASM_ZERO, WASM_ZERO));
EXPECT_SIZE(5, WASM_BRV(1, WASM_ZERO));
EXPECT_SIZE(7, WASM_BRV_IF(1, WASM_ZERO, WASM_ZERO));
EXPECT_SIZE(4, WASM_BLOCK(1, WASM_ZERO));
EXPECT_SIZE(5, WASM_BLOCK(2, WASM_NOP, WASM_ZERO));
......@@ -127,33 +127,32 @@ TEST_F(WasmMacroGenTest, Expressions) {
}
TEST_F(WasmMacroGenTest, CallFunction) {
EXPECT_SIZE(2, WASM_CALL_FUNCTION0(0));
EXPECT_SIZE(2, WASM_CALL_FUNCTION0(1));
EXPECT_SIZE(2, WASM_CALL_FUNCTION0(11));
EXPECT_SIZE(3, WASM_CALL_FUNCTION0(0));
EXPECT_SIZE(3, WASM_CALL_FUNCTION0(1));
EXPECT_SIZE(3, WASM_CALL_FUNCTION0(11));
EXPECT_SIZE(4, WASM_CALL_FUNCTION(0, WASM_ZERO));
EXPECT_SIZE(6, WASM_CALL_FUNCTION(1, WASM_ZERO, WASM_ZERO));
EXPECT_SIZE(5, WASM_CALL_FUNCTION1(0, WASM_ZERO));
EXPECT_SIZE(7, WASM_CALL_FUNCTION2(1, WASM_ZERO, WASM_ZERO));
}
TEST_F(WasmMacroGenTest, CallImport) {
EXPECT_SIZE(2, WASM_CALL_IMPORT0(0));
EXPECT_SIZE(2, WASM_CALL_IMPORT0(1));
EXPECT_SIZE(2, WASM_CALL_IMPORT0(11));
EXPECT_SIZE(3, WASM_CALL_IMPORT0(0));
EXPECT_SIZE(3, WASM_CALL_IMPORT0(1));
EXPECT_SIZE(3, WASM_CALL_IMPORT0(11));
EXPECT_SIZE(4, WASM_CALL_IMPORT(0, WASM_ZERO));
EXPECT_SIZE(6, WASM_CALL_IMPORT(1, WASM_ZERO, WASM_ZERO));
EXPECT_SIZE(5, WASM_CALL_IMPORT1(0, WASM_ZERO));
EXPECT_SIZE(7, WASM_CALL_IMPORT2(1, WASM_ZERO, WASM_ZERO));
}
TEST_F(WasmMacroGenTest, CallIndirect) {
EXPECT_SIZE(4, WASM_CALL_INDIRECT0(0, WASM_ZERO));
EXPECT_SIZE(4, WASM_CALL_INDIRECT0(1, WASM_ZERO));
EXPECT_SIZE(4, WASM_CALL_INDIRECT0(11, WASM_ZERO));
EXPECT_SIZE(5, WASM_CALL_INDIRECT0(0, WASM_ZERO));
EXPECT_SIZE(5, WASM_CALL_INDIRECT0(1, WASM_ZERO));
EXPECT_SIZE(5, WASM_CALL_INDIRECT0(11, WASM_ZERO));
EXPECT_SIZE(6, WASM_CALL_INDIRECT(0, WASM_ZERO, WASM_ZERO));
EXPECT_SIZE(8, WASM_CALL_INDIRECT(1, WASM_ZERO, WASM_ZERO, WASM_ZERO));
EXPECT_SIZE(7, WASM_CALL_INDIRECT1(0, WASM_ZERO, WASM_ZERO));
EXPECT_SIZE(9, WASM_CALL_INDIRECT2(1, WASM_ZERO, WASM_ZERO, WASM_ZERO));
}
TEST_F(WasmMacroGenTest, Int32Ops) {
EXPECT_SIZE(5, WASM_I32_ADD(WASM_ZERO, WASM_ZERO));
EXPECT_SIZE(5, WASM_I32_SUB(WASM_ZERO, WASM_ZERO));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment