зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1311994 - Baldr: add flags immediates to current_memory/grow_memory/call_indirect (r=sunfish)
MozReview-Commit-ID: 4qwtPliyesH --HG-- extra : rebase_source : a853549266fb1c3c763b90680eb5637e1cc13cb5
This commit is contained in:
Родитель
440f0a594e
Коммит
b615e9b281
|
@ -195,10 +195,12 @@ enum class AstExprKind
|
|||
ComparisonOperator,
|
||||
Const,
|
||||
ConversionOperator,
|
||||
CurrentMemory,
|
||||
Drop,
|
||||
First,
|
||||
GetGlobal,
|
||||
GetLocal,
|
||||
GrowMemory,
|
||||
If,
|
||||
Load,
|
||||
Nop,
|
||||
|
@ -210,7 +212,6 @@ enum class AstExprKind
|
|||
Store,
|
||||
TernaryOperator,
|
||||
UnaryOperator,
|
||||
NullaryOperator,
|
||||
Unreachable
|
||||
};
|
||||
|
||||
|
@ -545,6 +546,28 @@ class AstStore : public AstExpr
|
|||
AstExpr& value() const { return *value_; }
|
||||
};
|
||||
|
||||
class AstCurrentMemory final : public AstExpr
|
||||
{
|
||||
public:
|
||||
static const AstExprKind Kind = AstExprKind::CurrentMemory;
|
||||
explicit AstCurrentMemory()
|
||||
: AstExpr(Kind, ExprType::I32)
|
||||
{}
|
||||
};
|
||||
|
||||
class AstGrowMemory final : public AstExpr
|
||||
{
|
||||
AstExpr* op_;
|
||||
|
||||
public:
|
||||
static const AstExprKind Kind = AstExprKind::GrowMemory;
|
||||
explicit AstGrowMemory(AstExpr* op)
|
||||
: AstExpr(Kind, ExprType::I32), op_(op)
|
||||
{}
|
||||
|
||||
AstExpr* op() const { return op_; }
|
||||
};
|
||||
|
||||
class AstBranchTable : public AstExpr
|
||||
{
|
||||
AstExpr& index_;
|
||||
|
@ -873,20 +896,6 @@ class AstModule : public AstNode
|
|||
}
|
||||
};
|
||||
|
||||
class AstNullaryOperator final : public AstExpr
|
||||
{
|
||||
Expr expr_;
|
||||
|
||||
public:
|
||||
static const AstExprKind Kind = AstExprKind::NullaryOperator;
|
||||
explicit AstNullaryOperator(Expr expr)
|
||||
: AstExpr(Kind, ExprType::Limit),
|
||||
expr_(expr)
|
||||
{}
|
||||
|
||||
Expr expr() const { return expr_; }
|
||||
};
|
||||
|
||||
class AstUnaryOperator final : public AstExpr
|
||||
{
|
||||
Expr expr_;
|
||||
|
|
|
@ -2302,6 +2302,9 @@ class BaseCompiler
|
|||
void builtinInstanceMethodCall(SymbolicAddress builtin, const ABIArg& instanceArg,
|
||||
const FunctionCall& call)
|
||||
{
|
||||
// Builtin method calls assumed the TLS register has been set.
|
||||
loadFromFramePtr(WasmTlsReg, frameOffsetFromSlot(tlsSlot_, MIRType::Pointer));
|
||||
|
||||
CallSiteDesc desc(call.lineOrBytecode_, CallSiteDesc::Symbolic);
|
||||
masm.wasmCallBuiltinInstanceMethod(instanceArg, builtin);
|
||||
}
|
||||
|
@ -6229,23 +6232,23 @@ BaseCompiler::emitGrowMemory()
|
|||
if (deadCode_)
|
||||
return true;
|
||||
|
||||
uint32_t lineOrBytecode = readCallSiteLineOrBytecode();
|
||||
Nothing arg;
|
||||
if (!iter_.readGrowMemory(&arg))
|
||||
return false;
|
||||
|
||||
sync();
|
||||
|
||||
uint32_t numArgs = 1;
|
||||
size_t stackSpace = stackConsumed(numArgs);
|
||||
|
||||
FunctionCall baselineCall(lineOrBytecode);
|
||||
FunctionCall baselineCall(readCallSiteLineOrBytecode());
|
||||
beginCall(baselineCall, EscapesSandbox(true), IsBuiltinCall(true));
|
||||
|
||||
ABIArg instanceArg = reserveArgument(baselineCall);
|
||||
|
||||
if (!emitCallArgs(SigI_, baselineCall))
|
||||
return false;
|
||||
startCallArgs(baselineCall, stackArgAreaSize(SigI_));
|
||||
|
||||
if (!iter_.readCallReturn(ExprType::I32))
|
||||
return false;
|
||||
passArg(baselineCall, ValType::I32, peek(0));
|
||||
|
||||
builtinInstanceMethodCall(SymbolicAddress::GrowMemory, instanceArg, baselineCall);
|
||||
|
||||
|
@ -6265,20 +6268,17 @@ BaseCompiler::emitCurrentMemory()
|
|||
if (deadCode_)
|
||||
return true;
|
||||
|
||||
uint32_t lineOrBytecode = readCallSiteLineOrBytecode();
|
||||
if (!iter_.readCurrentMemory())
|
||||
return false;
|
||||
|
||||
sync();
|
||||
|
||||
FunctionCall baselineCall(lineOrBytecode);
|
||||
FunctionCall baselineCall(readCallSiteLineOrBytecode());
|
||||
beginCall(baselineCall, EscapesSandbox(true), IsBuiltinCall(true));
|
||||
|
||||
ABIArg instanceArg = reserveArgument(baselineCall);
|
||||
|
||||
if (!emitCallArgs(Sig_, baselineCall))
|
||||
return false;
|
||||
|
||||
if (!iter_.readCallReturn(ExprType::I32))
|
||||
return false;
|
||||
startCallArgs(baselineCall, stackArgAreaSize(Sig_));
|
||||
|
||||
builtinInstanceMethodCall(SymbolicAddress::CurrentMemory, instanceArg, baselineCall);
|
||||
|
||||
|
|
|
@ -153,6 +153,11 @@ enum class GlobalFlags
|
|||
AllowedMask = 0x1
|
||||
};
|
||||
|
||||
enum class MemoryTableFlags
|
||||
{
|
||||
Default = 0x0
|
||||
};
|
||||
|
||||
enum class Expr : uint32_t // fix type so we can cast from any u16 in decoder
|
||||
{
|
||||
// Control flow operators
|
||||
|
|
|
@ -110,7 +110,6 @@ wasm::Classify(Expr expr)
|
|||
case Expr::B8x16not:
|
||||
case Expr::B16x8not:
|
||||
case Expr::B32x4not:
|
||||
case Expr::GrowMemory:
|
||||
return ExprKind::Unary;
|
||||
case Expr::I32Add:
|
||||
case Expr::I32Sub:
|
||||
|
@ -491,7 +490,9 @@ wasm::Classify(Expr expr)
|
|||
case Expr::F32x4lessThanOrEqual:
|
||||
return ExprKind::SimdComparison;
|
||||
case Expr::CurrentMemory:
|
||||
return ExprKind::Nullary;
|
||||
return ExprKind::CurrentMemory;
|
||||
case Expr::GrowMemory:
|
||||
return ExprKind::GrowMemory;
|
||||
}
|
||||
MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE("unimplemented opcode");
|
||||
}
|
||||
|
|
|
@ -68,6 +68,8 @@ enum class ExprKind {
|
|||
Load,
|
||||
Store,
|
||||
TeeStore,
|
||||
CurrentMemory,
|
||||
GrowMemory,
|
||||
Select,
|
||||
GetLocal,
|
||||
SetLocal,
|
||||
|
@ -561,7 +563,8 @@ class MOZ_STACK_CLASS ExprIter : private Policy
|
|||
MOZ_MUST_USE bool readTeeStore(ValType resultType, uint32_t byteSize,
|
||||
LinearMemoryAddress<Value>* addr, Value* value);
|
||||
MOZ_MUST_USE bool readNop();
|
||||
MOZ_MUST_USE bool readNullary(ValType retType);
|
||||
MOZ_MUST_USE bool readCurrentMemory();
|
||||
MOZ_MUST_USE bool readGrowMemory(Value* input);
|
||||
MOZ_MUST_USE bool readSelect(ValType* type,
|
||||
Value* trueValue, Value* falseValue, Value* condition);
|
||||
MOZ_MUST_USE bool readGetLocal(const ValTypeVector& locals, uint32_t* id);
|
||||
|
@ -1348,13 +1351,41 @@ ExprIter<Policy>::readNop()
|
|||
|
||||
template <typename Policy>
|
||||
inline bool
|
||||
ExprIter<Policy>::readNullary(ValType retType)
|
||||
ExprIter<Policy>::readCurrentMemory()
|
||||
{
|
||||
MOZ_ASSERT(Classify(expr_) == ExprKind::Nullary);
|
||||
MOZ_ASSERT(Classify(expr_) == ExprKind::CurrentMemory);
|
||||
|
||||
if (!push(retType))
|
||||
uint32_t flags;
|
||||
if (!readVarU32(&flags))
|
||||
return false;
|
||||
|
||||
if (Validate && flags != uint32_t(MemoryTableFlags::Default))
|
||||
return fail("unexpected flags");
|
||||
|
||||
if (!push(ValType::I32))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Policy>
|
||||
inline bool
|
||||
ExprIter<Policy>::readGrowMemory(Value* input)
|
||||
{
|
||||
MOZ_ASSERT(Classify(expr_) == ExprKind::GrowMemory);
|
||||
|
||||
uint32_t flags;
|
||||
if (!readVarU32(&flags))
|
||||
return false;
|
||||
|
||||
if (Validate && flags != uint32_t(MemoryTableFlags::Default))
|
||||
return fail("unexpected flags");
|
||||
|
||||
if (!popWithType(ValType::I32, input))
|
||||
return false;
|
||||
|
||||
infalliblePush(ValType::I32);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1725,6 +1756,13 @@ ExprIter<Policy>::readCallIndirect(uint32_t* sigIndex, Value* callee)
|
|||
if (!readVarU32(sigIndex))
|
||||
return fail("unable to read call_indirect signature index");
|
||||
|
||||
uint32_t flags;
|
||||
if (!readVarU32(&flags))
|
||||
return false;
|
||||
|
||||
if (Validate && flags != uint32_t(MemoryTableFlags::Default))
|
||||
return fail("unexpected flags");
|
||||
|
||||
if (reachable_) {
|
||||
if (!popWithType(ValType::I32, callee))
|
||||
return false;
|
||||
|
|
|
@ -672,22 +672,6 @@ AstDecodeUnary(AstDecodeContext& c, ValType type, Expr expr)
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
AstDecodeNullary(AstDecodeContext& c, ValType type, Expr expr)
|
||||
{
|
||||
if (!c.iter().readNullary(type))
|
||||
return false;
|
||||
|
||||
AstNullaryOperator* nullary = new(c.lifo) AstNullaryOperator(expr);
|
||||
if (!nullary)
|
||||
return false;
|
||||
|
||||
if (!c.push(AstDecodeStackItem(nullary)))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
AstDecodeBinary(AstDecodeContext& c, ValType type, Expr expr)
|
||||
{
|
||||
|
@ -815,6 +799,40 @@ AstDecodeStore(AstDecodeContext& c, ValType type, uint32_t byteSize, Expr expr)
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
AstDecodeCurrentMemory(AstDecodeContext& c)
|
||||
{
|
||||
if (!c.iter().readCurrentMemory())
|
||||
return false;
|
||||
|
||||
AstCurrentMemory* gm = new(c.lifo) AstCurrentMemory();
|
||||
if (!gm)
|
||||
return false;
|
||||
|
||||
if (!c.push(AstDecodeStackItem(gm)))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
AstDecodeGrowMemory(AstDecodeContext& c)
|
||||
{
|
||||
if (!c.iter().readGrowMemory(nullptr))
|
||||
return false;
|
||||
|
||||
AstDecodeStackItem op = c.popCopy();
|
||||
|
||||
AstGrowMemory* gm = new(c.lifo) AstGrowMemory(op.expr);
|
||||
if (!gm)
|
||||
return false;
|
||||
|
||||
if (!c.push(AstDecodeStackItem(gm)))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
AstDecodeBranch(AstDecodeContext& c, Expr expr)
|
||||
{
|
||||
|
@ -1088,7 +1106,6 @@ AstDecodeExpr(AstDecodeContext& c)
|
|||
case Expr::I32Clz:
|
||||
case Expr::I32Ctz:
|
||||
case Expr::I32Popcnt:
|
||||
case Expr::GrowMemory:
|
||||
if (!AstDecodeUnary(c, ValType::I32, expr))
|
||||
return false;
|
||||
break;
|
||||
|
@ -1361,6 +1378,14 @@ AstDecodeExpr(AstDecodeContext& c)
|
|||
if (!AstDecodeStore(c, ValType::F64, 8, expr))
|
||||
return false;
|
||||
break;
|
||||
case Expr::CurrentMemory:
|
||||
if (!AstDecodeCurrentMemory(c))
|
||||
return false;
|
||||
break;
|
||||
case Expr::GrowMemory:
|
||||
if (!AstDecodeGrowMemory(c))
|
||||
return false;
|
||||
break;
|
||||
case Expr::SetGlobal:
|
||||
if (!AstDecodeSetGlobal(c))
|
||||
return false;
|
||||
|
@ -1382,10 +1407,6 @@ AstDecodeExpr(AstDecodeContext& c)
|
|||
if (!AstDecodeReturn(c))
|
||||
return false;
|
||||
break;
|
||||
case Expr::CurrentMemory:
|
||||
if (!AstDecodeNullary(c, ValType::I32, expr))
|
||||
return false;
|
||||
break;
|
||||
case Expr::Unreachable:
|
||||
if (!c.iter().readUnreachable())
|
||||
return false;
|
||||
|
|
|
@ -316,19 +316,6 @@ PrintBlockLevelExpr(WasmPrintContext& c, AstExpr& expr, bool isLast)
|
|||
/*****************************************************************************/
|
||||
// binary format parsing and rendering
|
||||
|
||||
static bool
|
||||
PrintNullaryOperator(WasmPrintContext& c, AstNullaryOperator& op)
|
||||
{
|
||||
const char* opStr;
|
||||
|
||||
switch (op.expr()) {
|
||||
case Expr::CurrentMemory: opStr = "curent_memory"; break;
|
||||
default: return false;
|
||||
}
|
||||
|
||||
return c.buffer.append(opStr, strlen(opStr));
|
||||
}
|
||||
|
||||
static bool
|
||||
PrintNop(WasmPrintContext& c)
|
||||
{
|
||||
|
@ -654,7 +641,6 @@ PrintUnaryOperator(WasmPrintContext& c, AstUnaryOperator& op)
|
|||
case Expr::F64Ceil: opStr = "f64.ceil"; break;
|
||||
case Expr::F64Floor: opStr = "f64.floor"; break;
|
||||
case Expr::F64Sqrt: opStr = "f64.sqrt"; break;
|
||||
case Expr::GrowMemory: opStr = "grow_memory"; break;
|
||||
default: return false;
|
||||
}
|
||||
|
||||
|
@ -1361,6 +1347,31 @@ PrintFirst(WasmPrintContext& c, AstFirst& first)
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
PrintCurrentMemory(WasmPrintContext& c, AstCurrentMemory& cm)
|
||||
{
|
||||
return c.buffer.append("current_memory");
|
||||
}
|
||||
|
||||
static bool
|
||||
PrintGrowMemory(WasmPrintContext& c, AstGrowMemory& gm)
|
||||
{
|
||||
if (!c.buffer.append("grow_memory("))
|
||||
return false;
|
||||
|
||||
PrintOperatorPrecedence lastPrecedence = c.currentPrecedence;
|
||||
c.currentPrecedence = ExpressionPrecedence;
|
||||
|
||||
if (!PrintExpr(c, *gm.op()))
|
||||
return false;
|
||||
|
||||
if (!c.buffer.append(")"))
|
||||
return false;
|
||||
|
||||
c.currentPrecedence = lastPrecedence;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
PrintExpr(WasmPrintContext& c, AstExpr& expr)
|
||||
{
|
||||
|
@ -1376,8 +1387,6 @@ PrintExpr(WasmPrintContext& c, AstExpr& expr)
|
|||
return PrintNop(c);
|
||||
case AstExprKind::Drop:
|
||||
return PrintDrop(c, expr.as<AstDrop>());
|
||||
case AstExprKind::NullaryOperator:
|
||||
return PrintNullaryOperator(c, expr.as<AstNullaryOperator>());
|
||||
case AstExprKind::Unreachable:
|
||||
return PrintUnreachable(c, expr.as<AstUnreachable>());
|
||||
case AstExprKind::Call:
|
||||
|
@ -1418,6 +1427,10 @@ PrintExpr(WasmPrintContext& c, AstExpr& expr)
|
|||
return PrintReturn(c, expr.as<AstReturn>());
|
||||
case AstExprKind::First:
|
||||
return PrintFirst(c, expr.as<AstFirst>());
|
||||
case AstExprKind::CurrentMemory:
|
||||
return PrintCurrentMemory(c, expr.as<AstCurrentMemory>());
|
||||
case AstExprKind::GrowMemory:
|
||||
return PrintGrowMemory(c, expr.as<AstGrowMemory>());
|
||||
default:
|
||||
// Note: it's important not to remove this default since readExpr()
|
||||
// can return Expr values for which there is no enumerator.
|
||||
|
|
|
@ -464,18 +464,25 @@ RenderFirst(WasmRenderContext& c, AstFirst& first)
|
|||
}
|
||||
|
||||
static bool
|
||||
RenderNullaryOperator(WasmRenderContext& c, AstNullaryOperator& op)
|
||||
RenderCurrentMemory(WasmRenderContext& c, AstCurrentMemory& cm)
|
||||
{
|
||||
if (!RenderIndent(c))
|
||||
return false;
|
||||
|
||||
const char* opStr;
|
||||
switch (op.expr()) {
|
||||
case Expr::CurrentMemory: opStr = "current_memory"; break;
|
||||
default: return false;
|
||||
}
|
||||
return c.buffer.append("current_memory\n");
|
||||
}
|
||||
|
||||
return c.buffer.append(opStr, strlen(opStr));
|
||||
static bool
|
||||
RenderGrowMemory(WasmRenderContext& c, AstGrowMemory& gm)
|
||||
{
|
||||
if (!RenderExpr(c, *gm.op()))
|
||||
return false;
|
||||
|
||||
if (!RenderIndent(c))
|
||||
return false;
|
||||
|
||||
MAP_AST_EXPR(c, gm);
|
||||
return c.buffer.append("grow_memory\n");
|
||||
}
|
||||
|
||||
static bool
|
||||
|
@ -511,7 +518,6 @@ RenderUnaryOperator(WasmRenderContext& c, AstUnaryOperator& op)
|
|||
case Expr::F64Nearest: opStr = "f64.nearest"; break;
|
||||
case Expr::F64Sqrt: opStr = "f64.sqrt"; break;
|
||||
case Expr::F64Trunc: opStr = "f64.trunc"; break;
|
||||
case Expr::GrowMemory: opStr = "grow_memory"; break;
|
||||
default: return false;
|
||||
}
|
||||
|
||||
|
@ -1049,10 +1055,6 @@ RenderExpr(WasmRenderContext& c, AstExpr& expr, bool newLine /* = true */)
|
|||
if (!RenderIf(c, expr.as<AstIf>()))
|
||||
return false;
|
||||
break;
|
||||
case AstExprKind::NullaryOperator:
|
||||
if (!RenderNullaryOperator(c, expr.as<AstNullaryOperator>()))
|
||||
return false;
|
||||
break;
|
||||
case AstExprKind::UnaryOperator:
|
||||
if (!RenderUnaryOperator(c, expr.as<AstUnaryOperator>()))
|
||||
return false;
|
||||
|
@ -1098,6 +1100,14 @@ RenderExpr(WasmRenderContext& c, AstExpr& expr, bool newLine /* = true */)
|
|||
if (!RenderFirst(c, expr.as<AstFirst>()))
|
||||
return false;
|
||||
break;
|
||||
case AstExprKind::CurrentMemory:
|
||||
if (!RenderCurrentMemory(c, expr.as<AstCurrentMemory>()))
|
||||
return false;
|
||||
break;
|
||||
case AstExprKind::GrowMemory:
|
||||
if (!RenderGrowMemory(c, expr.as<AstGrowMemory>()))
|
||||
return false;
|
||||
break;
|
||||
default:
|
||||
// Note: it's important not to remove this default since readExpr()
|
||||
// can return Expr values for which there is no enumerator.
|
||||
|
|
|
@ -408,9 +408,9 @@ DecodeFunctionBodyExprs(FunctionDecoder& f)
|
|||
case Expr::F64Store:
|
||||
CHECK(f.checkHasMemory() && f.iter().readStore(ValType::F64, 8, nullptr, nullptr));
|
||||
case Expr::GrowMemory:
|
||||
CHECK(f.checkHasMemory() && f.iter().readUnary(ValType::I32, nullptr));
|
||||
CHECK(f.checkHasMemory() && f.iter().readGrowMemory(nullptr));
|
||||
case Expr::CurrentMemory:
|
||||
CHECK(f.checkHasMemory() && f.iter().readNullary(ValType::I32));
|
||||
CHECK(f.checkHasMemory() && f.iter().readCurrentMemory());
|
||||
case Expr::Br:
|
||||
CHECK(f.iter().readBr(nullptr, nullptr, nullptr));
|
||||
case Expr::BrIf:
|
||||
|
|
|
@ -125,6 +125,8 @@ class WasmPrintBuffer
|
|||
}
|
||||
template <size_t ArrayLength>
|
||||
bool append(const char (&array)[ArrayLength]) {
|
||||
static_assert(ArrayLength > 0, "null-terminated");
|
||||
MOZ_ASSERT(array[ArrayLength - 1] == '\0');
|
||||
return append(array, ArrayLength - 1);
|
||||
}
|
||||
char16_t getChar(size_t index) {
|
||||
|
|
|
@ -3080,7 +3080,7 @@ EmitGrowMemory(FunctionCompiler& f)
|
|||
return false;
|
||||
|
||||
MDefinition* delta;
|
||||
if (!f.iter().readUnary(ValType::I32, &delta))
|
||||
if (!f.iter().readGrowMemory(&delta))
|
||||
return false;
|
||||
|
||||
if (!f.passArg(delta, ValType::I32, &args))
|
||||
|
@ -3106,7 +3106,7 @@ EmitCurrentMemory(FunctionCompiler& f)
|
|||
|
||||
CallCompileState args(f, lineOrBytecode);
|
||||
|
||||
if (!f.iter().readNullary(ValType::I32))
|
||||
if (!f.iter().readCurrentMemory())
|
||||
return false;
|
||||
|
||||
if (!f.startCall(&args))
|
||||
|
|
|
@ -78,6 +78,7 @@ class WasmToken
|
|||
ComparisonOpcode,
|
||||
Const,
|
||||
ConversionOpcode,
|
||||
CurrentMemory,
|
||||
Data,
|
||||
Drop,
|
||||
Elem,
|
||||
|
@ -92,6 +93,7 @@ class WasmToken
|
|||
GetGlobal,
|
||||
GetLocal,
|
||||
Global,
|
||||
GrowMemory,
|
||||
If,
|
||||
Import,
|
||||
Index,
|
||||
|
@ -120,7 +122,6 @@ class WasmToken
|
|||
Text,
|
||||
Then,
|
||||
Type,
|
||||
NullaryOpcode,
|
||||
UnaryOpcode,
|
||||
Unreachable,
|
||||
UnsignedInteger,
|
||||
|
@ -203,7 +204,7 @@ class WasmToken
|
|||
MOZ_ASSERT(begin != end);
|
||||
MOZ_ASSERT(kind_ == UnaryOpcode || kind_ == BinaryOpcode || kind_ == TernaryOpcode ||
|
||||
kind_ == ComparisonOpcode || kind_ == ConversionOpcode ||
|
||||
kind_ == Load || kind_ == Store || kind_ == NullaryOpcode);
|
||||
kind_ == Load || kind_ == Store);
|
||||
u.expr_ = expr;
|
||||
}
|
||||
explicit WasmToken(const char16_t* begin)
|
||||
|
@ -254,7 +255,7 @@ class WasmToken
|
|||
Expr expr() const {
|
||||
MOZ_ASSERT(kind_ == UnaryOpcode || kind_ == BinaryOpcode || kind_ == TernaryOpcode ||
|
||||
kind_ == ComparisonOpcode || kind_ == ConversionOpcode ||
|
||||
kind_ == Load || kind_ == Store || kind_ == NullaryOpcode);
|
||||
kind_ == Load || kind_ == Store);
|
||||
return u.expr_;
|
||||
}
|
||||
bool isOpcode() const {
|
||||
|
@ -269,9 +270,11 @@ class WasmToken
|
|||
case ComparisonOpcode:
|
||||
case Const:
|
||||
case ConversionOpcode:
|
||||
case CurrentMemory:
|
||||
case Drop:
|
||||
case GetGlobal:
|
||||
case GetLocal:
|
||||
case GrowMemory:
|
||||
case If:
|
||||
case Load:
|
||||
case Loop:
|
||||
|
@ -282,7 +285,6 @@ class WasmToken
|
|||
case Store:
|
||||
case TeeLocal:
|
||||
case TernaryOpcode:
|
||||
case NullaryOpcode:
|
||||
case UnaryOpcode:
|
||||
case Unreachable:
|
||||
return true;
|
||||
|
@ -854,7 +856,7 @@ WasmTokenStream::next()
|
|||
return WasmToken(WasmToken::Call, begin, cur_);
|
||||
}
|
||||
if (consume(u"current_memory"))
|
||||
return WasmToken(WasmToken::NullaryOpcode, Expr::CurrentMemory, begin, cur_);
|
||||
return WasmToken(WasmToken::CurrentMemory, begin, cur_);
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
|
@ -1091,7 +1093,7 @@ WasmTokenStream::next()
|
|||
if (consume(u"global"))
|
||||
return WasmToken(WasmToken::Global, begin, cur_);
|
||||
if (consume(u"grow_memory"))
|
||||
return WasmToken(WasmToken::UnaryOpcode, Expr::GrowMemory, begin, cur_);
|
||||
return WasmToken(WasmToken::GrowMemory, begin, cur_);
|
||||
break;
|
||||
|
||||
case 'i':
|
||||
|
@ -1406,7 +1408,7 @@ WasmTokenStream::next()
|
|||
if (consume(u"nan"))
|
||||
return nan(begin);
|
||||
if (consume(u"nop"))
|
||||
return WasmToken(WasmToken::NullaryOpcode, Expr::Nop, begin, cur_);
|
||||
return WasmToken(WasmToken::Nop, begin, cur_);
|
||||
break;
|
||||
|
||||
case 'o':
|
||||
|
@ -2088,12 +2090,6 @@ ParseUnaryOperator(WasmParseContext& c, Expr expr, bool inParens)
|
|||
return new(c.lifo) AstUnaryOperator(expr, op);
|
||||
}
|
||||
|
||||
static AstNullaryOperator*
|
||||
ParseNullaryOperator(WasmParseContext& c, Expr expr)
|
||||
{
|
||||
return new(c.lifo) AstNullaryOperator(expr);
|
||||
}
|
||||
|
||||
static AstBinaryOperator*
|
||||
ParseBinaryOperator(WasmParseContext& c, Expr expr, bool inParens)
|
||||
{
|
||||
|
@ -2381,6 +2377,16 @@ ParseBranchTable(WasmParseContext& c, WasmToken brTable, bool inParens)
|
|||
return new(c.lifo) AstBranchTable(*index, def, Move(table), value);
|
||||
}
|
||||
|
||||
static AstGrowMemory*
|
||||
ParseGrowMemory(WasmParseContext& c, bool inParens)
|
||||
{
|
||||
AstExpr* op = ParseExpr(c, inParens);
|
||||
if (!op)
|
||||
return nullptr;
|
||||
|
||||
return new(c.lifo) AstGrowMemory(op);
|
||||
}
|
||||
|
||||
static AstExpr*
|
||||
ParseExprBody(WasmParseContext& c, WasmToken token, bool inParens)
|
||||
{
|
||||
|
@ -2433,8 +2439,12 @@ ParseExprBody(WasmParseContext& c, WasmToken token, bool inParens)
|
|||
return ParseTernaryOperator(c, token.expr(), inParens);
|
||||
case WasmToken::UnaryOpcode:
|
||||
return ParseUnaryOperator(c, token.expr(), inParens);
|
||||
case WasmToken::NullaryOpcode:
|
||||
return ParseNullaryOperator(c, token.expr());
|
||||
case WasmToken::Nop:
|
||||
return new(c.lifo) AstNop();
|
||||
case WasmToken::CurrentMemory:
|
||||
return new(c.lifo) AstCurrentMemory();
|
||||
case WasmToken::GrowMemory:
|
||||
return ParseGrowMemory(c, inParens);
|
||||
default:
|
||||
c.ts.generateError(token, c.error);
|
||||
return nullptr;
|
||||
|
@ -3571,6 +3581,12 @@ ResolveUnaryOperator(Resolver& r, AstUnaryOperator& b)
|
|||
return ResolveExpr(r, *b.op());
|
||||
}
|
||||
|
||||
static bool
|
||||
ResolveGrowMemory(Resolver& r, AstGrowMemory& gm)
|
||||
{
|
||||
return ResolveExpr(r, *gm.op());
|
||||
}
|
||||
|
||||
static bool
|
||||
ResolveBinaryOperator(Resolver& r, AstBinaryOperator& b)
|
||||
{
|
||||
|
@ -3664,8 +3680,8 @@ ResolveExpr(Resolver& r, AstExpr& expr)
|
|||
switch (expr.kind()) {
|
||||
case AstExprKind::Nop:
|
||||
case AstExprKind::Pop:
|
||||
case AstExprKind::NullaryOperator:
|
||||
case AstExprKind::Unreachable:
|
||||
case AstExprKind::CurrentMemory:
|
||||
return true;
|
||||
case AstExprKind::Drop:
|
||||
return ResolveDropOperator(r, expr.as<AstDrop>());
|
||||
|
@ -3711,6 +3727,8 @@ ResolveExpr(Resolver& r, AstExpr& expr)
|
|||
return ResolveTernaryOperator(r, expr.as<AstTernaryOperator>());
|
||||
case AstExprKind::UnaryOperator:
|
||||
return ResolveUnaryOperator(r, expr.as<AstUnaryOperator>());
|
||||
case AstExprKind::GrowMemory:
|
||||
return ResolveGrowMemory(r, expr.as<AstGrowMemory>());
|
||||
}
|
||||
MOZ_CRASH("Bad expr kind");
|
||||
}
|
||||
|
@ -3930,6 +3948,9 @@ EncodeCallIndirect(Encoder& e, AstCallIndirect& c)
|
|||
if (!e.writeVarU32(c.sig().index()))
|
||||
return false;
|
||||
|
||||
if (!e.writeVarU32(uint32_t(MemoryTableFlags::Default)))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -4007,12 +4028,6 @@ EncodeUnaryOperator(Encoder& e, AstUnaryOperator& b)
|
|||
e.writeExpr(b.expr());
|
||||
}
|
||||
|
||||
static bool
|
||||
EncodeNullaryOperator(Encoder& e, AstNullaryOperator& b)
|
||||
{
|
||||
return e.writeExpr(b.expr());
|
||||
}
|
||||
|
||||
static bool
|
||||
EncodeBinaryOperator(Encoder& e, AstBinaryOperator& b)
|
||||
{
|
||||
|
@ -4139,6 +4154,33 @@ EncodeBranchTable(Encoder& e, AstBranchTable& bt)
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
EncodeCurrentMemory(Encoder& e, AstCurrentMemory& cm)
|
||||
{
|
||||
if (!e.writeExpr(Expr::CurrentMemory))
|
||||
return false;
|
||||
|
||||
if (!e.writeVarU32(uint32_t(MemoryTableFlags::Default)))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
EncodeGrowMemory(Encoder& e, AstGrowMemory& gm)
|
||||
{
|
||||
if (!EncodeExpr(e, *gm.op()))
|
||||
return false;
|
||||
|
||||
if (!e.writeExpr(Expr::GrowMemory))
|
||||
return false;
|
||||
|
||||
if (!e.writeVarU32(uint32_t(MemoryTableFlags::Default)))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
EncodeExpr(Encoder& e, AstExpr& expr)
|
||||
{
|
||||
|
@ -4193,8 +4235,10 @@ EncodeExpr(Encoder& e, AstExpr& expr)
|
|||
return EncodeTernaryOperator(e, expr.as<AstTernaryOperator>());
|
||||
case AstExprKind::UnaryOperator:
|
||||
return EncodeUnaryOperator(e, expr.as<AstUnaryOperator>());
|
||||
case AstExprKind::NullaryOperator:
|
||||
return EncodeNullaryOperator(e, expr.as<AstNullaryOperator>());
|
||||
case AstExprKind::CurrentMemory:
|
||||
return EncodeCurrentMemory(e, expr.as<AstCurrentMemory>());
|
||||
case AstExprKind::GrowMemory:
|
||||
return EncodeGrowMemory(e, expr.as<AstGrowMemory>());
|
||||
}
|
||||
MOZ_CRASH("Bad expr kind");
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче