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 {
void Else(Decoder* decoder, Control* if_block) {
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,
Value* result) {
unsupported(decoder, "memory load");
}
void StoreMem(Decoder* decoder, ValueType type, MachineRepresentation mem_rep,
void StoreMem(Decoder* decoder, StoreType type,
const MemoryAccessOperand<validate>& operand,
const Value& index, const Value& value) {
unsupported(decoder, "memory store");
......
......@@ -578,12 +578,10 @@ struct ControlWithNamedConstructors : public ControlBase<Value> {
F(BrIf, const Value& cond, Control* target) \
F(BrTable, const BranchTableOperand<validate>& operand, const Value& key) \
F(Else, Control* if_block) \
F(LoadMem, ValueType type, MachineType mem_type, \
const MemoryAccessOperand<validate>& operand, const Value& index, \
Value* result) \
F(StoreMem, ValueType type, MachineRepresentation mem_rep, \
const MemoryAccessOperand<validate>& operand, const Value& index, \
const Value& value) \
F(LoadMem, LoadType type, const MemoryAccessOperand<validate>& operand, \
const Value& index, Value* result) \
F(StoreMem, StoreType type, const MemoryAccessOperand<validate>& operand, \
const Value& index, const Value& value) \
F(CurrentMemoryPages, Value* result) \
F(GrowMemory, const Value& value, Value* result) \
F(CallDirect, const CallFunctionOperand<validate>& operand, \
......@@ -1667,73 +1665,73 @@ class WasmFullDecoder : public WasmDecoder<validate> {
break;
}
case kExprI32LoadMem8S:
len = 1 + DecodeLoadMem(kWasmI32, MachineType::Int8());
len = 1 + DecodeLoadMem(LoadType::kI32Load8S);
break;
case kExprI32LoadMem8U:
len = 1 + DecodeLoadMem(kWasmI32, MachineType::Uint8());
len = 1 + DecodeLoadMem(LoadType::kI32Load8U);
break;
case kExprI32LoadMem16S:
len = 1 + DecodeLoadMem(kWasmI32, MachineType::Int16());
len = 1 + DecodeLoadMem(LoadType::kI32Load16S);
break;
case kExprI32LoadMem16U:
len = 1 + DecodeLoadMem(kWasmI32, MachineType::Uint16());
len = 1 + DecodeLoadMem(LoadType::kI32Load16U);
break;
case kExprI32LoadMem:
len = 1 + DecodeLoadMem(kWasmI32, MachineType::Int32());
len = 1 + DecodeLoadMem(LoadType::kI32Load);
break;
case kExprI64LoadMem8S:
len = 1 + DecodeLoadMem(kWasmI64, MachineType::Int8());
len = 1 + DecodeLoadMem(LoadType::kI64Load8S);
break;
case kExprI64LoadMem8U:
len = 1 + DecodeLoadMem(kWasmI64, MachineType::Uint8());
len = 1 + DecodeLoadMem(LoadType::kI64Load8U);
break;
case kExprI64LoadMem16S:
len = 1 + DecodeLoadMem(kWasmI64, MachineType::Int16());
len = 1 + DecodeLoadMem(LoadType::kI64Load16S);
break;
case kExprI64LoadMem16U:
len = 1 + DecodeLoadMem(kWasmI64, MachineType::Uint16());
len = 1 + DecodeLoadMem(LoadType::kI64Load16U);
break;
case kExprI64LoadMem32S:
len = 1 + DecodeLoadMem(kWasmI64, MachineType::Int32());
len = 1 + DecodeLoadMem(LoadType::kI64Load32S);
break;
case kExprI64LoadMem32U:
len = 1 + DecodeLoadMem(kWasmI64, MachineType::Uint32());
len = 1 + DecodeLoadMem(LoadType::kI64Load32U);
break;
case kExprI64LoadMem:
len = 1 + DecodeLoadMem(kWasmI64, MachineType::Int64());
len = 1 + DecodeLoadMem(LoadType::kI64Load);
break;
case kExprF32LoadMem:
len = 1 + DecodeLoadMem(kWasmF32, MachineType::Float32());
len = 1 + DecodeLoadMem(LoadType::kF32Load);
break;
case kExprF64LoadMem:
len = 1 + DecodeLoadMem(kWasmF64, MachineType::Float64());
len = 1 + DecodeLoadMem(LoadType::kF64Load);
break;
case kExprI32StoreMem8:
len = 1 + DecodeStoreMem(kWasmI32, MachineType::Int8());
len = 1 + DecodeStoreMem(StoreType::kI32Store8);
break;
case kExprI32StoreMem16:
len = 1 + DecodeStoreMem(kWasmI32, MachineType::Int16());
len = 1 + DecodeStoreMem(StoreType::kI32Store16);
break;
case kExprI32StoreMem:
len = 1 + DecodeStoreMem(kWasmI32, MachineType::Int32());
len = 1 + DecodeStoreMem(StoreType::kI32Store);
break;
case kExprI64StoreMem8:
len = 1 + DecodeStoreMem(kWasmI64, MachineType::Int8());
len = 1 + DecodeStoreMem(StoreType::kI64Store8);
break;
case kExprI64StoreMem16:
len = 1 + DecodeStoreMem(kWasmI64, MachineType::Int16());
len = 1 + DecodeStoreMem(StoreType::kI64Store16);
break;
case kExprI64StoreMem32:
len = 1 + DecodeStoreMem(kWasmI64, MachineType::Int32());
len = 1 + DecodeStoreMem(StoreType::kI64Store32);
break;
case kExprI64StoreMem:
len = 1 + DecodeStoreMem(kWasmI64, MachineType::Int64());
len = 1 + DecodeStoreMem(StoreType::kI64Store);
break;
case kExprF32StoreMem:
len = 1 + DecodeStoreMem(kWasmF32, MachineType::Float32());
len = 1 + DecodeStoreMem(StoreType::kF32Store);
break;
case kExprF64StoreMem:
len = 1 + DecodeStoreMem(kWasmF64, MachineType::Float64());
len = 1 + DecodeStoreMem(StoreType::kF64Store);
break;
case kExprGrowMemory: {
if (!CheckHasMemory()) break;
......@@ -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;
MemoryAccessOperand<validate> operand(
this, this->pc_ + prefix_len,
ElementSizeLog2Of(mem_type.representation()));
MemoryAccessOperand<validate> operand(this, this->pc_ + prefix_len,
type.size_log_2());
auto index = Pop(0, kWasmI32);
auto* result = Push(type);
CALL_INTERFACE_IF_REACHABLE(LoadMem, type, mem_type, operand, index,
result);
auto* result = Push(type.value_type());
CALL_INTERFACE_IF_REACHABLE(LoadMem, type, operand, index, result);
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;
MemoryAccessOperand<validate> operand(
this, this->pc_ + prefix_len,
ElementSizeLog2Of(mem_type.representation()));
auto value = Pop(1, type);
MemoryAccessOperand<validate> operand(this, this->pc_ + prefix_len,
store.size_log_2());
auto value = Pop(1, store.value_type());
auto index = Pop(0, kWasmI32);
CALL_INTERFACE_IF_REACHABLE(StoreMem, type, mem_type.representation(),
operand, index, value);
CALL_INTERFACE_IF_REACHABLE(StoreMem, store, operand, index, value);
return operand.length;
}
......@@ -2088,10 +2081,10 @@ class WasmFullDecoder : public WasmDecoder<validate> {
break;
}
case kExprS128LoadMem:
len = DecodeLoadMem(kWasmS128, MachineType::Simd128(), 1);
len = DecodeLoadMem(LoadType::kS128Load, 1);
break;
case kExprS128StoreMem:
len = DecodeStoreMem(kWasmS128, MachineType::Simd128(), 1);
len = DecodeStoreMem(StoreType::kS128Store, 1);
break;
default: {
FunctionSig* sig = WasmOpcodes::Signature(opcode);
......
......@@ -340,18 +340,20 @@ class WasmGraphBuildingInterface {
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,
Value* result) {
result->node = BUILD(LoadMem, type, mem_type, index.node, operand.offset,
operand.alignment, decoder->position());
result->node =
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 Value& index, const Value& value) {
BUILD(StoreMem, mem_rep, index.node, operand.offset, operand.alignment,
value.node, decoder->position(), type);
BUILD(StoreMem, type.mem_rep(), index.node, operand.offset,
operand.alignment, value.node, decoder->position(),
type.value_type());
}
void CurrentMemoryPages(Decoder* decoder, Value* result) {
......
......@@ -422,6 +422,14 @@ FunctionSig* WasmOpcodes::AsmjsSignature(WasmOpcode 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) {
switch (reason) {
#define TRAPREASON_TO_MESSAGE(name) \
......
......@@ -535,6 +535,117 @@ enum TrapReason {
#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.
class V8_EXPORT_PRIVATE WasmOpcodes {
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