aboutsummaryrefslogtreecommitdiff
path: root/deps/v8/src/wasm/function-body-decoder.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/wasm/function-body-decoder.cc')
-rw-r--r--deps/v8/src/wasm/function-body-decoder.cc141
1 files changed, 135 insertions, 6 deletions
diff --git a/deps/v8/src/wasm/function-body-decoder.cc b/deps/v8/src/wasm/function-body-decoder.cc
index cae2fcca78..df74485a33 100644
--- a/deps/v8/src/wasm/function-body-decoder.cc
+++ b/deps/v8/src/wasm/function-body-decoder.cc
@@ -146,6 +146,22 @@ struct Control {
}
};
+namespace {
+inline unsigned GetShuffleMaskSize(WasmOpcode opcode) {
+ switch (opcode) {
+ case kExprS32x4Shuffle:
+ return 4;
+ case kExprS16x8Shuffle:
+ return 8;
+ case kExprS8x16Shuffle:
+ return 16;
+ default:
+ UNREACHABLE();
+ return 0;
+ }
+}
+} // namespace
+
// Macros that build nodes only if there is a graph and the current SSA
// environment is reachable from start. This avoids problems with malformed
// TF graphs when decoding inputs that have unreachable code.
@@ -175,6 +191,7 @@ class WasmDecoder : public Decoder {
static bool DecodeLocals(Decoder* decoder, const FunctionSig* sig,
ZoneVector<ValueType>* type_list) {
DCHECK_NOT_NULL(type_list);
+ DCHECK_EQ(0, type_list->size());
// Initialize from signature.
if (sig != nullptr) {
type_list->assign(sig->parameters().begin(), sig->parameters().end());
@@ -345,8 +362,12 @@ class WasmDecoder : public Decoder {
bool Validate(const byte* pc, BranchTableOperand<true>& operand,
size_t block_depth) {
- // TODO(titzer): add extra redundant validation for br_table here?
- return true;
+ if (operand.table_count >= kV8MaxWasmFunctionSize) {
+ errorf(pc + 1, "invalid table count (> max function size): %u",
+ operand.table_count);
+ return false;
+ }
+ return checkAvailable(operand.table_count);
}
inline bool Validate(const byte* pc, WasmOpcode opcode,
@@ -410,8 +431,23 @@ class WasmDecoder : public Decoder {
}
}
+ inline bool Validate(const byte* pc, WasmOpcode opcode,
+ SimdShuffleOperand<true>& operand) {
+ unsigned lanes = GetShuffleMaskSize(opcode);
+ uint8_t max_lane = 0;
+ for (unsigned i = 0; i < lanes; i++)
+ max_lane = std::max(max_lane, operand.shuffle[i]);
+ if (operand.lanes != lanes || max_lane > 2 * lanes) {
+ error(pc_ + 2, "invalid shuffle mask");
+ return false;
+ } else {
+ return true;
+ }
+ }
+
static unsigned OpcodeLength(Decoder* decoder, const byte* pc) {
- switch (static_cast<byte>(*pc)) {
+ WasmOpcode opcode = static_cast<WasmOpcode>(*pc);
+ switch (opcode) {
#define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name:
FOREACH_LOAD_MEM_OPCODE(DECLARE_OPCODE_CASE)
FOREACH_STORE_MEM_OPCODE(DECLARE_OPCODE_CASE)
@@ -494,6 +530,11 @@ class WasmDecoder : public Decoder {
{
return 3;
}
+ // Shuffles contain a byte array to determine the shuffle.
+ case kExprS32x4Shuffle:
+ case kExprS16x8Shuffle:
+ case kExprS8x16Shuffle:
+ return 2 + GetShuffleMaskSize(opcode);
default:
decoder->error(pc, "invalid SIMD opcode");
return 2;
@@ -503,6 +544,68 @@ class WasmDecoder : public Decoder {
return 1;
}
}
+
+ std::pair<uint32_t, uint32_t> StackEffect(const byte* pc) {
+ WasmOpcode opcode = static_cast<WasmOpcode>(*pc);
+ // Handle "simple" opcodes with a fixed signature first.
+ FunctionSig* sig = WasmOpcodes::Signature(opcode);
+ if (!sig) sig = WasmOpcodes::AsmjsSignature(opcode);
+ if (sig) return {sig->parameter_count(), sig->return_count()};
+
+#define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name:
+ // clang-format off
+ switch (opcode) {
+ case kExprSelect:
+ return {3, 1};
+ FOREACH_STORE_MEM_OPCODE(DECLARE_OPCODE_CASE)
+ return {2, 0};
+ FOREACH_LOAD_MEM_OPCODE(DECLARE_OPCODE_CASE)
+ case kExprTeeLocal:
+ case kExprGrowMemory:
+ return {1, 1};
+ case kExprSetLocal:
+ case kExprSetGlobal:
+ case kExprDrop:
+ case kExprBrIf:
+ case kExprBrTable:
+ case kExprIf:
+ return {1, 0};
+ case kExprGetLocal:
+ case kExprGetGlobal:
+ case kExprI32Const:
+ case kExprI64Const:
+ case kExprF32Const:
+ case kExprF64Const:
+ case kExprMemorySize:
+ return {0, 1};
+ case kExprCallFunction: {
+ CallFunctionOperand<true> operand(this, pc);
+ CHECK(Complete(pc, operand));
+ return {operand.sig->parameter_count(), operand.sig->return_count()};
+ }
+ case kExprCallIndirect: {
+ CallIndirectOperand<true> operand(this, pc);
+ CHECK(Complete(pc, operand));
+ // Indirect calls pop an additional argument for the table index.
+ return {operand.sig->parameter_count() + 1,
+ operand.sig->return_count()};
+ }
+ case kExprBr:
+ case kExprBlock:
+ case kExprLoop:
+ case kExprEnd:
+ case kExprElse:
+ case kExprNop:
+ case kExprReturn:
+ case kExprUnreachable:
+ return {0, 0};
+ default:
+ V8_Fatal(__FILE__, __LINE__, "unimplemented opcode: %x", opcode);
+ return {0, 0};
+ }
+#undef DECLARE_OPCODE_CASE
+ // clang-format on
+ }
};
static const int32_t kNullCatch = -1;
@@ -571,8 +674,8 @@ class WasmFullDecoder : public WasmDecoder {
}
bool TraceFailed() {
- TRACE("wasm-error module+%-6d func+%d: %s\n\n", baserel(error_pc_),
- startrel(error_pc_), error_msg_.c_str());
+ TRACE("wasm-error module+%-6d func+%d: %s\n\n",
+ baserel(start_ + error_offset_), error_offset_, error_msg_.c_str());
return false;
}
@@ -1474,6 +1577,19 @@ class WasmFullDecoder : public WasmDecoder {
return operand.length;
}
+ unsigned SimdShuffleOp(WasmOpcode opcode) {
+ SimdShuffleOperand<true> operand(this, pc_, GetShuffleMaskSize(opcode));
+ if (Validate(pc_, opcode, operand)) {
+ compiler::NodeVector inputs(2, zone_);
+ inputs[1] = Pop(1, ValueType::kSimd128).node;
+ inputs[0] = Pop(0, ValueType::kSimd128).node;
+ TFNode* node =
+ BUILD(SimdShuffleOp, operand.shuffle, operand.lanes, inputs);
+ Push(ValueType::kSimd128, node);
+ }
+ return operand.lanes;
+ }
+
unsigned DecodeSimdOpcode(WasmOpcode opcode) {
unsigned len = 0;
switch (opcode) {
@@ -1509,6 +1625,12 @@ class WasmFullDecoder : public WasmDecoder {
len = SimdShiftOp(opcode);
break;
}
+ case kExprS32x4Shuffle:
+ case kExprS16x8Shuffle:
+ case kExprS8x16Shuffle: {
+ len = SimdShuffleOp(opcode);
+ break;
+ }
default: {
FunctionSig* sig = WasmOpcodes::Signature(opcode);
if (sig != nullptr) {
@@ -1721,7 +1843,7 @@ class WasmFullDecoder : public WasmDecoder {
PrintF(", control = ");
compiler::WasmGraphBuilder::PrintDebugName(env->control);
}
- PrintF("}");
+ PrintF("}\n");
}
#endif
ssa_env_ = env;
@@ -2026,6 +2148,13 @@ unsigned OpcodeLength(const byte* pc, const byte* end) {
return WasmDecoder::OpcodeLength(&decoder, pc);
}
+std::pair<uint32_t, uint32_t> StackEffect(const WasmModule* module,
+ FunctionSig* sig, const byte* pc,
+ const byte* end) {
+ WasmDecoder decoder(module, sig, pc, end);
+ return decoder.StackEffect(pc);
+}
+
void PrintRawWasmCode(const byte* start, const byte* end) {
AccountingAllocator allocator;
PrintRawWasmCode(&allocator, FunctionBodyForTesting(start, end), nullptr);