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]);
} }
......
...@@ -15,17 +15,32 @@ namespace wasm { ...@@ -15,17 +15,32 @@ namespace wasm {
#define EMPTY_FUNCTION(sig_index) 0, SIG_INDEX(sig_index), U16_LE(0) #define EMPTY_FUNCTION(sig_index) 0, SIG_INDEX(sig_index), U16_LE(0)
#define EMPTY_FUNCTION_SIZE ((size_t)5) #define EMPTY_FUNCTION_SIZE ((size_t)5)
#define EMPTY_BODY 0 #define EMPTY_BODY 0
#define EMPTY_BODY_SIZE ((size_t)1) #define SIZEOF_EMPTY_BODY ((size_t)1)
#define NOP_BODY 2, 0, kExprNop #define NOP_BODY 2, 0, kExprNop
#define NOP_BODY_SIZE ((size_t)3) #define SIZEOF_NOP_BODY ((size_t)3)
#define VOID_VOID_SIG 0, kLocalVoid
#define VOID_VOID_SIG_SIZE ((size_t)2)
#define INT_INT_SIG 1, kLocalI32, kLocalI32
#define INT_INT_SIG_SIZE ((size_t)3)
// TODO(titzer): tricky size logic! Remove -1. #define SIG_ENTRY_i_i SIG_ENTRY_x_x(kLocalI32, kLocalI32)
#define SECTION(NAME, EXTRA_SIZE) \
U32V_1(WASM_SECTION_##NAME##_SIZE + (EXTRA_SIZE)), WASM_SECTION_##NAME #define UNKNOWN_EMPTY_SECTION_NAME 1, '\0'
#define UNKNOWN_SECTION_NAME 4, 'l', 'u', 'l', 'z'
#define SECTION(NAME, EXTRA_SIZE) WASM_SECTION_##NAME, U32V_1(EXTRA_SIZE)
#define SIGNATURES_SECTION(count, ...) \
SECTION(SIGNATURES, 1 + 3 * (count)), U32V_1(count), __VA_ARGS__
#define FUNCTION_SIGNATURES_SECTION(count, ...) \
SECTION(FUNCTION_SIGNATURES, 1 + (count)), U32V_1(count), __VA_ARGS__
#define FOO_STRING 3, 'f', 'o', 'o'
#define NO_LOCAL_NAMES 0
#define EMPTY_SIGNATURES_SECTION SECTION(SIGNATURES, 1), 0
#define EMPTY_FUNCTION_SIGNATURES_SECTION SECTION(FUNCTION_SIGNATURES, 1), 0
#define EMPTY_FUNCTION_BODIES_SECTION SECTION(FUNCTION_BODIES, 1), 0
#define EMPTY_NAMES_SECTION SECTION(NAMES, 1), 0
#define SIGNATURES_SECTION_VOID_VOID \
SECTION(SIGNATURES, 1 + SIZEOF_SIG_ENTRY_v_v), 1, SIG_ENTRY_v_v
#define EXPECT_VERIFIES(data) \ #define EXPECT_VERIFIES(data) \
do { \ do { \
...@@ -190,9 +205,8 @@ TEST_F(WasmModuleVerifyTest, NGlobals) { ...@@ -190,9 +205,8 @@ TEST_F(WasmModuleVerifyTest, NGlobals) {
for (uint32_t i = 0; i < 1000000; i = i * 13 + 1) { for (uint32_t i = 0; i < 1000000; i = i * 13 + 1) {
std::vector<byte> buffer; std::vector<byte> buffer;
size_t size = size_t size = SizeOfVarInt(i) + i * sizeof(data);
WASM_SECTION_GLOBALS_SIZE + SizeOfVarInt(i) + i * sizeof(data); const byte globals[] = {WASM_SECTION_GLOBALS, U32V_5(size)};
const byte globals[] = {U32V_5(size), WASM_SECTION_GLOBALS};
for (size_t g = 0; g != sizeof(globals); ++g) { for (size_t g = 0; g != sizeof(globals); ++g) {
buffer.push_back(globals[g]); buffer.push_back(globals[g]);
} }
...@@ -274,14 +288,13 @@ TEST_F(WasmModuleVerifyTest, TwoGlobals) { ...@@ -274,14 +288,13 @@ TEST_F(WasmModuleVerifyTest, TwoGlobals) {
TEST_F(WasmModuleVerifyTest, OneSignature) { TEST_F(WasmModuleVerifyTest, OneSignature) {
{ {
static const byte data[] = {SECTION(SIGNATURES, 1 + VOID_VOID_SIG_SIZE), 1, static const byte data[] = {SIGNATURES_SECTION_VOID_VOID};
VOID_VOID_SIG};
EXPECT_VERIFIES(data); EXPECT_VERIFIES(data);
} }
{ {
static const byte data[] = {SECTION(SIGNATURES, 1 + INT_INT_SIG_SIZE), 1, static const byte data[] = {SECTION(SIGNATURES, 1 + SIZEOF_SIG_ENTRY_x_x),
INT_INT_SIG}; 1, SIG_ENTRY_i_i};
EXPECT_VERIFIES(data); EXPECT_VERIFIES(data);
} }
} }
...@@ -289,17 +302,12 @@ TEST_F(WasmModuleVerifyTest, OneSignature) { ...@@ -289,17 +302,12 @@ TEST_F(WasmModuleVerifyTest, OneSignature) {
TEST_F(WasmModuleVerifyTest, MultipleSignatures) { TEST_F(WasmModuleVerifyTest, MultipleSignatures) {
static const byte data[] = { static const byte data[] = {
SECTION(SIGNATURES, 10), SECTION(SIGNATURES, 1 + SIZEOF_SIG_ENTRY_v_v + SIZEOF_SIG_ENTRY_x_x +
3, SIZEOF_SIG_ENTRY_x_xx), // --
0, 3, // --
kLocalVoid, // void -> void SIG_ENTRY_v_v, // void -> void
1, SIG_ENTRY_x_x(kLocalI32, kLocalF32), // f32 -> i32
kLocalI32, SIG_ENTRY_x_xx(kLocalI32, kLocalF64, kLocalF64), // f64,f64 -> i32
kLocalF32, // f32 -> i32
2,
kLocalI32,
kLocalF64,
kLocalF64, // (f64,f64) -> i32
}; };
ModuleResult result = DecodeModule(data, data + arraysize(data)); ModuleResult result = DecodeModule(data, data + arraysize(data));
...@@ -322,7 +330,7 @@ TEST_F(WasmModuleVerifyTest, MultipleSignatures) { ...@@ -322,7 +330,7 @@ TEST_F(WasmModuleVerifyTest, MultipleSignatures) {
TEST_F(WasmModuleVerifyTest, FunctionWithoutSig) { TEST_F(WasmModuleVerifyTest, FunctionWithoutSig) {
static const byte data[] = { static const byte data[] = {
SECTION(FUNCTIONS, 25), 1, SECTION(OLD_FUNCTIONS, 25), 1,
// func#0 ------------------------------------------------------ // func#0 ------------------------------------------------------
SIG_INDEX(0), // signature index SIG_INDEX(0), // signature index
NO_NAME, // name length NO_NAME, // name length
...@@ -343,15 +351,14 @@ TEST_F(WasmModuleVerifyTest, FunctionWithoutSig) { ...@@ -343,15 +351,14 @@ TEST_F(WasmModuleVerifyTest, FunctionWithoutSig) {
TEST_F(WasmModuleVerifyTest, OneEmptyVoidVoidFunction) { TEST_F(WasmModuleVerifyTest, OneEmptyVoidVoidFunction) {
const int kCodeStartOffset = 51; const int kCodeStartOffset = 49;
const int kCodeEndOffset = kCodeStartOffset + 1; const int kCodeEndOffset = kCodeStartOffset + 1;
static const byte data[] = { static const byte data[] = {
SECTION(SIGNATURES, 1 + VOID_VOID_SIG_SIZE), 1, // signatures
// sig#0 ------------------------------------------------------- SIGNATURES_SECTION_VOID_VOID,
VOID_VOID_SIG,
// func#0 ------------------------------------------------------ // func#0 ------------------------------------------------------
SECTION(FUNCTIONS, 18), 1, SECTION(OLD_FUNCTIONS, 18), 1,
kDeclFunctionLocals | kDeclFunctionExport | kDeclFunctionName, kDeclFunctionLocals | kDeclFunctionExport | kDeclFunctionName,
SIG_INDEX(0), // signature index SIG_INDEX(0), // signature index
NAME_LENGTH(2), 'h', 'i', // name NAME_LENGTH(2), 'h', 'i', // name
...@@ -375,7 +382,7 @@ TEST_F(WasmModuleVerifyTest, OneEmptyVoidVoidFunction) { ...@@ -375,7 +382,7 @@ TEST_F(WasmModuleVerifyTest, OneEmptyVoidVoidFunction) {
WasmFunction* function = &result.val->functions.back(); WasmFunction* function = &result.val->functions.back();
EXPECT_EQ(39, function->name_offset); EXPECT_EQ(37, function->name_offset);
EXPECT_EQ(2, function->name_length); EXPECT_EQ(2, function->name_length);
EXPECT_EQ(kCodeStartOffset, function->code_start_offset); EXPECT_EQ(kCodeStartOffset, function->code_start_offset);
EXPECT_EQ(kCodeEndOffset, function->code_end_offset); EXPECT_EQ(kCodeEndOffset, function->code_end_offset);
...@@ -398,11 +405,9 @@ TEST_F(WasmModuleVerifyTest, OneEmptyVoidVoidFunction) { ...@@ -398,11 +405,9 @@ TEST_F(WasmModuleVerifyTest, OneEmptyVoidVoidFunction) {
TEST_F(WasmModuleVerifyTest, OneFunctionImported) { TEST_F(WasmModuleVerifyTest, OneFunctionImported) {
static const byte data[] = { static const byte data[] = {
// signatures // signatures
SECTION(SIGNATURES, 1 + VOID_VOID_SIG_SIZE), 1, SIGNATURES_SECTION_VOID_VOID,
// sig#0 -------------------------------------------------------
VOID_VOID_SIG,
// functions // functions
SECTION(FUNCTIONS, 4), 1, SECTION(OLD_FUNCTIONS, 4), 1,
// func#0 ------------------------------------------------------ // func#0 ------------------------------------------------------
kDeclFunctionImport, // no name, no locals, imported kDeclFunctionImport, // no name, no locals, imported
SIG_INDEX(0), SIG_INDEX(0),
...@@ -429,14 +434,12 @@ TEST_F(WasmModuleVerifyTest, OneFunctionImported) { ...@@ -429,14 +434,12 @@ TEST_F(WasmModuleVerifyTest, OneFunctionImported) {
} }
TEST_F(WasmModuleVerifyTest, OneFunctionWithNopBody) { TEST_F(WasmModuleVerifyTest, OneFunctionWithNopBody) {
static const byte kCodeStartOffset = 40; static const byte kCodeStartOffset = 38;
static const byte kCodeEndOffset = kCodeStartOffset + 1; static const byte kCodeEndOffset = kCodeStartOffset + 1;
static const byte data[] = { static const byte data[] = {
SECTION(SIGNATURES, 3), 1, SIGNATURES_SECTION_VOID_VOID, // --
// sig#0 ------------------------------------------------------- SECTION(OLD_FUNCTIONS, 7), 1,
0, 0, // void -> void
SECTION(FUNCTIONS, 7), 1,
// func#0 ------------------------------------------------------ // func#0 ------------------------------------------------------
0, // no name, no locals 0, // no name, no locals
0, 0, // signature index 0, 0, // signature index
...@@ -466,14 +469,12 @@ TEST_F(WasmModuleVerifyTest, OneFunctionWithNopBody) { ...@@ -466,14 +469,12 @@ TEST_F(WasmModuleVerifyTest, OneFunctionWithNopBody) {
TEST_F(WasmModuleVerifyTest, OneFunctionWithNopBody_WithLocals) { TEST_F(WasmModuleVerifyTest, OneFunctionWithNopBody_WithLocals) {
static const byte kCodeStartOffset = 48; static const byte kCodeStartOffset = 46;
static const byte kCodeEndOffset = kCodeStartOffset + 1; static const byte kCodeEndOffset = kCodeStartOffset + 1;
static const byte data[] = { static const byte data[] = {
SECTION(SIGNATURES, 3), 1, SIGNATURES_SECTION_VOID_VOID, // --
// sig#0 ------------------------------------------------------- SECTION(OLD_FUNCTIONS, 15), 1,
0, 0, // void -> void
SECTION(FUNCTIONS, 15), 1,
// func#0 ------------------------------------------------------ // func#0 ------------------------------------------------------
kDeclFunctionLocals, 0, 0, // signature index kDeclFunctionLocals, 0, 0, // signature index
1, 2, // local int32 count 1, 2, // local int32 count
...@@ -506,9 +507,10 @@ TEST_F(WasmModuleVerifyTest, OneFunctionWithNopBody_WithLocals) { ...@@ -506,9 +507,10 @@ TEST_F(WasmModuleVerifyTest, OneFunctionWithNopBody_WithLocals) {
TEST_F(WasmModuleVerifyTest, OneGlobalOneFunctionWithNopBodyOneDataSegment) { TEST_F(WasmModuleVerifyTest, OneGlobalOneFunctionWithNopBodyOneDataSegment) {
static const byte kCodeStartOffset = 64; static const byte kNameOffset = 49;
static const byte kCodeStartOffset = 61;
static const byte kCodeEndOffset = kCodeStartOffset + 3; static const byte kCodeEndOffset = kCodeStartOffset + 3;
static const byte kDataSegmentSourceOffset = kCodeEndOffset + 31; static const byte kDataSegmentSourceOffset = kCodeEndOffset + 22;
static const byte data[] = { static const byte data[] = {
// global#0 -------------------------------------------------- // global#0 --------------------------------------------------
...@@ -517,9 +519,9 @@ TEST_F(WasmModuleVerifyTest, OneGlobalOneFunctionWithNopBodyOneDataSegment) { ...@@ -517,9 +519,9 @@ TEST_F(WasmModuleVerifyTest, OneGlobalOneFunctionWithNopBodyOneDataSegment) {
kMemU8, // memory type kMemU8, // memory type
0, // exported 0, // exported
// sig#0 ----------------------------------------------------- // sig#0 -----------------------------------------------------
SECTION(SIGNATURES, 3), 1, 0, 0, // void -> void SIGNATURES_SECTION_VOID_VOID,
// func#0 ---------------------------------------------------- // func#0 ----------------------------------------------------
SECTION(FUNCTIONS, 20), 1, SECTION(OLD_FUNCTIONS, 20), 1,
kDeclFunctionLocals | kDeclFunctionName, // -- kDeclFunctionLocals | kDeclFunctionName, // --
SIG_INDEX(0), // signature index SIG_INDEX(0), // signature index
2, 'h', 'i', // name 2, 'h', 'i', // name
...@@ -558,7 +560,7 @@ TEST_F(WasmModuleVerifyTest, OneGlobalOneFunctionWithNopBodyOneDataSegment) { ...@@ -558,7 +560,7 @@ TEST_F(WasmModuleVerifyTest, OneGlobalOneFunctionWithNopBodyOneDataSegment) {
WasmFunction* function = &result.val->functions.back(); WasmFunction* function = &result.val->functions.back();
EXPECT_EQ(52, function->name_offset); EXPECT_EQ(kNameOffset, function->name_offset);
EXPECT_EQ(2, function->name_length); EXPECT_EQ(2, function->name_length);
EXPECT_EQ(kCodeStartOffset, function->code_start_offset); EXPECT_EQ(kCodeStartOffset, function->code_start_offset);
EXPECT_EQ(kCodeEndOffset, function->code_end_offset); EXPECT_EQ(kCodeEndOffset, function->code_end_offset);
...@@ -579,7 +581,7 @@ TEST_F(WasmModuleVerifyTest, OneGlobalOneFunctionWithNopBodyOneDataSegment) { ...@@ -579,7 +581,7 @@ TEST_F(WasmModuleVerifyTest, OneGlobalOneFunctionWithNopBodyOneDataSegment) {
TEST_F(WasmModuleVerifyTest, OneDataSegment) { TEST_F(WasmModuleVerifyTest, OneDataSegment) {
const byte kDataSegmentSourceOffset = 39; const byte kDataSegmentSourceOffset = 30;
const byte data[] = { const byte data[] = {
SECTION(MEMORY, 3), SECTION(MEMORY, 3),
28, 28,
...@@ -617,8 +619,8 @@ TEST_F(WasmModuleVerifyTest, OneDataSegment) { ...@@ -617,8 +619,8 @@ TEST_F(WasmModuleVerifyTest, OneDataSegment) {
TEST_F(WasmModuleVerifyTest, TwoDataSegments) { TEST_F(WasmModuleVerifyTest, TwoDataSegments) {
const byte kDataSegment0SourceOffset = 39; const byte kDataSegment0SourceOffset = 30;
const byte kDataSegment1SourceOffset = 39 + 8; const byte kDataSegment1SourceOffset = 30 + 8;
const byte data[] = { const byte data[] = {
SECTION(MEMORY, 3), SECTION(MEMORY, 3),
...@@ -709,9 +711,9 @@ TEST_F(WasmModuleVerifyTest, DataSegmentWithInvalidDest) { ...@@ -709,9 +711,9 @@ TEST_F(WasmModuleVerifyTest, DataSegmentWithInvalidDest) {
TEST_F(WasmModuleVerifyTest, OneIndirectFunction) { TEST_F(WasmModuleVerifyTest, OneIndirectFunction) {
static const byte data[] = { static const byte data[] = {
// sig#0 ------------------------------------------------------- // sig#0 -------------------------------------------------------
SECTION(SIGNATURES, 3), 1, 0, 0, // void -> void SIGNATURES_SECTION_VOID_VOID,
// func#0 ------------------------------------------------------ // func#0 ------------------------------------------------------
SECTION(FUNCTIONS, 4), 1, FUNCTION(0, 0), SECTION(OLD_FUNCTIONS, 4), 1, FUNCTION(0, 0),
// indirect table ---------------------------------------------- // indirect table ----------------------------------------------
SECTION(FUNCTION_TABLE, 2), 1, U32V_1(0)}; SECTION(FUNCTION_TABLE, 2), 1, U32V_1(0)};
...@@ -730,13 +732,15 @@ TEST_F(WasmModuleVerifyTest, OneIndirectFunction) { ...@@ -730,13 +732,15 @@ TEST_F(WasmModuleVerifyTest, OneIndirectFunction) {
TEST_F(WasmModuleVerifyTest, MultipleIndirectFunctions) { TEST_F(WasmModuleVerifyTest, MultipleIndirectFunctions) {
static const byte data[] = { static const byte data[] = {
// sig#0 ------------------------------------------------------- // sig#0 -------------------------------------------------------
SECTION(SIGNATURES, 5), 2, 0, 0, // void -> void SECTION(SIGNATURES, 1 + SIZEOF_SIG_ENTRY_v_v + SIZEOF_SIG_ENTRY_v_x),
0, kLocalI32, // void -> i32 2, // --
SIG_ENTRY_v_v, // void -> void
SIG_ENTRY_v_x(kLocalI32), // void -> i32
// func#0 ------------------------------------------------------ // func#0 ------------------------------------------------------
SECTION(FUNCTIONS, 13), 4, FUNCTION(0, 1), // -- SECTION(OLD_FUNCTIONS, 13), 4, FUNCTION(0, 1), // --
FUNCTION(1, 1), // -- FUNCTION(1, 1), // --
FUNCTION(0, 1), // -- FUNCTION(0, 1), // --
FUNCTION(1, 1), // -- FUNCTION(1, 1), // --
// indirect table ---------------------------------------------- // indirect table ----------------------------------------------
SECTION(FUNCTION_TABLE, 9), 8, SECTION(FUNCTION_TABLE, 9), 8,
U32V_1(0), // -- U32V_1(0), // --
...@@ -766,7 +770,7 @@ TEST_F(WasmModuleVerifyTest, MultipleIndirectFunctions) { ...@@ -766,7 +770,7 @@ TEST_F(WasmModuleVerifyTest, MultipleIndirectFunctions) {
TEST_F(WasmModuleVerifyTest, IndirectFunctionNoFunctions) { TEST_F(WasmModuleVerifyTest, IndirectFunctionNoFunctions) {
static const byte data[] = { static const byte data[] = {
// sig#0 ------------------------------------------------------- // sig#0 -------------------------------------------------------
SECTION(SIGNATURES, 3), 1, 0, 0, // void -> void SIGNATURES_SECTION_VOID_VOID,
// indirect table ---------------------------------------------- // indirect table ----------------------------------------------
SECTION(FUNCTION_TABLE, 3), 1, 0, 0, SECTION(FUNCTION_TABLE, 3), 1, 0, 0,
}; };
...@@ -778,9 +782,9 @@ TEST_F(WasmModuleVerifyTest, IndirectFunctionNoFunctions) { ...@@ -778,9 +782,9 @@ TEST_F(WasmModuleVerifyTest, IndirectFunctionNoFunctions) {
TEST_F(WasmModuleVerifyTest, IndirectFunctionInvalidIndex) { TEST_F(WasmModuleVerifyTest, IndirectFunctionInvalidIndex) {
static const byte data[] = { static const byte data[] = {
// sig#0 ------------------------------------------------------- // sig#0 -------------------------------------------------------
SECTION(SIGNATURES, 3), 1, 0, 0, // void -> void SIGNATURES_SECTION_VOID_VOID,
// functions --------------------------------------------------- // functions ---------------------------------------------------
SECTION(FUNCTIONS, 4), 1, FUNCTION(0, 1), SECTION(OLD_FUNCTIONS, 4), 1, FUNCTION(0, 1),
// indirect table ---------------------------------------------- // indirect table ----------------------------------------------
SECTION(FUNCTION_TABLE, 3), 1, 1, 0, SECTION(FUNCTION_TABLE, 3), 1, 1, 0,
}; };
...@@ -793,7 +797,7 @@ class WasmSignatureDecodeTest : public TestWithZone {}; ...@@ -793,7 +797,7 @@ class WasmSignatureDecodeTest : public TestWithZone {};
TEST_F(WasmSignatureDecodeTest, Ok_v_v) { TEST_F(WasmSignatureDecodeTest, Ok_v_v) {
static const byte data[] = {0, 0}; static const byte data[] = {SIG_ENTRY_v_v};
base::AccountingAllocator allocator; base::AccountingAllocator allocator;
Zone zone(&allocator); Zone zone(&allocator);
FunctionSig* sig = FunctionSig* sig =
...@@ -808,7 +812,7 @@ TEST_F(WasmSignatureDecodeTest, Ok_v_v) { ...@@ -808,7 +812,7 @@ TEST_F(WasmSignatureDecodeTest, Ok_v_v) {
TEST_F(WasmSignatureDecodeTest, Ok_t_v) { TEST_F(WasmSignatureDecodeTest, Ok_t_v) {
for (size_t i = 0; i < arraysize(kLocalTypes); i++) { for (size_t i = 0; i < arraysize(kLocalTypes); i++) {
LocalTypePair ret_type = kLocalTypes[i]; LocalTypePair ret_type = kLocalTypes[i];
const byte data[] = {0, ret_type.code}; const byte data[] = {SIG_ENTRY_x(ret_type.code)};
FunctionSig* sig = FunctionSig* sig =
DecodeWasmSignatureForTesting(zone(), data, data + arraysize(data)); DecodeWasmSignatureForTesting(zone(), data, data + arraysize(data));
...@@ -823,7 +827,7 @@ TEST_F(WasmSignatureDecodeTest, Ok_t_v) { ...@@ -823,7 +827,7 @@ TEST_F(WasmSignatureDecodeTest, Ok_t_v) {
TEST_F(WasmSignatureDecodeTest, Ok_v_t) { TEST_F(WasmSignatureDecodeTest, Ok_v_t) {
for (size_t i = 0; i < arraysize(kLocalTypes); i++) { for (size_t i = 0; i < arraysize(kLocalTypes); i++) {
LocalTypePair param_type = kLocalTypes[i]; LocalTypePair param_type = kLocalTypes[i];
const byte data[] = {1, 0, param_type.code}; const byte data[] = {SIG_ENTRY_v_x(param_type.code)};
FunctionSig* sig = FunctionSig* sig =
DecodeWasmSignatureForTesting(zone(), data, data + arraysize(data)); DecodeWasmSignatureForTesting(zone(), data, data + arraysize(data));
...@@ -840,9 +844,7 @@ TEST_F(WasmSignatureDecodeTest, Ok_t_t) { ...@@ -840,9 +844,7 @@ TEST_F(WasmSignatureDecodeTest, Ok_t_t) {
LocalTypePair ret_type = kLocalTypes[i]; LocalTypePair ret_type = kLocalTypes[i];
for (size_t j = 0; j < arraysize(kLocalTypes); j++) { for (size_t j = 0; j < arraysize(kLocalTypes); j++) {
LocalTypePair param_type = kLocalTypes[j]; LocalTypePair param_type = kLocalTypes[j];
const byte data[] = {1, // param count const byte data[] = {SIG_ENTRY_x_x(ret_type.code, param_type.code)};
ret_type.code, // ret
param_type.code}; // param
FunctionSig* sig = FunctionSig* sig =
DecodeWasmSignatureForTesting(zone(), data, data + arraysize(data)); DecodeWasmSignatureForTesting(zone(), data, data + arraysize(data));
...@@ -861,10 +863,8 @@ TEST_F(WasmSignatureDecodeTest, Ok_i_tt) { ...@@ -861,10 +863,8 @@ TEST_F(WasmSignatureDecodeTest, Ok_i_tt) {
LocalTypePair p0_type = kLocalTypes[i]; LocalTypePair p0_type = kLocalTypes[i];
for (size_t j = 0; j < arraysize(kLocalTypes); j++) { for (size_t j = 0; j < arraysize(kLocalTypes); j++) {
LocalTypePair p1_type = kLocalTypes[j]; LocalTypePair p1_type = kLocalTypes[j];
const byte data[] = {2, // param count const byte data[] = {
kLocalI32, // ret SIG_ENTRY_x_xx(kLocalI32, p0_type.code, p1_type.code)};
p0_type.code, // p0
p1_type.code}; // p1
FunctionSig* sig = FunctionSig* sig =
DecodeWasmSignatureForTesting(zone(), data, data + arraysize(data)); DecodeWasmSignatureForTesting(zone(), data, data + arraysize(data));
...@@ -895,8 +895,8 @@ TEST_F(WasmSignatureDecodeTest, Fail_off_end) { ...@@ -895,8 +895,8 @@ TEST_F(WasmSignatureDecodeTest, Fail_off_end) {
TEST_F(WasmSignatureDecodeTest, Fail_invalid_type) { TEST_F(WasmSignatureDecodeTest, Fail_invalid_type) {
byte kInvalidType = 76; byte kInvalidType = 76;
for (int i = 1; i < 3; i++) { for (size_t i = 0; i < SIZEOF_SIG_ENTRY_x_xx; i++) {
byte data[] = {2, kLocalI32, kLocalI32, kLocalI32}; byte data[] = {SIG_ENTRY_x_xx(kLocalI32, kLocalI32, kLocalI32)};
data[i] = kInvalidType; data[i] = kInvalidType;
FunctionSig* sig = FunctionSig* sig =
DecodeWasmSignatureForTesting(zone(), data, data + arraysize(data)); DecodeWasmSignatureForTesting(zone(), data, data + arraysize(data));
...@@ -904,29 +904,42 @@ TEST_F(WasmSignatureDecodeTest, Fail_invalid_type) { ...@@ -904,29 +904,42 @@ TEST_F(WasmSignatureDecodeTest, Fail_invalid_type) {
} }
} }
TEST_F(WasmSignatureDecodeTest, Fail_invalid_ret_type1) {
static const byte data[] = {SIG_ENTRY_x_x(kLocalVoid, kLocalI32)};
FunctionSig* sig =
DecodeWasmSignatureForTesting(zone(), data, data + arraysize(data));
EXPECT_EQ(nullptr, sig);
}
TEST_F(WasmSignatureDecodeTest, Fail_invalid_param_type) { TEST_F(WasmSignatureDecodeTest, Fail_invalid_param_type1) {
static const int kParamCount = 3; static const byte data[] = {SIG_ENTRY_x_x(kLocalI32, kLocalVoid)};
for (int i = 0; i < kParamCount; i++) { FunctionSig* sig =
byte data[] = {kParamCount, kLocalI32, kLocalI32, kLocalI32, kLocalI32}; DecodeWasmSignatureForTesting(zone(), data, data + arraysize(data));
data[i + 2] = kLocalVoid; EXPECT_EQ(nullptr, sig);
FunctionSig* sig = }
DecodeWasmSignatureForTesting(zone(), data, data + arraysize(data));
EXPECT_EQ(nullptr, sig); TEST_F(WasmSignatureDecodeTest, Fail_invalid_param_type2) {
} static const byte data[] = {SIG_ENTRY_x_xx(kLocalI32, kLocalI32, kLocalVoid)};
FunctionSig* sig =
DecodeWasmSignatureForTesting(zone(), data, data + arraysize(data));
EXPECT_EQ(nullptr, sig);
} }
class WasmFunctionVerifyTest : public TestWithIsolateAndZone {}; class WasmFunctionVerifyTest : public TestWithIsolateAndZone {};
TEST_F(WasmFunctionVerifyTest, Ok_v_v_empty) { TEST_F(WasmFunctionVerifyTest, Ok_v_v_empty) {
static const byte data[] = { static const byte data[] = {
0, kLocalVoid, // signature SIG_ENTRY_v_v, // signature entry
4, // locals 4, // locals
3, kLocalI32, // -- 3,
4, kLocalI64, // -- kLocalI32, // --
5, kLocalF32, // -- 4,
6, kLocalF64, // -- kLocalI64, // --
kExprNop // body 5,
kLocalF32, // --
6,
kLocalF64, // --
kExprNop // body
}; };
FunctionResult result = DecodeWasmFunction(isolate(), zone(), nullptr, data, FunctionResult result = DecodeWasmFunction(isolate(), zone(), nullptr, data,
...@@ -938,7 +951,7 @@ TEST_F(WasmFunctionVerifyTest, Ok_v_v_empty) { ...@@ -938,7 +951,7 @@ TEST_F(WasmFunctionVerifyTest, Ok_v_v_empty) {
EXPECT_EQ(0, function->sig->parameter_count()); EXPECT_EQ(0, function->sig->parameter_count());
EXPECT_EQ(0, function->sig->return_count()); EXPECT_EQ(0, function->sig->return_count());
EXPECT_EQ(0, function->name_offset); EXPECT_EQ(0, function->name_offset);
EXPECT_EQ(2, function->code_start_offset); EXPECT_EQ(SIZEOF_SIG_ENTRY_v_v, function->code_start_offset);
EXPECT_EQ(arraysize(data), function->code_end_offset); EXPECT_EQ(arraysize(data), function->code_end_offset);
// TODO(titzer): verify encoding of local declarations // TODO(titzer): verify encoding of local declarations
EXPECT_FALSE(function->external); EXPECT_FALSE(function->external);
...@@ -955,47 +968,51 @@ TEST_F(WasmModuleVerifyTest, SectionWithoutNameLength) { ...@@ -955,47 +968,51 @@ TEST_F(WasmModuleVerifyTest, SectionWithoutNameLength) {
TEST_F(WasmModuleVerifyTest, TheLoneliestOfValidModulesTheTrulyEmptyOne) { TEST_F(WasmModuleVerifyTest, TheLoneliestOfValidModulesTheTrulyEmptyOne) {
const byte data[] = { const byte data[] = {
1, // Section size.
0, // Empty section name. 0, // Empty section name.
// No section name, no content, nothing but sadness. // No section name, no content, nothing but sadness.
0, // No section content.
}; };
EXPECT_VERIFIES(data); EXPECT_VERIFIES(data);
} }
TEST_F(WasmModuleVerifyTest, OnlyUnknownSectionEmpty) { TEST_F(WasmModuleVerifyTest, OnlyUnknownSectionEmpty) {
const byte data[] = { const byte data[] = {
5, // Section size. UNKNOWN_SECTION_NAME, 0,
4, 'l', 'u', 'l', 'z', // unknown section.
}; };
EXPECT_VERIFIES(data); EXPECT_VERIFIES(data);
} }
TEST_F(WasmModuleVerifyTest, OnlyUnknownSectionNonEmpty) { TEST_F(WasmModuleVerifyTest, OnlyUnknownSectionNonEmpty) {
const byte data[] = { const byte data[] = {
10, // Section size. UNKNOWN_SECTION_NAME,
4, 'l', 'u', 'l', 'z', // unknown section. 5, // section size
// Section content: 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff,
0xff,
0xff, // section data
}; };
EXPECT_VERIFIES(data); EXPECT_VERIFIES(data);
} }
TEST_F(WasmModuleVerifyTest, SignatureFollowedByEmptyUnknownSection) { TEST_F(WasmModuleVerifyTest, SignatureFollowedByEmptyUnknownSection) {
const byte data[] = { const byte data[] = {
SECTION(SIGNATURES, 1 + VOID_VOID_SIG_SIZE), 1, VOID_VOID_SIG, // signatures
SIGNATURES_SECTION_VOID_VOID,
// ----------------------------------------------------------- // -----------------------------------------------------------
5, // Section size. UNKNOWN_SECTION_NAME,
4, 'l', 'u', 'l', 'z', // unknown section. 0 // empty section
}; };
EXPECT_VERIFIES(data); EXPECT_VERIFIES(data);
} }
TEST_F(WasmModuleVerifyTest, SignatureFollowedByUnknownSection) { TEST_F(WasmModuleVerifyTest, SignatureFollowedByUnknownSection) {
const byte data[] = { const byte data[] = {
SECTION(SIGNATURES, 1 + VOID_VOID_SIG_SIZE), 1, VOID_VOID_SIG, // signatures
SIGNATURES_SECTION_VOID_VOID,
// ----------------------------------------------------------- // -----------------------------------------------------------
10, // Section size. UNKNOWN_SECTION_NAME,
4, 'l', 'u', 'l', 'z', // unknown section. 5, // section size
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
}; };
EXPECT_VERIFIES(data); EXPECT_VERIFIES(data);
...@@ -1003,29 +1020,46 @@ TEST_F(WasmModuleVerifyTest, SignatureFollowedByUnknownSection) { ...@@ -1003,29 +1020,46 @@ TEST_F(WasmModuleVerifyTest, SignatureFollowedByUnknownSection) {
TEST_F(WasmModuleVerifyTest, SignatureFollowedByUnknownSectionWithLongLEB) { TEST_F(WasmModuleVerifyTest, SignatureFollowedByUnknownSectionWithLongLEB) {
const byte data[] = { const byte data[] = {
SECTION(SIGNATURES, 1 + VOID_VOID_SIG_SIZE), 1, VOID_VOID_SIG, // signatures
SIGNATURES_SECTION_VOID_VOID,
// ----------------------------------------------------------- // -----------------------------------------------------------
0x85, 0x80, 0x80, 0x80, 0x00, // Section size: 1 but in a 5-byte LEB. UNKNOWN_SECTION_NAME, 0x81, 0x80, 0x80, 0x80,
4, 'l', 'u', 'l', 'z', // unknown section. 0x00, // section size: 1 but in a 5-byte LEB
0,
}; };
EXPECT_VERIFIES(data); EXPECT_VERIFIES(data);
} }
TEST_F(WasmModuleVerifyTest, UnknownSectionOverflow) { TEST_F(WasmModuleVerifyTest, UnknownSectionOverflow) {
static const byte data[] = { static const byte data[] = {
13, // Section size. UNKNOWN_EMPTY_SECTION_NAME,
1, // Section name length. 9, // section size
'\0', // Section name. 1,
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, // 10 byte section 2,
3,
4,
5,
6,
7,
8,
9,
10, // 10 byte section
}; };
EXPECT_FAILURE(data); EXPECT_FAILURE(data);
} }
TEST_F(WasmModuleVerifyTest, UnknownSectionUnderflow) { TEST_F(WasmModuleVerifyTest, UnknownSectionUnderflow) {
static const byte data[] = { static const byte data[] = {
0xff, 0xff, 0xff, 0xff, 0x0f, // Section size LEB128 0xffffffff UNKNOWN_EMPTY_SECTION_NAME,
1, '\0', // Section name and name length. 0xff,
1, 2, 3, 4, // 4 byte section 0xff,
0xff,
0xff,
0x0f, // Section size LEB128 0xffffffff
1,
2,
3,
4, // 4 byte section
}; };
EXPECT_FAILURE(data); EXPECT_FAILURE(data);
} }
...@@ -1033,19 +1067,25 @@ TEST_F(WasmModuleVerifyTest, UnknownSectionUnderflow) { ...@@ -1033,19 +1067,25 @@ TEST_F(WasmModuleVerifyTest, UnknownSectionUnderflow) {
TEST_F(WasmModuleVerifyTest, UnknownSectionLoop) { TEST_F(WasmModuleVerifyTest, UnknownSectionLoop) {
// Would infinite loop decoding if wrapping and allowed. // Would infinite loop decoding if wrapping and allowed.
static const byte data[] = { static const byte data[] = {
0xfa, 0xff, 0xff, 0xff, 0x0f, // Section size LEB128 0xfffffffa UNKNOWN_EMPTY_SECTION_NAME,
1, '\0', // Section name and name length. 1,
1, 2, 3, 4, // 4 byte section 2,
3,
4, // 4 byte section
0xfa,
0xff,
0xff,
0xff,
0x0f, // Section size LEB128 0xfffffffa
}; };
EXPECT_FAILURE(data); EXPECT_FAILURE(data);
} }
TEST_F(WasmModuleVerifyTest, UnknownSectionSkipped) { TEST_F(WasmModuleVerifyTest, UnknownSectionSkipped) {
static const byte data[] = { static const byte data[] = {
3, // Section size. UNKNOWN_EMPTY_SECTION_NAME,
1, 1, // section size
'\0', // Section name: LEB128 1, string '\0' 0, // one byte section
0, // one byte section
SECTION(GLOBALS, 4), SECTION(GLOBALS, 4),
1, 1,
0, // name length 0, // name length
...@@ -1092,19 +1132,19 @@ TEST_F(WasmModuleVerifyTest, ImportTable_nosigs2) { ...@@ -1092,19 +1132,19 @@ TEST_F(WasmModuleVerifyTest, ImportTable_nosigs2) {
TEST_F(WasmModuleVerifyTest, ImportTable_invalid_sig) { TEST_F(WasmModuleVerifyTest, ImportTable_invalid_sig) {
static const byte data[] = { static const byte data[] = {
SECTION(SIGNATURES, 1), 0, SECTION(IMPORT_TABLE, 6), 1, SECTION(SIGNATURES, 1), 0, // --
IMPORT_SIG_INDEX(0), // sig index SECTION(IMPORT_TABLE, 6), 1, // --
NAME_LENGTH(1), 'm', // module name IMPORT_SIG_INDEX(0), // sig index
NAME_LENGTH(1), 'f', // function name NAME_LENGTH(1), 'm', // module name
NAME_LENGTH(1), 'f', // function name
}; };
EXPECT_FAILURE(data); EXPECT_FAILURE(data);
} }
TEST_F(WasmModuleVerifyTest, ImportTable_one_sig) { TEST_F(WasmModuleVerifyTest, ImportTable_one_sig) {
static const byte data[] = { static const byte data[] = {
SECTION(SIGNATURES, 1 + VOID_VOID_SIG_SIZE), // signatures
1, SIGNATURES_SECTION_VOID_VOID,
VOID_VOID_SIG,
SECTION(IMPORT_TABLE, 6), SECTION(IMPORT_TABLE, 6),
1, // -- 1, // --
IMPORT_SIG_INDEX(0), // sig index IMPORT_SIG_INDEX(0), // sig index
...@@ -1118,9 +1158,8 @@ TEST_F(WasmModuleVerifyTest, ImportTable_one_sig) { ...@@ -1118,9 +1158,8 @@ TEST_F(WasmModuleVerifyTest, ImportTable_one_sig) {
TEST_F(WasmModuleVerifyTest, ImportTable_invalid_module) { TEST_F(WasmModuleVerifyTest, ImportTable_invalid_module) {
static const byte data[] = { static const byte data[] = {
SECTION(SIGNATURES, 1 + VOID_VOID_SIG_SIZE), // signatures
1, SIGNATURES_SECTION_VOID_VOID,
VOID_VOID_SIG,
SECTION(IMPORT_TABLE, 6), SECTION(IMPORT_TABLE, 6),
1, // -- 1, // --
IMPORT_SIG_INDEX(0), // sig index IMPORT_SIG_INDEX(0), // sig index
...@@ -1133,9 +1172,8 @@ TEST_F(WasmModuleVerifyTest, ImportTable_invalid_module) { ...@@ -1133,9 +1172,8 @@ TEST_F(WasmModuleVerifyTest, ImportTable_invalid_module) {
TEST_F(WasmModuleVerifyTest, ImportTable_off_end) { TEST_F(WasmModuleVerifyTest, ImportTable_off_end) {
static const byte data[] = { static const byte data[] = {
SECTION(SIGNATURES, 1 + VOID_VOID_SIG_SIZE), // signatures
1, SIGNATURES_SECTION_VOID_VOID,
VOID_VOID_SIG,
SECTION(IMPORT_TABLE, 6), SECTION(IMPORT_TABLE, 6),
1, 1,
IMPORT_SIG_INDEX(0), // sig index IMPORT_SIG_INDEX(0), // sig index
...@@ -1149,28 +1187,31 @@ TEST_F(WasmModuleVerifyTest, ImportTable_off_end) { ...@@ -1149,28 +1187,31 @@ TEST_F(WasmModuleVerifyTest, ImportTable_off_end) {
} }
TEST_F(WasmModuleVerifyTest, ExportTable_empty1) { TEST_F(WasmModuleVerifyTest, ExportTable_empty1) {
static const byte data[] = {SECTION(SIGNATURES, 1 + VOID_VOID_SIG_SIZE), static const byte data[] = {
1, // signatures
VOID_VOID_SIG, SIGNATURES_SECTION_VOID_VOID,
SECTION(FUNCTIONS, 1 + EMPTY_FUNCTION_SIZE), SECTION(OLD_FUNCTIONS, 1 + EMPTY_FUNCTION_SIZE),
1, 1,
EMPTY_FUNCTION(0), EMPTY_FUNCTION(0),
SECTION(EXPORT_TABLE, 1), SECTION(EXPORT_TABLE, 1),
0}; 0 // --
};
EXPECT_VERIFIES(data); EXPECT_VERIFIES(data);
} }
TEST_F(WasmModuleVerifyTest, ExportTable_empty2) { TEST_F(WasmModuleVerifyTest, ExportTable_empty2) {
static const byte data[] = {SECTION(SIGNATURES, 1), 0, static const byte data[] = {
SECTION(FUNCTIONS, 1), 0, SECTION(SIGNATURES, 1), 0, SECTION(OLD_FUNCTIONS, 1), 0,
SECTION(EXPORT_TABLE, 1), 0}; SECTION(EXPORT_TABLE, 1), 0 // --
};
// TODO(titzer): current behavior treats empty functions section as missing. // TODO(titzer): current behavior treats empty functions section as missing.
EXPECT_FAILURE(data); EXPECT_FAILURE(data);
} }
TEST_F(WasmModuleVerifyTest, ExportTable_NoFunctions1) { TEST_F(WasmModuleVerifyTest, ExportTable_NoFunctions1) {
static const byte data[] = {SECTION(SIGNATURES, 1), 0, static const byte data[] = {
SECTION(EXPORT_TABLE, 1), 0}; SECTION(SIGNATURES, 1), 0, SECTION(EXPORT_TABLE, 1), 0 // --
};
EXPECT_FAILURE(data); EXPECT_FAILURE(data);
} }
...@@ -1181,10 +1222,9 @@ TEST_F(WasmModuleVerifyTest, ExportTable_NoFunctions2) { ...@@ -1181,10 +1222,9 @@ TEST_F(WasmModuleVerifyTest, ExportTable_NoFunctions2) {
TEST_F(WasmModuleVerifyTest, ExportTableOne) { TEST_F(WasmModuleVerifyTest, ExportTableOne) {
static const byte data[] = { static const byte data[] = {
SECTION(SIGNATURES, 1 + VOID_VOID_SIG_SIZE), // signatures
1, // sigs SIGNATURES_SECTION_VOID_VOID,
VOID_VOID_SIG, // -- SECTION(OLD_FUNCTIONS, 1 + EMPTY_FUNCTION_SIZE),
SECTION(FUNCTIONS, 1 + EMPTY_FUNCTION_SIZE),
1, // functions 1, // functions
EMPTY_FUNCTION(0), // -- EMPTY_FUNCTION(0), // --
SECTION(EXPORT_TABLE, 3), SECTION(EXPORT_TABLE, 3),
...@@ -1197,10 +1237,9 @@ TEST_F(WasmModuleVerifyTest, ExportTableOne) { ...@@ -1197,10 +1237,9 @@ TEST_F(WasmModuleVerifyTest, ExportTableOne) {
TEST_F(WasmModuleVerifyTest, ExportTableTwo) { TEST_F(WasmModuleVerifyTest, ExportTableTwo) {
static const byte data[] = { static const byte data[] = {
SECTION(SIGNATURES, 1 + VOID_VOID_SIG_SIZE), // signatures
1, // sigs SIGNATURES_SECTION_VOID_VOID,
VOID_VOID_SIG, // -- SECTION(OLD_FUNCTIONS, 1 + EMPTY_FUNCTION_SIZE),
SECTION(FUNCTIONS, 1 + EMPTY_FUNCTION_SIZE),
1, // functions 1, // functions
EMPTY_FUNCTION(0), // -- EMPTY_FUNCTION(0), // --
SECTION(EXPORT_TABLE, 12), SECTION(EXPORT_TABLE, 12),
...@@ -1222,10 +1261,9 @@ TEST_F(WasmModuleVerifyTest, ExportTableTwo) { ...@@ -1222,10 +1261,9 @@ TEST_F(WasmModuleVerifyTest, ExportTableTwo) {
TEST_F(WasmModuleVerifyTest, ExportTableThree) { TEST_F(WasmModuleVerifyTest, ExportTableThree) {
static const byte data[] = { static const byte data[] = {
SECTION(SIGNATURES, 1 + VOID_VOID_SIG_SIZE), // signatures
1, // sigs SIGNATURES_SECTION_VOID_VOID,
VOID_VOID_SIG, // -- SECTION(OLD_FUNCTIONS, 1 + 3 * EMPTY_FUNCTION_SIZE),
SECTION(FUNCTIONS, 1 + 3 * EMPTY_FUNCTION_SIZE),
3, // functions 3, // functions
EMPTY_FUNCTION(0), // -- EMPTY_FUNCTION(0), // --
EMPTY_FUNCTION(0), // -- EMPTY_FUNCTION(0), // --
...@@ -1248,10 +1286,9 @@ TEST_F(WasmModuleVerifyTest, ExportTableThree) { ...@@ -1248,10 +1286,9 @@ TEST_F(WasmModuleVerifyTest, ExportTableThree) {
TEST_F(WasmModuleVerifyTest, ExportTableThreeOne) { TEST_F(WasmModuleVerifyTest, ExportTableThreeOne) {
for (int i = 0; i < 6; i++) { for (int i = 0; i < 6; i++) {
const byte data[] = { const byte data[] = {
SECTION(SIGNATURES, 1 + VOID_VOID_SIG_SIZE), // signatures
1, // sigs SIGNATURES_SECTION_VOID_VOID,
VOID_VOID_SIG, // -- SECTION(OLD_FUNCTIONS, 1 + 3 * EMPTY_FUNCTION_SIZE),
SECTION(FUNCTIONS, 1 + 3 * EMPTY_FUNCTION_SIZE),
3, // functions 3, // functions
EMPTY_FUNCTION(0), // -- EMPTY_FUNCTION(0), // --
EMPTY_FUNCTION(0), // -- EMPTY_FUNCTION(0), // --
...@@ -1274,10 +1311,9 @@ TEST_F(WasmModuleVerifyTest, ExportTableThreeOne) { ...@@ -1274,10 +1311,9 @@ TEST_F(WasmModuleVerifyTest, ExportTableThreeOne) {
TEST_F(WasmModuleVerifyTest, ExportTableOne_off_end) { TEST_F(WasmModuleVerifyTest, ExportTableOne_off_end) {
static const byte data[] = { static const byte data[] = {
SECTION(SIGNATURES, 1 + VOID_VOID_SIG_SIZE), // signatures
1, // sigs SIGNATURES_SECTION_VOID_VOID,
VOID_VOID_SIG, // -- SECTION(OLD_FUNCTIONS, 1 + EMPTY_FUNCTION_SIZE),
SECTION(FUNCTIONS, 1 + EMPTY_FUNCTION_SIZE),
1, // functions 1, // functions
EMPTY_FUNCTION(0), // -- EMPTY_FUNCTION(0), // --
SECTION(EXPORT_TABLE, 1 + 6), SECTION(EXPORT_TABLE, 1 + 6),
...@@ -1293,19 +1329,6 @@ TEST_F(WasmModuleVerifyTest, ExportTableOne_off_end) { ...@@ -1293,19 +1329,6 @@ TEST_F(WasmModuleVerifyTest, ExportTableOne_off_end) {
} }
} }
#define SIGNATURES_SECTION(count, ...) \
SECTION(SIGNATURES, 1 + 2 * (count)), U32V_1(count), __VA_ARGS__
#define FUNCTION_SIGNATURES_SECTION(count, ...) \
SECTION(FUNCTION_SIGNATURES, 1 + (count)), U32V_1(count), __VA_ARGS__
#define FOO_STRING 3, 'f', 'o', 'o'
#define NO_LOCAL_NAMES 0
#define EMPTY_SIGNATURES_SECTION SECTION(SIGNATURES, 1), 0
#define EMPTY_FUNCTION_SIGNATURES_SECTION SECTION(FUNCTION_SIGNATURES, 1), 0
#define EMPTY_FUNCTION_BODIES_SECTION SECTION(FUNCTION_BODIES, 1), 0
#define EMPTY_NAMES_SECTION SECTION(NAMES, 1), 0
TEST_F(WasmModuleVerifyTest, FunctionSignatures_empty) { TEST_F(WasmModuleVerifyTest, FunctionSignatures_empty) {
static const byte data[] = { static const byte data[] = {
SECTION(SIGNATURES, 1), 0, // -- SECTION(SIGNATURES, 1), 0, // --
...@@ -1316,7 +1339,7 @@ TEST_F(WasmModuleVerifyTest, FunctionSignatures_empty) { ...@@ -1316,7 +1339,7 @@ TEST_F(WasmModuleVerifyTest, FunctionSignatures_empty) {
TEST_F(WasmModuleVerifyTest, FunctionSignatures_one) { TEST_F(WasmModuleVerifyTest, FunctionSignatures_one) {
static const byte data[] = { static const byte data[] = {
SIGNATURES_SECTION(1, VOID_VOID_SIG), // -- SIGNATURES_SECTION(1, SIG_ENTRY_v_v), // --
FUNCTION_SIGNATURES_SECTION(1, 0) // -- FUNCTION_SIGNATURES_SECTION(1, 0) // --
}; };
EXPECT_VERIFIES(data); EXPECT_VERIFIES(data);
...@@ -1333,40 +1356,40 @@ TEST_F(WasmModuleVerifyTest, FunctionBodies_empty) { ...@@ -1333,40 +1356,40 @@ TEST_F(WasmModuleVerifyTest, FunctionBodies_empty) {
TEST_F(WasmModuleVerifyTest, FunctionBodies_one_empty) { TEST_F(WasmModuleVerifyTest, FunctionBodies_one_empty) {
static const byte data[] = { static const byte data[] = {
SIGNATURES_SECTION(1, VOID_VOID_SIG), // -- SIGNATURES_SECTION(1, SIG_ENTRY_v_v), // --
FUNCTION_SIGNATURES_SECTION(1, 0), // -- FUNCTION_SIGNATURES_SECTION(1, 0), // --
SECTION(FUNCTION_BODIES, 1 + EMPTY_BODY_SIZE), 1, EMPTY_BODY // -- SECTION(FUNCTION_BODIES, 1 + SIZEOF_EMPTY_BODY), 1, EMPTY_BODY // --
}; };
EXPECT_VERIFIES(data); EXPECT_VERIFIES(data);
} }
TEST_F(WasmModuleVerifyTest, FunctionBodies_one_nop) { TEST_F(WasmModuleVerifyTest, FunctionBodies_one_nop) {
static const byte data[] = { static const byte data[] = {
SIGNATURES_SECTION(1, VOID_VOID_SIG), // -- SIGNATURES_SECTION(1, SIG_ENTRY_v_v), // --
FUNCTION_SIGNATURES_SECTION(1, 0), // -- FUNCTION_SIGNATURES_SECTION(1, 0), // --
SECTION(FUNCTION_BODIES, 1 + NOP_BODY_SIZE), 1, NOP_BODY // -- SECTION(FUNCTION_BODIES, 1 + SIZEOF_NOP_BODY), 1, NOP_BODY // --
}; };
EXPECT_VERIFIES(data); EXPECT_VERIFIES(data);
} }
TEST_F(WasmModuleVerifyTest, FunctionBodies_count_mismatch1) { TEST_F(WasmModuleVerifyTest, FunctionBodies_count_mismatch1) {
static const byte data[] = { static const byte data[] = {
SIGNATURES_SECTION(1, VOID_VOID_SIG), // -- SIGNATURES_SECTION(1, SIG_ENTRY_v_v), // --
FUNCTION_SIGNATURES_SECTION(2, 0, 0), // -- FUNCTION_SIGNATURES_SECTION(2, 0, 0), // --
SECTION(FUNCTION_BODIES, 1 + EMPTY_BODY_SIZE), 1, // -- SECTION(FUNCTION_BODIES, 1 + SIZEOF_EMPTY_BODY), 1, // --
EMPTY_BODY // -- EMPTY_BODY // --
}; };
EXPECT_FAILURE(data); EXPECT_FAILURE(data);
} }
TEST_F(WasmModuleVerifyTest, FunctionBodies_count_mismatch2) { TEST_F(WasmModuleVerifyTest, FunctionBodies_count_mismatch2) {
static const byte data[] = { static const byte data[] = {
SIGNATURES_SECTION(1, VOID_VOID_SIG), // -- SIGNATURES_SECTION(1, SIG_ENTRY_v_v), // --
FUNCTION_SIGNATURES_SECTION(1, 0), // -- FUNCTION_SIGNATURES_SECTION(1, 0), // --
SECTION(FUNCTION_BODIES, 1 + 2 * NOP_BODY_SIZE), // -- SECTION(FUNCTION_BODIES, 1 + 2 * SIZEOF_NOP_BODY), // --
2, // -- 2, // --
NOP_BODY, // -- NOP_BODY, // --
NOP_BODY // -- NOP_BODY // --
}; };
EXPECT_FAILURE(data); EXPECT_FAILURE(data);
} }
...@@ -1380,9 +1403,9 @@ TEST_F(WasmModuleVerifyTest, Names_empty) { ...@@ -1380,9 +1403,9 @@ TEST_F(WasmModuleVerifyTest, Names_empty) {
TEST_F(WasmModuleVerifyTest, Names_one_empty) { TEST_F(WasmModuleVerifyTest, Names_one_empty) {
static const byte data[] = { static const byte data[] = {
SIGNATURES_SECTION(1, VOID_VOID_SIG), // -- SIGNATURES_SECTION(1, SIG_ENTRY_v_v), // --
FUNCTION_SIGNATURES_SECTION(1, 0), // -- FUNCTION_SIGNATURES_SECTION(1, 0), // --
SECTION(FUNCTION_BODIES, 1 + EMPTY_BODY_SIZE), SECTION(FUNCTION_BODIES, 1 + SIZEOF_EMPTY_BODY),
1, 1,
EMPTY_BODY, // -- EMPTY_BODY, // --
SECTION(NAMES, 1 + 5), SECTION(NAMES, 1 + 5),
...@@ -1395,9 +1418,9 @@ TEST_F(WasmModuleVerifyTest, Names_one_empty) { ...@@ -1395,9 +1418,9 @@ TEST_F(WasmModuleVerifyTest, Names_one_empty) {
TEST_F(WasmModuleVerifyTest, Names_two_empty) { TEST_F(WasmModuleVerifyTest, Names_two_empty) {
static const byte data[] = { static const byte data[] = {
SIGNATURES_SECTION(1, VOID_VOID_SIG), // -- SIGNATURES_SECTION(1, SIG_ENTRY_v_v), // --
FUNCTION_SIGNATURES_SECTION(2, 0, 0), // -- FUNCTION_SIGNATURES_SECTION(2, 0, 0), // --
SECTION(FUNCTION_BODIES, 1 + 2 * EMPTY_BODY_SIZE), // -- SECTION(FUNCTION_BODIES, 1 + 2 * SIZEOF_EMPTY_BODY), // --
2, 2,
EMPTY_BODY, EMPTY_BODY,
EMPTY_BODY, // -- EMPTY_BODY, // --
......
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