[wasm] Refactor import handling for 0xC.
Imports and exports in 0xC can be much more than functions, including tables, memories, and globals. This CL refactors the underlying organization of imports and exports to support these new import types. BUG= Review-Url: https://codereview.chromium.org/2390113003 Cr-Commit-Position: refs/heads/master@{#40033}
This commit is contained in:
parent
94c8170a88
commit
599f8a8342
@ -3151,8 +3151,8 @@ Handle<Code> CompileJSToWasmWrapper(Isolate* isolate, wasm::ModuleEnv* module,
|
||||
|
||||
Handle<Code> CompileWasmToJSWrapper(Isolate* isolate, Handle<JSReceiver> target,
|
||||
wasm::FunctionSig* sig, uint32_t index,
|
||||
Handle<String> import_module,
|
||||
MaybeHandle<String> import_function) {
|
||||
Handle<String> module_name,
|
||||
MaybeHandle<String> import_name) {
|
||||
//----------------------------------------------------------------------------
|
||||
// Create the Graph
|
||||
//----------------------------------------------------------------------------
|
||||
@ -3215,14 +3215,14 @@ Handle<Code> CompileWasmToJSWrapper(Isolate* isolate, Handle<JSReceiver> target,
|
||||
if (isolate->logger()->is_logging_code_events() || isolate->is_profiling()) {
|
||||
const char* function_name = nullptr;
|
||||
int function_name_size = 0;
|
||||
if (!import_function.is_null()) {
|
||||
Handle<String> handle = import_function.ToHandleChecked();
|
||||
if (!import_name.is_null()) {
|
||||
Handle<String> handle = import_name.ToHandleChecked();
|
||||
function_name = handle->ToCString().get();
|
||||
function_name_size = handle->length();
|
||||
}
|
||||
RecordFunctionCompilation(
|
||||
CodeEventListener::FUNCTION_TAG, isolate, code, "wasm-to-js", index,
|
||||
{import_module->ToCString().get(), import_module->length()},
|
||||
{module_name->ToCString().get(), module_name->length()},
|
||||
{function_name, function_name_size});
|
||||
}
|
||||
|
||||
|
@ -84,8 +84,8 @@ class WasmCompilationUnit final {
|
||||
// Wraps a JS function, producing a code object that can be called from WASM.
|
||||
Handle<Code> CompileWasmToJSWrapper(Isolate* isolate, Handle<JSReceiver> target,
|
||||
wasm::FunctionSig* sig, uint32_t index,
|
||||
Handle<String> import_module,
|
||||
MaybeHandle<String> import_function);
|
||||
Handle<String> module_name,
|
||||
MaybeHandle<String> import_name);
|
||||
|
||||
// Wraps a given wasm code object, producing a code object.
|
||||
Handle<Code> CompileJSToWasmWrapper(Isolate* isolate, wasm::ModuleEnv* module,
|
||||
|
@ -318,7 +318,7 @@ class ModuleDecoder : public Decoder {
|
||||
// ===== Imported global =========================================
|
||||
import->index = static_cast<uint32_t>(module->globals.size());
|
||||
module->globals.push_back(
|
||||
{kAstStmt, false, NO_INIT, 0, true, false});
|
||||
{kAstStmt, false, WasmInitExpr(), 0, true, false});
|
||||
WasmGlobal* global = &module->globals.back();
|
||||
global->type = consume_value_type();
|
||||
global->mutability = consume_u8("mutability") != 0;
|
||||
@ -399,7 +399,8 @@ class ModuleDecoder : public Decoder {
|
||||
TRACE("DecodeGlobal[%d] module+%d\n", i,
|
||||
static_cast<int>(pc_ - start_));
|
||||
// Add an uninitialized global and pass a pointer to it.
|
||||
module->globals.push_back({kAstStmt, false, NO_INIT, 0, false, false});
|
||||
module->globals.push_back(
|
||||
{kAstStmt, false, WasmInitExpr(), 0, false, false});
|
||||
WasmGlobal* global = &module->globals.back();
|
||||
DecodeGlobalInModule(module, i, global);
|
||||
}
|
||||
@ -545,9 +546,9 @@ class ModuleDecoder : public Decoder {
|
||||
TRACE("DecodeDataSegment[%d] module+%d\n", i,
|
||||
static_cast<int>(pc_ - start_));
|
||||
module->data_segments.push_back({
|
||||
NO_INIT, // dest_addr
|
||||
0, // source_offset
|
||||
0 // source_size
|
||||
WasmInitExpr(), // dest_addr
|
||||
0, // source_offset
|
||||
0 // source_size
|
||||
});
|
||||
WasmDataSegment* segment = &module->data_segments.back();
|
||||
DecodeDataSegmentInModule(module, segment);
|
||||
@ -647,13 +648,19 @@ class ModuleDecoder : public Decoder {
|
||||
const byte* pos = pc();
|
||||
global->init = consume_init_expr(module, kAstStmt);
|
||||
switch (global->init.kind) {
|
||||
case WasmInitExpr::kGlobalIndex:
|
||||
if (global->init.val.global_index >= index) {
|
||||
case WasmInitExpr::kGlobalIndex: {
|
||||
uint32_t other_index = global->init.val.global_index;
|
||||
if (other_index >= index) {
|
||||
error("invalid global index in init expression");
|
||||
} else if (module->globals[index].type != global->type) {
|
||||
error("type mismatch in global initialization");
|
||||
} else if (module->globals[other_index].type != global->type) {
|
||||
error(pos, pos,
|
||||
"type mismatch in global initialization "
|
||||
"(from global #%u), expected %s, got %s",
|
||||
other_index, WasmOpcodes::TypeName(global->type),
|
||||
WasmOpcodes::TypeName(module->globals[other_index].type));
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
if (global->type != TypeOf(module, global->init)) {
|
||||
error(pos, pos,
|
||||
|
@ -255,8 +255,9 @@ void WasmModuleBuilder::MarkStartFunction(WasmFunctionBuilder* function) {
|
||||
}
|
||||
|
||||
uint32_t WasmModuleBuilder::AddGlobal(LocalType type, bool exported,
|
||||
bool mutability) {
|
||||
globals_.push_back({type, exported, mutability});
|
||||
bool mutability,
|
||||
const WasmInitExpr& init) {
|
||||
globals_.push_back({type, exported, mutability, init});
|
||||
return static_cast<uint32_t>(globals_.size() - 1);
|
||||
}
|
||||
|
||||
@ -344,29 +345,64 @@ void WasmModuleBuilder::WriteTo(ZoneBuffer& buffer) const {
|
||||
for (auto global : globals_) {
|
||||
buffer.write_u8(WasmOpcodes::LocalTypeCodeFor(global.type));
|
||||
buffer.write_u8(global.mutability ? 1 : 0);
|
||||
switch (global.type) {
|
||||
case kAstI32: {
|
||||
static const byte code[] = {WASM_I32V_1(0)};
|
||||
switch (global.init.kind) {
|
||||
case WasmInitExpr::kI32Const: {
|
||||
DCHECK_EQ(kAstI32, global.type);
|
||||
const byte code[] = {WASM_I32V_5(global.init.val.i32_const)};
|
||||
buffer.write(code, sizeof(code));
|
||||
break;
|
||||
}
|
||||
case kAstF32: {
|
||||
static const byte code[] = {WASM_F32(0)};
|
||||
case WasmInitExpr::kI64Const: {
|
||||
DCHECK_EQ(kAstI64, global.type);
|
||||
const byte code[] = {WASM_I64V_10(global.init.val.i64_const)};
|
||||
buffer.write(code, sizeof(code));
|
||||
break;
|
||||
}
|
||||
case kAstI64: {
|
||||
static const byte code[] = {WASM_I64V_1(0)};
|
||||
case WasmInitExpr::kF32Const: {
|
||||
DCHECK_EQ(kAstF32, global.type);
|
||||
const byte code[] = {WASM_F32(global.init.val.f32_const)};
|
||||
buffer.write(code, sizeof(code));
|
||||
break;
|
||||
}
|
||||
case kAstF64: {
|
||||
static const byte code[] = {WASM_F64(0.0)};
|
||||
case WasmInitExpr::kF64Const: {
|
||||
DCHECK_EQ(kAstF64, global.type);
|
||||
const byte code[] = {WASM_F64(global.init.val.f64_const)};
|
||||
buffer.write(code, sizeof(code));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
UNREACHABLE();
|
||||
case WasmInitExpr::kGlobalIndex: {
|
||||
const byte code[] = {kExprGetGlobal,
|
||||
U32V_5(global.init.val.global_index)};
|
||||
buffer.write(code, sizeof(code));
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
// No initializer, emit a default value.
|
||||
switch (global.type) {
|
||||
case kAstI32: {
|
||||
const byte code[] = {WASM_I32V_1(0)};
|
||||
buffer.write(code, sizeof(code));
|
||||
break;
|
||||
}
|
||||
case kAstI64: {
|
||||
const byte code[] = {WASM_I64V_1(0)};
|
||||
buffer.write(code, sizeof(code));
|
||||
break;
|
||||
}
|
||||
case kAstF32: {
|
||||
const byte code[] = {WASM_F32(0.0)};
|
||||
buffer.write(code, sizeof(code));
|
||||
break;
|
||||
}
|
||||
case kAstF64: {
|
||||
const byte code[] = {WASM_F64(0.0)};
|
||||
buffer.write(code, sizeof(code));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
}
|
||||
buffer.write_u8(kExprEnd);
|
||||
}
|
||||
|
@ -212,7 +212,8 @@ class V8_EXPORT_PRIVATE WasmModuleBuilder : public ZoneObject {
|
||||
imports_[index].name_length = name_length;
|
||||
}
|
||||
WasmFunctionBuilder* AddFunction(FunctionSig* sig = nullptr);
|
||||
uint32_t AddGlobal(LocalType type, bool exported, bool mutability = true);
|
||||
uint32_t AddGlobal(LocalType type, bool exported, bool mutability = true,
|
||||
const WasmInitExpr& init = WasmInitExpr());
|
||||
void AddDataSegment(const byte* data, uint32_t size, uint32_t dest);
|
||||
uint32_t AddSignature(FunctionSig* sig);
|
||||
void AddIndirectFunction(uint32_t index);
|
||||
@ -241,6 +242,7 @@ class V8_EXPORT_PRIVATE WasmModuleBuilder : public ZoneObject {
|
||||
LocalType type;
|
||||
bool exported;
|
||||
bool mutability;
|
||||
WasmInitExpr init;
|
||||
};
|
||||
|
||||
struct WasmDataSegment {
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -86,12 +86,16 @@ struct WasmInitExpr {
|
||||
double f64_const;
|
||||
uint32_t global_index;
|
||||
} val;
|
||||
};
|
||||
|
||||
#define NO_INIT \
|
||||
{ \
|
||||
WasmInitExpr::kNone, { 0u } \
|
||||
WasmInitExpr() : kind(kNone) {}
|
||||
explicit WasmInitExpr(int32_t v) : kind(kI32Const) { val.i32_const = v; }
|
||||
explicit WasmInitExpr(int64_t v) : kind(kI64Const) { val.i64_const = v; }
|
||||
explicit WasmInitExpr(float v) : kind(kF32Const) { val.f32_const = v; }
|
||||
explicit WasmInitExpr(double v) : kind(kF64Const) { val.f64_const = v; }
|
||||
WasmInitExpr(WasmInitKind kind, uint32_t global_index) : kind(kGlobalIndex) {
|
||||
val.global_index = global_index;
|
||||
}
|
||||
};
|
||||
|
||||
// Static representation of a WASM function.
|
||||
struct WasmFunction {
|
||||
@ -384,8 +388,9 @@ class WasmCompiledModule : public FixedArray {
|
||||
|
||||
#define CORE_WCM_PROPERTY_TABLE(MACRO) \
|
||||
MACRO(OBJECT, FixedArray, code_table) \
|
||||
MACRO(OBJECT, FixedArray, import_data) \
|
||||
MACRO(OBJECT, FixedArray, imports) \
|
||||
MACRO(OBJECT, FixedArray, exports) \
|
||||
MACRO(OBJECT, FixedArray, inits) \
|
||||
MACRO(OBJECT, FixedArray, startup_function) \
|
||||
MACRO(OBJECT, FixedArray, indirect_function_tables) \
|
||||
MACRO(OBJECT, String, module_bytes) \
|
||||
@ -395,7 +400,6 @@ class WasmCompiledModule : public FixedArray {
|
||||
MACRO(OBJECT, ByteArray, data_segments) \
|
||||
MACRO(SMALL_NUMBER, uint32_t, globals_size) \
|
||||
MACRO(OBJECT, JSArrayBuffer, heap) \
|
||||
MACRO(SMALL_NUMBER, bool, export_memory) \
|
||||
MACRO(SMALL_NUMBER, ModuleOrigin, origin) \
|
||||
MACRO(WEAK_LINK, WasmCompiledModule, next_instance) \
|
||||
MACRO(WEAK_LINK, WasmCompiledModule, prev_instance) \
|
||||
@ -424,7 +428,6 @@ class WasmCompiledModule : public FixedArray {
|
||||
static Handle<WasmCompiledModule> New(Isolate* isolate,
|
||||
uint32_t min_memory_pages,
|
||||
uint32_t globals_size,
|
||||
bool export_memory,
|
||||
ModuleOrigin origin);
|
||||
|
||||
static Handle<WasmCompiledModule> Clone(Isolate* isolate,
|
||||
@ -454,9 +457,6 @@ class WasmCompiledModule : public FixedArray {
|
||||
void PrintInstancesChain();
|
||||
|
||||
private:
|
||||
#if DEBUG
|
||||
static uint32_t instance_id_counter_;
|
||||
#endif
|
||||
void Init();
|
||||
|
||||
DISALLOW_IMPLICIT_CONSTRUCTORS(WasmCompiledModule);
|
||||
|
@ -429,3 +429,94 @@ TEST(Run_WasmModule_GrowMemOobVariableIndex) {
|
||||
CHECK(try_catch.HasCaught());
|
||||
isolate->clear_pending_exception();
|
||||
}
|
||||
|
||||
TEST(Run_WasmModule_Global_init) {
|
||||
v8::internal::AccountingAllocator allocator;
|
||||
Zone zone(&allocator);
|
||||
TestSignatures sigs;
|
||||
|
||||
WasmModuleBuilder* builder = new (&zone) WasmModuleBuilder(&zone);
|
||||
uint32_t global1 =
|
||||
builder->AddGlobal(kAstI32, false, false, WasmInitExpr(777777));
|
||||
uint32_t global2 =
|
||||
builder->AddGlobal(kAstI32, false, false, WasmInitExpr(222222));
|
||||
WasmFunctionBuilder* f1 = builder->AddFunction(sigs.i_v());
|
||||
byte code[] = {
|
||||
WASM_I32_ADD(WASM_GET_GLOBAL(global1), WASM_GET_GLOBAL(global2))};
|
||||
f1->EmitCode(code, sizeof(code));
|
||||
ExportAsMain(f1);
|
||||
TestModule(&zone, builder, 999999);
|
||||
}
|
||||
|
||||
template <typename CType>
|
||||
static void RunWasmModuleGlobalInitTest(LocalType type, CType expected) {
|
||||
v8::internal::AccountingAllocator allocator;
|
||||
Zone zone(&allocator);
|
||||
TestSignatures sigs;
|
||||
|
||||
LocalType types[] = {type};
|
||||
FunctionSig sig(1, 0, types);
|
||||
|
||||
for (int padding = 0; padding < 5; padding++) {
|
||||
// Test with a simple initializer
|
||||
WasmModuleBuilder* builder = new (&zone) WasmModuleBuilder(&zone);
|
||||
|
||||
for (int i = 0; i < padding; i++) { // pad global before
|
||||
builder->AddGlobal(kAstI32, false, false, WasmInitExpr(i + 20000));
|
||||
}
|
||||
uint32_t global =
|
||||
builder->AddGlobal(type, false, false, WasmInitExpr(expected));
|
||||
for (int i = 0; i < padding; i++) { // pad global after
|
||||
builder->AddGlobal(kAstI32, false, false, WasmInitExpr(i + 30000));
|
||||
}
|
||||
|
||||
WasmFunctionBuilder* f1 = builder->AddFunction(&sig);
|
||||
byte code[] = {WASM_GET_GLOBAL(global)};
|
||||
f1->EmitCode(code, sizeof(code));
|
||||
ExportAsMain(f1);
|
||||
TestModule(&zone, builder, expected);
|
||||
}
|
||||
|
||||
for (int padding = 0; padding < 5; padding++) {
|
||||
// Test with a global index
|
||||
WasmModuleBuilder* builder = new (&zone) WasmModuleBuilder(&zone);
|
||||
for (int i = 0; i < padding; i++) { // pad global before
|
||||
builder->AddGlobal(kAstI32, false, false, WasmInitExpr(i + 40000));
|
||||
}
|
||||
|
||||
uint32_t global1 =
|
||||
builder->AddGlobal(type, false, false, WasmInitExpr(expected));
|
||||
|
||||
for (int i = 0; i < padding; i++) { // pad global middle
|
||||
builder->AddGlobal(kAstI32, false, false, WasmInitExpr(i + 50000));
|
||||
}
|
||||
|
||||
uint32_t global2 = builder->AddGlobal(
|
||||
type, false, false, WasmInitExpr(WasmInitExpr::kGlobalIndex, global1));
|
||||
|
||||
for (int i = 0; i < padding; i++) { // pad global after
|
||||
builder->AddGlobal(kAstI32, false, false, WasmInitExpr(i + 60000));
|
||||
}
|
||||
|
||||
WasmFunctionBuilder* f1 = builder->AddFunction(&sig);
|
||||
byte code[] = {WASM_GET_GLOBAL(global2)};
|
||||
f1->EmitCode(code, sizeof(code));
|
||||
ExportAsMain(f1);
|
||||
TestModule(&zone, builder, expected);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Run_WasmModule_Global_i32) {
|
||||
RunWasmModuleGlobalInitTest<int32_t>(kAstI32, -983489);
|
||||
RunWasmModuleGlobalInitTest<int32_t>(kAstI32, 11223344);
|
||||
}
|
||||
|
||||
TEST(Run_WasmModule_Global_f32) {
|
||||
RunWasmModuleGlobalInitTest<float>(kAstF32, -983.9f);
|
||||
RunWasmModuleGlobalInitTest<float>(kAstF32, 1122.99f);
|
||||
}
|
||||
|
||||
TEST(Run_WasmModule_Global_f64) {
|
||||
RunWasmModuleGlobalInitTest<double>(kAstF64, -833.9);
|
||||
RunWasmModuleGlobalInitTest<double>(kAstF64, 86374.25);
|
||||
}
|
||||
|
@ -268,7 +268,7 @@ class TestingModule : public ModuleEnv {
|
||||
byte size = WasmOpcodes::MemSize(WasmOpcodes::MachineTypeFor(type));
|
||||
global_offset = (global_offset + size - 1) & ~(size - 1); // align
|
||||
module_.globals.push_back(
|
||||
{type, true, NO_INIT, global_offset, false, false});
|
||||
{type, true, WasmInitExpr(), global_offset, false, false});
|
||||
global_offset += size;
|
||||
// limit number of globals.
|
||||
CHECK_LT(global_offset, kMaxGlobalsSize);
|
||||
|
@ -14,8 +14,8 @@ load("test/mjsunit/wasm/wasm-module-builder.js");
|
||||
var builder = new WasmModuleBuilder();
|
||||
|
||||
builder.addMemory(1,1, true);
|
||||
builder.addImport("getValue", kSig_i);
|
||||
builder.addFunction("f", kSig_i)
|
||||
builder.addImport("getValue", kSig_i_v);
|
||||
builder.addFunction("f", kSig_i_v)
|
||||
.addBody([
|
||||
kExprCallFunction, 0
|
||||
]).exportFunc();
|
||||
|
@ -12,7 +12,7 @@ load("test/mjsunit/wasm/wasm-module-builder.js");
|
||||
builder.addMemory(1,1, true);
|
||||
var kSig_v_i = makeSig([kAstI32], []);
|
||||
var signature = builder.addType(kSig_v_i);
|
||||
builder.addImport("some_value", kSig_i);
|
||||
builder.addImport("some_value", kSig_i_v);
|
||||
builder.addImport("writer", signature);
|
||||
|
||||
builder.addFunction("main", kSig_i_i)
|
||||
@ -65,7 +65,7 @@ load("test/mjsunit/wasm/wasm-module-builder.js");
|
||||
|
||||
(function RelationBetweenModuleAndClone() {
|
||||
let builder = new WasmModuleBuilder();
|
||||
builder.addFunction("main", kSig_i)
|
||||
builder.addFunction("main", kSig_i_v)
|
||||
.addBody([kExprI8Const, 42])
|
||||
.exportFunc();
|
||||
|
||||
@ -81,7 +81,7 @@ load("test/mjsunit/wasm/wasm-module-builder.js");
|
||||
|
||||
(function SerializeAfterInstantiation() {
|
||||
let builder = new WasmModuleBuilder();
|
||||
builder.addFunction("main", kSig_i)
|
||||
builder.addFunction("main", kSig_i_v)
|
||||
.addBody([kExprI8Const, 42])
|
||||
.exportFunc();
|
||||
|
||||
|
@ -11,7 +11,7 @@ load("test/mjsunit/wasm/wasm-module-builder.js");
|
||||
var kReturnValue = 88;
|
||||
var builder = new WasmModuleBuilder();
|
||||
|
||||
builder.addFunction("main", kSig_i)
|
||||
builder.addFunction("main", kSig_i_v)
|
||||
.addBody([
|
||||
kExprI8Const,
|
||||
kReturnValue,
|
||||
@ -32,7 +32,7 @@ load("test/mjsunit/wasm/wasm-module-builder.js");
|
||||
|
||||
var builder = new WasmModuleBuilder();
|
||||
|
||||
builder.addFunction("main", kSig_i)
|
||||
builder.addFunction("main", kSig_i_v)
|
||||
.addBody([
|
||||
kExprI8Const,
|
||||
kReturnValue,
|
||||
@ -57,7 +57,7 @@ load("test/mjsunit/wasm/wasm-module-builder.js");
|
||||
|
||||
var builder = new WasmModuleBuilder();
|
||||
|
||||
builder.addFunction("main", kSig_i)
|
||||
builder.addFunction("main", kSig_i_v)
|
||||
.addBody([
|
||||
kExprI8Const,
|
||||
kReturnValue,
|
||||
|
@ -94,7 +94,7 @@ print("Native function");
|
||||
|
||||
var builder = new WasmModuleBuilder();
|
||||
|
||||
var sig_index = builder.addType(kSig_d);
|
||||
var sig_index = builder.addType(kSig_d_v);
|
||||
builder.addImport("func", sig_index);
|
||||
builder.addFunction("main", sig_index)
|
||||
.addBody([
|
||||
|
@ -10,7 +10,7 @@ load("test/mjsunit/wasm/wasm-module-builder.js");
|
||||
(function TestFunctionPrototype() {
|
||||
var builder = new WasmModuleBuilder();
|
||||
|
||||
builder.addFunction("nine", kSig_i)
|
||||
builder.addFunction("nine", kSig_i_v)
|
||||
.addBody([kExprI8Const, 9])
|
||||
.exportFunc();
|
||||
|
||||
|
66
test/mjsunit/wasm/globals.js
Normal file
66
test/mjsunit/wasm/globals.js
Normal file
@ -0,0 +1,66 @@
|
||||
// Copyright 2016 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Flags: --expose-wasm
|
||||
|
||||
load("test/mjsunit/wasm/wasm-constants.js");
|
||||
load("test/mjsunit/wasm/wasm-module-builder.js");
|
||||
|
||||
function TestImported(type, val, expected) {
|
||||
print("TestImported " + type + "(" + val +")" + " = " + expected);
|
||||
var builder = new WasmModuleBuilder();
|
||||
var sig = makeSig([], [type]);
|
||||
var g = builder.addImportedGlobal("foo", undefined, type);
|
||||
builder.addFunction("main", sig)
|
||||
.addBody([kExprGetGlobal, g.index])
|
||||
.exportAs("main");
|
||||
builder.addGlobal(kAstI32); // pad
|
||||
|
||||
var instance = builder.instantiate({foo: val});
|
||||
assertEquals(expected, instance.exports.main());
|
||||
}
|
||||
|
||||
TestImported(kAstI32, 300.1, 300);
|
||||
TestImported(kAstF32, 87234.87238, Math.fround(87234.87238));
|
||||
TestImported(kAstF64, 77777.88888, 77777.88888);
|
||||
TestImported(kAstF64, "89", 89);
|
||||
|
||||
|
||||
function TestExported(type, val, expected) {
|
||||
print("TestExported " + type + "(" + val +")" + " = " + expected);
|
||||
var builder = new WasmModuleBuilder();
|
||||
var sig = makeSig([type], []);
|
||||
builder.addGlobal(kAstI32); // pad
|
||||
var g = builder.addGlobal(type, false)
|
||||
.exportAs("foo");
|
||||
g.init = val;
|
||||
builder.addGlobal(kAstI32); // pad
|
||||
|
||||
var instance = builder.instantiate();
|
||||
assertEquals(expected, instance.exports.foo);
|
||||
}
|
||||
|
||||
TestExported(kAstI32, 455.5, 455);
|
||||
TestExported(kAstF32, -999.34343, Math.fround(-999.34343));
|
||||
TestExported(kAstF64, 87347.66666, 87347.66666);
|
||||
|
||||
|
||||
function TestImportedExported(type, val, expected) {
|
||||
print("TestImportedExported " + type + "(" + val +")" + " = " + expected);
|
||||
var builder = new WasmModuleBuilder();
|
||||
var sig = makeSig([type], []);
|
||||
var i = builder.addImportedGlobal("foo", undefined, type);
|
||||
builder.addGlobal(kAstI32); // pad
|
||||
var o = builder.addGlobal(type, false)
|
||||
.exportAs("bar");
|
||||
o.init_index = i;
|
||||
builder.addGlobal(kAstI32); // pad
|
||||
|
||||
var instance = builder.instantiate({foo: val});
|
||||
assertEquals(expected, instance.exports.bar);
|
||||
}
|
||||
|
||||
TestImportedExported(kAstI32, 415.5, 415);
|
||||
TestImportedExported(kAstF32, -979.34343, Math.fround(-979.34343));
|
||||
TestImportedExported(kAstF64, 81347.66666, 81347.66666);
|
@ -266,9 +266,9 @@ testCallPrint();
|
||||
function testCallImport2(foo, bar, expected) {
|
||||
var builder = new WasmModuleBuilder();
|
||||
|
||||
builder.addImport("foo", kSig_i);
|
||||
builder.addImport("bar", kSig_i);
|
||||
builder.addFunction("main", kSig_i)
|
||||
builder.addImport("foo", kSig_i_v);
|
||||
builder.addImport("bar", kSig_i_v);
|
||||
builder.addFunction("main", kSig_i_v)
|
||||
.addBody([
|
||||
kExprCallFunction, 0, // --
|
||||
kExprCallFunction, 1, // --
|
||||
|
@ -12,7 +12,7 @@ let nogc = () => {};
|
||||
function newModule() {
|
||||
let builder = new WasmModuleBuilder();
|
||||
builder.addMemory(1, 1, true);
|
||||
builder.addFunction("main", kSig_i)
|
||||
builder.addFunction("main", kSig_i_v)
|
||||
.addBody([kExprI32Const, 0, kExprI32LoadMem, 0, 0])
|
||||
.exportFunc();
|
||||
|
||||
|
@ -12,7 +12,7 @@ let kReturnValue = 117;
|
||||
let buffer = (() => {
|
||||
let builder = new WasmModuleBuilder();
|
||||
builder.addMemory(1, 1, true);
|
||||
builder.addFunction("main", kSig_i)
|
||||
builder.addFunction("main", kSig_i_v)
|
||||
.addBody([kExprI8Const, kReturnValue])
|
||||
.exportFunc();
|
||||
|
||||
@ -119,7 +119,7 @@ assertFalse(WebAssembly.validate(bytes(88, 88, 88, 88, 88, 88, 88, 88)));
|
||||
builder.addMemory(1,1, true);
|
||||
var kSig_v_i = makeSig([kAstI32], []);
|
||||
var signature = builder.addType(kSig_v_i);
|
||||
builder.addImport("some_value", kSig_i);
|
||||
builder.addImport("some_value", kSig_i_v);
|
||||
builder.addImport("writer", signature);
|
||||
|
||||
builder.addFunction("main", kSig_i_i)
|
||||
@ -169,7 +169,7 @@ assertFalse(WebAssembly.validate(bytes(88, 88, 88, 88, 88, 88, 88, 88)));
|
||||
(function GlobalsArePrivateToTheInstance() {
|
||||
print("GlobalsArePrivateToTheInstance...");
|
||||
var builder = new WasmModuleBuilder();
|
||||
builder.addGlobal(kAstI32);
|
||||
builder.addGlobal(kAstI32, true);
|
||||
builder.addFunction("read", kSig_i_v)
|
||||
.addBody([
|
||||
kExprGetGlobal, 0])
|
||||
@ -196,7 +196,7 @@ assertFalse(WebAssembly.validate(bytes(88, 88, 88, 88, 88, 88, 88, 88)));
|
||||
var builder = new WasmModuleBuilder();
|
||||
builder.addMemory(1,1, true);
|
||||
|
||||
builder.addFunction("f", kSig_i)
|
||||
builder.addFunction("f", kSig_i_v)
|
||||
.addBody([
|
||||
kExprI32Const, 0,
|
||||
kExprI32LoadMem, 0, 0
|
||||
|
@ -38,7 +38,7 @@ function assertVerifies(sig, body) {
|
||||
}
|
||||
|
||||
assertVerifies(kSig_v_v, [kExprNop]);
|
||||
assertVerifies(kSig_i, [kExprI8Const, 0]);
|
||||
assertVerifies(kSig_i_v, [kExprI8Const, 0]);
|
||||
|
||||
// Arguments aren't allow to start functions.
|
||||
assertFails(kSig_i_i, [kExprGetLocal, 0]);
|
||||
|
@ -12,7 +12,7 @@ var debug = true;
|
||||
(function BasicTest() {
|
||||
var module = new WasmModuleBuilder();
|
||||
module.addMemory(1, 2, false);
|
||||
module.addFunction("foo", kSig_i)
|
||||
module.addFunction("foo", kSig_i_v)
|
||||
.addBody([kExprI8Const, 11])
|
||||
.exportAs("blarg");
|
||||
|
||||
@ -116,7 +116,7 @@ var debug = true;
|
||||
(function BasicTestWithUint8Array() {
|
||||
var module = new WasmModuleBuilder();
|
||||
module.addMemory(1, 2, false);
|
||||
module.addFunction("foo", kSig_i)
|
||||
module.addFunction("foo", kSig_i_v)
|
||||
.addBody([kExprI8Const, 17])
|
||||
.exportAs("blarg");
|
||||
|
||||
|
@ -89,8 +89,6 @@ var kExternalMemory = 2;
|
||||
var kExternalGlobal = 3;
|
||||
|
||||
// Useful signatures
|
||||
var kSig_i = makeSig([], [kAstI32]);
|
||||
var kSig_d = makeSig([], [kAstF64]);
|
||||
var kSig_i_i = makeSig([kAstI32], [kAstI32]);
|
||||
var kSig_i_l = makeSig([kAstI64], [kAstI32]);
|
||||
var kSig_i_ii = makeSig([kAstI32, kAstI32], [kAstI32]);
|
||||
@ -100,6 +98,8 @@ var kSig_l_ll = makeSig([kAstI64, kAstI64], [kAstI64]);
|
||||
var kSig_i_dd = makeSig([kAstF64, kAstF64], [kAstI32]);
|
||||
var kSig_v_v = makeSig([], []);
|
||||
var kSig_i_v = makeSig([], [kAstI32]);
|
||||
var kSig_f_v = makeSig([], [kAstF64]);
|
||||
var kSig_d_v = makeSig([], [kAstF64]);
|
||||
var kSig_v_i = makeSig([kAstI32], []);
|
||||
var kSig_v_ii = makeSig([kAstI32, kAstI32], []);
|
||||
var kSig_v_iii = makeSig([kAstI32, kAstI32, kAstI32], []);
|
||||
|
@ -2,6 +2,12 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Used for encoding f32 and double constants to bits.
|
||||
let __buffer = new ArrayBuffer(8);
|
||||
let byte_view = new Int8Array(__buffer);
|
||||
let f32_view = new Float32Array(__buffer);
|
||||
let f64_view = new Float64Array(__buffer);
|
||||
|
||||
class Binary extends Array {
|
||||
emit_u8(val) {
|
||||
this.push(val);
|
||||
@ -19,7 +25,7 @@ class Binary extends Array {
|
||||
this.push((val >> 24) & 0xff);
|
||||
}
|
||||
|
||||
emit_varint(val) {
|
||||
emit_u32v(val) {
|
||||
while (true) {
|
||||
let v = val & 0xff;
|
||||
val = val >>> 7;
|
||||
@ -40,7 +46,7 @@ class Binary extends Array {
|
||||
emit_string(string) {
|
||||
// When testing illegal names, we pass a byte array directly.
|
||||
if (string instanceof Array) {
|
||||
this.emit_varint(string.length);
|
||||
this.emit_u32v(string.length);
|
||||
this.emit_bytes(string);
|
||||
return;
|
||||
}
|
||||
@ -48,7 +54,7 @@ class Binary extends Array {
|
||||
// This is the hacky way to convert a JavaScript string to a UTF8 encoded
|
||||
// string only containing single-byte characters.
|
||||
let string_utf8 = unescape(encodeURIComponent(string));
|
||||
this.emit_varint(string_utf8.length);
|
||||
this.emit_u32v(string_utf8.length);
|
||||
for (let i = 0; i < string_utf8.length; i++) {
|
||||
this.emit_u8(string_utf8.charCodeAt(i));
|
||||
}
|
||||
@ -66,26 +72,26 @@ class Binary extends Array {
|
||||
let section = new Binary;
|
||||
content_generator(section);
|
||||
// Emit section length.
|
||||
this.emit_varint(section.length);
|
||||
this.emit_u32v(section.length);
|
||||
// Copy the temporary buffer.
|
||||
this.push(...section);
|
||||
}
|
||||
}
|
||||
|
||||
class WasmFunctionBuilder {
|
||||
constructor(name, type_index) {
|
||||
constructor(module, name, type_index) {
|
||||
this.module = module;
|
||||
this.name = name;
|
||||
this.type_index = type_index;
|
||||
this.exports = [];
|
||||
}
|
||||
|
||||
exportAs(name) {
|
||||
this.exports.push(name);
|
||||
this.module.exports.push({name: name, kind: kExternalFunction, index: this.index});
|
||||
return this;
|
||||
}
|
||||
|
||||
exportFunc() {
|
||||
this.exports.push(this.name);
|
||||
this.exportAs(this.name);
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -100,17 +106,33 @@ class WasmFunctionBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
class WasmGlobalBuilder {
|
||||
constructor(module, type, mutable) {
|
||||
this.module = module;
|
||||
this.type = type;
|
||||
this.mutable = mutable;
|
||||
this.init = 0;
|
||||
}
|
||||
|
||||
exportAs(name) {
|
||||
this.module.exports.push({name: name, kind: kExternalGlobal, index: this.index});
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
class WasmModuleBuilder {
|
||||
constructor() {
|
||||
this.types = [];
|
||||
this.imports = [];
|
||||
this.exports = [];
|
||||
this.globals = [];
|
||||
this.functions = [];
|
||||
this.exports = [];
|
||||
this.table = [];
|
||||
this.segments = [];
|
||||
this.explicit = [];
|
||||
this.pad = null;
|
||||
this.num_imported_funcs = 0;
|
||||
this.num_imported_globals = 0;
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -139,29 +161,39 @@ class WasmModuleBuilder {
|
||||
return this.types.length - 1;
|
||||
}
|
||||
|
||||
addGlobal(local_type) {
|
||||
this.globals.push(local_type);
|
||||
return this.globals.length - 1;
|
||||
addGlobal(local_type, mutable) {
|
||||
let glob = new WasmGlobalBuilder(this, local_type, mutable);
|
||||
glob.index = this.globals.length + this.num_imported_globals;
|
||||
this.globals.push(glob);
|
||||
return glob;
|
||||
}
|
||||
|
||||
addFunction(name, type) {
|
||||
let type_index = (typeof type) == "number" ? type : this.addType(type);
|
||||
let func = new WasmFunctionBuilder(name, type_index);
|
||||
func.index = this.functions.length + this.imports.length;
|
||||
let func = new WasmFunctionBuilder(this, name, type_index);
|
||||
func.index = this.functions.length + this.num_imported_funcs;
|
||||
this.functions.push(func);
|
||||
return func;
|
||||
}
|
||||
|
||||
addImportWithModule(module, name, type) {
|
||||
let type_index = (typeof type) == "number" ? type : this.addType(type);
|
||||
this.imports.push({module: module, name: name, type: type_index});
|
||||
return this.imports.length - 1;
|
||||
this.imports.push({module: module, name: name, kind: kExternalFunction,
|
||||
type: type_index});
|
||||
return this.num_imported_funcs++;
|
||||
}
|
||||
|
||||
addImport(name, type) {
|
||||
return this.addImportWithModule(name, undefined, type);
|
||||
}
|
||||
|
||||
addImportedGlobal(module, name, type) {
|
||||
let o = {module: module, name: name, kind: kExternalGlobal, type: type,
|
||||
mutable: false}
|
||||
this.imports.push(o);
|
||||
return this.num_imported_globals++;
|
||||
}
|
||||
|
||||
addDataSegment(addr, data, init) {
|
||||
this.segments.push({addr: addr, data: data, init: init});
|
||||
return this.segments.length - 1;
|
||||
@ -183,14 +215,14 @@ class WasmModuleBuilder {
|
||||
if (wasm.types.length > 0) {
|
||||
if (debug) print("emitting types @ " + binary.length);
|
||||
binary.emit_section(kTypeSectionCode, section => {
|
||||
section.emit_varint(wasm.types.length);
|
||||
section.emit_u32v(wasm.types.length);
|
||||
for (let type of wasm.types) {
|
||||
section.emit_u8(kWasmFunctionTypeForm);
|
||||
section.emit_varint(type.params.length);
|
||||
section.emit_u32v(type.params.length);
|
||||
for (let param of type.params) {
|
||||
section.emit_u8(param);
|
||||
}
|
||||
section.emit_varint(type.results.length);
|
||||
section.emit_u32v(type.results.length);
|
||||
for (let result of type.results) {
|
||||
section.emit_u8(result);
|
||||
}
|
||||
@ -202,12 +234,19 @@ class WasmModuleBuilder {
|
||||
if (wasm.imports.length > 0) {
|
||||
if (debug) print("emitting imports @ " + binary.length);
|
||||
binary.emit_section(kImportSectionCode, section => {
|
||||
section.emit_varint(wasm.imports.length);
|
||||
section.emit_u32v(wasm.imports.length);
|
||||
for (let imp of wasm.imports) {
|
||||
section.emit_string(imp.module);
|
||||
section.emit_string(imp.name || '');
|
||||
section.emit_u8(kExternalFunction);
|
||||
section.emit_varint(imp.type);
|
||||
section.emit_u8(imp.kind);
|
||||
if (imp.kind == kExternalFunction) {
|
||||
section.emit_u32v(imp.type);
|
||||
} else if (imp.kind == kExternalGlobal) {
|
||||
section.emit_u32v(imp.type);
|
||||
section.emit_u8(imp.mutable);
|
||||
} else {
|
||||
throw new Error("unknown/unsupported import kind " + imp.kind);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -215,16 +254,14 @@ class WasmModuleBuilder {
|
||||
// Add functions declarations
|
||||
let has_names = false;
|
||||
let names = false;
|
||||
let exports = 0;
|
||||
if (wasm.functions.length > 0) {
|
||||
if (debug) print("emitting function decls @ " + binary.length);
|
||||
binary.emit_section(kFunctionSectionCode, section => {
|
||||
section.emit_varint(wasm.functions.length);
|
||||
section.emit_u32v(wasm.functions.length);
|
||||
for (let func of wasm.functions) {
|
||||
has_names = has_names || (func.name != undefined &&
|
||||
func.name.length > 0);
|
||||
exports += func.exports.length;
|
||||
section.emit_varint(func.type_index);
|
||||
section.emit_u32v(func.type_index);
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -236,8 +273,8 @@ class WasmModuleBuilder {
|
||||
section.emit_u8(1); // one table entry
|
||||
section.emit_u8(kWasmAnyFunctionTypeForm);
|
||||
section.emit_u8(1);
|
||||
section.emit_varint(wasm.table.length);
|
||||
section.emit_varint(wasm.table.length);
|
||||
section.emit_u32v(wasm.table.length);
|
||||
section.emit_u32v(wasm.table.length);
|
||||
});
|
||||
}
|
||||
|
||||
@ -246,9 +283,9 @@ class WasmModuleBuilder {
|
||||
if (debug) print("emitting memory @ " + binary.length);
|
||||
binary.emit_section(kMemorySectionCode, section => {
|
||||
section.emit_u8(1); // one memory entry
|
||||
section.emit_varint(kResizableMaximumFlag);
|
||||
section.emit_varint(wasm.memory.min);
|
||||
section.emit_varint(wasm.memory.max);
|
||||
section.emit_u32v(kResizableMaximumFlag);
|
||||
section.emit_u32v(wasm.memory.min);
|
||||
section.emit_u32v(wasm.memory.max);
|
||||
});
|
||||
}
|
||||
|
||||
@ -256,28 +293,46 @@ class WasmModuleBuilder {
|
||||
if (wasm.globals.length > 0) {
|
||||
if (debug) print ("emitting globals @ " + binary.length);
|
||||
binary.emit_section(kGlobalSectionCode, section => {
|
||||
section.emit_varint(wasm.globals.length);
|
||||
for (let global_type of wasm.globals) {
|
||||
section.emit_u8(global_type);
|
||||
section.emit_u8(true); // mutable
|
||||
switch (global_type) {
|
||||
section.emit_u32v(wasm.globals.length);
|
||||
for (let global of wasm.globals) {
|
||||
section.emit_u8(global.type);
|
||||
section.emit_u8(global.mutable);
|
||||
if ((typeof global.init_index) == "undefined") {
|
||||
// Emit a constant initializer.
|
||||
switch (global.type) {
|
||||
case kAstI32:
|
||||
section.emit_u8(kExprI32Const);
|
||||
section.emit_u8(0);
|
||||
section.emit_u32v(global.init);
|
||||
break;
|
||||
case kAstI64:
|
||||
section.emit_u8(kExprI64Const);
|
||||
section.emit_u8(0);
|
||||
section.emit_u8(global.init);
|
||||
break;
|
||||
case kAstF32:
|
||||
section.emit_u8(kExprF32Const);
|
||||
section.emit_u32(0);
|
||||
f32_view[0] = global.init;
|
||||
section.emit_u8(byte_view[0]);
|
||||
section.emit_u8(byte_view[1]);
|
||||
section.emit_u8(byte_view[2]);
|
||||
section.emit_u8(byte_view[3]);
|
||||
break;
|
||||
case kAstF64:
|
||||
section.emit_u8(kExprI32Const);
|
||||
section.emit_u32(0);
|
||||
section.emit_u32(0);
|
||||
section.emit_u8(kExprF64Const);
|
||||
f64_view[0] = global.init;
|
||||
section.emit_u8(byte_view[0]);
|
||||
section.emit_u8(byte_view[1]);
|
||||
section.emit_u8(byte_view[2]);
|
||||
section.emit_u8(byte_view[3]);
|
||||
section.emit_u8(byte_view[4]);
|
||||
section.emit_u8(byte_view[5]);
|
||||
section.emit_u8(byte_view[6]);
|
||||
section.emit_u8(byte_view[7]);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
// Emit a global-index initializer.
|
||||
section.emit_u8(kExprGetGlobal);
|
||||
section.emit_u32v(global.init_index);
|
||||
}
|
||||
section.emit_u8(kExprEnd); // end of init expression
|
||||
}
|
||||
@ -286,16 +341,15 @@ class WasmModuleBuilder {
|
||||
|
||||
// Add export table.
|
||||
var mem_export = (wasm.memory != undefined && wasm.memory.exp);
|
||||
if (exports > 0 || mem_export) {
|
||||
var exports_count = wasm.exports.length + (mem_export ? 1 : 0);
|
||||
if (exports_count > 0) {
|
||||
if (debug) print("emitting exports @ " + binary.length);
|
||||
binary.emit_section(kExportSectionCode, section => {
|
||||
section.emit_varint(exports + (mem_export ? 1 : 0));
|
||||
for (let func of wasm.functions) {
|
||||
for (let exp of func.exports) {
|
||||
section.emit_string(exp);
|
||||
section.emit_u8(kExternalFunction);
|
||||
section.emit_varint(func.index);
|
||||
}
|
||||
section.emit_u32v(exports_count);
|
||||
for (let exp of wasm.exports) {
|
||||
section.emit_string(exp.name);
|
||||
section.emit_u8(exp.kind);
|
||||
section.emit_u32v(exp.index);
|
||||
}
|
||||
if (mem_export) {
|
||||
section.emit_string("memory");
|
||||
@ -309,7 +363,7 @@ class WasmModuleBuilder {
|
||||
if (wasm.start_index != undefined) {
|
||||
if (debug) print("emitting start function @ " + binary.length);
|
||||
binary.emit_section(kStartSectionCode, section => {
|
||||
section.emit_varint(wasm.start_index);
|
||||
section.emit_u32v(wasm.start_index);
|
||||
});
|
||||
}
|
||||
|
||||
@ -322,9 +376,9 @@ class WasmModuleBuilder {
|
||||
section.emit_u8(kExprI32Const);
|
||||
section.emit_u8(0);
|
||||
section.emit_u8(kExprEnd);
|
||||
section.emit_varint(wasm.table.length);
|
||||
section.emit_u32v(wasm.table.length);
|
||||
for (let index of wasm.table) {
|
||||
section.emit_varint(index);
|
||||
section.emit_u32v(index);
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -334,7 +388,7 @@ class WasmModuleBuilder {
|
||||
// emit function bodies
|
||||
if (debug) print("emitting code @ " + binary.length);
|
||||
binary.emit_section(kCodeSectionCode, section => {
|
||||
section.emit_varint(wasm.functions.length);
|
||||
section.emit_u32v(wasm.functions.length);
|
||||
for (let func of wasm.functions) {
|
||||
// Function body length will be patched later.
|
||||
let local_decls = [];
|
||||
@ -356,13 +410,13 @@ class WasmModuleBuilder {
|
||||
}
|
||||
|
||||
let header = new Binary;
|
||||
header.emit_varint(local_decls.length);
|
||||
header.emit_u32v(local_decls.length);
|
||||
for (let decl of local_decls) {
|
||||
header.emit_varint(decl.count);
|
||||
header.emit_u32v(decl.count);
|
||||
header.emit_u8(decl.type);
|
||||
}
|
||||
|
||||
section.emit_varint(header.length + func.body.length);
|
||||
section.emit_u32v(header.length + func.body.length);
|
||||
section.emit_bytes(header);
|
||||
section.emit_bytes(func.body);
|
||||
}
|
||||
@ -373,13 +427,13 @@ class WasmModuleBuilder {
|
||||
if (wasm.segments.length > 0) {
|
||||
if (debug) print("emitting data segments @ " + binary.length);
|
||||
binary.emit_section(kDataSectionCode, section => {
|
||||
section.emit_varint(wasm.segments.length);
|
||||
section.emit_u32v(wasm.segments.length);
|
||||
for (let seg of wasm.segments) {
|
||||
section.emit_u8(0); // linear memory index 0
|
||||
section.emit_u8(kExprI32Const);
|
||||
section.emit_varint(seg.addr);
|
||||
section.emit_u32v(seg.addr);
|
||||
section.emit_u8(kExprEnd);
|
||||
section.emit_varint(seg.data.length);
|
||||
section.emit_u32v(seg.data.length);
|
||||
section.emit_bytes(seg.data);
|
||||
}
|
||||
});
|
||||
@ -396,7 +450,7 @@ class WasmModuleBuilder {
|
||||
if (debug) print("emitting names @ " + binary.length);
|
||||
binary.emit_section(kUnknownSectionCode, section => {
|
||||
section.emit_string("name");
|
||||
section.emit_varint(wasm.functions.length);
|
||||
section.emit_u32v(wasm.functions.length);
|
||||
for (let func of wasm.functions) {
|
||||
var name = func.name == undefined ? "" : func.name;
|
||||
section.emit_string(name);
|
||||
|
@ -1283,7 +1283,7 @@ class TestModuleEnv : public ModuleEnv {
|
||||
module = &mod;
|
||||
}
|
||||
byte AddGlobal(LocalType type, bool mutability = true) {
|
||||
mod.globals.push_back({type, mutability, NO_INIT, 0, false, false});
|
||||
mod.globals.push_back({type, mutability, WasmInitExpr(), 0, false, false});
|
||||
CHECK(mod.globals.size() <= 127);
|
||||
return static_cast<byte>(mod.globals.size() - 1);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user