Commit aba57b11 authored by Clemens Hammacher's avatar Clemens Hammacher Committed by Commit Bot

[wasm] Introduce LoadType and StoreType enums

These enums capture the "type" of a load and store in one value, with
accessors to get the value type, memory type, memory size etc.
This will simplify implementing memory operations in Liftoff.

R=titzer@chromium.org

Bug: v8:6600
Change-Id: Ief673e90fe63292853f97e5e95b5c39da1296730
Reviewed-on: https://chromium-review.googlesource.com/822476
Commit-Queue: Clemens Hammacher <clemensh@chromium.org>
Reviewed-by: 's avatarBen Titzer <titzer@chromium.org>
Cr-Commit-Position: refs/heads/master@{#50054}
parent 12208099
...@@ -523,12 +523,12 @@ class LiftoffCompiler { ...@@ -523,12 +523,12 @@ class LiftoffCompiler {
void Else(Decoder* decoder, Control* if_block) { void Else(Decoder* decoder, Control* if_block) {
unsupported(decoder, "else"); unsupported(decoder, "else");
} }
void LoadMem(Decoder* decoder, ValueType type, MachineType mem_type, void LoadMem(Decoder* decoder, LoadType type,
const MemoryAccessOperand<validate>& operand, const Value& index, const MemoryAccessOperand<validate>& operand, const Value& index,
Value* result) { Value* result) {
unsupported(decoder, "memory load"); unsupported(decoder, "memory load");
} }
void StoreMem(Decoder* decoder, ValueType type, MachineRepresentation mem_rep, void StoreMem(Decoder* decoder, StoreType type,
const MemoryAccessOperand<validate>& operand, const MemoryAccessOperand<validate>& operand,
const Value& index, const Value& value) { const Value& index, const Value& value) {
unsupported(decoder, "memory store"); unsupported(decoder, "memory store");
......
...@@ -578,12 +578,10 @@ struct ControlWithNamedConstructors : public ControlBase<Value> { ...@@ -578,12 +578,10 @@ struct ControlWithNamedConstructors : public ControlBase<Value> {
F(BrIf, const Value& cond, Control* target) \ F(BrIf, const Value& cond, Control* target) \
F(BrTable, const BranchTableOperand<validate>& operand, const Value& key) \ F(BrTable, const BranchTableOperand<validate>& operand, const Value& key) \
F(Else, Control* if_block) \ F(Else, Control* if_block) \
F(LoadMem, ValueType type, MachineType mem_type, \ F(LoadMem, LoadType type, const MemoryAccessOperand<validate>& operand, \
const MemoryAccessOperand<validate>& operand, const Value& index, \ const Value& index, Value* result) \
Value* result) \ F(StoreMem, StoreType type, const MemoryAccessOperand<validate>& operand, \
F(StoreMem, ValueType type, MachineRepresentation mem_rep, \ const Value& index, const Value& value) \
const MemoryAccessOperand<validate>& operand, const Value& index, \
const Value& value) \
F(CurrentMemoryPages, Value* result) \ F(CurrentMemoryPages, Value* result) \
F(GrowMemory, const Value& value, Value* result) \ F(GrowMemory, const Value& value, Value* result) \
F(CallDirect, const CallFunctionOperand<validate>& operand, \ F(CallDirect, const CallFunctionOperand<validate>& operand, \
...@@ -1667,73 +1665,73 @@ class WasmFullDecoder : public WasmDecoder<validate> { ...@@ -1667,73 +1665,73 @@ class WasmFullDecoder : public WasmDecoder<validate> {
break; break;
} }
case kExprI32LoadMem8S: case kExprI32LoadMem8S:
len = 1 + DecodeLoadMem(kWasmI32, MachineType::Int8()); len = 1 + DecodeLoadMem(LoadType::kI32Load8S);
break; break;
case kExprI32LoadMem8U: case kExprI32LoadMem8U:
len = 1 + DecodeLoadMem(kWasmI32, MachineType::Uint8()); len = 1 + DecodeLoadMem(LoadType::kI32Load8U);
break; break;
case kExprI32LoadMem16S: case kExprI32LoadMem16S:
len = 1 + DecodeLoadMem(kWasmI32, MachineType::Int16()); len = 1 + DecodeLoadMem(LoadType::kI32Load16S);
break; break;
case kExprI32LoadMem16U: case kExprI32LoadMem16U:
len = 1 + DecodeLoadMem(kWasmI32, MachineType::Uint16()); len = 1 + DecodeLoadMem(LoadType::kI32Load16U);
break; break;
case kExprI32LoadMem: case kExprI32LoadMem:
len = 1 + DecodeLoadMem(kWasmI32, MachineType::Int32()); len = 1 + DecodeLoadMem(LoadType::kI32Load);
break; break;
case kExprI64LoadMem8S: case kExprI64LoadMem8S:
len = 1 + DecodeLoadMem(kWasmI64, MachineType::Int8()); len = 1 + DecodeLoadMem(LoadType::kI64Load8S);
break; break;
case kExprI64LoadMem8U: case kExprI64LoadMem8U:
len = 1 + DecodeLoadMem(kWasmI64, MachineType::Uint8()); len = 1 + DecodeLoadMem(LoadType::kI64Load8U);
break; break;
case kExprI64LoadMem16S: case kExprI64LoadMem16S:
len = 1 + DecodeLoadMem(kWasmI64, MachineType::Int16()); len = 1 + DecodeLoadMem(LoadType::kI64Load16S);
break; break;
case kExprI64LoadMem16U: case kExprI64LoadMem16U:
len = 1 + DecodeLoadMem(kWasmI64, MachineType::Uint16()); len = 1 + DecodeLoadMem(LoadType::kI64Load16U);
break; break;
case kExprI64LoadMem32S: case kExprI64LoadMem32S:
len = 1 + DecodeLoadMem(kWasmI64, MachineType::Int32()); len = 1 + DecodeLoadMem(LoadType::kI64Load32S);
break; break;
case kExprI64LoadMem32U: case kExprI64LoadMem32U:
len = 1 + DecodeLoadMem(kWasmI64, MachineType::Uint32()); len = 1 + DecodeLoadMem(LoadType::kI64Load32U);
break; break;
case kExprI64LoadMem: case kExprI64LoadMem:
len = 1 + DecodeLoadMem(kWasmI64, MachineType::Int64()); len = 1 + DecodeLoadMem(LoadType::kI64Load);
break; break;
case kExprF32LoadMem: case kExprF32LoadMem:
len = 1 + DecodeLoadMem(kWasmF32, MachineType::Float32()); len = 1 + DecodeLoadMem(LoadType::kF32Load);
break; break;
case kExprF64LoadMem: case kExprF64LoadMem:
len = 1 + DecodeLoadMem(kWasmF64, MachineType::Float64()); len = 1 + DecodeLoadMem(LoadType::kF64Load);
break; break;
case kExprI32StoreMem8: case kExprI32StoreMem8:
len = 1 + DecodeStoreMem(kWasmI32, MachineType::Int8()); len = 1 + DecodeStoreMem(StoreType::kI32Store8);
break; break;
case kExprI32StoreMem16: case kExprI32StoreMem16:
len = 1 + DecodeStoreMem(kWasmI32, MachineType::Int16()); len = 1 + DecodeStoreMem(StoreType::kI32Store16);
break; break;
case kExprI32StoreMem: case kExprI32StoreMem:
len = 1 + DecodeStoreMem(kWasmI32, MachineType::Int32()); len = 1 + DecodeStoreMem(StoreType::kI32Store);
break; break;
case kExprI64StoreMem8: case kExprI64StoreMem8:
len = 1 + DecodeStoreMem(kWasmI64, MachineType::Int8()); len = 1 + DecodeStoreMem(StoreType::kI64Store8);
break; break;
case kExprI64StoreMem16: case kExprI64StoreMem16:
len = 1 + DecodeStoreMem(kWasmI64, MachineType::Int16()); len = 1 + DecodeStoreMem(StoreType::kI64Store16);
break; break;
case kExprI64StoreMem32: case kExprI64StoreMem32:
len = 1 + DecodeStoreMem(kWasmI64, MachineType::Int32()); len = 1 + DecodeStoreMem(StoreType::kI64Store32);
break; break;
case kExprI64StoreMem: case kExprI64StoreMem:
len = 1 + DecodeStoreMem(kWasmI64, MachineType::Int64()); len = 1 + DecodeStoreMem(StoreType::kI64Store);
break; break;
case kExprF32StoreMem: case kExprF32StoreMem:
len = 1 + DecodeStoreMem(kWasmF32, MachineType::Float32()); len = 1 + DecodeStoreMem(StoreType::kF32Store);
break; break;
case kExprF64StoreMem: case kExprF64StoreMem:
len = 1 + DecodeStoreMem(kWasmF64, MachineType::Float64()); len = 1 + DecodeStoreMem(StoreType::kF64Store);
break; break;
case kExprGrowMemory: { case kExprGrowMemory: {
if (!CheckHasMemory()) break; if (!CheckHasMemory()) break;
...@@ -1977,28 +1975,23 @@ class WasmFullDecoder : public WasmDecoder<validate> { ...@@ -1977,28 +1975,23 @@ class WasmFullDecoder : public WasmDecoder<validate> {
} }
} }
int DecodeLoadMem(ValueType type, MachineType mem_type, int prefix_len = 0) { int DecodeLoadMem(LoadType type, int prefix_len = 0) {
if (!CheckHasMemory()) return 0; if (!CheckHasMemory()) return 0;
MemoryAccessOperand<validate> operand( MemoryAccessOperand<validate> operand(this, this->pc_ + prefix_len,
this, this->pc_ + prefix_len, type.size_log_2());
ElementSizeLog2Of(mem_type.representation()));
auto index = Pop(0, kWasmI32); auto index = Pop(0, kWasmI32);
auto* result = Push(type); auto* result = Push(type.value_type());
CALL_INTERFACE_IF_REACHABLE(LoadMem, type, mem_type, operand, index, CALL_INTERFACE_IF_REACHABLE(LoadMem, type, operand, index, result);
result);
return operand.length; return operand.length;
} }
int DecodeStoreMem(ValueType type, MachineType mem_type, int prefix_len = 0) { int DecodeStoreMem(StoreType store, int prefix_len = 0) {
if (!CheckHasMemory()) return 0; if (!CheckHasMemory()) return 0;
MemoryAccessOperand<validate> operand( MemoryAccessOperand<validate> operand(this, this->pc_ + prefix_len,
this, this->pc_ + prefix_len, store.size_log_2());
ElementSizeLog2Of(mem_type.representation())); auto value = Pop(1, store.value_type());
auto value = Pop(1, type);
auto index = Pop(0, kWasmI32); auto index = Pop(0, kWasmI32);
CALL_INTERFACE_IF_REACHABLE(StoreMem, type, mem_type.representation(), CALL_INTERFACE_IF_REACHABLE(StoreMem, store, operand, index, value);
operand, index, value);
return operand.length; return operand.length;
} }
...@@ -2088,10 +2081,10 @@ class WasmFullDecoder : public WasmDecoder<validate> { ...@@ -2088,10 +2081,10 @@ class WasmFullDecoder : public WasmDecoder<validate> {
break; break;
} }
case kExprS128LoadMem: case kExprS128LoadMem:
len = DecodeLoadMem(kWasmS128, MachineType::Simd128(), 1); len = DecodeLoadMem(LoadType::kS128Load, 1);
break; break;
case kExprS128StoreMem: case kExprS128StoreMem:
len = DecodeStoreMem(kWasmS128, MachineType::Simd128(), 1); len = DecodeStoreMem(StoreType::kS128Store, 1);
break; break;
default: { default: {
FunctionSig* sig = WasmOpcodes::Signature(opcode); FunctionSig* sig = WasmOpcodes::Signature(opcode);
......
...@@ -340,18 +340,20 @@ class WasmGraphBuildingInterface { ...@@ -340,18 +340,20 @@ class WasmGraphBuildingInterface {
SetEnv(if_block->false_env); SetEnv(if_block->false_env);
} }
void LoadMem(Decoder* decoder, ValueType type, MachineType mem_type, void LoadMem(Decoder* decoder, LoadType type,
const MemoryAccessOperand<validate>& operand, const Value& index, const MemoryAccessOperand<validate>& operand, const Value& index,
Value* result) { Value* result) {
result->node = BUILD(LoadMem, type, mem_type, index.node, operand.offset, result->node =
operand.alignment, decoder->position()); BUILD(LoadMem, type.value_type(), type.mem_type(), index.node,
operand.offset, operand.alignment, decoder->position());
} }
void StoreMem(Decoder* decoder, ValueType type, MachineRepresentation mem_rep, void StoreMem(Decoder* decoder, StoreType type,
const MemoryAccessOperand<validate>& operand, const MemoryAccessOperand<validate>& operand,
const Value& index, const Value& value) { const Value& index, const Value& value) {
BUILD(StoreMem, mem_rep, index.node, operand.offset, operand.alignment, BUILD(StoreMem, type.mem_rep(), index.node, operand.offset,
value.node, decoder->position(), type); operand.alignment, value.node, decoder->position(),
type.value_type());
} }
void CurrentMemoryPages(Decoder* decoder, Value* result) { void CurrentMemoryPages(Decoder* decoder, Value* result) {
......
...@@ -422,6 +422,14 @@ FunctionSig* WasmOpcodes::AsmjsSignature(WasmOpcode opcode) { ...@@ -422,6 +422,14 @@ FunctionSig* WasmOpcodes::AsmjsSignature(WasmOpcode opcode) {
kSimpleExprSigs[kSimpleAsmjsExprSigTable[opcode]]); kSimpleExprSigs[kSimpleAsmjsExprSigTable[opcode]]);
} }
// Define constexpr arrays.
constexpr uint8_t LoadType::kLoadSizeLog2[];
constexpr ValueType LoadType::kValueType[];
constexpr MachineType LoadType::kMemType[];
constexpr uint8_t StoreType::kStoreSizeLog2[];
constexpr ValueType StoreType::kValueType[];
constexpr MachineRepresentation StoreType::kMemRep[];
int WasmOpcodes::TrapReasonToMessageId(TrapReason reason) { int WasmOpcodes::TrapReasonToMessageId(TrapReason reason) {
switch (reason) { switch (reason) {
#define TRAPREASON_TO_MESSAGE(name) \ #define TRAPREASON_TO_MESSAGE(name) \
......
...@@ -535,6 +535,117 @@ enum TrapReason { ...@@ -535,6 +535,117 @@ enum TrapReason {
#undef DECLARE_ENUM #undef DECLARE_ENUM
}; };
// TODO(clemensh): Compute memtype and size from ValueType once we have c++14
// constexpr support.
#define FOREACH_LOAD_TYPE(V) \
V(I32, , Int32, 2) \
V(I32, 8S, Int8, 0) \
V(I32, 8U, Uint8, 0) \
V(I32, 16S, Int16, 1) \
V(I32, 16U, Uint16, 1) \
V(I64, , Int64, 3) \
V(I64, 8S, Int8, 0) \
V(I64, 8U, Uint8, 0) \
V(I64, 16S, Int16, 1) \
V(I64, 16U, Uint16, 1) \
V(I64, 32S, Int32, 2) \
V(I64, 32U, Uint32, 2) \
V(F32, , Float32, 2) \
V(F64, , Float64, 3) \
V(S128, , Simd128, 4)
class LoadType {
public:
enum LoadTypeValue : uint8_t {
#define DEF_ENUM(type, suffix, ...) k##type##Load##suffix,
FOREACH_LOAD_TYPE(DEF_ENUM)
#undef DEF_ENUM
};
// Allow implicit convertion of the enum value to this wrapper.
constexpr LoadType(LoadTypeValue val) // NOLINT(runtime/explicit)
: val_(val) {}
constexpr LoadTypeValue value() const { return val_; }
constexpr unsigned size_log_2() const { return kLoadSizeLog2[val_]; }
constexpr unsigned size() const { return 1 << size_log_2(); }
constexpr ValueType value_type() const { return kValueType[val_]; }
constexpr MachineType mem_type() const { return kMemType[val_]; }
private:
const LoadTypeValue val_;
static constexpr uint8_t kLoadSizeLog2[] = {
#define LOAD_SIZE(_, __, ___, size) size,
FOREACH_LOAD_TYPE(LOAD_SIZE)
#undef LOAD_SIZE
};
static constexpr ValueType kValueType[] = {
#define VALUE_TYPE(type, ...) kWasm##type,
FOREACH_LOAD_TYPE(VALUE_TYPE)
#undef VALUE_TYPE
};
static constexpr MachineType kMemType[] = {
#define MEMTYPE(_, __, memtype, ___) MachineType::memtype(),
FOREACH_LOAD_TYPE(MEMTYPE)
#undef MEMTYPE
};
};
#define FOREACH_STORE_TYPE(V) \
V(I32, , Word32, 2) \
V(I32, 8, Word8, 0) \
V(I32, 16, Word16, 1) \
V(I64, , Word64, 3) \
V(I64, 8, Word8, 0) \
V(I64, 16, Word16, 1) \
V(I64, 32, Word32, 2) \
V(F32, , Float32, 2) \
V(F64, , Float64, 3) \
V(S128, , Simd128, 4)
class StoreType {
public:
enum StoreTypeValue : uint8_t {
#define DEF_ENUM(type, suffix, ...) k##type##Store##suffix,
FOREACH_STORE_TYPE(DEF_ENUM)
#undef DEF_ENUM
};
// Allow implicit convertion of the enum value to this wrapper.
constexpr StoreType(StoreTypeValue val) // NOLINT(runtime/explicit)
: val_(val) {}
constexpr StoreTypeValue value() const { return val_; }
constexpr unsigned size_log_2() const { return kStoreSizeLog2[val_]; }
constexpr unsigned size() const { return 1 << size_log_2(); }
constexpr ValueType value_type() const { return kValueType[val_]; }
constexpr ValueType mem_rep() const { return kMemRep[val_]; }
private:
const StoreTypeValue val_;
static constexpr uint8_t kStoreSizeLog2[] = {
#define STORE_SIZE(_, __, ___, size) size,
FOREACH_STORE_TYPE(STORE_SIZE)
#undef STORE_SIZE
};
static constexpr ValueType kValueType[] = {
#define VALUE_TYPE(type, ...) kWasm##type,
FOREACH_STORE_TYPE(VALUE_TYPE)
#undef VALUE_TYPE
};
static constexpr MachineRepresentation kMemRep[] = {
#define MEMREP(_, __, memrep, ___) MachineRepresentation::k##memrep,
FOREACH_STORE_TYPE(MEMREP)
#undef MEMREP
};
};
// A collection of opcode-related static methods. // A collection of opcode-related static methods.
class V8_EXPORT_PRIVATE WasmOpcodes { class V8_EXPORT_PRIVATE WasmOpcodes {
public: public:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment