зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1310949: Tighten Global parsing/decoding; r=luke
MozReview-Commit-ID: 4AVFOFWlgub --HG-- rename : js/src/asmjs/WasmBinary.cpp => js/src/asmjs/WasmBinaryFormat.cpp extra : rebase_source : ac85ca85277beb0fb07f18fb3676da30d11b49e2
This commit is contained in:
Родитель
a738b37621
Коммит
7d330e2dd1
|
@ -29,6 +29,7 @@
|
|||
|
||||
#include "jswrapper.h"
|
||||
|
||||
#include "asmjs/WasmBinaryFormat.h"
|
||||
#include "asmjs/WasmGenerator.h"
|
||||
#include "asmjs/WasmInstance.h"
|
||||
#include "asmjs/WasmJS.h"
|
||||
|
|
|
@ -595,21 +595,21 @@ class AstFunc : public AstNode
|
|||
class AstGlobal : public AstNode
|
||||
{
|
||||
AstName name_;
|
||||
uint32_t flags_;
|
||||
bool isMutable_;
|
||||
ValType type_;
|
||||
Maybe<AstExpr*> init_;
|
||||
|
||||
public:
|
||||
AstGlobal() : flags_(0), type_(ValType::Limit)
|
||||
AstGlobal() : isMutable_(false), type_(ValType::Limit)
|
||||
{}
|
||||
|
||||
explicit AstGlobal(AstName name, ValType type, uint32_t flags,
|
||||
explicit AstGlobal(AstName name, ValType type, bool isMutable,
|
||||
Maybe<AstExpr*> init = Maybe<AstExpr*>())
|
||||
: name_(name), flags_(flags), type_(type), init_(init)
|
||||
: name_(name), isMutable_(isMutable), type_(type), init_(init)
|
||||
{}
|
||||
|
||||
AstName name() const { return name_; }
|
||||
uint32_t flags() const { return flags_; }
|
||||
bool isMutable() const { return isMutable_; }
|
||||
ValType type() const { return type_; }
|
||||
|
||||
bool hasInit() const { return !!init_; }
|
||||
|
|
|
@ -94,6 +94,7 @@
|
|||
|
||||
#include "mozilla/MathAlgorithms.h"
|
||||
|
||||
#include "asmjs/WasmBinaryFormat.h"
|
||||
#include "asmjs/WasmBinaryIterator.h"
|
||||
#include "asmjs/WasmGenerator.h"
|
||||
#include "asmjs/WasmSignalHandlers.h"
|
||||
|
|
|
@ -41,146 +41,10 @@ Decoder::fail(const char* msg, ...) {
|
|||
bool
|
||||
Decoder::fail(UniqueChars msg) {
|
||||
MOZ_ASSERT(error_);
|
||||
UniqueChars strWithOffset(JS_smprintf("at offset %" PRIuSIZE ": %s",
|
||||
currentOffset(), msg.get()));
|
||||
UniqueChars strWithOffset(JS_smprintf("at offset %" PRIuSIZE ": %s", currentOffset(), msg.get()));
|
||||
if (!strWithOffset)
|
||||
return false;
|
||||
|
||||
*error_ = Move(strWithOffset);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
wasm::DecodePreamble(Decoder& d)
|
||||
{
|
||||
uint32_t u32;
|
||||
if (!d.readFixedU32(&u32) || u32 != MagicNumber)
|
||||
return d.fail("failed to match magic number");
|
||||
|
||||
if (!d.readFixedU32(&u32) || u32 != EncodingVersion)
|
||||
return d.fail("binary version 0x%" PRIx32 " does not match expected version 0x%" PRIx32,
|
||||
u32, EncodingVersion);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
wasm::EncodeLocalEntries(Encoder& e, const ValTypeVector& locals)
|
||||
{
|
||||
uint32_t numLocalEntries = 0;
|
||||
ValType prev = ValType::Limit;
|
||||
for (ValType t : locals) {
|
||||
if (t != prev) {
|
||||
numLocalEntries++;
|
||||
prev = t;
|
||||
}
|
||||
}
|
||||
|
||||
if (!e.writeVarU32(numLocalEntries))
|
||||
return false;
|
||||
|
||||
if (numLocalEntries) {
|
||||
prev = locals[0];
|
||||
uint32_t count = 1;
|
||||
for (uint32_t i = 1; i < locals.length(); i++, count++) {
|
||||
if (prev != locals[i]) {
|
||||
if (!e.writeVarU32(count))
|
||||
return false;
|
||||
if (!e.writeValType(prev))
|
||||
return false;
|
||||
prev = locals[i];
|
||||
count = 0;
|
||||
}
|
||||
}
|
||||
if (!e.writeVarU32(count))
|
||||
return false;
|
||||
if (!e.writeValType(prev))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
wasm::DecodeLocalEntries(Decoder& d, ValTypeVector* locals)
|
||||
{
|
||||
uint32_t numLocalEntries;
|
||||
if (!d.readVarU32(&numLocalEntries))
|
||||
return false;
|
||||
|
||||
for (uint32_t i = 0; i < numLocalEntries; i++) {
|
||||
uint32_t count;
|
||||
if (!d.readVarU32(&count))
|
||||
return false;
|
||||
|
||||
if (MaxLocals - locals->length() < count)
|
||||
return false;
|
||||
|
||||
ValType type;
|
||||
if (!d.readValType(&type))
|
||||
return false;
|
||||
|
||||
if (!locals->appendN(type, count))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
wasm::DecodeGlobalType(Decoder& d, ValType* type, uint32_t* flags)
|
||||
{
|
||||
if (!d.readValType(type))
|
||||
return d.fail("bad global type");
|
||||
|
||||
if (!d.readVarU32(flags))
|
||||
return d.fail("expected global flags");
|
||||
|
||||
if (*flags & ~uint32_t(GlobalFlags::AllowedMask))
|
||||
return d.fail("unexpected bits set in global flags");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
wasm::DecodeLimits(Decoder& d, Limits* limits)
|
||||
{
|
||||
uint32_t flags;
|
||||
if (!d.readVarU32(&flags))
|
||||
return d.fail("expected flags");
|
||||
|
||||
// TODO (bug 1310149): tighten this check (s/3/1) when the AngryBots demo
|
||||
// gets updated.
|
||||
if (flags & ~uint32_t(0x3))
|
||||
return d.fail("unexpected bits set in flags: %" PRIu32, (flags & ~uint32_t(0x3)));
|
||||
|
||||
if (!d.readVarU32(&limits->initial))
|
||||
return d.fail("expected initial length");
|
||||
|
||||
if (flags & 0x1) {
|
||||
uint32_t maximum;
|
||||
if (!d.readVarU32(&maximum))
|
||||
return d.fail("expected maximum length");
|
||||
|
||||
if (limits->initial > maximum) {
|
||||
return d.fail("memory size minimum must not be greater than maximum; "
|
||||
"maximum length %" PRIu32 " is less than initial length %" PRIu32 ,
|
||||
maximum, limits->initial);
|
||||
}
|
||||
|
||||
limits->maximum.emplace(maximum);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
wasm::DecodeUnknownSections(Decoder& d)
|
||||
{
|
||||
while (!d.done()) {
|
||||
if (!d.skipUserDefinedSection())
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -109,6 +109,8 @@ enum class ValType
|
|||
Limit
|
||||
};
|
||||
|
||||
typedef Vector<ValType, 8, SystemAllocPolicy> ValTypeVector;
|
||||
|
||||
enum class TypeConstructor
|
||||
{
|
||||
AnyFunc = 0x20,
|
||||
|
@ -1072,31 +1074,6 @@ class Decoder
|
|||
}
|
||||
};
|
||||
|
||||
// Reusable macro encoding/decoding functions reused by both the two
|
||||
// encoders (AsmJS/WasmText) and decoders (Wasm/WasmIonCompile).
|
||||
|
||||
typedef Vector<ValType, 8, SystemAllocPolicy> ValTypeVector;
|
||||
|
||||
MOZ_MUST_USE bool
|
||||
DecodePreamble(Decoder& d);
|
||||
|
||||
MOZ_MUST_USE bool
|
||||
EncodeLocalEntries(Encoder& d, const ValTypeVector& locals);
|
||||
|
||||
MOZ_MUST_USE bool
|
||||
DecodeLocalEntries(Decoder& d, ValTypeVector* locals);
|
||||
|
||||
MOZ_MUST_USE bool
|
||||
DecodeGlobalType(Decoder& d, ValType* type, uint32_t* flags);
|
||||
|
||||
struct Limits;
|
||||
|
||||
MOZ_MUST_USE bool
|
||||
DecodeLimits(Decoder& d, Limits* limits);
|
||||
|
||||
MOZ_MUST_USE bool
|
||||
DecodeUnknownSections(Decoder& d);
|
||||
|
||||
} // namespace wasm
|
||||
} // namespace js
|
||||
|
||||
|
|
|
@ -0,0 +1,222 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sts=4 et sw=4 tw=99:
|
||||
*
|
||||
* Copyright 2016 Mozilla Foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "asmjs/WasmBinaryFormat.h"
|
||||
|
||||
using namespace js;
|
||||
using namespace js::wasm;
|
||||
|
||||
bool
|
||||
wasm::DecodePreamble(Decoder& d)
|
||||
{
|
||||
uint32_t u32;
|
||||
if (!d.readFixedU32(&u32) || u32 != MagicNumber)
|
||||
return d.fail("failed to match magic number");
|
||||
|
||||
if (!d.readFixedU32(&u32) || u32 != EncodingVersion)
|
||||
return d.fail("binary version 0x%" PRIx32 " does not match expected version 0x%" PRIx32,
|
||||
u32, EncodingVersion);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
wasm::EncodeLocalEntries(Encoder& e, const ValTypeVector& locals)
|
||||
{
|
||||
uint32_t numLocalEntries = 0;
|
||||
ValType prev = ValType::Limit;
|
||||
for (ValType t : locals) {
|
||||
if (t != prev) {
|
||||
numLocalEntries++;
|
||||
prev = t;
|
||||
}
|
||||
}
|
||||
|
||||
if (!e.writeVarU32(numLocalEntries))
|
||||
return false;
|
||||
|
||||
if (numLocalEntries) {
|
||||
prev = locals[0];
|
||||
uint32_t count = 1;
|
||||
for (uint32_t i = 1; i < locals.length(); i++, count++) {
|
||||
if (prev != locals[i]) {
|
||||
if (!e.writeVarU32(count))
|
||||
return false;
|
||||
if (!e.writeValType(prev))
|
||||
return false;
|
||||
prev = locals[i];
|
||||
count = 0;
|
||||
}
|
||||
}
|
||||
if (!e.writeVarU32(count))
|
||||
return false;
|
||||
if (!e.writeValType(prev))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
wasm::DecodeLocalEntries(Decoder& d, ValTypeVector* locals)
|
||||
{
|
||||
uint32_t numLocalEntries;
|
||||
if (!d.readVarU32(&numLocalEntries))
|
||||
return false;
|
||||
|
||||
for (uint32_t i = 0; i < numLocalEntries; i++) {
|
||||
uint32_t count;
|
||||
if (!d.readVarU32(&count))
|
||||
return false;
|
||||
|
||||
if (MaxLocals - locals->length() < count)
|
||||
return false;
|
||||
|
||||
ValType type;
|
||||
if (!d.readValType(&type))
|
||||
return false;
|
||||
|
||||
if (!locals->appendN(type, count))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
wasm::DecodeGlobalType(Decoder& d, ValType* type, bool* isMutable)
|
||||
{
|
||||
if (!d.readValType(type))
|
||||
return d.fail("bad global type");
|
||||
|
||||
uint32_t flags;
|
||||
if (!d.readVarU32(&flags))
|
||||
return d.fail("expected global flags");
|
||||
|
||||
if (flags & ~uint32_t(GlobalFlags::AllowedMask))
|
||||
return d.fail("unexpected bits set in global flags");
|
||||
|
||||
*isMutable = flags & uint32_t(GlobalFlags::IsMutable);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
wasm::DecodeInitializerExpression(Decoder& d, const GlobalDescVector& globals, ValType expected,
|
||||
InitExpr* init)
|
||||
{
|
||||
Expr expr;
|
||||
if (!d.readExpr(&expr))
|
||||
return d.fail("failed to read initializer type");
|
||||
|
||||
switch (expr) {
|
||||
case Expr::I32Const: {
|
||||
int32_t i32;
|
||||
if (!d.readVarS32(&i32))
|
||||
return d.fail("failed to read initializer i32 expression");
|
||||
*init = InitExpr(Val(uint32_t(i32)));
|
||||
break;
|
||||
}
|
||||
case Expr::I64Const: {
|
||||
int64_t i64;
|
||||
if (!d.readVarS64(&i64))
|
||||
return d.fail("failed to read initializer i64 expression");
|
||||
*init = InitExpr(Val(uint64_t(i64)));
|
||||
break;
|
||||
}
|
||||
case Expr::F32Const: {
|
||||
RawF32 f32;
|
||||
if (!d.readFixedF32(&f32))
|
||||
return d.fail("failed to read initializer f32 expression");
|
||||
*init = InitExpr(Val(f32));
|
||||
break;
|
||||
}
|
||||
case Expr::F64Const: {
|
||||
RawF64 f64;
|
||||
if (!d.readFixedF64(&f64))
|
||||
return d.fail("failed to read initializer f64 expression");
|
||||
*init = InitExpr(Val(f64));
|
||||
break;
|
||||
}
|
||||
case Expr::GetGlobal: {
|
||||
uint32_t i;
|
||||
if (!d.readVarU32(&i))
|
||||
return d.fail("failed to read get_global index in initializer expression");
|
||||
if (i >= globals.length())
|
||||
return d.fail("global index out of range in initializer expression");
|
||||
if (!globals[i].isImport() || globals[i].isMutable())
|
||||
return d.fail("initializer expression must reference a global immutable import");
|
||||
*init = InitExpr(i, globals[i].type());
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
return d.fail("unexpected initializer expression");
|
||||
}
|
||||
}
|
||||
|
||||
if (expected != init->type())
|
||||
return d.fail("type mismatch: initializer type and expected type don't match");
|
||||
|
||||
Expr end;
|
||||
if (!d.readExpr(&end) || end != Expr::End)
|
||||
return d.fail("failed to read end of initializer expression");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
wasm::DecodeLimits(Decoder& d, Limits* limits)
|
||||
{
|
||||
uint32_t flags;
|
||||
if (!d.readVarU32(&flags))
|
||||
return d.fail("expected flags");
|
||||
|
||||
// TODO (bug 1310149): tighten this check (s/3/1) when the AngryBots demo
|
||||
// gets updated.
|
||||
if (flags & ~uint32_t(0x3))
|
||||
return d.fail("unexpected bits set in flags: %" PRIu32, (flags & ~uint32_t(0x3)));
|
||||
|
||||
if (!d.readVarU32(&limits->initial))
|
||||
return d.fail("expected initial length");
|
||||
|
||||
if (flags & 0x1) {
|
||||
uint32_t maximum;
|
||||
if (!d.readVarU32(&maximum))
|
||||
return d.fail("expected maximum length");
|
||||
|
||||
if (limits->initial > maximum) {
|
||||
return d.fail("memory size minimum must not be greater than maximum; "
|
||||
"maximum length %" PRIu32 " is less than initial length %" PRIu32,
|
||||
maximum, limits->initial);
|
||||
}
|
||||
|
||||
limits->maximum.emplace(maximum);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
wasm::DecodeUnknownSections(Decoder& d)
|
||||
{
|
||||
while (!d.done()) {
|
||||
if (!d.skipUserDefinedSection())
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sts=4 et sw=4 tw=99:
|
||||
*
|
||||
* Copyright 2016 Mozilla Foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef wasm_binary_format_h
|
||||
#define wasm_binary_format_h
|
||||
|
||||
#include "asmjs/WasmBinary.h"
|
||||
#include "asmjs/WasmTypes.h"
|
||||
|
||||
namespace js {
|
||||
namespace wasm {
|
||||
|
||||
// Reusable macro encoding/decoding functions reused by both the two
|
||||
// encoders (AsmJS/WasmTextToBinary) and all the decoders
|
||||
// (WasmCompile/WasmIonCompile/WasmBaselineCompile/WasmBinaryToText).
|
||||
|
||||
MOZ_MUST_USE bool
|
||||
DecodePreamble(Decoder& d);
|
||||
|
||||
MOZ_MUST_USE bool
|
||||
EncodeLocalEntries(Encoder& d, const ValTypeVector& locals);
|
||||
|
||||
MOZ_MUST_USE bool
|
||||
DecodeLocalEntries(Decoder& d, ValTypeVector* locals);
|
||||
|
||||
MOZ_MUST_USE bool
|
||||
DecodeGlobalType(Decoder& d, ValType* type, bool* isMutable);
|
||||
|
||||
MOZ_MUST_USE bool
|
||||
DecodeInitializerExpression(Decoder& d, const GlobalDescVector& globals, ValType expected,
|
||||
InitExpr* init);
|
||||
|
||||
MOZ_MUST_USE bool
|
||||
DecodeLimits(Decoder& d, Limits* limits);
|
||||
|
||||
MOZ_MUST_USE bool
|
||||
DecodeUnknownSections(Decoder& d);
|
||||
|
||||
} // namespace wasm
|
||||
} // namespace js
|
||||
|
||||
#endif // wasm_binary_format_h
|
|
@ -24,6 +24,7 @@
|
|||
|
||||
#include "jscntxt.h"
|
||||
|
||||
#include "asmjs/WasmBinaryFormat.h"
|
||||
#include "asmjs/WasmBinaryIterator.h"
|
||||
|
||||
using namespace js;
|
||||
|
@ -1599,15 +1600,12 @@ AstDecodeImport(AstDecodeContext& c, uint32_t importIndex, AstImport** import)
|
|||
}
|
||||
case uint32_t(DefinitionKind::Global): {
|
||||
ValType type;
|
||||
if (!c.d.readValType(&type))
|
||||
return false;
|
||||
|
||||
uint32_t flags;
|
||||
if (!c.d.readVarU32(&flags))
|
||||
bool isMutable;
|
||||
if (!DecodeGlobalType(c.d, &type, &isMutable))
|
||||
return false;
|
||||
|
||||
*import = new(c.lifo) AstImport(importName, moduleName, fieldName,
|
||||
AstGlobal(importName, type, flags));
|
||||
AstGlobal(importName, type, isMutable));
|
||||
break;
|
||||
}
|
||||
case uint32_t(DefinitionKind::Table): {
|
||||
|
@ -1768,15 +1766,15 @@ AstDecodeGlobal(AstDecodeContext& c, uint32_t i, AstGlobal* global)
|
|||
return false;
|
||||
|
||||
ValType type;
|
||||
uint32_t flags;
|
||||
if (!DecodeGlobalType(c.d, &type, &flags))
|
||||
bool isMutable;
|
||||
if (!DecodeGlobalType(c.d, &type, &isMutable))
|
||||
return false;
|
||||
|
||||
AstExpr* init;
|
||||
if (!AstDecodeInitializerExpression(c, &init, type))
|
||||
return c.d.fail("missing initializer expression");
|
||||
|
||||
*global = AstGlobal(name, type, flags, Some(init));
|
||||
*global = AstGlobal(name, type, isMutable, Some(init));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
|
||||
#include "jsprf.h"
|
||||
|
||||
#include "asmjs/WasmBinaryFormat.h"
|
||||
#include "asmjs/WasmBinaryIterator.h"
|
||||
#include "asmjs/WasmGenerator.h"
|
||||
#include "asmjs/WasmSignalHandlers.h"
|
||||
|
@ -712,10 +713,9 @@ DecodeImport(Decoder& d, ModuleGeneratorData* init, ImportVector* imports)
|
|||
}
|
||||
case DefinitionKind::Global: {
|
||||
ValType type;
|
||||
uint32_t flags;
|
||||
if (!DecodeGlobalType(d, &type, &flags))
|
||||
bool isMutable;
|
||||
if (!DecodeGlobalType(d, &type, &isMutable))
|
||||
return false;
|
||||
bool isMutable = flags & uint32_t(GlobalFlags::IsMutable);
|
||||
if (!GlobalIsJSCompatible(d, type, isMutable))
|
||||
return false;
|
||||
if (!init->globals.append(GlobalDesc(type, isMutable, init->globals.length())))
|
||||
|
@ -806,69 +806,6 @@ DecodeMemorySection(Decoder& d, ModuleGeneratorData* init, bool* exported)
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
DecodeInitializerExpression(Decoder& d, const GlobalDescVector& globals, ValType expected,
|
||||
InitExpr* init)
|
||||
{
|
||||
Expr expr;
|
||||
if (!d.readExpr(&expr))
|
||||
return d.fail("failed to read initializer type");
|
||||
|
||||
switch (expr) {
|
||||
case Expr::I32Const: {
|
||||
int32_t i32;
|
||||
if (!d.readVarS32(&i32))
|
||||
return d.fail("failed to read initializer i32 expression");
|
||||
*init = InitExpr(Val(uint32_t(i32)));
|
||||
break;
|
||||
}
|
||||
case Expr::I64Const: {
|
||||
int64_t i64;
|
||||
if (!d.readVarS64(&i64))
|
||||
return d.fail("failed to read initializer i64 expression");
|
||||
*init = InitExpr(Val(uint64_t(i64)));
|
||||
break;
|
||||
}
|
||||
case Expr::F32Const: {
|
||||
RawF32 f32;
|
||||
if (!d.readFixedF32(&f32))
|
||||
return d.fail("failed to read initializer f32 expression");
|
||||
*init = InitExpr(Val(f32));
|
||||
break;
|
||||
}
|
||||
case Expr::F64Const: {
|
||||
RawF64 f64;
|
||||
if (!d.readFixedF64(&f64))
|
||||
return d.fail("failed to read initializer f64 expression");
|
||||
*init = InitExpr(Val(f64));
|
||||
break;
|
||||
}
|
||||
case Expr::GetGlobal: {
|
||||
uint32_t i;
|
||||
if (!d.readVarU32(&i))
|
||||
return d.fail("failed to read get_global index in initializer expression");
|
||||
if (i >= globals.length())
|
||||
return d.fail("global index out of range in initializer expression");
|
||||
if (!globals[i].isImport() || globals[i].isMutable())
|
||||
return d.fail("initializer expression must reference a global immutable import");
|
||||
*init = InitExpr(i, globals[i].type());
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
return d.fail("unexpected initializer expression");
|
||||
}
|
||||
}
|
||||
|
||||
if (expected != init->type())
|
||||
return d.fail("type mismatch: initializer type and expected type don't match");
|
||||
|
||||
Expr end;
|
||||
if (!d.readExpr(&end) || end != Expr::End)
|
||||
return d.fail("failed to read end of initializer expression");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
DecodeGlobalSection(Decoder& d, ModuleGeneratorData* init)
|
||||
{
|
||||
|
@ -887,15 +824,14 @@ DecodeGlobalSection(Decoder& d, ModuleGeneratorData* init)
|
|||
|
||||
for (uint32_t i = 0; i < numGlobals; i++) {
|
||||
ValType type;
|
||||
uint32_t flags;
|
||||
if (!DecodeGlobalType(d, &type, &flags))
|
||||
bool isMutable;
|
||||
if (!DecodeGlobalType(d, &type, &isMutable))
|
||||
return false;
|
||||
|
||||
InitExpr initializer;
|
||||
if (!DecodeInitializerExpression(d, init->globals, type, &initializer))
|
||||
return false;
|
||||
|
||||
bool isMutable = flags & uint32_t(GlobalFlags::IsMutable);
|
||||
if (!init->globals.append(GlobalDesc(initializer, isMutable)))
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "mozilla/MathAlgorithms.h"
|
||||
|
||||
#include "asmjs/WasmBaselineCompile.h"
|
||||
#include "asmjs/WasmBinaryFormat.h"
|
||||
#include "asmjs/WasmBinaryIterator.h"
|
||||
#include "asmjs/WasmGenerator.h"
|
||||
#include "asmjs/WasmSignalHandlers.h"
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
#include "jsstr.h"
|
||||
|
||||
#include "asmjs/WasmAST.h"
|
||||
#include "asmjs/WasmBinary.h"
|
||||
#include "asmjs/WasmBinaryFormat.h"
|
||||
#include "asmjs/WasmTypes.h"
|
||||
#include "ds/LifoAlloc.h"
|
||||
#include "js/CharacterEncoding.h"
|
||||
|
@ -2844,12 +2844,14 @@ ParseStartFunc(WasmParseContext& c, WasmToken token, AstModule* module)
|
|||
}
|
||||
|
||||
static bool
|
||||
ParseGlobalType(WasmParseContext& c, WasmToken* typeToken, uint32_t* flags)
|
||||
ParseGlobalType(WasmParseContext& c, WasmToken* typeToken, bool* isMutable)
|
||||
{
|
||||
*isMutable = false;
|
||||
|
||||
// Either (mut i32) or i32.
|
||||
if (c.ts.getIf(WasmToken::OpenParen)) {
|
||||
// Immutable by default.
|
||||
*flags = c.ts.getIf(WasmToken::Mutable) ? 0x1 : 0x0;
|
||||
*isMutable = c.ts.getIf(WasmToken::Mutable);
|
||||
if (!c.ts.match(WasmToken::ValueType, typeToken, c.error))
|
||||
return false;
|
||||
if (!c.ts.match(WasmToken::CloseParen, c.error))
|
||||
|
@ -2919,14 +2921,14 @@ ParseImport(WasmParseContext& c, AstModule* module)
|
|||
name = c.ts.getIfName();
|
||||
|
||||
WasmToken typeToken;
|
||||
uint32_t flags = 0;
|
||||
if (!ParseGlobalType(c, &typeToken, &flags))
|
||||
bool isMutable;
|
||||
if (!ParseGlobalType(c, &typeToken, &isMutable))
|
||||
return nullptr;
|
||||
if (!c.ts.match(WasmToken::CloseParen, c.error))
|
||||
return nullptr;
|
||||
|
||||
return new(c.lifo) AstImport(name, moduleName.text(), fieldName.text(),
|
||||
AstGlobal(AstName(), typeToken.valueType(), flags));
|
||||
AstGlobal(AstName(), typeToken.valueType(), isMutable));
|
||||
}
|
||||
if (c.ts.getIf(WasmToken::Func)) {
|
||||
if (name.empty())
|
||||
|
@ -3156,7 +3158,7 @@ ParseGlobal(WasmParseContext& c, AstModule* module)
|
|||
AstName name = c.ts.getIfName();
|
||||
|
||||
WasmToken typeToken;
|
||||
uint32_t flags = 0;
|
||||
bool isMutable;
|
||||
|
||||
WasmToken openParen;
|
||||
if (c.ts.getIf(WasmToken::OpenParen, &openParen)) {
|
||||
|
@ -3172,11 +3174,12 @@ ParseGlobal(WasmParseContext& c, AstModule* module)
|
|||
if (!c.ts.match(WasmToken::CloseParen, c.error))
|
||||
return false;
|
||||
|
||||
if (!ParseGlobalType(c, &typeToken, &flags))
|
||||
if (!ParseGlobalType(c, &typeToken, &isMutable))
|
||||
return false;
|
||||
|
||||
auto* imp = new(c.lifo) AstImport(name, names.module.text(), names.field.text(),
|
||||
AstGlobal(AstName(), typeToken.valueType(), flags));
|
||||
AstGlobal(AstName(), typeToken.valueType(),
|
||||
isMutable));
|
||||
return imp && module->append(imp);
|
||||
}
|
||||
|
||||
|
@ -3193,14 +3196,14 @@ ParseGlobal(WasmParseContext& c, AstModule* module)
|
|||
}
|
||||
}
|
||||
|
||||
if (!ParseGlobalType(c, &typeToken, &flags))
|
||||
if (!ParseGlobalType(c, &typeToken, &isMutable))
|
||||
return false;
|
||||
|
||||
AstExpr* init = ParseExpr(c, true);
|
||||
if (!init)
|
||||
return false;
|
||||
|
||||
auto* glob = new(c.lifo) AstGlobal(name, typeToken.valueType(), flags, Some(init));
|
||||
auto* glob = new(c.lifo) AstGlobal(name, typeToken.valueType(), isMutable, Some(init));
|
||||
return glob && module->append(glob);
|
||||
}
|
||||
|
||||
|
@ -4310,6 +4313,13 @@ EncodeTableLimits(Encoder& e, const Limits& limits)
|
|||
return EncodeLimits(e, limits);
|
||||
}
|
||||
|
||||
static bool
|
||||
EncodeGlobalType(Encoder& e, const AstGlobal* global)
|
||||
{
|
||||
return e.writeValType(global->type()) &&
|
||||
e.writeVarU32(global->isMutable() ? uint32_t(GlobalFlags::IsMutable) : 0);
|
||||
}
|
||||
|
||||
static bool
|
||||
EncodeImport(Encoder& e, AstImport& imp)
|
||||
{
|
||||
|
@ -4329,9 +4339,7 @@ EncodeImport(Encoder& e, AstImport& imp)
|
|||
break;
|
||||
case DefinitionKind::Global:
|
||||
MOZ_ASSERT(!imp.global().hasInit());
|
||||
if (!e.writeValType(imp.global().type()))
|
||||
return false;
|
||||
if (!e.writeVarU32(imp.global().flags()))
|
||||
if (!EncodeGlobalType(e, &imp.global()))
|
||||
return false;
|
||||
break;
|
||||
case DefinitionKind::Table:
|
||||
|
@ -4406,9 +4414,7 @@ EncodeGlobalSection(Encoder& e, AstModule& module)
|
|||
|
||||
for (const AstGlobal* global : globals) {
|
||||
MOZ_ASSERT(global->hasInit());
|
||||
if (!e.writeValType(global->type()))
|
||||
return false;
|
||||
if (!e.writeVarU32(global->flags()))
|
||||
if (!EncodeGlobalType(e, global))
|
||||
return false;
|
||||
if (!EncodeExpr(e, global->init()))
|
||||
return false;
|
||||
|
|
|
@ -157,6 +157,7 @@ UNIFIED_SOURCES += [
|
|||
'asmjs/AsmJS.cpp',
|
||||
'asmjs/WasmBaselineCompile.cpp',
|
||||
'asmjs/WasmBinary.cpp',
|
||||
'asmjs/WasmBinaryFormat.cpp',
|
||||
'asmjs/WasmBinaryIterator.cpp',
|
||||
'asmjs/WasmBinaryToAST.cpp',
|
||||
'asmjs/WasmBinaryToExperimentalText.cpp',
|
||||
|
|
Загрузка…
Ссылка в новой задаче