Commit 4531c865 authored by Clemens Hammacher's avatar Clemens Hammacher Committed by Commit Bot

[wasm] Reuse LEB encoding logic in module builder

Instead of using the WASM_I32V_* macros (and other) from
wasm-macro-gen.h, use the appropriate methods to encode LEB integers.
This also saves some spaces for the wasm bytecode generated from asm.js.

Specifically, this CL
1) renames EmitVarInt to EmitI32V and EmitVarUint to EmitU32V (on
   WasmFunctionBuilder).
2) introduces more methods on the WasmFunctionBuilder to emit i64v,
   u64v, f32, and f64 values.
3) uses the ZoneBuffer instead of a plain ZoneVector<char> in the
   WasmFunctionBuilder to build the body of the function.
4) introduces more helper functions on the ZoneBuffer to encode i64v,
   u64v, f32 and f64 values.

R=ahaas@chromium.org

Change-Id: Ifa59a6a67380ecf9a3823c382daf00855f5bc61e
Reviewed-on: https://chromium-review.googlesource.com/486803Reviewed-by: 's avatarAndreas Haas <ahaas@chromium.org>
Commit-Queue: Clemens Hammacher <clemensh@chromium.org>
Cr-Commit-Position: refs/heads/master@{#44842}
parent fe916cd2
......@@ -369,8 +369,8 @@ void AsmJsParser::ValidateModule() {
uint32_t import_index = module_builder_->AddGlobalImport(
global_import.import_name.start(), global_import.import_name.length(),
global_import.value_type);
start->EmitWithVarInt(kExprGetGlobal, import_index);
start->EmitWithVarInt(kExprSetGlobal, VarIndex(global_import.var_info));
start->EmitWithI32V(kExprGetGlobal, import_index);
start->EmitWithI32V(kExprSetGlobal, VarIndex(global_import.var_info));
}
start->Emit(kExprEnd);
FunctionSig::Builder b(zone(), 0, 0);
......@@ -879,8 +879,7 @@ void AsmJsParser::ValidateFunctionLocals(
info->type = AsmType::Double();
info->index = static_cast<uint32_t>(param_count + locals->size());
locals->push_back(kWasmF64);
byte code[] = {WASM_F64(-dvalue)};
current_function_builder_->EmitCode(code, sizeof(code));
current_function_builder_->EmitF64Const(-dvalue);
current_function_builder_->EmitSetLocal(info->index);
} else if (CheckForUnsigned(&uvalue)) {
if (uvalue > 0x7fffffff) {
......@@ -914,7 +913,7 @@ void AsmJsParser::ValidateFunctionLocals(
} else {
FAIL("Bad local variable definition");
}
current_function_builder_->EmitWithVarInt(kExprGetGlobal,
current_function_builder_->EmitWithI32V(kExprGetGlobal,
VarIndex(sinfo));
current_function_builder_->EmitSetLocal(info->index);
} else if (sinfo->type->IsA(stdlib_fround_)) {
......@@ -932,8 +931,7 @@ void AsmJsParser::ValidateFunctionLocals(
if (negate) {
dvalue = -dvalue;
}
byte code[] = {WASM_F32(dvalue)};
current_function_builder_->EmitCode(code, sizeof(code));
current_function_builder_->EmitF32Const(dvalue);
current_function_builder_->EmitSetLocal(info->index);
} else if (CheckForUnsigned(&uvalue)) {
if (uvalue > 0x7fffffff) {
......@@ -947,9 +945,8 @@ void AsmJsParser::ValidateFunctionLocals(
if (negate) {
value = -value;
}
double fvalue = static_cast<double>(value);
byte code[] = {WASM_F32(fvalue)};
current_function_builder_->EmitCode(code, sizeof(code));
float fvalue = static_cast<float>(value);
current_function_builder_->EmitF32Const(fvalue);
current_function_builder_->EmitSetLocal(info->index);
} else {
FAIL("Expected variable initial value");
......@@ -963,8 +960,7 @@ void AsmJsParser::ValidateFunctionLocals(
info->type = AsmType::Double();
info->index = static_cast<uint32_t>(param_count + locals->size());
locals->push_back(kWasmF64);
byte code[] = {WASM_F64(dvalue)};
current_function_builder_->EmitCode(code, sizeof(code));
current_function_builder_->EmitF64Const(dvalue);
current_function_builder_->EmitSetLocal(info->index);
} else if (CheckForUnsigned(&uvalue)) {
info->kind = VarKind::kLocal;
......@@ -1218,7 +1214,7 @@ void AsmJsParser::BreakStatement() {
FAIL("Illegal break");
}
current_function_builder_->Emit(kExprBr);
current_function_builder_->EmitVarInt(depth);
current_function_builder_->EmitI32V(depth);
SkipSemicolon();
}
......@@ -1234,8 +1230,7 @@ void AsmJsParser::ContinueStatement() {
if (depth < 0) {
FAIL("Illegal continue");
}
current_function_builder_->Emit(kExprBr);
current_function_builder_->EmitVarInt(depth);
current_function_builder_->EmitWithI32V(kExprBr, depth);
SkipSemicolon();
}
......@@ -1280,9 +1275,9 @@ void AsmJsParser::SwitchStatement() {
current_function_builder_->EmitGetLocal(tmp);
current_function_builder_->EmitI32Const(c);
current_function_builder_->Emit(kExprI32Eq);
current_function_builder_->EmitWithVarInt(kExprBrIf, table_pos++);
current_function_builder_->EmitWithI32V(kExprBrIf, table_pos++);
}
current_function_builder_->EmitWithVarInt(kExprBr, table_pos++);
current_function_builder_->EmitWithI32V(kExprBr, table_pos++);
while (!failed_ && Peek(TOK(case))) {
current_function_builder_->Emit(kExprEnd);
BareEnd();
......@@ -1367,8 +1362,7 @@ AsmType* AsmJsParser::NumericLiteral() {
double dvalue = 0.0;
uint64_t uvalue = 0;
if (CheckForDouble(&dvalue)) {
byte code[] = {WASM_F64(dvalue)};
current_function_builder_->EmitCode(code, sizeof(code));
current_function_builder_->EmitF64Const(dvalue);
return AsmType::Double();
} else if (CheckForUnsigned(&uvalue)) {
if (uvalue <= 0x7fffffff) {
......@@ -1400,7 +1394,7 @@ AsmType* AsmJsParser::Identifier() {
if (info->kind != VarKind::kGlobal) {
FAILn("Undefined global variable");
}
current_function_builder_->EmitWithVarInt(kExprGetGlobal, VarIndex(info));
current_function_builder_->EmitWithI32V(kExprGetGlobal, VarIndex(info));
return info->type;
}
UNREACHABLE();
......@@ -1505,10 +1499,8 @@ AsmType* AsmJsParser::AssignmentExpression() {
if (!info->mutable_variable) {
FAILn("Expected mutable variable in assignment");
}
current_function_builder_->EmitWithVarUint(kExprSetGlobal,
VarIndex(info));
current_function_builder_->EmitWithVarUint(kExprGetGlobal,
VarIndex(info));
current_function_builder_->EmitWithU32V(kExprSetGlobal, VarIndex(info));
current_function_builder_->EmitWithU32V(kExprGetGlobal, VarIndex(info));
} else {
UNREACHABLE();
}
......@@ -2159,8 +2151,7 @@ AsmType* AsmJsParser::ValidateCall() {
function_info->import->cache[sig] = index;
}
current_function_builder_->AddAsmWasmOffset(call_pos, to_number_pos);
current_function_builder_->Emit(kExprCallFunction);
current_function_builder_->EmitVarUint(index);
current_function_builder_->EmitWithU32V(kExprCallFunction, index);
} else if (function_info->kind > VarKind::kImportedFunction) {
AsmCallableType* callable = function_info->type->AsCallableType();
if (!callable) {
......@@ -2294,8 +2285,8 @@ AsmType* AsmJsParser::ValidateCall() {
current_function_builder_->EmitGetLocal(tmp.get()->get());
current_function_builder_->AddAsmWasmOffset(call_pos, to_number_pos);
current_function_builder_->Emit(kExprCallIndirect);
current_function_builder_->EmitVarUint(signature_index);
current_function_builder_->EmitVarUint(0); // table index
current_function_builder_->EmitU32V(signature_index);
current_function_builder_->EmitU32V(0); // table index
} else {
current_function_builder_->AddAsmWasmOffset(call_pos, to_number_pos);
current_function_builder_->Emit(kExprCallFunction);
......
......@@ -109,7 +109,7 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
foreign_init_function_->EmitGetLocal(static_cast<uint32_t>(pos));
ForeignVariable* fv = &foreign_variables_[pos];
uint32_t index = LookupOrInsertGlobal(fv->var, fv->type);
foreign_init_function_->EmitWithVarUint(kExprSetGlobal, index);
foreign_init_function_->EmitWithU32V(kExprSetGlobal, index);
}
foreign_init_function_->Emit(kExprEnd);
}
......@@ -324,7 +324,7 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
auto elem = breakable_blocks_.at(i);
if (elem.first == target && elem.second == type) {
int block_distance = static_cast<int>(breakable_blocks_.size() - i - 1);
current_function_builder_->EmitWithVarUint(kExprBr, block_distance);
current_function_builder_->EmitWithU32V(kExprBr, block_distance);
return;
}
}
......@@ -395,8 +395,8 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
current_function_builder_->EmitWithU8(kExprIf, kLocalVoid);
DCHECK(case_to_block.find(node->begin) != case_to_block.end());
current_function_builder_->Emit(kExprBr);
current_function_builder_->EmitVarUint(1 + if_depth +
case_to_block[node->begin]);
current_function_builder_->EmitU32V(1 + if_depth +
case_to_block[node->begin]);
current_function_builder_->Emit(kExprEnd);
} else {
if (node->begin != 0) {
......@@ -407,21 +407,21 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
VisitVariableProxy(tag);
}
current_function_builder_->Emit(kExprBrTable);
current_function_builder_->EmitVarUint(node->end - node->begin + 1);
current_function_builder_->EmitU32V(node->end - node->begin + 1);
for (int v = node->begin; v <= node->end; ++v) {
if (case_to_block.find(v) != case_to_block.end()) {
uint32_t target = if_depth + case_to_block[v];
current_function_builder_->EmitVarUint(target);
current_function_builder_->EmitU32V(target);
} else {
uint32_t target = if_depth + default_block;
current_function_builder_->EmitVarUint(target);
current_function_builder_->EmitU32V(target);
}
if (v == kMaxInt) {
break;
}
}
uint32_t target = if_depth + default_block;
current_function_builder_->EmitVarUint(target);
current_function_builder_->EmitU32V(target);
}
while (if_depth-- != prev_if_depth) {
......@@ -469,7 +469,7 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
if (root->left != nullptr || root->right != nullptr ||
root->begin == root->end) {
current_function_builder_->Emit(kExprBr);
current_function_builder_->EmitVarUint(default_block);
current_function_builder_->EmitU32V(default_block);
}
}
for (int i = 0; i < case_count; ++i) {
......@@ -649,8 +649,7 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
}
default: { return false; }
}
byte code[] = {WASM_F64(value)};
current_function_builder_->EmitCode(code, sizeof(code));
current_function_builder_->EmitF64Const(value);
return true;
}
......@@ -663,7 +662,7 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
ValueType var_type = TypeOf(expr);
DCHECK_NE(kWasmStmt, var_type);
if (var->IsContextSlot()) {
current_function_builder_->EmitWithVarUint(
current_function_builder_->EmitWithU32V(
kExprGetGlobal, LookupOrInsertGlobal(var, var_type));
} else {
current_function_builder_->EmitGetLocal(
......@@ -699,17 +698,14 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
// The parser can collapse !0, !1 etc to true / false.
// Allow these as int literals.
if (expr->raw_value()->IsTrue()) {
byte code[] = {WASM_ONE};
current_function_builder_->EmitCode(code, sizeof(code));
current_function_builder_->EmitI32Const(1);
} else if (expr->raw_value()->IsFalse()) {
byte code[] = {WASM_ZERO};
current_function_builder_->EmitCode(code, sizeof(code));
current_function_builder_->EmitI32Const(0);
} else if (expr->raw_value()->IsNumber()) {
// This can happen when -x becomes x * -1 (due to the parser).
int32_t i = 0;
CHECK(value->ToInt32(&i) && i == -1);
byte code[] = {WASM_I32V_1(-1)};
current_function_builder_->EmitCode(code, sizeof(code));
current_function_builder_->EmitI32Const(-1);
} else {
UNREACHABLE();
}
......@@ -717,16 +713,14 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
// TODO(bradnelson): Pattern match the case where negation occurs and
// emit f64.neg instead.
double val = expr->raw_value()->AsNumber();
byte code[] = {WASM_F64(val)};
current_function_builder_->EmitCode(code, sizeof(code));
current_function_builder_->EmitF64Const(val);
} else if (type->IsA(AsmType::Float())) {
// This can happen when -fround(x) becomes fround(x) * 1.0[float]
// (due to the parser).
// TODO(bradnelson): Pattern match this and emit f32.neg instead.
double val = expr->raw_value()->AsNumber();
DCHECK_EQ(-1.0, val);
byte code[] = {WASM_F32(val)};
current_function_builder_->EmitCode(code, sizeof(code));
current_function_builder_->EmitF32Const(val);
} else {
UNREACHABLE();
}
......@@ -958,9 +952,9 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
DCHECK_NE(kWasmStmt, var_type);
if (var->IsContextSlot()) {
uint32_t index = LookupOrInsertGlobal(var, var_type);
current_function_builder_->EmitWithVarUint(kExprSetGlobal, index);
current_function_builder_->EmitWithU32V(kExprSetGlobal, index);
if (fate == kLeaveOnStack) {
current_function_builder_->EmitWithVarUint(kExprGetGlobal, index);
current_function_builder_->EmitWithU32V(kExprGetGlobal, index);
}
} else {
if (fate == kDrop) {
......@@ -1260,13 +1254,12 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
// if set_local(tmp, x) < 0
Visit(call->arguments()->at(0));
current_function_builder_->EmitTeeLocal(tmp.index());
byte code[] = {WASM_ZERO};
current_function_builder_->EmitCode(code, sizeof(code));
current_function_builder_->EmitI32Const(0);
current_function_builder_->Emit(kExprI32LtS);
current_function_builder_->EmitWithU8(kExprIf, kLocalI32);
// then (0 - tmp)
current_function_builder_->EmitCode(code, sizeof(code));
current_function_builder_->EmitI32Const(0);
current_function_builder_->EmitGetLocal(tmp.index());
current_function_builder_->Emit(kExprI32Sub);
......@@ -1382,8 +1375,7 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
// constant fold Math.fround(#const);
if (literal->raw_value()->IsNumber()) {
float val = static_cast<float>(literal->raw_value()->AsNumber());
byte code[] = {WASM_F32(val)};
current_function_builder_->EmitCode(code, sizeof(code));
current_function_builder_->EmitF32Const(val);
return true;
}
}
......@@ -1470,7 +1462,7 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
int parent_pos = returns_value ? parent_binop->position() : pos;
current_function_builder_->AddAsmWasmOffset(pos, parent_pos);
current_function_builder_->Emit(kExprCallFunction);
current_function_builder_->EmitVarUint(index);
current_function_builder_->EmitU32V(index);
} else {
WasmFunctionBuilder* function = LookupOrInsertFunction(vp->var());
VisitCallArgs(expr);
......@@ -1504,8 +1496,8 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
current_function_builder_->AddAsmWasmOffset(expr->position(),
expr->position());
current_function_builder_->Emit(kExprCallIndirect);
current_function_builder_->EmitVarUint(indices->signature_index);
current_function_builder_->EmitVarUint(0); // table index
current_function_builder_->EmitU32V(indices->signature_index);
current_function_builder_->EmitU32V(0); // table index
returns_value =
builder_->GetSignature(indices->signature_index)->return_count() >
0;
......
......@@ -5,12 +5,16 @@
#ifndef V8_WASM_LEB_HELPER_H_
#define V8_WASM_LEB_HELPER_H_
#include <cstddef>
#include <cstdint>
namespace v8 {
namespace internal {
namespace wasm {
static const size_t kPaddedVarInt32Size = 5;
static const size_t kMaxVarInt32Size = 5;
constexpr size_t kPaddedVarInt32Size = 5;
constexpr size_t kMaxVarInt32Size = 5;
constexpr size_t kMaxVarInt64Size = 10;
class LEBHelper {
public:
......
......@@ -32,6 +32,8 @@ namespace v8 {
namespace internal {
namespace wasm {
namespace {
// Emit a section code and the size as a padded varint that can be patched
// later.
size_t EmitSection(SectionCode code, ZoneBuffer& buffer) {
......@@ -48,6 +50,8 @@ void FixupSection(ZoneBuffer& buffer, size_t start) {
kPaddedVarInt32Size));
}
} // namespace
WasmFunctionBuilder::WasmFunctionBuilder(WasmModuleBuilder* builder)
: builder_(builder),
locals_(builder->zone()),
......@@ -63,21 +67,9 @@ WasmFunctionBuilder::WasmFunctionBuilder(WasmModuleBuilder* builder)
direct_calls_(builder->zone()),
asm_offsets_(builder->zone(), 8) {}
void WasmFunctionBuilder::EmitVarInt(int32_t val) {
byte buffer[5];
byte* ptr = buffer;
LEBHelper::write_i32v(&ptr, val);
DCHECK_GE(5, ptr - buffer);
body_.insert(body_.end(), buffer, ptr);
}
void WasmFunctionBuilder::EmitI32V(int32_t val) { body_.write_i32v(val); }
void WasmFunctionBuilder::EmitVarUint(uint32_t val) {
byte buffer[5];
byte* ptr = buffer;
LEBHelper::write_u32v(&ptr, val);
DCHECK_GE(5, ptr - buffer);
body_.insert(body_.end(), buffer, ptr);
}
void WasmFunctionBuilder::EmitU32V(uint32_t val) { body_.write_u32v(val); }
void WasmFunctionBuilder::SetSignature(FunctionSig* sig) {
DCHECK(!locals_.has_sig());
......@@ -91,52 +83,62 @@ uint32_t WasmFunctionBuilder::AddLocal(ValueType type) {
}
void WasmFunctionBuilder::EmitGetLocal(uint32_t local_index) {
EmitWithVarUint(kExprGetLocal, local_index);
EmitWithU32V(kExprGetLocal, local_index);
}
void WasmFunctionBuilder::EmitSetLocal(uint32_t local_index) {
EmitWithVarUint(kExprSetLocal, local_index);
EmitWithU32V(kExprSetLocal, local_index);
}
void WasmFunctionBuilder::EmitTeeLocal(uint32_t local_index) {
EmitWithVarUint(kExprTeeLocal, local_index);
EmitWithU32V(kExprTeeLocal, local_index);
}
void WasmFunctionBuilder::EmitCode(const byte* code, uint32_t code_size) {
for (size_t i = 0; i < code_size; ++i) {
body_.push_back(code[i]);
}
body_.write(code, code_size);
}
void WasmFunctionBuilder::Emit(WasmOpcode opcode) {
body_.push_back(static_cast<byte>(opcode));
}
void WasmFunctionBuilder::Emit(WasmOpcode opcode) { body_.write_u8(opcode); }
void WasmFunctionBuilder::EmitWithU8(WasmOpcode opcode, const byte immediate) {
body_.push_back(static_cast<byte>(opcode));
body_.push_back(immediate);
body_.write_u8(opcode);
body_.write_u8(immediate);
}
void WasmFunctionBuilder::EmitWithU8U8(WasmOpcode opcode, const byte imm1,
const byte imm2) {
body_.push_back(static_cast<byte>(opcode));
body_.push_back(imm1);
body_.push_back(imm2);
body_.write_u8(opcode);
body_.write_u8(imm1);
body_.write_u8(imm2);
}
void WasmFunctionBuilder::EmitWithVarInt(WasmOpcode opcode, int32_t immediate) {
body_.push_back(static_cast<byte>(opcode));
EmitVarInt(immediate);
void WasmFunctionBuilder::EmitWithI32V(WasmOpcode opcode, int32_t immediate) {
body_.write_u8(opcode);
body_.write_i32v(immediate);
}
void WasmFunctionBuilder::EmitWithVarUint(WasmOpcode opcode,
uint32_t immediate) {
body_.push_back(static_cast<byte>(opcode));
EmitVarUint(immediate);
void WasmFunctionBuilder::EmitWithU32V(WasmOpcode opcode, uint32_t immediate) {
body_.write_u8(opcode);
body_.write_u32v(immediate);
}
void WasmFunctionBuilder::EmitI32Const(int32_t value) {
EmitWithVarInt(kExprI32Const, value);
EmitWithI32V(kExprI32Const, value);
}
void WasmFunctionBuilder::EmitI64Const(int64_t value) {
body_.write_u8(kExprI64Const);
body_.write_i64v(value);
}
void WasmFunctionBuilder::EmitF32Const(float value) {
body_.write_u8(kExprF32Const);
body_.write_f32(value);
}
void WasmFunctionBuilder::EmitF64Const(double value) {
body_.write_u8(kExprF64Const);
body_.write_f64(value);
}
void WasmFunctionBuilder::EmitDirectCallIndex(uint32_t index) {
......@@ -144,8 +146,8 @@ void WasmFunctionBuilder::EmitDirectCallIndex(uint32_t index) {
call.offset = body_.size();
call.direct_index = index;
direct_calls_.push_back(call);
byte code[] = {U32V_5(0)};
EmitCode(code, sizeof(code));
byte placeholder_bytes[kMaxVarInt32Size] = {0};
EmitCode(placeholder_bytes, arraysize(placeholder_bytes));
}
void WasmFunctionBuilder::ExportAs(Vector<const char> name) {
......@@ -187,7 +189,7 @@ void WasmFunctionBuilder::SetAsmFunctionStartPosition(int position) {
void WasmFunctionBuilder::DeleteCodeAfter(size_t position) {
DCHECK_LE(position, body_.size());
body_.resize(position);
body_.Truncate(position);
}
void WasmFunctionBuilder::WriteSignature(ZoneBuffer& buffer) const {
......@@ -212,7 +214,7 @@ void WasmFunctionBuilder::WriteBody(ZoneBuffer& buffer) const {
(*ptr) += locals_size; // UGLY: manual bump of position pointer
if (body_.size() > 0) {
size_t base = buffer.offset();
buffer.write(&body_[0], body_.size());
buffer.write(body_.begin(), body_.size());
for (DirectCallIndex call : direct_calls_) {
buffer.patch_u32v(
base + call.offset,
......@@ -425,59 +427,51 @@ void WasmModuleBuilder::WriteTo(ZoneBuffer& buffer) const {
buffer.write_u8(WasmOpcodes::ValueTypeCodeFor(global.type));
buffer.write_u8(global.mutability ? 1 : 0);
switch (global.init.kind) {
case WasmInitExpr::kI32Const: {
case WasmInitExpr::kI32Const:
DCHECK_EQ(kWasmI32, global.type);
const byte code[] = {WASM_I32V_5(global.init.val.i32_const)};
buffer.write(code, sizeof(code));
buffer.write_u8(kExprI32Const);
buffer.write_i32v(global.init.val.i32_const);
break;
}
case WasmInitExpr::kI64Const: {
case WasmInitExpr::kI64Const:
DCHECK_EQ(kWasmI64, global.type);
const byte code[] = {WASM_I64V_10(global.init.val.i64_const)};
buffer.write(code, sizeof(code));
buffer.write_u8(kExprI64Const);
buffer.write_i64v(global.init.val.i64_const);
break;
}
case WasmInitExpr::kF32Const: {
case WasmInitExpr::kF32Const:
DCHECK_EQ(kWasmF32, global.type);
const byte code[] = {WASM_F32(global.init.val.f32_const)};
buffer.write(code, sizeof(code));
buffer.write_u8(kExprF32Const);
buffer.write_f32(global.init.val.f32_const);
break;
}
case WasmInitExpr::kF64Const: {
case WasmInitExpr::kF64Const:
DCHECK_EQ(kWasmF64, global.type);
const byte code[] = {WASM_F64(global.init.val.f64_const)};
buffer.write(code, sizeof(code));
buffer.write_u8(kExprF64Const);
buffer.write_f64(global.init.val.f64_const);
break;
}
case WasmInitExpr::kGlobalIndex: {
const byte code[] = {kExprGetGlobal,
U32V_5(global.init.val.global_index)};
buffer.write(code, sizeof(code));
case WasmInitExpr::kGlobalIndex:
buffer.write_u8(kExprGetGlobal);
buffer.write_u32v(global.init.val.global_index);
break;
}
default: {
// No initializer, emit a default value.
switch (global.type) {
case kWasmI32: {
const byte code[] = {WASM_I32V_1(0)};
buffer.write(code, sizeof(code));
case kWasmI32:
buffer.write_u8(kExprI32Const);
// LEB encoding of 0.
buffer.write_u8(0);
break;
}
case kWasmI64: {
const byte code[] = {WASM_I64V_1(0)};
buffer.write(code, sizeof(code));
case kWasmI64:
buffer.write_u8(kExprI64Const);
// LEB encoding of 0.
buffer.write_u8(0);
break;
}
case kWasmF32: {
const byte code[] = {WASM_F32(0.0)};
buffer.write(code, sizeof(code));
case kWasmF32:
buffer.write_u8(kExprF32Const);
buffer.write_f32(0.f);
break;
}
case kWasmF64: {
const byte code[] = {WASM_F64(0.0)};
buffer.write(code, sizeof(code));
case kWasmF64:
buffer.write_u8(kExprF64Const);
buffer.write_f64(0.);
break;
}
default:
UNREACHABLE();
}
......
......@@ -45,6 +45,12 @@ class ZoneBuffer : public ZoneObject {
pos_ += 4;
}
void write_u64(uint64_t x) {
EnsureSpace(8);
WriteLittleEndianValue<uint64_t>(pos_, x);
pos_ += 8;
}
void write_u32v(uint32_t val) {
EnsureSpace(kMaxVarInt32Size);
LEBHelper::write_u32v(&pos_, val);
......@@ -55,12 +61,26 @@ class ZoneBuffer : public ZoneObject {
LEBHelper::write_i32v(&pos_, val);
}
void write_u64v(uint64_t val) {
EnsureSpace(kMaxVarInt64Size);
LEBHelper::write_u64v(&pos_, val);
}
void write_i64v(int64_t val) {
EnsureSpace(kMaxVarInt64Size);
LEBHelper::write_i64v(&pos_, val);
}
void write_size(size_t val) {
EnsureSpace(kMaxVarInt32Size);
DCHECK_EQ(val, static_cast<uint32_t>(val));
LEBHelper::write_u32v(&pos_, static_cast<uint32_t>(val));
}
void write_f32(float val) { write_u32(bit_cast<uint32_t>(val)); }
void write_f64(double val) { write_u64(bit_cast<uint64_t>(val)); }
void write(const byte* data, size_t size) {
EnsureSpace(size);
memcpy(pos_, data, size);
......@@ -89,6 +109,11 @@ class ZoneBuffer : public ZoneObject {
}
}
void patch_u8(size_t offset, byte val) {
DCHECK_GE(size(), offset);
buffer_[offset] = val;
}
size_t offset() const { return static_cast<size_t>(pos_ - buffer_); }
size_t size() const { return static_cast<size_t>(pos_ - buffer_); }
const byte* begin() const { return buffer_; }
......@@ -106,6 +131,11 @@ class ZoneBuffer : public ZoneObject {
DCHECK(pos_ + size <= end_);
}
void Truncate(size_t size) {
DCHECK_GE(offset(), size);
pos_ = buffer_ + size;
}
byte** pos_ptr() { return &pos_; }
private:
......@@ -122,18 +152,21 @@ class V8_EXPORT_PRIVATE WasmFunctionBuilder : public ZoneObject {
// Building methods.
void SetSignature(FunctionSig* sig);
uint32_t AddLocal(ValueType type);
void EmitVarInt(int32_t val);
void EmitVarUint(uint32_t val);
void EmitI32V(int32_t val);
void EmitU32V(uint32_t val);
void EmitCode(const byte* code, uint32_t code_size);
void Emit(WasmOpcode opcode);
void EmitGetLocal(uint32_t index);
void EmitSetLocal(uint32_t index);
void EmitTeeLocal(uint32_t index);
void EmitI32Const(int32_t val);
void EmitI64Const(int64_t val);
void EmitF32Const(float val);
void EmitF64Const(double val);
void EmitWithU8(WasmOpcode opcode, const byte immediate);
void EmitWithU8U8(WasmOpcode opcode, const byte imm1, const byte imm2);
void EmitWithVarInt(WasmOpcode opcode, int32_t immediate);
void EmitWithVarUint(WasmOpcode opcode, uint32_t immediate);
void EmitWithI32V(WasmOpcode opcode, int32_t immediate);
void EmitWithU32V(WasmOpcode opcode, uint32_t immediate);
void EmitDirectCallIndex(uint32_t index);
void ExportAs(Vector<const char> name);
void SetName(Vector<const char> name);
......@@ -141,7 +174,9 @@ class V8_EXPORT_PRIVATE WasmFunctionBuilder : public ZoneObject {
void SetAsmFunctionStartPosition(int position);
size_t GetPosition() const { return body_.size(); }
void FixupByte(size_t position, byte value) { body_[position] = value; }
void FixupByte(size_t position, byte value) {
body_.patch_u8(position, value);
}
void DeleteCodeAfter(size_t position);
void WriteSignature(ZoneBuffer& buffer) const;
......@@ -166,7 +201,7 @@ class V8_EXPORT_PRIVATE WasmFunctionBuilder : public ZoneObject {
LocalDeclEncoder locals_;
uint32_t signature_index_;
uint32_t func_index_;
ZoneVector<uint8_t> body_;
ZoneBuffer body_;
ZoneVector<char> name_;
ZoneVector<ZoneVector<char>> exported_names_;
ZoneVector<uint32_t> i32_temps_;
......
......@@ -104,7 +104,7 @@ class WasmGenerator {
const ValueType break_type = blocks_[target_block];
Generate(break_type, data);
builder_->EmitWithVarInt(kExprBr, target_block);
builder_->EmitWithI32V(kExprBr, target_block);
builder_->Emit(kExprEnd);
blocks_.pop_back();
};
......@@ -205,8 +205,7 @@ void WasmGenerator::Generate<kWasmI32>(DataRange data) {
template <>
void WasmGenerator::Generate<kWasmI64>(DataRange data) {
if (data.size() <= sizeof(uint64_t)) {
const uint8_t bytes[] = {WASM_I64V(data.get<uint64_t>())};
builder_->EmitCode(bytes, arraysize(bytes));
builder_->EmitI64Const(data.get<int64_t>());
} else {
const std::function<void(DataRange)> alternates[] = {
op<kExprI64Add, kWasmI64, kWasmI64>(),
......@@ -244,10 +243,8 @@ void WasmGenerator::Generate<kWasmI64>(DataRange data) {
template <>
void WasmGenerator::Generate<kWasmF32>(DataRange data) {
if (data.size() <= sizeof(uint32_t)) {
const uint32_t i = data.get<uint32_t>();
builder_->Emit(kExprF32Const);
builder_->EmitCode(reinterpret_cast<const uint8_t*>(&i), sizeof(i));
if (data.size() <= sizeof(float)) {
builder_->EmitF32Const(data.get<float>());
} else {
const std::function<void(DataRange)> alternates[] = {
op<kExprF32Add, kWasmF32, kWasmF32>(),
......@@ -266,15 +263,8 @@ void WasmGenerator::Generate<kWasmF32>(DataRange data) {
template <>
void WasmGenerator::Generate<kWasmF64>(DataRange data) {
if (data.size() <= sizeof(uint64_t)) {
// TODO (eholk): generate full 64-bit constants
uint64_t i = 0;
while (data.size() > 0) {
i <<= 8;
i |= data.get<uint8_t>();
}
builder_->Emit(kExprF64Const);
builder_->EmitCode(reinterpret_cast<uint8_t*>(&i), sizeof(i));
if (data.size() <= sizeof(double)) {
builder_->EmitF64Const(data.get<double>());
} else {
const std::function<void(DataRange)> alternates[] = {
op<kExprF64Add, kWasmF64, kWasmF64>(),
......
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