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