[Wasm] Convert many of the fixed-size values to LEB128.
This CL modifies the following to be LEB128: * Function table indices * Import table signature indices * Export table function indices * Function signature param count * br/br_if break depth * br_table target count * block/loop expression count Still to do: * Import/export names (LEB128 count + inline data) * Data segments (LEB128 offset + size + inline data) * Function header stuff (should seperate into function sig and body sections) * Memory access alignment + offset (still discussing) BUG= R=titzer@chromium.org Review URL: https://codereview.chromium.org/1775873002 Cr-Commit-Position: refs/heads/master@{#34603}
This commit is contained in:
parent
fd40570419
commit
78f6f838f0
@ -138,13 +138,14 @@ class AsmWasmBuilderImpl : public AstVisitor {
|
||||
: builder_(builder) {
|
||||
builder_->breakable_blocks_.push_back(std::make_pair(stmt, is_loop));
|
||||
builder_->current_function_builder_->Emit(opcode);
|
||||
index_ = builder_->current_function_builder_->EmitEditableImmediate(0);
|
||||
index_ =
|
||||
builder_->current_function_builder_->EmitEditableVarIntImmediate();
|
||||
prev_block_size_ = builder_->block_size_;
|
||||
builder_->block_size_ = initial_block_size;
|
||||
}
|
||||
~BlockVisitor() {
|
||||
builder_->current_function_builder_->EditImmediate(index_,
|
||||
builder_->block_size_);
|
||||
builder_->current_function_builder_->EditVarIntImmediate(
|
||||
index_, builder_->block_size_);
|
||||
builder_->block_size_ = prev_block_size_;
|
||||
builder_->breakable_blocks_.pop_back();
|
||||
}
|
||||
@ -193,7 +194,7 @@ class AsmWasmBuilderImpl : public AstVisitor {
|
||||
}
|
||||
}
|
||||
DCHECK(i >= 0);
|
||||
current_function_builder_->EmitWithU8(kExprBr, block_distance);
|
||||
current_function_builder_->EmitWithVarInt(kExprBr, block_distance);
|
||||
current_function_builder_->Emit(kExprNop);
|
||||
}
|
||||
|
||||
@ -216,7 +217,7 @@ class AsmWasmBuilderImpl : public AstVisitor {
|
||||
}
|
||||
}
|
||||
DCHECK(i >= 0);
|
||||
current_function_builder_->EmitWithU8(kExprBr, block_distance);
|
||||
current_function_builder_->EmitWithVarInt(kExprBr, block_distance);
|
||||
current_function_builder_->Emit(kExprNop);
|
||||
}
|
||||
|
||||
@ -292,7 +293,7 @@ class AsmWasmBuilderImpl : public AstVisitor {
|
||||
RECURSE(Visit(stmt->body()));
|
||||
current_function_builder_->Emit(kExprIf);
|
||||
RECURSE(Visit(stmt->cond()));
|
||||
current_function_builder_->EmitWithU8(kExprBr, 0);
|
||||
current_function_builder_->EmitWithVarInt(kExprBr, 0);
|
||||
current_function_builder_->Emit(kExprNop);
|
||||
}
|
||||
|
||||
@ -302,7 +303,7 @@ class AsmWasmBuilderImpl : public AstVisitor {
|
||||
1);
|
||||
current_function_builder_->Emit(kExprIf);
|
||||
RECURSE(Visit(stmt->cond()));
|
||||
current_function_builder_->EmitWithU8(kExprBr, 0);
|
||||
current_function_builder_->EmitWithVarInt(kExprBr, 0);
|
||||
RECURSE(Visit(stmt->body()));
|
||||
}
|
||||
|
||||
@ -319,7 +320,7 @@ class AsmWasmBuilderImpl : public AstVisitor {
|
||||
current_function_builder_->Emit(kExprIf);
|
||||
current_function_builder_->Emit(kExprI32Eqz);
|
||||
RECURSE(Visit(stmt->cond()));
|
||||
current_function_builder_->EmitWithU8(kExprBr, 1);
|
||||
current_function_builder_->EmitWithVarInt(kExprBr, 1);
|
||||
current_function_builder_->Emit(kExprNop);
|
||||
}
|
||||
if (stmt->body() != nullptr) {
|
||||
@ -331,7 +332,7 @@ class AsmWasmBuilderImpl : public AstVisitor {
|
||||
RECURSE(Visit(stmt->next()));
|
||||
}
|
||||
block_size_++;
|
||||
current_function_builder_->EmitWithU8(kExprBr, 0);
|
||||
current_function_builder_->EmitWithVarInt(kExprBr, 0);
|
||||
current_function_builder_->Emit(kExprNop);
|
||||
}
|
||||
|
||||
@ -1058,8 +1059,8 @@ class AsmWasmBuilderImpl : public AstVisitor {
|
||||
VariableProxy* var = p->obj()->AsVariableProxy();
|
||||
DCHECK_NOT_NULL(var);
|
||||
FunctionTableIndices* indices = LookupFunctionTable(var->var());
|
||||
current_function_builder_->EmitWithU8(kExprCallIndirect,
|
||||
indices->signature_index);
|
||||
current_function_builder_->EmitWithVarInt(kExprCallIndirect,
|
||||
indices->signature_index);
|
||||
current_function_builder_->Emit(kExprI32Add);
|
||||
// TODO(bradnelson): variable size
|
||||
byte code[] = {WASM_I32V(indices->start_index)};
|
||||
@ -1283,7 +1284,7 @@ class AsmWasmBuilderImpl : public AstVisitor {
|
||||
break;
|
||||
}
|
||||
case Token::COMMA: {
|
||||
current_function_builder_->EmitWithU8(kExprBlock, 2);
|
||||
current_function_builder_->EmitWithVarInt(kExprBlock, 2);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
@ -200,7 +200,7 @@ class WasmDecoder : public Decoder {
|
||||
size_t block_depth) {
|
||||
// Verify table.
|
||||
for (uint32_t i = 0; i < operand.table_count + 1; i++) {
|
||||
uint16_t target = operand.read_entry(this, i);
|
||||
uint32_t target = operand.read_entry(this, i);
|
||||
if (target >= block_depth) {
|
||||
error(operand.table + i * 2, "improper branch in br_table");
|
||||
return false;
|
||||
@ -1107,7 +1107,7 @@ class SR_WasmDecoder : public WasmDecoder {
|
||||
SsaEnv* prev = ssa_env_;
|
||||
SsaEnv* copy = Steal(prev);
|
||||
for (uint32_t i = 0; i < operand.table_count + 1; i++) {
|
||||
uint16_t target = operand.read_entry(this, i);
|
||||
uint32_t target = operand.read_entry(this, i);
|
||||
SsaEnv* env = copy;
|
||||
if (build_switch) {
|
||||
ssa_env_ = env = Split(env);
|
||||
|
@ -97,8 +97,7 @@ struct BreakDepthOperand {
|
||||
Block* target;
|
||||
int length;
|
||||
inline BreakDepthOperand(Decoder* decoder, const byte* pc) {
|
||||
depth = decoder->checked_read_u8(pc, 1, "break depth");
|
||||
length = 1;
|
||||
depth = decoder->checked_read_u32v(pc, 1, &length, "break depth");
|
||||
target = nullptr;
|
||||
}
|
||||
};
|
||||
@ -107,8 +106,7 @@ struct BlockCountOperand {
|
||||
uint32_t count;
|
||||
int length;
|
||||
inline BlockCountOperand(Decoder* decoder, const byte* pc) {
|
||||
count = decoder->checked_read_u8(pc, 1, "block count");
|
||||
length = 1;
|
||||
count = decoder->checked_read_u32v(pc, 1, &length, "block count");
|
||||
}
|
||||
};
|
||||
|
||||
@ -147,19 +145,22 @@ struct BranchTableOperand {
|
||||
const byte* table;
|
||||
int length;
|
||||
inline BranchTableOperand(Decoder* decoder, const byte* pc) {
|
||||
table_count = decoder->checked_read_u16(pc, 1, "expected #entries");
|
||||
length = 2 + table_count * 2 + 2;
|
||||
int varint_length;
|
||||
table_count =
|
||||
decoder->checked_read_u32v(pc, 1, &varint_length, "expected #entries");
|
||||
length = varint_length + (table_count + 1) * sizeof(uint32_t);
|
||||
|
||||
if (decoder->check(pc, 3, table_count * 2 + 2,
|
||||
uint32_t table_start = 1 + varint_length;
|
||||
if (decoder->check(pc, table_start, (table_count + 1) * sizeof(uint32_t),
|
||||
"expected <table entries>")) {
|
||||
table = pc + 3;
|
||||
table = pc + table_start;
|
||||
} else {
|
||||
table = nullptr;
|
||||
}
|
||||
}
|
||||
inline uint16_t read_entry(Decoder* decoder, int i) {
|
||||
inline uint32_t read_entry(Decoder* decoder, int i) {
|
||||
DCHECK(i >= 0 && static_cast<uint32_t>(i) <= table_count);
|
||||
return table ? decoder->read_u16(table + i * sizeof(uint16_t)) : 0;
|
||||
return table ? decoder->read_u32(table + i * sizeof(uint32_t)) : 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -55,6 +55,16 @@ void EmitVarInt(byte** b, size_t val) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
size_t SizeOfVarInt(size_t value) {
|
||||
size_t size = 0;
|
||||
do {
|
||||
size++;
|
||||
value = value >> 7;
|
||||
} while (value > 0);
|
||||
return size;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
@ -121,16 +131,41 @@ void WasmFunctionBuilder::EmitWithU8(WasmOpcode opcode, const byte immediate) {
|
||||
body_.push_back(immediate);
|
||||
}
|
||||
|
||||
void WasmFunctionBuilder::EmitWithVarInt(WasmOpcode opcode,
|
||||
uint32_t immediate) {
|
||||
body_.push_back(static_cast<byte>(opcode));
|
||||
size_t immediate_size = SizeOfVarInt(immediate);
|
||||
body_.insert(body_.end(), immediate_size, 0);
|
||||
byte* p = &body_[body_.size() - immediate_size];
|
||||
EmitVarInt(&p, immediate);
|
||||
}
|
||||
|
||||
uint32_t WasmFunctionBuilder::EmitEditableImmediate(const byte immediate) {
|
||||
body_.push_back(immediate);
|
||||
uint32_t WasmFunctionBuilder::EmitEditableVarIntImmediate() {
|
||||
// Guess that the immediate will be 1 byte. If it is more, we'll have to
|
||||
// shift everything down.
|
||||
body_.push_back(0);
|
||||
return static_cast<uint32_t>(body_.size()) - 1;
|
||||
}
|
||||
|
||||
void WasmFunctionBuilder::EditVarIntImmediate(uint32_t offset,
|
||||
const uint32_t immediate) {
|
||||
uint32_t immediate_size = static_cast<uint32_t>(SizeOfVarInt(immediate));
|
||||
// In EmitEditableVarIntImmediate, we guessed that we'd only need one byte.
|
||||
// If we need more, shift everything down to make room for the larger
|
||||
// immediate.
|
||||
if (immediate_size > 1) {
|
||||
uint32_t diff = immediate_size - 1;
|
||||
body_.insert(body_.begin() + offset, diff, 0);
|
||||
|
||||
void WasmFunctionBuilder::EditImmediate(uint32_t offset, const byte immediate) {
|
||||
DCHECK(offset < body_.size());
|
||||
body_[offset] = immediate;
|
||||
for (size_t i = 0; i < local_indices_.size(); ++i) {
|
||||
if (local_indices_[i] >= offset) {
|
||||
local_indices_[i] += diff;
|
||||
}
|
||||
}
|
||||
}
|
||||
DCHECK(offset + immediate_size <= body_.size());
|
||||
byte* p = &body_[offset];
|
||||
EmitVarInt(&p, immediate);
|
||||
}
|
||||
|
||||
|
||||
@ -446,15 +481,6 @@ WasmModuleWriter::WasmModuleWriter(Zone* zone)
|
||||
indirect_functions_(zone),
|
||||
globals_(zone) {}
|
||||
|
||||
size_t SizeOfVarInt(size_t value) {
|
||||
size_t size = 0;
|
||||
do {
|
||||
size++;
|
||||
value = value >> 7;
|
||||
} while (value > 0);
|
||||
return size;
|
||||
}
|
||||
|
||||
struct Sizes {
|
||||
size_t header_size;
|
||||
size_t body_size;
|
||||
@ -485,7 +511,8 @@ WasmModuleIndex* WasmModuleWriter::WriteTo(Zone* zone) const {
|
||||
|
||||
sizes.AddSection(signatures_.size());
|
||||
for (auto sig : signatures_) {
|
||||
sizes.Add(2 + sig->parameter_count(), 0);
|
||||
sizes.Add(1 + SizeOfVarInt(sig->parameter_count()) + sig->parameter_count(),
|
||||
0);
|
||||
}
|
||||
|
||||
sizes.AddSection(globals_.size());
|
||||
@ -510,7 +537,9 @@ WasmModuleIndex* WasmModuleWriter::WriteTo(Zone* zone) const {
|
||||
}
|
||||
|
||||
sizes.AddSection(indirect_functions_.size());
|
||||
sizes.Add(2 * static_cast<uint32_t>(indirect_functions_.size()), 0);
|
||||
for (auto function_index : indirect_functions_) {
|
||||
sizes.Add(SizeOfVarInt(function_index), 0);
|
||||
}
|
||||
|
||||
if (sizes.body_size > 0) sizes.Add(1, 0);
|
||||
|
||||
@ -525,9 +554,9 @@ WasmModuleIndex* WasmModuleWriter::WriteTo(Zone* zone) const {
|
||||
|
||||
// -- emit memory declaration ------------------------------------------------
|
||||
EmitUint8(&header, kDeclMemory);
|
||||
EmitUint8(&header, 16); // min memory size
|
||||
EmitUint8(&header, 16); // max memory size
|
||||
EmitUint8(&header, 0); // memory export
|
||||
EmitVarInt(&header, 16); // min memory size
|
||||
EmitVarInt(&header, 16); // max memory size
|
||||
EmitUint8(&header, 0); // memory export
|
||||
|
||||
// -- emit globals -----------------------------------------------------------
|
||||
if (globals_.size() > 0) {
|
||||
@ -547,7 +576,7 @@ WasmModuleIndex* WasmModuleWriter::WriteTo(Zone* zone) const {
|
||||
EmitVarInt(&header, signatures_.size());
|
||||
|
||||
for (FunctionSig* sig : signatures_) {
|
||||
EmitUint8(&header, static_cast<byte>(sig->parameter_count()));
|
||||
EmitVarInt(&header, sig->parameter_count());
|
||||
if (sig->return_count() > 0) {
|
||||
EmitUint8(&header, WasmOpcodes::LocalTypeCodeFor(sig->GetReturn()));
|
||||
} else {
|
||||
@ -591,7 +620,7 @@ WasmModuleIndex* WasmModuleWriter::WriteTo(Zone* zone) const {
|
||||
EmitVarInt(&header, indirect_functions_.size());
|
||||
|
||||
for (auto index : indirect_functions_) {
|
||||
EmitUint16(&header, index);
|
||||
EmitVarInt(&header, index);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -55,8 +55,9 @@ class WasmFunctionBuilder : public ZoneObject {
|
||||
const uint32_t* local_indices, uint32_t indices_size);
|
||||
void Emit(WasmOpcode opcode);
|
||||
void EmitWithU8(WasmOpcode opcode, const byte immediate);
|
||||
uint32_t EmitEditableImmediate(const byte immediate);
|
||||
void EditImmediate(uint32_t offset, const byte immediate);
|
||||
void EmitWithVarInt(WasmOpcode opcode, uint32_t immediate);
|
||||
uint32_t EmitEditableVarIntImmediate();
|
||||
void EditVarIntImmediate(uint32_t offset, const uint32_t immediate);
|
||||
void Exported(uint8_t flag);
|
||||
void External(uint8_t flag);
|
||||
void SetName(const unsigned char* name, int name_length);
|
||||
|
@ -195,7 +195,7 @@ class ModuleDecoder : public Decoder {
|
||||
if (failed()) break;
|
||||
TRACE("DecodeFunctionTable[%d] module+%d\n", i,
|
||||
static_cast<int>(pc_ - start_));
|
||||
uint16_t index = consume_u16();
|
||||
uint16_t index = consume_u32v(&length);
|
||||
if (index >= module->functions.size()) {
|
||||
error(pc_ - 2, "invalid function index");
|
||||
break;
|
||||
@ -244,7 +244,7 @@ class ModuleDecoder : public Decoder {
|
||||
WasmImport* import = &module->import_table.back();
|
||||
|
||||
const byte* sigpos = pc_;
|
||||
import->sig_index = consume_u16("signature index");
|
||||
import->sig_index = consume_u32v(&length, "signature index");
|
||||
|
||||
if (import->sig_index >= module->signatures.size()) {
|
||||
error(sigpos, "invalid signature index");
|
||||
@ -278,7 +278,7 @@ class ModuleDecoder : public Decoder {
|
||||
WasmExport* exp = &module->export_table.back();
|
||||
|
||||
const byte* sigpos = pc_;
|
||||
exp->func_index = consume_u16("function index");
|
||||
exp->func_index = consume_u32v(&length, "function index");
|
||||
if (exp->func_index >= module->functions.size()) {
|
||||
error(sigpos, sigpos,
|
||||
"function index %u out of bounds (%d functions)",
|
||||
@ -566,7 +566,8 @@ class ModuleDecoder : public Decoder {
|
||||
|
||||
// Parses an inline function signature.
|
||||
FunctionSig* consume_sig() {
|
||||
byte count = consume_u8("param count");
|
||||
int length;
|
||||
byte count = consume_u32v(&length, "param count");
|
||||
LocalType ret = consume_local_type();
|
||||
FunctionSig::Builder builder(module_zone, ret == kAstStmt ? 0 : 1, count);
|
||||
if (ret != kAstStmt) builder.AddReturn(ret);
|
||||
|
@ -16,9 +16,10 @@
|
||||
#define WASM_MODULE_HEADER U32_LE(kWasmMagic), U32_LE(kWasmVersion)
|
||||
|
||||
#define SIG_INDEX(v) U16_LE(v)
|
||||
#define FUNC_INDEX(v) U16_LE(v)
|
||||
#define FUNC_INDEX(v) U32V_1(v)
|
||||
#define NAME_OFFSET(v) U32_LE(v)
|
||||
#define BR_TARGET(v) U16_LE(v)
|
||||
|
||||
#define BR_TARGET(v) U32_LE(v)
|
||||
|
||||
#define MASK_7 ((1 << 7) - 1)
|
||||
#define MASK_14 ((1 << 14) - 1)
|
||||
@ -71,7 +72,7 @@
|
||||
#define WASM_UNREACHABLE kExprUnreachable
|
||||
|
||||
#define WASM_BR_TABLE(key, count, ...) \
|
||||
kExprBrTable, U16_LE(count), __VA_ARGS__, key
|
||||
kExprBrTable, U32V_1(count), __VA_ARGS__, key
|
||||
|
||||
#define WASM_CASE(x) static_cast<byte>(x), static_cast<byte>(x >> 8)
|
||||
#define WASM_CASE_BR(x) static_cast<byte>(x), static_cast<byte>(0x80 | (x) >> 8)
|
||||
|
@ -64,7 +64,7 @@ static const size_t kDeclDataSegmentSize = 13;
|
||||
struct WasmFunction {
|
||||
FunctionSig* sig; // signature of the function.
|
||||
uint32_t func_index; // index into the function table.
|
||||
uint16_t sig_index; // index into the signature table.
|
||||
uint32_t sig_index; // index into the signature table.
|
||||
uint32_t name_offset; // offset in the module bytes of the name, if any.
|
||||
uint32_t code_start_offset; // offset in the module bytes of code start.
|
||||
uint32_t code_end_offset; // offset in the module bytes of code end.
|
||||
@ -79,14 +79,14 @@ struct WasmFunction {
|
||||
// Static representation of an imported WASM function.
|
||||
struct WasmImport {
|
||||
FunctionSig* sig; // signature of the function.
|
||||
uint16_t sig_index; // index into the signature table.
|
||||
uint32_t sig_index; // index into the signature table.
|
||||
uint32_t module_name_offset; // offset in module bytes of the module name.
|
||||
uint32_t function_name_offset; // offset in module bytes of the import name.
|
||||
};
|
||||
|
||||
// Static representation of an exported WASM function.
|
||||
struct WasmExport {
|
||||
uint16_t func_index; // index into the function table.
|
||||
uint32_t func_index; // index into the function table.
|
||||
uint32_t name_offset; // offset in module bytes of the name to export.
|
||||
};
|
||||
|
||||
|
@ -1089,7 +1089,7 @@ TEST(Run_Wasm_BrTable_br2) {
|
||||
TEST(Run_Wasm_BrTable4) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
for (int t = 0; t < 4; t++) {
|
||||
uint16_t cases[] = {0, 1, 2, 3};
|
||||
uint32_t cases[] = {0, 1, 2, 3};
|
||||
cases[i] = t;
|
||||
byte code[] = {B2(B2(B2(B2(B1(WASM_BR_TABLE(
|
||||
WASM_GET_LOCAL(0), 3, BR_TARGET(cases[0]),
|
||||
@ -1119,7 +1119,7 @@ TEST(Run_Wasm_BrTable4x4) {
|
||||
for (byte c = 0; c < 4; c++) {
|
||||
for (byte d = 0; d < 4; d++) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
uint16_t cases[] = {a, b, c, d};
|
||||
uint32_t cases[] = {a, b, c, d};
|
||||
byte code[] = {
|
||||
B2(B2(B2(B2(B1(WASM_BR_TABLE(
|
||||
WASM_GET_LOCAL(0), 3, BR_TARGET(cases[0]),
|
||||
|
@ -164,7 +164,7 @@ WasmModuleBuilder.prototype.toArray = function(debug) {
|
||||
emit_varint(bytes, this.signatures.length);
|
||||
for (sig of this.signatures) {
|
||||
var params = sig.length - 1;
|
||||
emit_u8(bytes, params);
|
||||
emit_varint(bytes, params);
|
||||
for (var j = 0; j < sig.length; j++) {
|
||||
emit_u8(bytes, sig[j]);
|
||||
}
|
||||
@ -177,7 +177,7 @@ WasmModuleBuilder.prototype.toArray = function(debug) {
|
||||
emit_u8(bytes, kDeclImportTable);
|
||||
emit_varint(bytes, this.imports.length);
|
||||
for (imp of this.imports) {
|
||||
emit_u16(bytes, imp.sig_index);
|
||||
emit_varint(bytes, imp.sig_index);
|
||||
emit_string(bytes, imp.module);
|
||||
if (imp.name == undefined) {
|
||||
emit_u32(bytes, 0);
|
||||
@ -228,7 +228,7 @@ WasmModuleBuilder.prototype.toArray = function(debug) {
|
||||
local_decls.push({count: l.f64_count, type: kAstF64});
|
||||
}
|
||||
}
|
||||
emit_u8(bytes, local_decls.length);
|
||||
emit_varint(bytes, local_decls.length);
|
||||
for (decl of local_decls) {
|
||||
emit_varint(bytes, decl.count);
|
||||
emit_u8(bytes, decl.type);
|
||||
@ -257,7 +257,7 @@ WasmModuleBuilder.prototype.toArray = function(debug) {
|
||||
emit_u8(bytes, kDeclFunctionTable);
|
||||
emit_varint(bytes, this.function_table.length);
|
||||
for (index of this.function_table) {
|
||||
emit_u16(bytes, index);
|
||||
emit_varint(bytes, index);
|
||||
}
|
||||
}
|
||||
|
||||
@ -267,7 +267,7 @@ WasmModuleBuilder.prototype.toArray = function(debug) {
|
||||
emit_varint(bytes, exports);
|
||||
for (func of this.functions) {
|
||||
for (exp of func.exports) {
|
||||
emit_u16(bytes, func.index);
|
||||
emit_varint(bytes, func.index);
|
||||
emit_string(bytes, exp);
|
||||
}
|
||||
}
|
||||
|
@ -108,6 +108,80 @@ TEST_F(EncoderTest, Function_Builder_Indexing_Variable_Width) {
|
||||
body = buffer + f->HeaderSize();
|
||||
}
|
||||
|
||||
TEST_F(EncoderTest, Function_Builder_Block_Variable_Width) {
|
||||
Zone zone;
|
||||
WasmModuleBuilder* builder = new (&zone) WasmModuleBuilder(&zone);
|
||||
uint16_t f_index = builder->AddFunction();
|
||||
WasmFunctionBuilder* function = builder->FunctionAt(f_index);
|
||||
function->EmitWithVarInt(kExprBlock, 200);
|
||||
for (int i = 0; i < 200; ++i) {
|
||||
function->Emit(kExprNop);
|
||||
}
|
||||
|
||||
WasmFunctionEncoder* f = function->Build(&zone, builder);
|
||||
CHECK_EQ(f->BodySize(), 204);
|
||||
}
|
||||
|
||||
TEST_F(EncoderTest, Function_Builder_EmitEditableVarIntImmediate) {
|
||||
Zone zone;
|
||||
WasmModuleBuilder* builder = new (&zone) WasmModuleBuilder(&zone);
|
||||
uint16_t f_index = builder->AddFunction();
|
||||
WasmFunctionBuilder* function = builder->FunctionAt(f_index);
|
||||
function->Emit(kExprLoop);
|
||||
uint32_t offset = function->EmitEditableVarIntImmediate();
|
||||
for (int i = 0; i < 200; ++i) {
|
||||
function->Emit(kExprNop);
|
||||
}
|
||||
function->EditVarIntImmediate(offset, 200);
|
||||
|
||||
WasmFunctionEncoder* f = function->Build(&zone, builder);
|
||||
CHECK_EQ(f->BodySize(), 204);
|
||||
}
|
||||
|
||||
TEST_F(EncoderTest, Function_Builder_EmitEditableVarIntImmediate_Locals) {
|
||||
Zone zone;
|
||||
WasmModuleBuilder* builder = new (&zone) WasmModuleBuilder(&zone);
|
||||
uint16_t f_index = builder->AddFunction();
|
||||
WasmFunctionBuilder* function = builder->FunctionAt(f_index);
|
||||
function->Emit(kExprBlock);
|
||||
uint32_t offset = function->EmitEditableVarIntImmediate();
|
||||
for (int i = 0; i < 200; ++i) {
|
||||
AddLocal(function, kAstI32);
|
||||
}
|
||||
function->EditVarIntImmediate(offset, 200);
|
||||
|
||||
WasmFunctionEncoder* f = function->Build(&zone, builder);
|
||||
ZoneVector<uint8_t> buffer_vector(f->HeaderSize() + f->BodySize(), &zone);
|
||||
byte* buffer = &buffer_vector[0];
|
||||
byte* header = buffer;
|
||||
byte* body = buffer + f->HeaderSize();
|
||||
f->Serialize(buffer, &header, &body);
|
||||
body = buffer + f->HeaderSize();
|
||||
|
||||
CHECK_EQ(f->BodySize(), 479);
|
||||
const uint8_t varint200_low = (200 & 0x7f) | 0x80;
|
||||
const uint8_t varint200_high = (200 >> 7) & 0x7f;
|
||||
offset = 0;
|
||||
CHECK_EQ(body[offset++], 1); // Local decl count.
|
||||
CHECK_EQ(body[offset++], varint200_low);
|
||||
CHECK_EQ(body[offset++], varint200_high);
|
||||
CHECK_EQ(body[offset++], kLocalI32);
|
||||
CHECK_EQ(body[offset++], kExprBlock);
|
||||
CHECK_EQ(body[offset++], varint200_low);
|
||||
CHECK_EQ(body[offset++], varint200_high);
|
||||
// GetLocal with one-byte indices.
|
||||
for (int i = 0; i <= 127; ++i) {
|
||||
CHECK_EQ(body[offset++], kExprGetLocal);
|
||||
CHECK_EQ(body[offset++], i);
|
||||
}
|
||||
// GetLocal with two-byte indices.
|
||||
for (int i = 128; i < 200; ++i) {
|
||||
CHECK_EQ(body[offset++], kExprGetLocal);
|
||||
CHECK_EQ(body[offset++], (i & 0x7f) | 0x80);
|
||||
CHECK_EQ(body[offset++], (i >> 7) & 0x7f);
|
||||
}
|
||||
CHECK_EQ(offset, 479);
|
||||
}
|
||||
|
||||
TEST_F(EncoderTest, LEB_Functions) {
|
||||
byte leb_value[5] = {0, 0, 0, 0, 0};
|
||||
|
@ -681,10 +681,7 @@ TEST_F(WasmModuleVerifyTest, DataSegmentWithInvalidDest) {
|
||||
|
||||
|
||||
// To make below tests for indirect calls much shorter.
|
||||
#define FUNCTION(sig_index, external) \
|
||||
kDeclFunctionImport, static_cast<byte>(sig_index), \
|
||||
static_cast<byte>(sig_index >> 8)
|
||||
|
||||
#define FUNCTION(sig_index, external) kDeclFunctionImport, SIG_INDEX(sig_index)
|
||||
|
||||
TEST_F(WasmModuleVerifyTest, OneIndirectFunction) {
|
||||
static const byte data[] = {
|
||||
@ -693,7 +690,7 @@ TEST_F(WasmModuleVerifyTest, OneIndirectFunction) {
|
||||
// func#0 ------------------------------------------------------
|
||||
kDeclFunctions, 1, FUNCTION(0, 0),
|
||||
// indirect table ----------------------------------------------
|
||||
kDeclFunctionTable, 1, 0, 0};
|
||||
kDeclFunctionTable, 1, U32V_1(0)};
|
||||
|
||||
ModuleResult result = DecodeModule(data, data + arraysize(data));
|
||||
EXPECT_TRUE(result.ok());
|
||||
@ -719,14 +716,14 @@ TEST_F(WasmModuleVerifyTest, MultipleIndirectFunctions) {
|
||||
FUNCTION(1, 1), // --
|
||||
// indirect table ----------------------------------------------
|
||||
kDeclFunctionTable, 8,
|
||||
U16_LE(0), // --
|
||||
U16_LE(1), // --
|
||||
U16_LE(2), // --
|
||||
U16_LE(3), // --
|
||||
U16_LE(0), // --
|
||||
U16_LE(1), // --
|
||||
U16_LE(2), // --
|
||||
U16_LE(3), // --
|
||||
U32V_1(0), // --
|
||||
U32V_1(1), // --
|
||||
U32V_1(2), // --
|
||||
U32V_1(3), // --
|
||||
U32V_1(0), // --
|
||||
U32V_1(1), // --
|
||||
U32V_1(2), // --
|
||||
U32V_1(3), // --
|
||||
};
|
||||
|
||||
ModuleResult result = DecodeModule(data, data + arraysize(data));
|
||||
@ -1087,7 +1084,7 @@ TEST_F(WasmModuleVerifyTest, ImportTable_one_sig) {
|
||||
VOID_VOID_SIG,
|
||||
kDeclImportTable,
|
||||
1, // --
|
||||
SIG_INDEX(0), // sig index
|
||||
U32V_1(0), // sig index
|
||||
NAME_OFFSET(1), // module name
|
||||
NAME_OFFSET(1) // function name
|
||||
};
|
||||
|
@ -93,7 +93,7 @@ TEST_F(WasmMacroGenTest, MacroStatements) {
|
||||
}
|
||||
|
||||
TEST_F(WasmMacroGenTest, BrTable) {
|
||||
EXPECT_SIZE(7, WASM_BR_TABLE(WASM_ZERO, 1, BR_TARGET(1)));
|
||||
EXPECT_SIZE(8, WASM_BR_TABLE(WASM_ZERO, 1, BR_TARGET(1)));
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user