Commit ee03b721 authored by titzer's avatar titzer Committed by Commit bot

[wasm] Binary 11: Bump module version to 0xB.

[wasm] Binary 11: Swap the order of section name / section length.
[wasm] Binary 11: Shorter section names.
[wasm] Binary 11: Add a prefix for function type declarations.
[wasm] Binary 11: Function types encoded as pcount, p*, rcount, r*
[wasm] Fix numeric names for functions.

R=rossberg@chromium.org,jfb@chromium.org,ahaas@chromium.org
BUG=chromium:575167
LOG=Y

Review-Url: https://codereview.chromium.org/1896863003
Cr-Commit-Position: refs/heads/master@{#35897}
parent 2aa4656e
...@@ -80,11 +80,6 @@ void FixupSection(byte* start, byte* end) { ...@@ -80,11 +80,6 @@ void FixupSection(byte* start, byte* end) {
// Returns the start of the section, where the section VarInt size is. // Returns the start of the section, where the section VarInt size is.
byte* EmitSection(WasmSection::Code code, byte** b) { byte* EmitSection(WasmSection::Code code, byte** b) {
// Emit a placeholder for the length.
byte* start = *b;
for (size_t padding = 0; padding != kPaddedVarintSize; ++padding) {
EmitUint8(b, 0xff); // Will get fixed up later.
}
// Emit the section name. // Emit the section name.
const char* name = WasmSection::getName(code); const char* name = WasmSection::getName(code);
TRACE("emit section: %s\n", name); TRACE("emit section: %s\n", name);
...@@ -92,6 +87,12 @@ byte* EmitSection(WasmSection::Code code, byte** b) { ...@@ -92,6 +87,12 @@ byte* EmitSection(WasmSection::Code code, byte** b) {
EmitVarInt(b, length); // Section name string size. EmitVarInt(b, length); // Section name string size.
for (size_t i = 0; i != length; ++i) EmitUint8(b, name[i]); for (size_t i = 0; i != length; ++i) EmitUint8(b, name[i]);
// Emit a placeholder for the length.
byte* start = *b;
for (size_t padding = 0; padding != kPaddedVarintSize; ++padding) {
EmitUint8(b, 0xff); // Will get fixed up later.
}
return start; return start;
} }
} // namespace } // namespace
...@@ -586,7 +587,9 @@ WasmModuleIndex* WasmModuleWriter::WriteTo(Zone* zone) const { ...@@ -586,7 +587,9 @@ WasmModuleIndex* WasmModuleWriter::WriteTo(Zone* zone) const {
sizes.AddSection(WasmSection::Code::Signatures, signatures_.size()); sizes.AddSection(WasmSection::Code::Signatures, signatures_.size());
for (auto sig : signatures_) { for (auto sig : signatures_) {
sizes.Add(1 + LEBHelper::sizeof_u32v(sig->parameter_count()) + sizes.Add(1 + LEBHelper::sizeof_u32v(sig->parameter_count()) +
sig->parameter_count(), sig->parameter_count() +
LEBHelper::sizeof_u32v(sig->return_count()) +
sig->return_count(),
0); 0);
} }
TRACE("Size after signatures: %u, %u\n", (unsigned)sizes.header_size, TRACE("Size after signatures: %u, %u\n", (unsigned)sizes.header_size,
...@@ -594,7 +597,7 @@ WasmModuleIndex* WasmModuleWriter::WriteTo(Zone* zone) const { ...@@ -594,7 +597,7 @@ WasmModuleIndex* WasmModuleWriter::WriteTo(Zone* zone) const {
} }
if (functions_.size() > 0) { if (functions_.size() > 0) {
sizes.AddSection(WasmSection::Code::Functions, functions_.size()); sizes.AddSection(WasmSection::Code::OldFunctions, functions_.size());
for (auto function : functions_) { for (auto function : functions_) {
sizes.Add(function->HeaderSize() + function->BodySize(), sizes.Add(function->HeaderSize() + function->BodySize(),
function->NameSize()); function->NameSize());
...@@ -669,22 +672,22 @@ WasmModuleIndex* WasmModuleWriter::WriteTo(Zone* zone) const { ...@@ -669,22 +672,22 @@ WasmModuleIndex* WasmModuleWriter::WriteTo(Zone* zone) const {
EmitVarInt(&header, signatures_.size()); EmitVarInt(&header, signatures_.size());
for (FunctionSig* sig : signatures_) { for (FunctionSig* sig : signatures_) {
EmitUint8(&header, kWasmFunctionTypeForm);
EmitVarInt(&header, sig->parameter_count()); EmitVarInt(&header, sig->parameter_count());
if (sig->return_count() > 0) {
EmitUint8(&header, WasmOpcodes::LocalTypeCodeFor(sig->GetReturn()));
} else {
EmitUint8(&header, kLocalVoid);
}
for (size_t j = 0; j < sig->parameter_count(); j++) { for (size_t j = 0; j < sig->parameter_count(); j++) {
EmitUint8(&header, WasmOpcodes::LocalTypeCodeFor(sig->GetParam(j))); EmitUint8(&header, WasmOpcodes::LocalTypeCodeFor(sig->GetParam(j)));
} }
EmitVarInt(&header, sig->return_count());
for (size_t j = 0; j < sig->return_count(); j++) {
EmitUint8(&header, WasmOpcodes::LocalTypeCodeFor(sig->GetReturn(j)));
}
} }
FixupSection(section, header); FixupSection(section, header);
} }
// -- emit functions --------------------------------------------------------- // -- emit functions ---------------------------------------------------------
if (functions_.size() > 0) { if (functions_.size() > 0) {
byte* section = EmitSection(WasmSection::Code::Functions, &header); byte* section = EmitSection(WasmSection::Code::OldFunctions, &header);
EmitVarInt(&header, functions_.size()); EmitVarInt(&header, functions_.size());
for (auto func : functions_) { for (auto func : functions_) {
......
...@@ -107,17 +107,6 @@ class ModuleDecoder : public Decoder { ...@@ -107,17 +107,6 @@ class ModuleDecoder : public Decoder {
TRACE("DecodeSection\n"); TRACE("DecodeSection\n");
pos = pc_; pos = pc_;
// Read and check the section size.
int section_leb_length = 0;
uint32_t section_length =
consume_u32v(&section_leb_length, "section length");
if (!checkAvailable(section_length)) {
// The section would extend beyond the end of the module.
break;
}
const byte* section_start = pc_;
const byte* expected_section_end = pc_ + section_length;
// Read the section name. // Read the section name.
int string_leb_length = 0; int string_leb_length = 0;
uint32_t string_length = uint32_t string_length =
...@@ -128,15 +117,21 @@ class ModuleDecoder : public Decoder { ...@@ -128,15 +117,21 @@ class ModuleDecoder : public Decoder {
TRACE("Section name of length %u couldn't be read\n", string_length); TRACE("Section name of length %u couldn't be read\n", string_length);
break; break;
} }
if (pc_ > expected_section_end) {
error(section_name_start, pc_,
"section name string %u longer than total section bytes %u",
string_length, section_length);
}
WasmSection::Code section = WasmSection::Code section =
WasmSection::lookup(section_name_start, string_length); WasmSection::lookup(section_name_start, string_length);
// Read and check the section size.
int section_leb_length = 0;
uint32_t section_length =
consume_u32v(&section_leb_length, "section length");
if (!checkAvailable(section_length)) {
// The section would extend beyond the end of the module.
break;
}
const byte* section_start = pc_;
const byte* expected_section_end = pc_ + section_length;
current_order = CheckSectionOrder(current_order, section); current_order = CheckSectionOrder(current_order, section);
switch (section) { switch (section) {
...@@ -144,12 +139,13 @@ class ModuleDecoder : public Decoder { ...@@ -144,12 +139,13 @@ class ModuleDecoder : public Decoder {
// Terminate section decoding. // Terminate section decoding.
limit_ = pc_; limit_ = pc_;
break; break;
case WasmSection::Code::Memory: case WasmSection::Code::Memory: {
int length; int length;
module->min_mem_pages = consume_u32v(&length, "min memory"); module->min_mem_pages = consume_u32v(&length, "min memory");
module->max_mem_pages = consume_u32v(&length, "max memory"); module->max_mem_pages = consume_u32v(&length, "max memory");
module->mem_export = consume_u8("export memory") != 0; module->mem_export = consume_u8("export memory") != 0;
break; break;
}
case WasmSection::Code::Signatures: { case WasmSection::Code::Signatures: {
int length; int length;
uint32_t signatures_count = consume_u32v(&length, "signatures count"); uint32_t signatures_count = consume_u32v(&length, "signatures count");
...@@ -159,7 +155,7 @@ class ModuleDecoder : public Decoder { ...@@ -159,7 +155,7 @@ class ModuleDecoder : public Decoder {
if (failed()) break; if (failed()) break;
TRACE("DecodeSignature[%d] module+%d\n", i, TRACE("DecodeSignature[%d] module+%d\n", i,
static_cast<int>(pc_ - start_)); static_cast<int>(pc_ - start_));
FunctionSig* s = consume_sig(); // read function sig. FunctionSig* s = consume_sig();
module->signatures.push_back(s); module->signatures.push_back(s);
} }
break; break;
...@@ -202,7 +198,7 @@ class ModuleDecoder : public Decoder { ...@@ -202,7 +198,7 @@ class ModuleDecoder : public Decoder {
} }
break; break;
} }
case WasmSection::Code::Functions: { case WasmSection::Code::OldFunctions: {
int length; int length;
uint32_t functions_count = consume_u32v(&length, "functions count"); uint32_t functions_count = consume_u32v(&length, "functions count");
module->functions.reserve(SafeReserve(functions_count)); module->functions.reserve(SafeReserve(functions_count));
...@@ -385,7 +381,7 @@ class ModuleDecoder : public Decoder { ...@@ -385,7 +381,7 @@ class ModuleDecoder : public Decoder {
TRACE("%c", *(section_name_start + i)); TRACE("%c", *(section_name_start + i));
} }
TRACE("'\n"); TRACE("'\n");
consume_bytes(section_length - string_length - string_leb_length); consume_bytes(section_length);
break; break;
} }
...@@ -700,20 +696,48 @@ class ModuleDecoder : public Decoder { ...@@ -700,20 +696,48 @@ class ModuleDecoder : public Decoder {
} }
} }
// Parses an inline function signature. // Parses a type entry, which is currently limited to functions only.
FunctionSig* consume_sig() { FunctionSig* consume_sig() {
const byte* pos = pc_;
byte form = consume_u8("type form");
if (form != kWasmFunctionTypeForm) {
error(pos, pos, "expected function type form (0x%02x), got: 0x%02x",
kWasmFunctionTypeForm, form);
return nullptr;
}
int length; int length;
byte count = consume_u32v(&length, "param count"); // parse parameter types
LocalType ret = consume_local_type(); uint32_t param_count = consume_u32v(&length, "param count");
FunctionSig::Builder builder(module_zone, ret == kAstStmt ? 0 : 1, count); std::vector<LocalType> params;
if (ret != kAstStmt) builder.AddReturn(ret); for (uint32_t i = 0; i < param_count; i++) {
for (int i = 0; i < count; i++) {
LocalType param = consume_local_type(); LocalType param = consume_local_type();
if (param == kAstStmt) error(pc_ - 1, "invalid void parameter type"); if (param == kAstStmt) error(pc_ - 1, "invalid void parameter type");
builder.AddParam(param); params.push_back(param);
}
// parse return types
const byte* pt = pc_;
uint32_t return_count = consume_u32v(&length, "return count");
if (return_count > kMaxReturnCount) {
error(pt, pt, "return count of %u exceeds maximum of %u", return_count,
kMaxReturnCount);
return nullptr;
}
std::vector<LocalType> returns;
for (uint32_t i = 0; i < return_count; i++) {
LocalType ret = consume_local_type();
if (ret == kAstStmt) error(pc_ - 1, "invalid void return type");
returns.push_back(ret);
} }
return builder.Build();
// FunctionSig stores the return types first.
LocalType* buffer =
module_zone->NewArray<LocalType>(param_count + return_count);
uint32_t b = 0;
for (uint32_t i = 0; i < return_count; i++) buffer[b++] = returns[i];
for (uint32_t i = 0; i < param_count; i++) buffer[b++] = params[i];
return new (module_zone) FunctionSig(return_count, param_count, buffer);
} }
}; };
......
...@@ -564,4 +564,23 @@ class LocalDeclEncoder { ...@@ -564,4 +564,23 @@ class LocalDeclEncoder {
#define WASM_I32_REINTERPRET_F32(x) x, kExprI32ReinterpretF32 #define WASM_I32_REINTERPRET_F32(x) x, kExprI32ReinterpretF32
#define WASM_I64_REINTERPRET_F64(x) x, kExprI64ReinterpretF64 #define WASM_I64_REINTERPRET_F64(x) x, kExprI64ReinterpretF64
#define SIG_ENTRY_v_v kWasmFunctionTypeForm, 0, 0
#define SIZEOF_SIG_ENTRY_v_v 3
#define SIG_ENTRY_v_x(a) kWasmFunctionTypeForm, 1, a, 0
#define SIG_ENTRY_v_xx(a, b) kWasmFunctionTypeForm, 2, a, b, 0
#define SIG_ENTRY_v_xxx(a, b, c) kWasmFunctionTypeForm, 3, a, b, c, 0
#define SIZEOF_SIG_ENTRY_v_x 4
#define SIZEOF_SIG_ENTRY_v_xx 5
#define SIZEOF_SIG_ENTRY_v_xxx 6
#define SIG_ENTRY_x(r) kWasmFunctionTypeForm, 0, 1, r
#define SIG_ENTRY_x_x(r, a) kWasmFunctionTypeForm, 1, a, 1, r
#define SIG_ENTRY_x_xx(r, a, b) kWasmFunctionTypeForm, 2, a, b, 1, r
#define SIG_ENTRY_x_xxx(r, a, b, c) kWasmFunctionTypeForm, 3, a, b, c, 1, r
#define SIZEOF_SIG_ENTRY_x 4
#define SIZEOF_SIG_ENTRY_x_x 5
#define SIZEOF_SIG_ENTRY_x_xx 6
#define SIZEOF_SIG_ENTRY_x_xxx 7
#endif // V8_WASM_MACRO_GEN_H_ #endif // V8_WASM_MACRO_GEN_H_
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#include "src/macro-assembler.h" #include "src/macro-assembler.h"
#include "src/objects.h" #include "src/objects.h"
#include "src/property-descriptor.h"
#include "src/v8.h" #include "src/v8.h"
#include "src/simulator.h" #include "src/simulator.h"
...@@ -409,6 +410,9 @@ MaybeHandle<JSObject> WasmModule::Instantiate(Isolate* isolate, ...@@ -409,6 +410,9 @@ MaybeHandle<JSObject> WasmModule::Instantiate(Isolate* isolate,
ErrorThrower thrower(isolate, "WasmModule::Instantiate()"); ErrorThrower thrower(isolate, "WasmModule::Instantiate()");
Factory* factory = isolate->factory(); Factory* factory = isolate->factory();
PropertyDescriptor desc;
desc.set_writable(false);
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
// Allocate the instance and its JS counterpart. // Allocate the instance and its JS counterpart.
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
...@@ -562,7 +566,11 @@ MaybeHandle<JSObject> WasmModule::Instantiate(Isolate* isolate, ...@@ -562,7 +566,11 @@ MaybeHandle<JSObject> WasmModule::Instantiate(Isolate* isolate,
if (func.exported) { if (func.exported) {
// Exported functions are installed as read-only properties on the // Exported functions are installed as read-only properties on the
// module. // module.
JSObject::AddProperty(instance.js_object, name, function, READ_ONLY); desc.set_value(function);
Maybe<bool> status = JSReceiver::DefineOwnProperty(
isolate, instance.js_object, name, &desc, Object::THROW_ON_ERROR);
if (!status.IsJust())
thrower.Error("export of %.*s failed.", str.length(), str.start());
} }
} }
...@@ -593,7 +601,11 @@ MaybeHandle<JSObject> WasmModule::Instantiate(Isolate* isolate, ...@@ -593,7 +601,11 @@ MaybeHandle<JSObject> WasmModule::Instantiate(Isolate* isolate,
Handle<JSFunction> function = compiler::CompileJSToWasmWrapper( Handle<JSFunction> function = compiler::CompileJSToWasmWrapper(
isolate, &module_env, name, code, instance.js_object, isolate, &module_env, name, code, instance.js_object,
exp.func_index); exp.func_index);
JSObject::AddProperty(exports_object, name, function, READ_ONLY); desc.set_value(function);
Maybe<bool> status = JSReceiver::DefineOwnProperty(
isolate, exports_object, name, &desc, Object::THROW_ON_ERROR);
if (!status.IsJust())
thrower.Error("export of %.*s failed.", str.length(), str.start());
} }
if (mem_export) { if (mem_export) {
......
...@@ -24,65 +24,59 @@ const size_t kMaxModuleSize = 1024 * 1024 * 1024; ...@@ -24,65 +24,59 @@ const size_t kMaxModuleSize = 1024 * 1024 * 1024;
const size_t kMaxFunctionSize = 128 * 1024; const size_t kMaxFunctionSize = 128 * 1024;
const size_t kMaxStringSize = 256; const size_t kMaxStringSize = 256;
const uint32_t kWasmMagic = 0x6d736100; const uint32_t kWasmMagic = 0x6d736100;
const uint32_t kWasmVersion = 0x0a; const uint32_t kWasmVersion = 0x0b;
const uint8_t kWasmFunctionTypeForm = 0x40;
// WebAssembly sections are named as strings in the binary format, but // WebAssembly sections are named as strings in the binary format, but
// internally V8 uses an enum to handle them. // internally V8 uses an enum to handle them.
// //
// Entries have the form F(enumerator, order, string). // Entries have the form F(enumerator, string).
#define FOR_EACH_WASM_SECTION_TYPE(F) \ #define FOR_EACH_WASM_SECTION_TYPE(F) \
F(Signatures, 1, "signatures") \ F(Signatures, 1, "type") \
F(ImportTable, 2, "import_table") \ F(ImportTable, 2, "import") \
F(FunctionSignatures, 3, "function_signatures") \ F(FunctionSignatures, 3, "function") \
F(FunctionTable, 4, "function_table") \ F(FunctionTable, 4, "table") \
F(Memory, 5, "memory") \ F(Memory, 5, "memory") \
F(ExportTable, 6, "export_table") \ F(ExportTable, 6, "export") \
F(StartFunction, 7, "start_function") \ F(StartFunction, 7, "start") \
F(FunctionBodies, 8, "function_bodies") \ F(FunctionBodies, 8, "code") \
F(DataSegments, 9, "data_segments") \ F(DataSegments, 9, "data") \
F(Names, 10, "names") \ F(Names, 10, "name") \
F(Globals, 0, "globals") \ F(OldFunctions, 0, "old_function") \
F(Functions, 0, "functions") \ F(Globals, 0, "global") \
F(End, 0, "end") F(End, 0, "end")
// Contants for the above section types: {LEB128 length, characters...}. // Contants for the above section types: {LEB128 length, characters...}.
#define WASM_SECTION_MEMORY 6, 'm', 'e', 'm', 'o', 'r', 'y' #define WASM_SECTION_MEMORY 6, 'm', 'e', 'm', 'o', 'r', 'y'
#define WASM_SECTION_SIGNATURES \ #define WASM_SECTION_SIGNATURES 4, 't', 'y', 'p', 'e'
10, 's', 'i', 'g', 'n', 'a', 't', 'u', 'r', 'e', 's' #define WASM_SECTION_OLD_FUNCTIONS \
#define WASM_SECTION_FUNCTIONS 9, 'f', 'u', 'n', 'c', 't', 'i', 'o', 'n', 's' 12, 'o', 'l', 'd', '_', 'f', 'u', 'n', 'c', 't', 'i', 'o', 'n'
#define WASM_SECTION_GLOBALS 7, 'g', 'l', 'o', 'b', 'a', 'l', 's' #define WASM_SECTION_GLOBALS 6, 'g', 'l', 'o', 'b', 'a', 'l'
#define WASM_SECTION_DATA_SEGMENTS \ #define WASM_SECTION_DATA_SEGMENTS 4, 'd', 'a', 't', 'a'
13, 'd', 'a', 't', 'a', '_', 's', 'e', 'g', 'm', 'e', 'n', 't', 's' #define WASM_SECTION_FUNCTION_TABLE 5, 't', 'a', 'b', 'l', 'e'
#define WASM_SECTION_FUNCTION_TABLE \
14, 'f', 'u', 'n', 'c', 't', 'i', 'o', 'n', '_', 't', 'a', 'b', 'l', 'e'
#define WASM_SECTION_END 3, 'e', 'n', 'd' #define WASM_SECTION_END 3, 'e', 'n', 'd'
#define WASM_SECTION_START_FUNCTION \ #define WASM_SECTION_START_FUNCTION 5, 's', 't', 'a', 'r', 't'
14, 's', 't', 'a', 'r', 't', '_', 'f', 'u', 'n', 'c', 't', 'i', 'o', 'n' #define WASM_SECTION_IMPORT_TABLE 6, 'i', 'm', 'p', 'o', 'r', 't'
#define WASM_SECTION_IMPORT_TABLE \ #define WASM_SECTION_EXPORT_TABLE 6, 'e', 'x', 'p', 'o', 'r', 't'
12, 'i', 'm', 'p', 'o', 'r', 't', '_', 't', 'a', 'b', 'l', 'e' #define WASM_SECTION_FUNCTION_SIGNATURES \
#define WASM_SECTION_EXPORT_TABLE \ 8, 'f', 'u', 'n', 'c', 't', 'i', 'o', 'n'
12, 'e', 'x', 'p', 'o', 'r', 't', '_', 't', 'a', 'b', 'l', 'e' #define WASM_SECTION_FUNCTION_BODIES 4, 'c', 'o', 'd', 'e'
#define WASM_SECTION_FUNCTION_SIGNATURES \ #define WASM_SECTION_NAMES 4, 'n', 'a', 'm', 'e'
19, 'f', 'u', 'n', 'c', 't', 'i', 'o', 'n', '_', 's', 'i', 'g', 'n', 'a', \
't', 'u', 'r', 'e', 's'
#define WASM_SECTION_FUNCTION_BODIES \
15, 'f', 'u', 'n', 'c', 't', 'i', 'o', 'n', '_', 'b', 'o', 'd', 'i', 'e', 's'
#define WASM_SECTION_NAMES 5, 'n', 'a', 'm', 'e', 's'
// Constants for the above section headers' size (LEB128 + characters). // Constants for the above section headers' size (LEB128 + characters).
#define WASM_SECTION_MEMORY_SIZE ((size_t)7) #define WASM_SECTION_MEMORY_SIZE ((size_t)7)
#define WASM_SECTION_SIGNATURES_SIZE ((size_t)11) #define WASM_SECTION_SIGNATURES_SIZE ((size_t)5)
#define WASM_SECTION_FUNCTIONS_SIZE ((size_t)10) #define WASM_SECTION_OLD_FUNCTIONS_SIZE ((size_t)13)
#define WASM_SECTION_GLOBALS_SIZE ((size_t)8) #define WASM_SECTION_GLOBALS_SIZE ((size_t)7)
#define WASM_SECTION_DATA_SEGMENTS_SIZE ((size_t)14) #define WASM_SECTION_DATA_SEGMENTS_SIZE ((size_t)5)
#define WASM_SECTION_FUNCTION_TABLE_SIZE ((size_t)15) #define WASM_SECTION_FUNCTION_TABLE_SIZE ((size_t)6)
#define WASM_SECTION_END_SIZE ((size_t)4) #define WASM_SECTION_END_SIZE ((size_t)4)
#define WASM_SECTION_START_FUNCTION_SIZE ((size_t)15) #define WASM_SECTION_START_FUNCTION_SIZE ((size_t)6)
#define WASM_SECTION_IMPORT_TABLE_SIZE ((size_t)13) #define WASM_SECTION_IMPORT_TABLE_SIZE ((size_t)7)
#define WASM_SECTION_EXPORT_TABLE_SIZE ((size_t)13) #define WASM_SECTION_EXPORT_TABLE_SIZE ((size_t)7)
#define WASM_SECTION_FUNCTION_SIGNATURES_SIZE ((size_t)20) #define WASM_SECTION_FUNCTION_SIGNATURES_SIZE ((size_t)9)
#define WASM_SECTION_FUNCTION_BODIES_SIZE ((size_t)16) #define WASM_SECTION_FUNCTION_BODIES_SIZE ((size_t)5)
#define WASM_SECTION_NAMES_SIZE ((size_t)6) #define WASM_SECTION_NAMES_SIZE ((size_t)5)
struct WasmSection { struct WasmSection {
enum class Code : uint32_t { enum class Code : uint32_t {
...@@ -111,6 +105,8 @@ enum WasmFunctionDeclBit { ...@@ -111,6 +105,8 @@ enum WasmFunctionDeclBit {
static const size_t kDeclMemorySize = 3; static const size_t kDeclMemorySize = 3;
static const size_t kDeclDataSegmentSize = 13; static const size_t kDeclDataSegmentSize = 13;
static const uint32_t kMaxReturnCount = 1;
// Static representation of a WASM function. // Static representation of a WASM function.
struct WasmFunction { struct WasmFunction {
FunctionSig* sig; // signature of the function. FunctionSig* sig; // signature of the function.
......
...@@ -18,8 +18,6 @@ using namespace v8::internal; ...@@ -18,8 +18,6 @@ using namespace v8::internal;
using namespace v8::internal::compiler; using namespace v8::internal::compiler;
using namespace v8::internal::wasm; using namespace v8::internal::wasm;
// TODO(titzer): fix arm64 frame alignment.
namespace { namespace {
void TestModule(WasmModuleIndex* module, int32_t expected_result) { void TestModule(WasmModuleIndex* module, int32_t expected_result) {
Isolate* isolate = CcTest::InitIsolateOnce(); Isolate* isolate = CcTest::InitIsolateOnce();
...@@ -31,43 +29,6 @@ void TestModule(WasmModuleIndex* module, int32_t expected_result) { ...@@ -31,43 +29,6 @@ void TestModule(WasmModuleIndex* module, int32_t expected_result) {
} }
} // namespace } // namespace
// A raw test that skips the WasmModuleBuilder.
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
// func#0 (main) ----------------------------------
WASM_SECTION_FUNCTIONS_SIZE + 25, WASM_SECTION_FUNCTIONS, 2,
kDeclFunctionExport, 0, 0, // sig index
8, 0, // body size
0, // locals
kExprI8Const, 77, // --
kExprI8Const, 22, // --
kExprCallFunction, 2, 1, // --
// func#1 -----------------------------------------
0, // no name, not exported
1, 0, // sig index
6, 0, // body size
0, // locals
kExprGetLocal, 0, // --
kExprGetLocal, 1, // --
kExprI32Add, // --
};
Isolate* isolate = CcTest::InitIsolateOnce();
HandleScope scope(isolate);
WasmJs::InstallWasmFunctionMap(isolate, isolate->native_context());
int32_t result =
CompileAndRunWasmModule(isolate, data, data + arraysize(data));
CHECK_EQ(99, result);
}
TEST(Run_WasmModule_Return114) { TEST(Run_WasmModule_Return114) {
static const int32_t kReturnValue = 114; static const int32_t kReturnValue = 114;
v8::base::AccountingAllocator allocator; v8::base::AccountingAllocator allocator;
......
...@@ -27,8 +27,10 @@ function makeSelect(type, args, which) { ...@@ -27,8 +27,10 @@ function makeSelect(type, args, which) {
var builder = new WasmModuleBuilder(); var builder = new WasmModuleBuilder();
var sig = new Array(); var sig = new Array();
sig.push(type); sig.push(args);
for (var i = 0; i < args; i++) sig.push(type); for (var i = 0; i < args; i++) sig.push(type);
sig.push(1);
sig.push(type);
builder.addFunction("select", sig) builder.addFunction("select", sig)
.addBody([kExprGetLocal, which]) .addBody([kExprGetLocal, which])
.exportFunc(); .exportFunc();
......
...@@ -45,7 +45,7 @@ function assertFunction(module, func) { ...@@ -45,7 +45,7 @@ function assertFunction(module, func) {
var builder = new WasmModuleBuilder(); var builder = new WasmModuleBuilder();
builder.addMemory(1, 1, true); builder.addMemory(1, 1, true);
builder.addFunction("sub", [kAstI64, kAstI64, kAstI64]) builder.addFunction("sub", kSig_l_ll)
.addBody([ // -- .addBody([ // --
kExprGetLocal, 0, // -- kExprGetLocal, 0, // --
kExprGetLocal, 1, // -- kExprGetLocal, 1, // --
...@@ -67,7 +67,7 @@ function assertFunction(module, func) { ...@@ -67,7 +67,7 @@ function assertFunction(module, func) {
var builder = new WasmModuleBuilder(); var builder = new WasmModuleBuilder();
builder.addMemory(1, 1, true); builder.addMemory(1, 1, true);
builder.addFunction("sub", [kAstI32, kAstI32, kAstI32]) builder.addFunction("sub", kSig_i_ii)
.addBody([ .addBody([
kExprGetLocal, 0, // -- kExprGetLocal, 0, // --
kExprGetLocal, 1, // -- kExprGetLocal, 1, // --
...@@ -92,7 +92,7 @@ function assertFunction(module, func) { ...@@ -92,7 +92,7 @@ function assertFunction(module, func) {
var kPages = 2; var kPages = 2;
builder.addMemory(kPages, kPages, true); builder.addMemory(kPages, kPages, true);
builder.addFunction("nop", [kAstStmt]) builder.addFunction("nop", kSig_v_v)
.addBody([kExprNop]) .addBody([kExprNop])
.exportFunc(); .exportFunc();
...@@ -109,7 +109,7 @@ function assertFunction(module, func) { ...@@ -109,7 +109,7 @@ function assertFunction(module, func) {
var kPages = 3; var kPages = 3;
builder.addMemory(kPages, kPages, true); builder.addMemory(kPages, kPages, true);
builder.addFunction("flt", [kAstI32, kAstF64, kAstF64]) builder.addFunction("flt", kSig_i_dd)
.addBody([ .addBody([
kExprGetLocal, 0, // -- kExprGetLocal, 0, // --
kExprGetLocal, 1, // -- kExprGetLocal, 1, // --
......
...@@ -33,7 +33,7 @@ function assertTraps(code, msg) { ...@@ -33,7 +33,7 @@ function assertTraps(code, msg) {
function makeBinop(opcode) { function makeBinop(opcode) {
var builder = new WasmModuleBuilder(); var builder = new WasmModuleBuilder();
builder.addFunction("main", [kAstI32, kAstI32, kAstI32]) builder.addFunction("main", kSig_i_ii)
.addBody([ .addBody([
kExprGetLocal, 0, // -- kExprGetLocal, 0, // --
kExprGetLocal, 1, // -- kExprGetLocal, 1, // --
......
...@@ -11,7 +11,7 @@ load("test/mjsunit/wasm/wasm-module-builder.js"); ...@@ -11,7 +11,7 @@ load("test/mjsunit/wasm/wasm-module-builder.js");
var kReturnValue = 88; var kReturnValue = 88;
var builder = new WasmModuleBuilder(); var builder = new WasmModuleBuilder();
builder.addFunction("main", [kAstI32]) builder.addFunction("main", kSig_i)
.addBody([ .addBody([
kExprI8Const, kExprI8Const,
kReturnValue, kReturnValue,
...@@ -32,7 +32,7 @@ load("test/mjsunit/wasm/wasm-module-builder.js"); ...@@ -32,7 +32,7 @@ load("test/mjsunit/wasm/wasm-module-builder.js");
var builder = new WasmModuleBuilder(); var builder = new WasmModuleBuilder();
builder.addFunction("main", [kAstI32]) builder.addFunction("main", kSig_i)
.addBody([ .addBody([
kExprI8Const, kExprI8Const,
kReturnValue, kReturnValue,
...@@ -50,3 +50,25 @@ load("test/mjsunit/wasm/wasm-module-builder.js"); ...@@ -50,3 +50,25 @@ load("test/mjsunit/wasm/wasm-module-builder.js");
assertEquals(kReturnValue, module.exports.foo()); assertEquals(kReturnValue, module.exports.foo());
assertEquals(kReturnValue, module.exports.blah()); assertEquals(kReturnValue, module.exports.blah());
})(); })();
(function testNumericName() {
var kReturnValue = 93;
var builder = new WasmModuleBuilder();
builder.addFunction("main", kSig_i)
.addBody([
kExprI8Const,
kReturnValue,
kExprReturn, kArity1
])
.exportAs("0");
var module = builder.instantiate();
assertEquals("object", typeof module.exports);
assertEquals("function", typeof module.exports["0"]);
assertEquals(kReturnValue, module.exports["0"]());
})();
...@@ -10,7 +10,7 @@ load("test/mjsunit/wasm/wasm-module-builder.js"); ...@@ -10,7 +10,7 @@ load("test/mjsunit/wasm/wasm-module-builder.js");
function testCallFFI(ffi) { function testCallFFI(ffi) {
var builder = new WasmModuleBuilder(); var builder = new WasmModuleBuilder();
var sig_index = [kAstI32, kAstF64, kAstF64]; var sig_index = kSig_i_dd;
builder.addImport("fun", sig_index); builder.addImport("fun", sig_index);
builder.addFunction("main", sig_index) builder.addFunction("main", sig_index)
.addBody([ .addBody([
......
...@@ -10,7 +10,7 @@ load("test/mjsunit/wasm/wasm-module-builder.js"); ...@@ -10,7 +10,7 @@ load("test/mjsunit/wasm/wasm-module-builder.js");
function testCallFFI(func, check) { function testCallFFI(func, check) {
var builder = new WasmModuleBuilder(); var builder = new WasmModuleBuilder();
var sig_index = builder.addSignature([kAstI32, kAstF64, kAstF64]); var sig_index = builder.addSignature(kSig_i_dd);
builder.addImport("func", sig_index); builder.addImport("func", sig_index);
builder.addFunction("main", sig_index) builder.addFunction("main", sig_index)
.addBody([ .addBody([
...@@ -185,8 +185,8 @@ function testCallBinopVoid(type, func, check) { ...@@ -185,8 +185,8 @@ function testCallBinopVoid(type, func, check) {
var builder = new WasmModuleBuilder(); var builder = new WasmModuleBuilder();
builder.addImport("func", [kAstStmt, type, type]); builder.addImport("func", makeSig_v_xx(type));
builder.addFunction("main", [kAstI32, type, type]) builder.addFunction("main", makeSig_r_xx(kAstI32, type))
.addBody([ .addBody([
kExprGetLocal, 0, // -- kExprGetLocal, 0, // --
kExprGetLocal, 1, // -- kExprGetLocal, 1, // --
...@@ -241,9 +241,9 @@ testCallBinopVoid(kAstF64); ...@@ -241,9 +241,9 @@ testCallBinopVoid(kAstF64);
function testCallPrint() { function testCallPrint() {
var builder = new WasmModuleBuilder(); var builder = new WasmModuleBuilder();
builder.addImport("print", [kAstStmt, kAstI32]); builder.addImport("print", makeSig_v_x(kAstI32));
builder.addImport("print", [kAstStmt, kAstF64]); builder.addImport("print", makeSig_v_x(kAstF64));
builder.addFunction("main", [kAstStmt, kAstF64]) builder.addFunction("main", makeSig_v_x(kAstF64))
.addBody([ .addBody([
kExprI8Const, 97, // -- kExprI8Const, 97, // --
kExprCallImport, kArity1, 0, // -- kExprCallImport, kArity1, 0, // --
......
...@@ -10,7 +10,7 @@ load("test/mjsunit/wasm/wasm-module-builder.js"); ...@@ -10,7 +10,7 @@ load("test/mjsunit/wasm/wasm-module-builder.js");
(function TestFunctionPrototype() { (function TestFunctionPrototype() {
var builder = new WasmModuleBuilder(); var builder = new WasmModuleBuilder();
builder.addFunction("nine", [kAstI32]) builder.addFunction("nine", kSig_i)
.addBody([kExprI8Const, 9]) .addBody([kExprI8Const, 9])
.exportFunc(); .exportFunc();
......
...@@ -10,7 +10,7 @@ load("test/mjsunit/wasm/wasm-module-builder.js"); ...@@ -10,7 +10,7 @@ load("test/mjsunit/wasm/wasm-module-builder.js");
function makeFFI(func, t) { function makeFFI(func, t) {
var builder = new WasmModuleBuilder(); var builder = new WasmModuleBuilder();
var sig_index = builder.addSignature([t,t,t,t,t,t,t,t,t,t,t]); var sig_index = builder.addSignature([10,t,t,t,t,t,t,t,t,t,t,1,t]);
builder.addImport("func", sig_index); builder.addImport("func", sig_index);
// Try to create a frame with lots of spilled values and parameters // Try to create a frame with lots of spilled values and parameters
// on the stack to try to catch GC bugs in the reference maps for // on the stack to try to catch GC bugs in the reference maps for
......
...@@ -10,7 +10,7 @@ load("test/mjsunit/wasm/wasm-module-builder.js"); ...@@ -10,7 +10,7 @@ load("test/mjsunit/wasm/wasm-module-builder.js");
function testCallImport(func, check) { function testCallImport(func, check) {
var builder = new WasmModuleBuilder(); var builder = new WasmModuleBuilder();
var sig_index = builder.addSignature([kAstI32, kAstF64, kAstF64]); var sig_index = builder.addSignature(kSig_i_dd);
builder.addImport("func", sig_index); builder.addImport("func", sig_index);
builder.addFunction("main", sig_index) builder.addFunction("main", sig_index)
.addBody([ .addBody([
...@@ -186,8 +186,8 @@ function testCallBinopVoid(type, func, check) { ...@@ -186,8 +186,8 @@ function testCallBinopVoid(type, func, check) {
var builder = new WasmModuleBuilder(); var builder = new WasmModuleBuilder();
builder.addImport("func", [kAstStmt, type, type]); builder.addImport("func", makeSig_v_xx(type));
builder.addFunction("main", [kAstI32, type, type]) builder.addFunction("main", makeSig_r_xx(kAstI32, type))
.addBody([ .addBody([
kExprGetLocal, 0, // -- kExprGetLocal, 0, // --
kExprGetLocal, 1, // -- kExprGetLocal, 1, // --
...@@ -241,9 +241,9 @@ testCallBinopVoid(kAstF64); ...@@ -241,9 +241,9 @@ testCallBinopVoid(kAstF64);
function testCallPrint() { function testCallPrint() {
var builder = new WasmModuleBuilder(); var builder = new WasmModuleBuilder();
builder.addImport("print", [kAstStmt, kAstI32]); builder.addImport("print", makeSig_v_x(kAstI32));
builder.addImport("print", [kAstStmt, kAstF64]); builder.addImport("print", makeSig_r_x(kAstF64, kAstF64));
builder.addFunction("main", [kAstStmt, kAstF64]) builder.addFunction("main", makeSig_r_x(kAstF64, kAstF64))
.addBody([ .addBody([
kExprI8Const, 97, // -- kExprI8Const, 97, // --
kExprCallImport, kArity1, 0, // -- kExprCallImport, kArity1, 0, // --
...@@ -266,9 +266,9 @@ testCallPrint(); ...@@ -266,9 +266,9 @@ testCallPrint();
function testCallImport2(foo, bar, expected) { function testCallImport2(foo, bar, expected) {
var builder = new WasmModuleBuilder(); var builder = new WasmModuleBuilder();
builder.addImport("foo", [kAstI32]); builder.addImport("foo", kSig_i);
builder.addImport("bar", [kAstI32]); builder.addImport("bar", kSig_i);
builder.addFunction("main", [kAstI32]) builder.addFunction("main", kSig_i)
.addBody([ .addBody([
kExprCallImport, kArity0, 0, // -- kExprCallImport, kArity0, 0, // --
kExprCallImport, kArity0, 1, // -- kExprCallImport, kArity0, 1, // --
......
...@@ -10,7 +10,7 @@ load("test/mjsunit/wasm/wasm-module-builder.js"); ...@@ -10,7 +10,7 @@ load("test/mjsunit/wasm/wasm-module-builder.js");
var module = (function () { var module = (function () {
var builder = new WasmModuleBuilder(); var builder = new WasmModuleBuilder();
var sig_index = builder.addSignature([kAstI32, kAstI32, kAstI32]); var sig_index = builder.addSignature(kSig_i_ii);
builder.addImport("add", sig_index); builder.addImport("add", sig_index);
builder.addFunction("add", sig_index) builder.addFunction("add", sig_index)
.addBody([ .addBody([
...@@ -22,7 +22,7 @@ var module = (function () { ...@@ -22,7 +22,7 @@ var module = (function () {
kExprGetLocal, 1, // -- kExprGetLocal, 1, // --
kExprI32Sub, // -- kExprI32Sub, // --
]); ]);
builder.addFunction("main", [kAstI32, kAstI32, kAstI32, kAstI32]) builder.addFunction("main", kSig_i_iii)
.addBody([ .addBody([
kExprGetLocal, 0, kExprGetLocal, 0,
kExprGetLocal, 1, kExprGetLocal, 1,
......
...@@ -13,7 +13,7 @@ var module = (function Build() { ...@@ -13,7 +13,7 @@ var module = (function Build() {
var builder = new WasmModuleBuilder(); var builder = new WasmModuleBuilder();
builder.addMemory(1, 1, true); builder.addMemory(1, 1, true);
builder.addFunction("main", [kAstI32]) builder.addFunction("main", kSig_i)
.addBody([kExprI8Const, kReturnValue]) .addBody([kExprI8Const, kReturnValue])
.exportFunc(); .exportFunc();
......
...@@ -11,7 +11,7 @@ load("test/mjsunit/wasm/wasm-module-builder.js"); ...@@ -11,7 +11,7 @@ load("test/mjsunit/wasm/wasm-module-builder.js");
var kReturnValue = 107; var kReturnValue = 107;
var builder = new WasmModuleBuilder(); var builder = new WasmModuleBuilder();
builder.addFunction("main", [kAstI32]) builder.addFunction("main", kSig_i_i)
.addBody([kExprI8Const, kReturnValue]) .addBody([kExprI8Const, kReturnValue])
.exportFunc(); .exportFunc();
......
...@@ -13,7 +13,7 @@ function genModule(memory) { ...@@ -13,7 +13,7 @@ function genModule(memory) {
var builder = new WasmModuleBuilder(); var builder = new WasmModuleBuilder();
builder.addMemory(1, 1, true); builder.addMemory(1, 1, true);
builder.addFunction("main", [kAstI32, kAstI32]) builder.addFunction("main", kSig_i_i)
.addBody([ .addBody([
// main body: while(i) { if(mem[i]) return -1; i -= 4; } return 0; // main body: while(i) { if(mem[i]) return -1; i -= 4; } return 0;
kExprLoop, kExprLoop,
...@@ -128,7 +128,7 @@ function testOOBThrows() { ...@@ -128,7 +128,7 @@ function testOOBThrows() {
var builder = new WasmModuleBuilder(); var builder = new WasmModuleBuilder();
builder.addMemory(1, 1, true); builder.addMemory(1, 1, true);
builder.addFunction("geti", [kAstI32, kAstI32, kAstI32]) builder.addFunction("geti", kSig_i_ii)
.addBody([ .addBody([
kExprGetLocal, 0, kExprGetLocal, 0,
kExprGetLocal, 1, kExprGetLocal, 1,
......
...@@ -17,7 +17,7 @@ function testSelect2(type) { ...@@ -17,7 +17,7 @@ function testSelect2(type) {
var builder = new WasmModuleBuilder(); var builder = new WasmModuleBuilder();
builder.addFunction("select", [type, type, type]) builder.addFunction("select", makeSig_r_xx(type, type))
.addBody([kExprGetLocal, which]) .addBody([kExprGetLocal, which])
.exportFunc() .exportFunc()
...@@ -79,7 +79,7 @@ function testSelect10(t) { ...@@ -79,7 +79,7 @@ function testSelect10(t) {
print("type = " + t + ", which = " + which); print("type = " + t + ", which = " + which);
var builder = new WasmModuleBuilder(); var builder = new WasmModuleBuilder();
builder.addFunction("select", [t,t,t,t,t,t,t,t,t,t,t]) builder.addFunction("select", [10,t,t,t,t,t,t,t,t,t,t,1,t])
.addBody([kExprGetLocal, which]) .addBody([kExprGetLocal, which])
.exportFunc(); .exportFunc();
......
...@@ -36,24 +36,24 @@ function STACK() { ...@@ -36,24 +36,24 @@ function STACK() {
var builder = new WasmModuleBuilder(); var builder = new WasmModuleBuilder();
builder.addImport("func", [kAstStmt]); builder.addImport("func", kSig_v_v);
builder.addFunction("main", [kAstStmt]) builder.addFunction("main", kSig_v_v)
.addBody([kExprCallImport, kArity0, 0]) .addBody([kExprCallImport, kArity0, 0])
.exportAs("main"); .exportAs("main");
builder.addFunction("exec_unreachable", [kAstStmt]) builder.addFunction("exec_unreachable", kSig_v_v)
.addBody([kExprUnreachable]) .addBody([kExprUnreachable])
.exportAs("exec_unreachable"); .exportAs("exec_unreachable");
// 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, kSig_v_v)
// access the memory at offset -1 // access the memory at offset -1
.addBody([kExprI32Const, 0x7f, kExprI32LoadMem8S, 0, 0]) .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", kSig_v_v)
.addBody([kExprCallFunction, kArity0, mem_oob_func.index]) .addBody([kExprCallFunction, kArity0, mem_oob_func.index])
.exportAs("call_mem_out_of_bounds"); .exportAs("call_mem_out_of_bounds");
......
...@@ -10,7 +10,7 @@ load("test/mjsunit/wasm/wasm-module-builder.js"); ...@@ -10,7 +10,7 @@ load("test/mjsunit/wasm/wasm-module-builder.js");
function makeFFI(func) { function makeFFI(func) {
var builder = new WasmModuleBuilder(); var builder = new WasmModuleBuilder();
var sig_index = builder.addSignature([kAstI32, kAstF64, kAstF64]); var sig_index = builder.addSignature(kSig_i_dd);
builder.addImport("func", sig_index); builder.addImport("func", sig_index);
builder.addFunction("main", sig_index) builder.addFunction("main", sig_index)
.addBody([ .addBody([
......
...@@ -37,19 +37,19 @@ function assertVerifies(sig, body) { ...@@ -37,19 +37,19 @@ function assertVerifies(sig, body) {
return module; return module;
} }
assertVerifies([kAstStmt], [kExprNop]); assertVerifies(kSig_v_v, [kExprNop]);
assertVerifies([kAstI32], [kExprI8Const, 0]); assertVerifies(kSig_i, [kExprI8Const, 0]);
// Arguments aren't allow to start functions. // Arguments aren't allow to start functions.
assertFails([kAstI32, kAstI32], [kExprGetLocal, 0]); assertFails(kSig_i_i, [kExprGetLocal, 0]);
assertFails([kAstI32, kAstI32, kAstF32], [kExprGetLocal, 0]); assertFails(kSig_i_ii, [kExprGetLocal, 0]);
assertFails([kAstI32, kAstI32, kAstF32, kAstF64], [kExprGetLocal, 0]); assertFails(kSig_i_dd, [kExprGetLocal, 0]);
(function testInvalidIndex() { (function testInvalidIndex() {
print("testInvalidIndex"); print("testInvalidIndex");
var builder = new WasmModuleBuilder(); var builder = new WasmModuleBuilder();
var func = builder.addFunction("", [kAstStmt]) var func = builder.addFunction("", kSig_v_v)
.addBody([kExprNop]); .addBody([kExprNop]);
builder.addStart(func.index + 1); builder.addStart(func.index + 1);
...@@ -62,7 +62,7 @@ assertFails([kAstI32, kAstI32, kAstF32, kAstF64], [kExprGetLocal, 0]); ...@@ -62,7 +62,7 @@ assertFails([kAstI32, kAstI32, kAstF32, kAstF64], [kExprGetLocal, 0]);
print("testTwoStartFuncs"); print("testTwoStartFuncs");
var builder = new WasmModuleBuilder(); var builder = new WasmModuleBuilder();
var func = builder.addFunction("", [kAstStmt]) var func = builder.addFunction("", kSig_v_v)
.addBody([kExprNop]); .addBody([kExprNop]);
builder.addExplicitSection([kDeclStartFunction, 0]); builder.addExplicitSection([kDeclStartFunction, 0]);
...@@ -78,7 +78,7 @@ assertFails([kAstI32, kAstI32, kAstF32, kAstF64], [kExprGetLocal, 0]); ...@@ -78,7 +78,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("", kSig_v_v)
.addBody([kExprI8Const, 0, kExprI8Const, 77, kExprI32StoreMem, 0, 0]); .addBody([kExprI8Const, 0, kExprI8Const, 77, kExprI32StoreMem, 0, 0]);
builder.addStart(func.index); builder.addStart(func.index);
...@@ -98,7 +98,7 @@ assertFails([kAstI32, kAstI32, kAstF32, kAstF64], [kExprGetLocal, 0]); ...@@ -98,7 +98,7 @@ assertFails([kAstI32, kAstI32, kAstF32, kAstF64], [kExprGetLocal, 0]);
}}; }};
var builder = new WasmModuleBuilder(); var builder = new WasmModuleBuilder();
var sig_index = builder.addSignature([kAstStmt]); var sig_index = builder.addSignature(kSig_v_v);
builder.addImport("foo", sig_index); builder.addImport("foo", sig_index);
var func = builder.addFunction("", sig_index) var func = builder.addFunction("", sig_index)
......
...@@ -12,7 +12,7 @@ var debug = false; ...@@ -12,7 +12,7 @@ var debug = false;
(function BasicTest() { (function BasicTest() {
var module = new WasmModuleBuilder(); var module = new WasmModuleBuilder();
module.addMemory(1, 2, false); module.addMemory(1, 2, false);
module.addFunction("foo", [kAstI32]) module.addFunction("foo", kSig_i)
.addBody([kExprI8Const, 11]) .addBody([kExprI8Const, 11])
.exportAs("blarg"); .exportAs("blarg");
...@@ -23,8 +23,8 @@ var debug = false; ...@@ -23,8 +23,8 @@ var debug = false;
(function ImportTest() { (function ImportTest() {
var module = new WasmModuleBuilder(); var module = new WasmModuleBuilder();
var index = module.addImport("print", [kAstStmt, kAstI32]); var index = module.addImport("print", makeSig_v_x(kAstI32));
module.addFunction("foo", [kAstStmt]) module.addFunction("foo", kSig_v_v)
.addBody([kExprI8Const, 13, kExprCallImport, kArity1, index]) .addBody([kExprI8Const, 13, kExprCallImport, kArity1, index])
.exportAs("main"); .exportAs("main");
...@@ -36,7 +36,7 @@ var debug = false; ...@@ -36,7 +36,7 @@ var debug = false;
(function LocalsTest() { (function LocalsTest() {
var module = new WasmModuleBuilder(); var module = new WasmModuleBuilder();
module.addFunction(undefined, [kAstI32, kAstI32]) module.addFunction(undefined, kSig_i_i)
.addLocals({i32_count: 1}) .addLocals({i32_count: 1})
.addBody([kExprGetLocal, 0, kExprSetLocal, 1]) .addBody([kExprGetLocal, 0, kExprSetLocal, 1])
.exportAs("main"); .exportAs("main");
...@@ -58,7 +58,7 @@ var debug = false; ...@@ -58,7 +58,7 @@ var debug = false;
for (p of types) { for (p of types) {
var module = new WasmModuleBuilder(); var module = new WasmModuleBuilder();
module.addFunction(undefined, [p.type, p.type]) module.addFunction(undefined, makeSig_r_x(p.type, p.type))
.addLocals(p.locals) .addLocals(p.locals)
.addBody([kExprGetLocal, 0, kExprSetLocal, 1]) .addBody([kExprGetLocal, 0, kExprSetLocal, 1])
.exportAs("main"); .exportAs("main");
...@@ -72,9 +72,9 @@ var debug = false; ...@@ -72,9 +72,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", kSig_i_ii)
.addBody([kExprGetLocal, 0, kExprGetLocal, 1, kExprI32Add]); .addBody([kExprGetLocal, 0, kExprGetLocal, 1, kExprI32Add]);
module.addFunction("main", [kAstI32, kAstI32, kAstI32]) module.addFunction("main", kSig_i_ii)
.addBody([kExprGetLocal, 0, kExprGetLocal, 1, kExprCallFunction, kArity2, 0]) .addBody([kExprGetLocal, 0, kExprGetLocal, 1, kExprCallFunction, kArity2, 0])
.exportAs("main"); .exportAs("main");
...@@ -85,9 +85,9 @@ var debug = false; ...@@ -85,9 +85,9 @@ var debug = false;
(function IndirectCallTest() { (function IndirectCallTest() {
var module = new WasmModuleBuilder(); var module = new WasmModuleBuilder();
module.addFunction("add", [kAstI32, kAstI32, kAstI32]) module.addFunction("add", kSig_i_ii)
.addBody([kExprGetLocal, 0, kExprGetLocal, 1, kExprI32Add]); .addBody([kExprGetLocal, 0, kExprGetLocal, 1, kExprI32Add]);
module.addFunction("main", [kAstI32, kAstI32, kAstI32, kAstI32]) module.addFunction("main", kSig_i_iii)
.addBody([kExprGetLocal, .addBody([kExprGetLocal,
0, kExprGetLocal, 1, kExprGetLocal, 2, kExprCallIndirect, kArity2, 0]) 0, kExprGetLocal, 1, kExprGetLocal, 2, kExprCallIndirect, kArity2, 0])
.exportAs("main"); .exportAs("main");
...@@ -102,7 +102,7 @@ var debug = false; ...@@ -102,7 +102,7 @@ var debug = false;
(function DataSegmentTest() { (function DataSegmentTest() {
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", kSig_i_i)
.addBody([kExprGetLocal, 0, kExprI32LoadMem, 0, 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);
...@@ -116,7 +116,7 @@ var debug = false; ...@@ -116,7 +116,7 @@ var debug = false;
(function BasicTestWithUint8Array() { (function BasicTestWithUint8Array() {
var module = new WasmModuleBuilder(); var module = new WasmModuleBuilder();
module.addMemory(1, 2, false); module.addMemory(1, 2, false);
module.addFunction("foo", [kAstI32]) module.addFunction("foo", kSig_i)
.addBody([kExprI8Const, 17]) .addBody([kExprI8Const, 17])
.exportAs("blarg"); .exportAs("blarg");
...@@ -141,8 +141,8 @@ var debug = false; ...@@ -141,8 +141,8 @@ var debug = false;
(function ImportTestTwoLevel() { (function ImportTestTwoLevel() {
var module = new WasmModuleBuilder(); var module = new WasmModuleBuilder();
var index = module.addImportWithModule("mod", "print", [kAstStmt, kAstI32]); var index = module.addImportWithModule("mod", "print", makeSig_v_x(kAstI32));
module.addFunction("foo", [kAstStmt]) module.addFunction("foo", kSig_v_v)
.addBody([kExprI8Const, 19, kExprCallImport, kArity1, index]) .addBody([kExprI8Const, 19, kExprCallImport, kArity1, index])
.exportAs("main"); .exportAs("main");
......
...@@ -9,7 +9,7 @@ load("test/mjsunit/wasm/wasm-module-builder.js"); ...@@ -9,7 +9,7 @@ load("test/mjsunit/wasm/wasm-module-builder.js");
var main = (function () { var main = (function () {
var builder = new WasmModuleBuilder(); var builder = new WasmModuleBuilder();
builder.addFunction("main", [kAstStmt]) builder.addFunction("main", kSig_v_v)
.addBody([kExprUnreachable]) .addBody([kExprUnreachable])
.exportAs("main"); .exportAs("main");
......
...@@ -8,9 +8,9 @@ load("test/mjsunit/wasm/wasm-constants.js"); ...@@ -8,9 +8,9 @@ load("test/mjsunit/wasm/wasm-constants.js");
try { try {
var data = bytes( var data = bytes(
0, kAstStmt, // signature kWasmFunctionTypeForm, 0, kAstStmt, // signature
kDeclNoLocals, // -- kDeclNoLocals, // --
kExprNop // body kExprNop // body
); );
Wasm.verifyFunction(data); Wasm.verifyFunction(data);
...@@ -23,8 +23,8 @@ try { ...@@ -23,8 +23,8 @@ try {
var threw = false; var threw = false;
try { try {
var data = bytes( var data = bytes(
0, kAstI32, // signature kWasmFunctionTypeForm, 0, 1, kAstI32, // signature
kDeclNoLocals, // -- kDeclNoLocals, // --
kExprBlock, kExprNop, kExprNop, kExprEnd // body kExprBlock, kExprNop, kExprNop, kExprEnd // body
); );
......
...@@ -21,7 +21,7 @@ var kWasmH1 = 0x61; ...@@ -21,7 +21,7 @@ var kWasmH1 = 0x61;
var kWasmH2 = 0x73; var kWasmH2 = 0x73;
var kWasmH3 = 0x6d; var kWasmH3 = 0x6d;
var kWasmV0 = 10; var kWasmV0 = 11;
var kWasmV1 = 0; var kWasmV1 = 0;
var kWasmV2 = 0; var kWasmV2 = 0;
var kWasmV3 = 0; var kWasmV3 = 0;
...@@ -69,11 +69,12 @@ var kArity0 = 0; ...@@ -69,11 +69,12 @@ var kArity0 = 0;
var kArity1 = 1; var kArity1 = 1;
var kArity2 = 2; var kArity2 = 2;
var kArity3 = 3; var kArity3 = 3;
var kWasmFunctionTypeForm = 0x40;
var section_names = [ var section_names = [
"memory", "signatures", "functions", "globals", "data_segments", "memory", "type", "old_function", "global", "data",
"function_table", "end", "start_function", "import_table", "export_table", "table", "end", "start", "import", "export",
"function_signatures", "function_bodies", "names"]; "function", "code", "name"];
// Function declaration flags // Function declaration flags
var kDeclFunctionName = 0x01; var kDeclFunctionName = 0x01;
...@@ -88,6 +89,33 @@ var kAstI64 = 2; ...@@ -88,6 +89,33 @@ var kAstI64 = 2;
var kAstF32 = 3; var kAstF32 = 3;
var kAstF64 = 4; var kAstF64 = 4;
// Useful signatures
var kSig_i = [0, 1, kAstI32];
var kSig_d = [0, 1, kAstF64];
var kSig_i_i = [1, kAstI32, 1, kAstI32];
var kSig_i_ii = [2, kAstI32, kAstI32, 1, kAstI32];
var kSig_i_iii = [3, kAstI32, kAstI32, kAstI32, 1, kAstI32];
var kSig_d_dd = [2, kAstF64, kAstF64, 1, kAstF64];
var kSig_l_ll = [2, kAstI64, kAstI64, 1, kAstI64];
var kSig_i_dd = [2, kAstF64, kAstF64, 1, kAstI32];
var kSig_v_v = [0, 0];
function makeSig_v_xx(x) {
return [2, x, x, 0];
}
function makeSig_v_x(x) {
return [1, x, 0];
}
function makeSig_r_xx(r, x) {
return [2, x, x, 1, r];
}
function makeSig_r_x(r, x) {
return [1, x, 1, r];
}
// Opcodes // Opcodes
var kExprNop = 0x00; var kExprNop = 0x00;
var kExprBlock = 0x01; var kExprBlock = 0x01;
......
...@@ -53,7 +53,7 @@ WasmModuleBuilder.prototype.addExplicitSection = function(bytes) { ...@@ -53,7 +53,7 @@ WasmModuleBuilder.prototype.addExplicitSection = function(bytes) {
return this; return this;
} }
// Add a signature; format is [rettype, param0, param1, ...] // Add a signature; format is [param_count, param0, param1, ..., retcount, ret0]
WasmModuleBuilder.prototype.addSignature = function(sig) { WasmModuleBuilder.prototype.addSignature = function(sig) {
// TODO: canonicalize signatures? // TODO: canonicalize signatures?
this.signatures.push(sig); this.signatures.push(sig);
...@@ -132,12 +132,14 @@ function emit_bytes(bytes, data) { ...@@ -132,12 +132,14 @@ function emit_bytes(bytes, data) {
} }
function emit_section(bytes, section_code, content_generator) { function emit_section(bytes, section_code, content_generator) {
// Start the section in a temporary buffer: its full length isn't know yet. // Emit section name.
emit_string(bytes, section_names[section_code]);
// Emit the section to a temporary buffer: its full length isn't know yet.
var tmp_bytes = []; var tmp_bytes = [];
emit_string(tmp_bytes, section_names[section_code]);
content_generator(tmp_bytes); content_generator(tmp_bytes);
// Now that we know the section length, emit it and copy the section. // Emit section length.
emit_varint(bytes, tmp_bytes.length); emit_varint(bytes, tmp_bytes.length);
// Copy the temporary buffer.
Array.prototype.push.apply(bytes, tmp_bytes); Array.prototype.push.apply(bytes, tmp_bytes);
} }
...@@ -155,8 +157,7 @@ WasmModuleBuilder.prototype.toArray = function(debug) { ...@@ -155,8 +157,7 @@ WasmModuleBuilder.prototype.toArray = function(debug) {
emit_section(bytes, kDeclSignatures, function(bytes) { emit_section(bytes, kDeclSignatures, function(bytes) {
emit_varint(bytes, wasm.signatures.length); emit_varint(bytes, wasm.signatures.length);
for (sig of wasm.signatures) { for (sig of wasm.signatures) {
var params = sig.length - 1; emit_u8(bytes, kWasmFunctionTypeForm);
emit_varint(bytes, params);
for (var j = 0; j < sig.length; j++) { for (var j = 0; j < sig.length; j++) {
emit_u8(bytes, sig[j]); emit_u8(bytes, sig[j]);
} }
......
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