11cb0ef41Sopenharmony_ci// Copyright 2015 the V8 project authors. All rights reserved. 21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be 31cb0ef41Sopenharmony_ci// found in the LICENSE file. 41cb0ef41Sopenharmony_ci 51cb0ef41Sopenharmony_ci#include "src/wasm/wasm-module-builder.h" 61cb0ef41Sopenharmony_ci 71cb0ef41Sopenharmony_ci#include "src/base/memory.h" 81cb0ef41Sopenharmony_ci#include "src/codegen/signature.h" 91cb0ef41Sopenharmony_ci#include "src/handles/handles.h" 101cb0ef41Sopenharmony_ci#include "src/init/v8.h" 111cb0ef41Sopenharmony_ci#include "src/objects/objects-inl.h" 121cb0ef41Sopenharmony_ci#include "src/wasm/function-body-decoder.h" 131cb0ef41Sopenharmony_ci#include "src/wasm/leb-helper.h" 141cb0ef41Sopenharmony_ci#include "src/wasm/wasm-constants.h" 151cb0ef41Sopenharmony_ci#include "src/wasm/wasm-module.h" 161cb0ef41Sopenharmony_ci#include "src/zone/zone-containers.h" 171cb0ef41Sopenharmony_ci 181cb0ef41Sopenharmony_cinamespace v8 { 191cb0ef41Sopenharmony_cinamespace internal { 201cb0ef41Sopenharmony_cinamespace wasm { 211cb0ef41Sopenharmony_ci 221cb0ef41Sopenharmony_cinamespace { 231cb0ef41Sopenharmony_ci 241cb0ef41Sopenharmony_ci// Emit a section code and the size as a padded varint that can be patched 251cb0ef41Sopenharmony_ci// later. 261cb0ef41Sopenharmony_cisize_t EmitSection(SectionCode code, ZoneBuffer* buffer) { 271cb0ef41Sopenharmony_ci // Emit the section code. 281cb0ef41Sopenharmony_ci buffer->write_u8(code); 291cb0ef41Sopenharmony_ci 301cb0ef41Sopenharmony_ci // Emit a placeholder for the length. 311cb0ef41Sopenharmony_ci return buffer->reserve_u32v(); 321cb0ef41Sopenharmony_ci} 331cb0ef41Sopenharmony_ci 341cb0ef41Sopenharmony_ci// Patch the size of a section after it's finished. 351cb0ef41Sopenharmony_civoid FixupSection(ZoneBuffer* buffer, size_t start) { 361cb0ef41Sopenharmony_ci buffer->patch_u32v(start, static_cast<uint32_t>(buffer->offset() - start - 371cb0ef41Sopenharmony_ci kPaddedVarInt32Size)); 381cb0ef41Sopenharmony_ci} 391cb0ef41Sopenharmony_ci 401cb0ef41Sopenharmony_ci} // namespace 411cb0ef41Sopenharmony_ci 421cb0ef41Sopenharmony_ciWasmFunctionBuilder::WasmFunctionBuilder(WasmModuleBuilder* builder) 431cb0ef41Sopenharmony_ci : builder_(builder), 441cb0ef41Sopenharmony_ci locals_(builder->zone()), 451cb0ef41Sopenharmony_ci signature_index_(0), 461cb0ef41Sopenharmony_ci func_index_(static_cast<uint32_t>(builder->functions_.size())), 471cb0ef41Sopenharmony_ci body_(builder->zone(), 256), 481cb0ef41Sopenharmony_ci i32_temps_(builder->zone()), 491cb0ef41Sopenharmony_ci i64_temps_(builder->zone()), 501cb0ef41Sopenharmony_ci f32_temps_(builder->zone()), 511cb0ef41Sopenharmony_ci f64_temps_(builder->zone()), 521cb0ef41Sopenharmony_ci direct_calls_(builder->zone()), 531cb0ef41Sopenharmony_ci asm_offsets_(builder->zone(), 8) {} 541cb0ef41Sopenharmony_ci 551cb0ef41Sopenharmony_civoid WasmFunctionBuilder::EmitByte(byte val) { body_.write_u8(val); } 561cb0ef41Sopenharmony_ci 571cb0ef41Sopenharmony_civoid WasmFunctionBuilder::EmitI32V(int32_t val) { body_.write_i32v(val); } 581cb0ef41Sopenharmony_ci 591cb0ef41Sopenharmony_civoid WasmFunctionBuilder::EmitU32V(uint32_t val) { body_.write_u32v(val); } 601cb0ef41Sopenharmony_ci 611cb0ef41Sopenharmony_civoid WasmFunctionBuilder::SetSignature(const FunctionSig* sig) { 621cb0ef41Sopenharmony_ci DCHECK(!locals_.has_sig()); 631cb0ef41Sopenharmony_ci locals_.set_sig(sig); 641cb0ef41Sopenharmony_ci signature_index_ = builder_->AddSignature(sig); 651cb0ef41Sopenharmony_ci} 661cb0ef41Sopenharmony_ci 671cb0ef41Sopenharmony_civoid WasmFunctionBuilder::SetSignature(uint32_t sig_index) { 681cb0ef41Sopenharmony_ci DCHECK(!locals_.has_sig()); 691cb0ef41Sopenharmony_ci DCHECK_EQ(builder_->types_[sig_index].kind, TypeDefinition::kFunction); 701cb0ef41Sopenharmony_ci signature_index_ = sig_index; 711cb0ef41Sopenharmony_ci locals_.set_sig(builder_->types_[sig_index].function_sig); 721cb0ef41Sopenharmony_ci} 731cb0ef41Sopenharmony_ci 741cb0ef41Sopenharmony_ciuint32_t WasmFunctionBuilder::AddLocal(ValueType type) { 751cb0ef41Sopenharmony_ci DCHECK(locals_.has_sig()); 761cb0ef41Sopenharmony_ci return locals_.AddLocals(1, type); 771cb0ef41Sopenharmony_ci} 781cb0ef41Sopenharmony_ci 791cb0ef41Sopenharmony_civoid WasmFunctionBuilder::EmitGetLocal(uint32_t local_index) { 801cb0ef41Sopenharmony_ci EmitWithU32V(kExprLocalGet, local_index); 811cb0ef41Sopenharmony_ci} 821cb0ef41Sopenharmony_ci 831cb0ef41Sopenharmony_civoid WasmFunctionBuilder::EmitSetLocal(uint32_t local_index) { 841cb0ef41Sopenharmony_ci EmitWithU32V(kExprLocalSet, local_index); 851cb0ef41Sopenharmony_ci} 861cb0ef41Sopenharmony_ci 871cb0ef41Sopenharmony_civoid WasmFunctionBuilder::EmitTeeLocal(uint32_t local_index) { 881cb0ef41Sopenharmony_ci EmitWithU32V(kExprLocalTee, local_index); 891cb0ef41Sopenharmony_ci} 901cb0ef41Sopenharmony_ci 911cb0ef41Sopenharmony_civoid WasmFunctionBuilder::EmitCode(const byte* code, uint32_t code_size) { 921cb0ef41Sopenharmony_ci body_.write(code, code_size); 931cb0ef41Sopenharmony_ci} 941cb0ef41Sopenharmony_ci 951cb0ef41Sopenharmony_civoid WasmFunctionBuilder::Emit(WasmOpcode opcode) { body_.write_u8(opcode); } 961cb0ef41Sopenharmony_ci 971cb0ef41Sopenharmony_civoid WasmFunctionBuilder::EmitWithPrefix(WasmOpcode opcode) { 981cb0ef41Sopenharmony_ci DCHECK_NE(0, opcode & 0xff00); 991cb0ef41Sopenharmony_ci body_.write_u8(opcode >> 8); 1001cb0ef41Sopenharmony_ci if ((opcode >> 8) == WasmOpcode::kSimdPrefix) { 1011cb0ef41Sopenharmony_ci // SIMD opcodes are LEB encoded 1021cb0ef41Sopenharmony_ci body_.write_u32v(opcode & 0xff); 1031cb0ef41Sopenharmony_ci } else { 1041cb0ef41Sopenharmony_ci body_.write_u8(opcode); 1051cb0ef41Sopenharmony_ci } 1061cb0ef41Sopenharmony_ci} 1071cb0ef41Sopenharmony_ci 1081cb0ef41Sopenharmony_civoid WasmFunctionBuilder::EmitWithU8(WasmOpcode opcode, const byte immediate) { 1091cb0ef41Sopenharmony_ci body_.write_u8(opcode); 1101cb0ef41Sopenharmony_ci body_.write_u8(immediate); 1111cb0ef41Sopenharmony_ci} 1121cb0ef41Sopenharmony_ci 1131cb0ef41Sopenharmony_civoid WasmFunctionBuilder::EmitWithU8U8(WasmOpcode opcode, const byte imm1, 1141cb0ef41Sopenharmony_ci const byte imm2) { 1151cb0ef41Sopenharmony_ci body_.write_u8(opcode); 1161cb0ef41Sopenharmony_ci body_.write_u8(imm1); 1171cb0ef41Sopenharmony_ci body_.write_u8(imm2); 1181cb0ef41Sopenharmony_ci} 1191cb0ef41Sopenharmony_ci 1201cb0ef41Sopenharmony_civoid WasmFunctionBuilder::EmitWithI32V(WasmOpcode opcode, int32_t immediate) { 1211cb0ef41Sopenharmony_ci body_.write_u8(opcode); 1221cb0ef41Sopenharmony_ci body_.write_i32v(immediate); 1231cb0ef41Sopenharmony_ci} 1241cb0ef41Sopenharmony_ci 1251cb0ef41Sopenharmony_civoid WasmFunctionBuilder::EmitWithU32V(WasmOpcode opcode, uint32_t immediate) { 1261cb0ef41Sopenharmony_ci body_.write_u8(opcode); 1271cb0ef41Sopenharmony_ci body_.write_u32v(immediate); 1281cb0ef41Sopenharmony_ci} 1291cb0ef41Sopenharmony_ci 1301cb0ef41Sopenharmony_cinamespace { 1311cb0ef41Sopenharmony_civoid WriteValueType(ZoneBuffer* buffer, const ValueType& type) { 1321cb0ef41Sopenharmony_ci buffer->write_u8(type.value_type_code()); 1331cb0ef41Sopenharmony_ci if (type.encoding_needs_heap_type()) { 1341cb0ef41Sopenharmony_ci buffer->write_i32v(type.heap_type().code()); 1351cb0ef41Sopenharmony_ci } 1361cb0ef41Sopenharmony_ci if (type.is_rtt()) { 1371cb0ef41Sopenharmony_ci buffer->write_u32v(type.ref_index()); 1381cb0ef41Sopenharmony_ci } 1391cb0ef41Sopenharmony_ci} 1401cb0ef41Sopenharmony_ci} // namespace 1411cb0ef41Sopenharmony_ci 1421cb0ef41Sopenharmony_civoid WasmFunctionBuilder::EmitValueType(ValueType type) { 1431cb0ef41Sopenharmony_ci WriteValueType(&body_, type); 1441cb0ef41Sopenharmony_ci} 1451cb0ef41Sopenharmony_ci 1461cb0ef41Sopenharmony_civoid WasmFunctionBuilder::EmitI32Const(int32_t value) { 1471cb0ef41Sopenharmony_ci EmitWithI32V(kExprI32Const, value); 1481cb0ef41Sopenharmony_ci} 1491cb0ef41Sopenharmony_ci 1501cb0ef41Sopenharmony_civoid WasmFunctionBuilder::EmitI64Const(int64_t value) { 1511cb0ef41Sopenharmony_ci body_.write_u8(kExprI64Const); 1521cb0ef41Sopenharmony_ci body_.write_i64v(value); 1531cb0ef41Sopenharmony_ci} 1541cb0ef41Sopenharmony_ci 1551cb0ef41Sopenharmony_civoid WasmFunctionBuilder::EmitF32Const(float value) { 1561cb0ef41Sopenharmony_ci body_.write_u8(kExprF32Const); 1571cb0ef41Sopenharmony_ci body_.write_f32(value); 1581cb0ef41Sopenharmony_ci} 1591cb0ef41Sopenharmony_ci 1601cb0ef41Sopenharmony_civoid WasmFunctionBuilder::EmitF64Const(double value) { 1611cb0ef41Sopenharmony_ci body_.write_u8(kExprF64Const); 1621cb0ef41Sopenharmony_ci body_.write_f64(value); 1631cb0ef41Sopenharmony_ci} 1641cb0ef41Sopenharmony_ci 1651cb0ef41Sopenharmony_civoid WasmFunctionBuilder::EmitDirectCallIndex(uint32_t index) { 1661cb0ef41Sopenharmony_ci DirectCallIndex call; 1671cb0ef41Sopenharmony_ci call.offset = body_.size(); 1681cb0ef41Sopenharmony_ci call.direct_index = index; 1691cb0ef41Sopenharmony_ci direct_calls_.push_back(call); 1701cb0ef41Sopenharmony_ci byte placeholder_bytes[kMaxVarInt32Size] = {0}; 1711cb0ef41Sopenharmony_ci EmitCode(placeholder_bytes, arraysize(placeholder_bytes)); 1721cb0ef41Sopenharmony_ci} 1731cb0ef41Sopenharmony_ci 1741cb0ef41Sopenharmony_civoid WasmFunctionBuilder::SetName(base::Vector<const char> name) { 1751cb0ef41Sopenharmony_ci name_ = name; 1761cb0ef41Sopenharmony_ci} 1771cb0ef41Sopenharmony_ci 1781cb0ef41Sopenharmony_civoid WasmFunctionBuilder::AddAsmWasmOffset(size_t call_position, 1791cb0ef41Sopenharmony_ci size_t to_number_position) { 1801cb0ef41Sopenharmony_ci // We only want to emit one mapping per byte offset. 1811cb0ef41Sopenharmony_ci DCHECK(asm_offsets_.size() == 0 || body_.size() > last_asm_byte_offset_); 1821cb0ef41Sopenharmony_ci 1831cb0ef41Sopenharmony_ci DCHECK_LE(body_.size(), kMaxUInt32); 1841cb0ef41Sopenharmony_ci uint32_t byte_offset = static_cast<uint32_t>(body_.size()); 1851cb0ef41Sopenharmony_ci asm_offsets_.write_u32v(byte_offset - last_asm_byte_offset_); 1861cb0ef41Sopenharmony_ci last_asm_byte_offset_ = byte_offset; 1871cb0ef41Sopenharmony_ci 1881cb0ef41Sopenharmony_ci DCHECK_GE(std::numeric_limits<uint32_t>::max(), call_position); 1891cb0ef41Sopenharmony_ci uint32_t call_position_u32 = static_cast<uint32_t>(call_position); 1901cb0ef41Sopenharmony_ci asm_offsets_.write_i32v(call_position_u32 - last_asm_source_position_); 1911cb0ef41Sopenharmony_ci 1921cb0ef41Sopenharmony_ci DCHECK_GE(std::numeric_limits<uint32_t>::max(), to_number_position); 1931cb0ef41Sopenharmony_ci uint32_t to_number_position_u32 = static_cast<uint32_t>(to_number_position); 1941cb0ef41Sopenharmony_ci asm_offsets_.write_i32v(to_number_position_u32 - call_position_u32); 1951cb0ef41Sopenharmony_ci last_asm_source_position_ = to_number_position_u32; 1961cb0ef41Sopenharmony_ci} 1971cb0ef41Sopenharmony_ci 1981cb0ef41Sopenharmony_civoid WasmFunctionBuilder::SetAsmFunctionStartPosition( 1991cb0ef41Sopenharmony_ci size_t function_position) { 2001cb0ef41Sopenharmony_ci DCHECK_EQ(0, asm_func_start_source_position_); 2011cb0ef41Sopenharmony_ci DCHECK_GE(std::numeric_limits<uint32_t>::max(), function_position); 2021cb0ef41Sopenharmony_ci uint32_t function_position_u32 = static_cast<uint32_t>(function_position); 2031cb0ef41Sopenharmony_ci // Must be called before emitting any asm.js source position. 2041cb0ef41Sopenharmony_ci DCHECK_EQ(0, asm_offsets_.size()); 2051cb0ef41Sopenharmony_ci asm_func_start_source_position_ = function_position_u32; 2061cb0ef41Sopenharmony_ci last_asm_source_position_ = function_position_u32; 2071cb0ef41Sopenharmony_ci} 2081cb0ef41Sopenharmony_ci 2091cb0ef41Sopenharmony_civoid WasmFunctionBuilder::SetCompilationHint( 2101cb0ef41Sopenharmony_ci WasmCompilationHintStrategy strategy, WasmCompilationHintTier baseline, 2111cb0ef41Sopenharmony_ci WasmCompilationHintTier top_tier) { 2121cb0ef41Sopenharmony_ci uint8_t hint_byte = static_cast<uint8_t>(strategy) | 2131cb0ef41Sopenharmony_ci static_cast<uint8_t>(baseline) << 2 | 2141cb0ef41Sopenharmony_ci static_cast<uint8_t>(top_tier) << 4; 2151cb0ef41Sopenharmony_ci DCHECK_NE(hint_byte, kNoCompilationHint); 2161cb0ef41Sopenharmony_ci hint_ = hint_byte; 2171cb0ef41Sopenharmony_ci} 2181cb0ef41Sopenharmony_ci 2191cb0ef41Sopenharmony_civoid WasmFunctionBuilder::DeleteCodeAfter(size_t position) { 2201cb0ef41Sopenharmony_ci DCHECK_LE(position, body_.size()); 2211cb0ef41Sopenharmony_ci body_.Truncate(position); 2221cb0ef41Sopenharmony_ci} 2231cb0ef41Sopenharmony_ci 2241cb0ef41Sopenharmony_civoid WasmFunctionBuilder::WriteSignature(ZoneBuffer* buffer) const { 2251cb0ef41Sopenharmony_ci buffer->write_u32v(signature_index_); 2261cb0ef41Sopenharmony_ci} 2271cb0ef41Sopenharmony_ci 2281cb0ef41Sopenharmony_civoid WasmFunctionBuilder::WriteBody(ZoneBuffer* buffer) const { 2291cb0ef41Sopenharmony_ci size_t locals_size = locals_.Size(); 2301cb0ef41Sopenharmony_ci buffer->write_size(locals_size + body_.size()); 2311cb0ef41Sopenharmony_ci buffer->EnsureSpace(locals_size); 2321cb0ef41Sopenharmony_ci byte** ptr = buffer->pos_ptr(); 2331cb0ef41Sopenharmony_ci locals_.Emit(*ptr); 2341cb0ef41Sopenharmony_ci (*ptr) += locals_size; // UGLY: manual bump of position pointer 2351cb0ef41Sopenharmony_ci if (body_.size() > 0) { 2361cb0ef41Sopenharmony_ci size_t base = buffer->offset(); 2371cb0ef41Sopenharmony_ci buffer->write(body_.begin(), body_.size()); 2381cb0ef41Sopenharmony_ci for (DirectCallIndex call : direct_calls_) { 2391cb0ef41Sopenharmony_ci buffer->patch_u32v( 2401cb0ef41Sopenharmony_ci base + call.offset, 2411cb0ef41Sopenharmony_ci call.direct_index + 2421cb0ef41Sopenharmony_ci static_cast<uint32_t>(builder_->function_imports_.size())); 2431cb0ef41Sopenharmony_ci } 2441cb0ef41Sopenharmony_ci } 2451cb0ef41Sopenharmony_ci} 2461cb0ef41Sopenharmony_ci 2471cb0ef41Sopenharmony_civoid WasmFunctionBuilder::WriteAsmWasmOffsetTable(ZoneBuffer* buffer) const { 2481cb0ef41Sopenharmony_ci if (asm_func_start_source_position_ == 0 && asm_offsets_.size() == 0) { 2491cb0ef41Sopenharmony_ci buffer->write_size(0); 2501cb0ef41Sopenharmony_ci return; 2511cb0ef41Sopenharmony_ci } 2521cb0ef41Sopenharmony_ci size_t locals_enc_size = LEBHelper::sizeof_u32v(locals_.Size()); 2531cb0ef41Sopenharmony_ci size_t func_start_size = 2541cb0ef41Sopenharmony_ci LEBHelper::sizeof_u32v(asm_func_start_source_position_); 2551cb0ef41Sopenharmony_ci buffer->write_size(asm_offsets_.size() + locals_enc_size + func_start_size); 2561cb0ef41Sopenharmony_ci // Offset of the recorded byte offsets. 2571cb0ef41Sopenharmony_ci DCHECK_GE(kMaxUInt32, locals_.Size()); 2581cb0ef41Sopenharmony_ci buffer->write_u32v(static_cast<uint32_t>(locals_.Size())); 2591cb0ef41Sopenharmony_ci // Start position of the function. 2601cb0ef41Sopenharmony_ci buffer->write_u32v(asm_func_start_source_position_); 2611cb0ef41Sopenharmony_ci buffer->write(asm_offsets_.begin(), asm_offsets_.size()); 2621cb0ef41Sopenharmony_ci} 2631cb0ef41Sopenharmony_ci 2641cb0ef41Sopenharmony_ciWasmModuleBuilder::WasmModuleBuilder(Zone* zone) 2651cb0ef41Sopenharmony_ci : zone_(zone), 2661cb0ef41Sopenharmony_ci types_(zone), 2671cb0ef41Sopenharmony_ci function_imports_(zone), 2681cb0ef41Sopenharmony_ci global_imports_(zone), 2691cb0ef41Sopenharmony_ci exports_(zone), 2701cb0ef41Sopenharmony_ci functions_(zone), 2711cb0ef41Sopenharmony_ci tables_(zone), 2721cb0ef41Sopenharmony_ci data_segments_(zone), 2731cb0ef41Sopenharmony_ci element_segments_(zone), 2741cb0ef41Sopenharmony_ci globals_(zone), 2751cb0ef41Sopenharmony_ci exceptions_(zone), 2761cb0ef41Sopenharmony_ci signature_map_(zone), 2771cb0ef41Sopenharmony_ci current_recursive_group_start_(-1), 2781cb0ef41Sopenharmony_ci recursive_groups_(zone), 2791cb0ef41Sopenharmony_ci start_function_index_(-1), 2801cb0ef41Sopenharmony_ci min_memory_size_(16), 2811cb0ef41Sopenharmony_ci max_memory_size_(0), 2821cb0ef41Sopenharmony_ci has_max_memory_size_(false), 2831cb0ef41Sopenharmony_ci has_shared_memory_(false) {} 2841cb0ef41Sopenharmony_ci 2851cb0ef41Sopenharmony_ciWasmFunctionBuilder* WasmModuleBuilder::AddFunction(const FunctionSig* sig) { 2861cb0ef41Sopenharmony_ci functions_.push_back(zone_->New<WasmFunctionBuilder>(this)); 2871cb0ef41Sopenharmony_ci // Add the signature if one was provided here. 2881cb0ef41Sopenharmony_ci if (sig) functions_.back()->SetSignature(sig); 2891cb0ef41Sopenharmony_ci return functions_.back(); 2901cb0ef41Sopenharmony_ci} 2911cb0ef41Sopenharmony_ci 2921cb0ef41Sopenharmony_ciWasmFunctionBuilder* WasmModuleBuilder::AddFunction(uint32_t sig_index) { 2931cb0ef41Sopenharmony_ci functions_.push_back(zone_->New<WasmFunctionBuilder>(this)); 2941cb0ef41Sopenharmony_ci functions_.back()->SetSignature(sig_index); 2951cb0ef41Sopenharmony_ci return functions_.back(); 2961cb0ef41Sopenharmony_ci} 2971cb0ef41Sopenharmony_ci 2981cb0ef41Sopenharmony_civoid WasmModuleBuilder::AddDataSegment(const byte* data, uint32_t size, 2991cb0ef41Sopenharmony_ci uint32_t dest) { 3001cb0ef41Sopenharmony_ci data_segments_.push_back({ZoneVector<byte>(zone()), dest}); 3011cb0ef41Sopenharmony_ci ZoneVector<byte>& vec = data_segments_.back().data; 3021cb0ef41Sopenharmony_ci for (uint32_t i = 0; i < size; i++) { 3031cb0ef41Sopenharmony_ci vec.push_back(data[i]); 3041cb0ef41Sopenharmony_ci } 3051cb0ef41Sopenharmony_ci} 3061cb0ef41Sopenharmony_ci 3071cb0ef41Sopenharmony_ciuint32_t WasmModuleBuilder::ForceAddSignature(const FunctionSig* sig, 3081cb0ef41Sopenharmony_ci uint32_t supertype) { 3091cb0ef41Sopenharmony_ci uint32_t index = static_cast<uint32_t>(types_.size()); 3101cb0ef41Sopenharmony_ci signature_map_.emplace(*sig, index); 3111cb0ef41Sopenharmony_ci types_.emplace_back(sig, supertype); 3121cb0ef41Sopenharmony_ci return index; 3131cb0ef41Sopenharmony_ci} 3141cb0ef41Sopenharmony_ci 3151cb0ef41Sopenharmony_ciuint32_t WasmModuleBuilder::AddSignature(const FunctionSig* sig, 3161cb0ef41Sopenharmony_ci uint32_t supertype) { 3171cb0ef41Sopenharmony_ci auto sig_entry = signature_map_.find(*sig); 3181cb0ef41Sopenharmony_ci if (sig_entry != signature_map_.end()) return sig_entry->second; 3191cb0ef41Sopenharmony_ci return ForceAddSignature(sig, supertype); 3201cb0ef41Sopenharmony_ci} 3211cb0ef41Sopenharmony_ci 3221cb0ef41Sopenharmony_ciuint32_t WasmModuleBuilder::AddException(const FunctionSig* type) { 3231cb0ef41Sopenharmony_ci DCHECK_EQ(0, type->return_count()); 3241cb0ef41Sopenharmony_ci int type_index = AddSignature(type); 3251cb0ef41Sopenharmony_ci uint32_t except_index = static_cast<uint32_t>(exceptions_.size()); 3261cb0ef41Sopenharmony_ci exceptions_.push_back(type_index); 3271cb0ef41Sopenharmony_ci return except_index; 3281cb0ef41Sopenharmony_ci} 3291cb0ef41Sopenharmony_ci 3301cb0ef41Sopenharmony_ciuint32_t WasmModuleBuilder::AddStructType(StructType* type, 3311cb0ef41Sopenharmony_ci uint32_t supertype) { 3321cb0ef41Sopenharmony_ci uint32_t index = static_cast<uint32_t>(types_.size()); 3331cb0ef41Sopenharmony_ci types_.emplace_back(type, supertype); 3341cb0ef41Sopenharmony_ci return index; 3351cb0ef41Sopenharmony_ci} 3361cb0ef41Sopenharmony_ci 3371cb0ef41Sopenharmony_ciuint32_t WasmModuleBuilder::AddArrayType(ArrayType* type, uint32_t supertype) { 3381cb0ef41Sopenharmony_ci uint32_t index = static_cast<uint32_t>(types_.size()); 3391cb0ef41Sopenharmony_ci types_.emplace_back(type, supertype); 3401cb0ef41Sopenharmony_ci return index; 3411cb0ef41Sopenharmony_ci} 3421cb0ef41Sopenharmony_ci 3431cb0ef41Sopenharmony_ciuint32_t WasmModuleBuilder::IncreaseTableMinSize(uint32_t table_index, 3441cb0ef41Sopenharmony_ci uint32_t count) { 3451cb0ef41Sopenharmony_ci DCHECK_LT(table_index, tables_.size()); 3461cb0ef41Sopenharmony_ci uint32_t old_min_size = tables_[table_index].min_size; 3471cb0ef41Sopenharmony_ci if (count > FLAG_wasm_max_table_size - old_min_size) { 3481cb0ef41Sopenharmony_ci return std::numeric_limits<uint32_t>::max(); 3491cb0ef41Sopenharmony_ci } 3501cb0ef41Sopenharmony_ci tables_[table_index].min_size = old_min_size + count; 3511cb0ef41Sopenharmony_ci tables_[table_index].max_size = 3521cb0ef41Sopenharmony_ci std::max(old_min_size + count, tables_[table_index].max_size); 3531cb0ef41Sopenharmony_ci return old_min_size; 3541cb0ef41Sopenharmony_ci} 3551cb0ef41Sopenharmony_ci 3561cb0ef41Sopenharmony_ciuint32_t WasmModuleBuilder::AddTable(ValueType type, uint32_t min_size) { 3571cb0ef41Sopenharmony_ci tables_.push_back({type, min_size, 0, false, {}}); 3581cb0ef41Sopenharmony_ci return static_cast<uint32_t>(tables_.size() - 1); 3591cb0ef41Sopenharmony_ci} 3601cb0ef41Sopenharmony_ci 3611cb0ef41Sopenharmony_ciuint32_t WasmModuleBuilder::AddTable(ValueType type, uint32_t min_size, 3621cb0ef41Sopenharmony_ci uint32_t max_size) { 3631cb0ef41Sopenharmony_ci tables_.push_back({type, min_size, max_size, true, {}}); 3641cb0ef41Sopenharmony_ci return static_cast<uint32_t>(tables_.size() - 1); 3651cb0ef41Sopenharmony_ci} 3661cb0ef41Sopenharmony_ci 3671cb0ef41Sopenharmony_ciuint32_t WasmModuleBuilder::AddTable(ValueType type, uint32_t min_size, 3681cb0ef41Sopenharmony_ci uint32_t max_size, WasmInitExpr init) { 3691cb0ef41Sopenharmony_ci tables_.push_back({type, min_size, max_size, true, init}); 3701cb0ef41Sopenharmony_ci return static_cast<uint32_t>(tables_.size() - 1); 3711cb0ef41Sopenharmony_ci} 3721cb0ef41Sopenharmony_ci 3731cb0ef41Sopenharmony_civoid WasmModuleBuilder::AddElementSegment(WasmElemSegment segment) { 3741cb0ef41Sopenharmony_ci element_segments_.push_back(std::move(segment)); 3751cb0ef41Sopenharmony_ci} 3761cb0ef41Sopenharmony_ci 3771cb0ef41Sopenharmony_civoid WasmModuleBuilder::SetIndirectFunction( 3781cb0ef41Sopenharmony_ci uint32_t table_index, uint32_t index_in_table, 3791cb0ef41Sopenharmony_ci uint32_t direct_function_index, 3801cb0ef41Sopenharmony_ci WasmElemSegment::FunctionIndexingMode indexing_mode) { 3811cb0ef41Sopenharmony_ci WasmElemSegment segment(zone_, kWasmFuncRef, table_index, 3821cb0ef41Sopenharmony_ci WasmInitExpr(static_cast<int>(index_in_table))); 3831cb0ef41Sopenharmony_ci segment.indexing_mode = indexing_mode; 3841cb0ef41Sopenharmony_ci segment.entries.emplace_back(WasmElemSegment::Entry::kRefFuncEntry, 3851cb0ef41Sopenharmony_ci direct_function_index); 3861cb0ef41Sopenharmony_ci AddElementSegment(std::move(segment)); 3871cb0ef41Sopenharmony_ci} 3881cb0ef41Sopenharmony_ci 3891cb0ef41Sopenharmony_ciuint32_t WasmModuleBuilder::AddImport(base::Vector<const char> name, 3901cb0ef41Sopenharmony_ci FunctionSig* sig, 3911cb0ef41Sopenharmony_ci base::Vector<const char> module) { 3921cb0ef41Sopenharmony_ci DCHECK(adding_imports_allowed_); 3931cb0ef41Sopenharmony_ci function_imports_.push_back({module, name, AddSignature(sig)}); 3941cb0ef41Sopenharmony_ci return static_cast<uint32_t>(function_imports_.size() - 1); 3951cb0ef41Sopenharmony_ci} 3961cb0ef41Sopenharmony_ci 3971cb0ef41Sopenharmony_ciuint32_t WasmModuleBuilder::AddGlobalImport(base::Vector<const char> name, 3981cb0ef41Sopenharmony_ci ValueType type, bool mutability, 3991cb0ef41Sopenharmony_ci base::Vector<const char> module) { 4001cb0ef41Sopenharmony_ci global_imports_.push_back({module, name, type.value_type_code(), mutability}); 4011cb0ef41Sopenharmony_ci return static_cast<uint32_t>(global_imports_.size() - 1); 4021cb0ef41Sopenharmony_ci} 4031cb0ef41Sopenharmony_ci 4041cb0ef41Sopenharmony_civoid WasmModuleBuilder::MarkStartFunction(WasmFunctionBuilder* function) { 4051cb0ef41Sopenharmony_ci start_function_index_ = function->func_index(); 4061cb0ef41Sopenharmony_ci} 4071cb0ef41Sopenharmony_ci 4081cb0ef41Sopenharmony_civoid WasmModuleBuilder::AddExport(base::Vector<const char> name, 4091cb0ef41Sopenharmony_ci ImportExportKindCode kind, uint32_t index) { 4101cb0ef41Sopenharmony_ci DCHECK_LE(index, std::numeric_limits<int>::max()); 4111cb0ef41Sopenharmony_ci exports_.push_back({name, kind, static_cast<int>(index)}); 4121cb0ef41Sopenharmony_ci} 4131cb0ef41Sopenharmony_ci 4141cb0ef41Sopenharmony_ciuint32_t WasmModuleBuilder::AddExportedGlobal(ValueType type, bool mutability, 4151cb0ef41Sopenharmony_ci WasmInitExpr init, 4161cb0ef41Sopenharmony_ci base::Vector<const char> name) { 4171cb0ef41Sopenharmony_ci uint32_t index = AddGlobal(type, mutability, init); 4181cb0ef41Sopenharmony_ci AddExport(name, kExternalGlobal, index); 4191cb0ef41Sopenharmony_ci return index; 4201cb0ef41Sopenharmony_ci} 4211cb0ef41Sopenharmony_ci 4221cb0ef41Sopenharmony_civoid WasmModuleBuilder::ExportImportedFunction(base::Vector<const char> name, 4231cb0ef41Sopenharmony_ci int import_index) { 4241cb0ef41Sopenharmony_ci#if DEBUG 4251cb0ef41Sopenharmony_ci // The size of function_imports_ must not change any more. 4261cb0ef41Sopenharmony_ci adding_imports_allowed_ = false; 4271cb0ef41Sopenharmony_ci#endif 4281cb0ef41Sopenharmony_ci exports_.push_back( 4291cb0ef41Sopenharmony_ci {name, kExternalFunction, 4301cb0ef41Sopenharmony_ci import_index - static_cast<int>(function_imports_.size())}); 4311cb0ef41Sopenharmony_ci} 4321cb0ef41Sopenharmony_ci 4331cb0ef41Sopenharmony_ciuint32_t WasmModuleBuilder::AddGlobal(ValueType type, bool mutability, 4341cb0ef41Sopenharmony_ci WasmInitExpr init) { 4351cb0ef41Sopenharmony_ci globals_.push_back({type, mutability, init}); 4361cb0ef41Sopenharmony_ci return static_cast<uint32_t>(globals_.size() - 1); 4371cb0ef41Sopenharmony_ci} 4381cb0ef41Sopenharmony_ci 4391cb0ef41Sopenharmony_civoid WasmModuleBuilder::SetMinMemorySize(uint32_t value) { 4401cb0ef41Sopenharmony_ci min_memory_size_ = value; 4411cb0ef41Sopenharmony_ci} 4421cb0ef41Sopenharmony_ci 4431cb0ef41Sopenharmony_civoid WasmModuleBuilder::SetMaxMemorySize(uint32_t value) { 4441cb0ef41Sopenharmony_ci has_max_memory_size_ = true; 4451cb0ef41Sopenharmony_ci max_memory_size_ = value; 4461cb0ef41Sopenharmony_ci} 4471cb0ef41Sopenharmony_ci 4481cb0ef41Sopenharmony_civoid WasmModuleBuilder::SetHasSharedMemory() { has_shared_memory_ = true; } 4491cb0ef41Sopenharmony_ci 4501cb0ef41Sopenharmony_cinamespace { 4511cb0ef41Sopenharmony_civoid WriteInitializerExpressionWithEnd(ZoneBuffer* buffer, 4521cb0ef41Sopenharmony_ci const WasmInitExpr& init, 4531cb0ef41Sopenharmony_ci ValueType type) { 4541cb0ef41Sopenharmony_ci switch (init.kind()) { 4551cb0ef41Sopenharmony_ci case WasmInitExpr::kI32Const: 4561cb0ef41Sopenharmony_ci buffer->write_u8(kExprI32Const); 4571cb0ef41Sopenharmony_ci buffer->write_i32v(init.immediate().i32_const); 4581cb0ef41Sopenharmony_ci break; 4591cb0ef41Sopenharmony_ci case WasmInitExpr::kI64Const: 4601cb0ef41Sopenharmony_ci buffer->write_u8(kExprI64Const); 4611cb0ef41Sopenharmony_ci buffer->write_i64v(init.immediate().i64_const); 4621cb0ef41Sopenharmony_ci break; 4631cb0ef41Sopenharmony_ci case WasmInitExpr::kF32Const: 4641cb0ef41Sopenharmony_ci buffer->write_u8(kExprF32Const); 4651cb0ef41Sopenharmony_ci buffer->write_f32(init.immediate().f32_const); 4661cb0ef41Sopenharmony_ci break; 4671cb0ef41Sopenharmony_ci case WasmInitExpr::kF64Const: 4681cb0ef41Sopenharmony_ci buffer->write_u8(kExprF64Const); 4691cb0ef41Sopenharmony_ci buffer->write_f64(init.immediate().f64_const); 4701cb0ef41Sopenharmony_ci break; 4711cb0ef41Sopenharmony_ci case WasmInitExpr::kS128Const: 4721cb0ef41Sopenharmony_ci buffer->write_u8(kSimdPrefix); 4731cb0ef41Sopenharmony_ci buffer->write_u8(kExprS128Const & 0xFF); 4741cb0ef41Sopenharmony_ci buffer->write(init.immediate().s128_const.data(), kSimd128Size); 4751cb0ef41Sopenharmony_ci break; 4761cb0ef41Sopenharmony_ci case WasmInitExpr::kGlobalGet: 4771cb0ef41Sopenharmony_ci buffer->write_u8(kExprGlobalGet); 4781cb0ef41Sopenharmony_ci buffer->write_u32v(init.immediate().index); 4791cb0ef41Sopenharmony_ci break; 4801cb0ef41Sopenharmony_ci case WasmInitExpr::kRefNullConst: 4811cb0ef41Sopenharmony_ci buffer->write_u8(kExprRefNull); 4821cb0ef41Sopenharmony_ci buffer->write_i32v(HeapType(init.immediate().heap_type).code()); 4831cb0ef41Sopenharmony_ci break; 4841cb0ef41Sopenharmony_ci case WasmInitExpr::kRefFuncConst: 4851cb0ef41Sopenharmony_ci buffer->write_u8(kExprRefFunc); 4861cb0ef41Sopenharmony_ci buffer->write_u32v(init.immediate().index); 4871cb0ef41Sopenharmony_ci break; 4881cb0ef41Sopenharmony_ci case WasmInitExpr::kNone: { 4891cb0ef41Sopenharmony_ci // No initializer, emit a default value. 4901cb0ef41Sopenharmony_ci switch (type.kind()) { 4911cb0ef41Sopenharmony_ci case kI32: 4921cb0ef41Sopenharmony_ci buffer->write_u8(kExprI32Const); 4931cb0ef41Sopenharmony_ci // LEB encoding of 0. 4941cb0ef41Sopenharmony_ci buffer->write_u8(0); 4951cb0ef41Sopenharmony_ci break; 4961cb0ef41Sopenharmony_ci case kI64: 4971cb0ef41Sopenharmony_ci buffer->write_u8(kExprI64Const); 4981cb0ef41Sopenharmony_ci // LEB encoding of 0. 4991cb0ef41Sopenharmony_ci buffer->write_u8(0); 5001cb0ef41Sopenharmony_ci break; 5011cb0ef41Sopenharmony_ci case kF32: 5021cb0ef41Sopenharmony_ci buffer->write_u8(kExprF32Const); 5031cb0ef41Sopenharmony_ci buffer->write_f32(0.f); 5041cb0ef41Sopenharmony_ci break; 5051cb0ef41Sopenharmony_ci case kF64: 5061cb0ef41Sopenharmony_ci buffer->write_u8(kExprF64Const); 5071cb0ef41Sopenharmony_ci buffer->write_f64(0.); 5081cb0ef41Sopenharmony_ci break; 5091cb0ef41Sopenharmony_ci case kOptRef: 5101cb0ef41Sopenharmony_ci buffer->write_u8(kExprRefNull); 5111cb0ef41Sopenharmony_ci buffer->write_i32v(type.heap_type().code()); 5121cb0ef41Sopenharmony_ci break; 5131cb0ef41Sopenharmony_ci case kS128: 5141cb0ef41Sopenharmony_ci buffer->write_u8(static_cast<byte>(kSimdPrefix)); 5151cb0ef41Sopenharmony_ci buffer->write_u8(static_cast<byte>(kExprS128Const & 0xff)); 5161cb0ef41Sopenharmony_ci for (int i = 0; i < kSimd128Size; i++) buffer->write_u8(0); 5171cb0ef41Sopenharmony_ci break; 5181cb0ef41Sopenharmony_ci case kI8: 5191cb0ef41Sopenharmony_ci case kI16: 5201cb0ef41Sopenharmony_ci case kVoid: 5211cb0ef41Sopenharmony_ci case kBottom: 5221cb0ef41Sopenharmony_ci case kRef: 5231cb0ef41Sopenharmony_ci case kRtt: 5241cb0ef41Sopenharmony_ci UNREACHABLE(); 5251cb0ef41Sopenharmony_ci } 5261cb0ef41Sopenharmony_ci break; 5271cb0ef41Sopenharmony_ci } 5281cb0ef41Sopenharmony_ci case WasmInitExpr::kStructNew: 5291cb0ef41Sopenharmony_ci case WasmInitExpr::kStructNewWithRtt: 5301cb0ef41Sopenharmony_ci case WasmInitExpr::kStructNewDefault: 5311cb0ef41Sopenharmony_ci case WasmInitExpr::kStructNewDefaultWithRtt: 5321cb0ef41Sopenharmony_ci STATIC_ASSERT((kExprStructNew >> 8) == kGCPrefix); 5331cb0ef41Sopenharmony_ci STATIC_ASSERT((kExprStructNewWithRtt >> 8) == kGCPrefix); 5341cb0ef41Sopenharmony_ci STATIC_ASSERT((kExprStructNewDefault >> 8) == kGCPrefix); 5351cb0ef41Sopenharmony_ci STATIC_ASSERT((kExprStructNewDefaultWithRtt >> 8) == kGCPrefix); 5361cb0ef41Sopenharmony_ci for (const WasmInitExpr& operand : *init.operands()) { 5371cb0ef41Sopenharmony_ci WriteInitializerExpressionWithEnd(buffer, operand, kWasmBottom); 5381cb0ef41Sopenharmony_ci } 5391cb0ef41Sopenharmony_ci buffer->write_u8(kGCPrefix); 5401cb0ef41Sopenharmony_ci WasmOpcode opcode; 5411cb0ef41Sopenharmony_ci switch (init.kind()) { 5421cb0ef41Sopenharmony_ci case WasmInitExpr::kStructNewWithRtt: 5431cb0ef41Sopenharmony_ci opcode = kExprStructNewWithRtt; 5441cb0ef41Sopenharmony_ci break; 5451cb0ef41Sopenharmony_ci case WasmInitExpr::kStructNew: 5461cb0ef41Sopenharmony_ci opcode = kExprStructNew; 5471cb0ef41Sopenharmony_ci break; 5481cb0ef41Sopenharmony_ci case WasmInitExpr::kStructNewDefaultWithRtt: 5491cb0ef41Sopenharmony_ci opcode = kExprStructNewDefaultWithRtt; 5501cb0ef41Sopenharmony_ci break; 5511cb0ef41Sopenharmony_ci case WasmInitExpr::kStructNewDefault: 5521cb0ef41Sopenharmony_ci opcode = kExprStructNewDefault; 5531cb0ef41Sopenharmony_ci break; 5541cb0ef41Sopenharmony_ci default: 5551cb0ef41Sopenharmony_ci UNREACHABLE(); 5561cb0ef41Sopenharmony_ci } 5571cb0ef41Sopenharmony_ci buffer->write_u8(static_cast<uint8_t>(opcode)); 5581cb0ef41Sopenharmony_ci buffer->write_u32v(init.immediate().index); 5591cb0ef41Sopenharmony_ci break; 5601cb0ef41Sopenharmony_ci case WasmInitExpr::kArrayInit: 5611cb0ef41Sopenharmony_ci case WasmInitExpr::kArrayInitStatic: 5621cb0ef41Sopenharmony_ci STATIC_ASSERT((kExprArrayInit >> 8) == kGCPrefix); 5631cb0ef41Sopenharmony_ci STATIC_ASSERT((kExprArrayInitStatic >> 8) == kGCPrefix); 5641cb0ef41Sopenharmony_ci for (const WasmInitExpr& operand : *init.operands()) { 5651cb0ef41Sopenharmony_ci WriteInitializerExpressionWithEnd(buffer, operand, kWasmBottom); 5661cb0ef41Sopenharmony_ci } 5671cb0ef41Sopenharmony_ci buffer->write_u8(kGCPrefix); 5681cb0ef41Sopenharmony_ci buffer->write_u8(static_cast<uint8_t>( 5691cb0ef41Sopenharmony_ci init.kind() == WasmInitExpr::kArrayInit ? kExprArrayInit 5701cb0ef41Sopenharmony_ci : kExprArrayInitStatic)); 5711cb0ef41Sopenharmony_ci buffer->write_u32v(init.immediate().index); 5721cb0ef41Sopenharmony_ci buffer->write_u32v(static_cast<uint32_t>(init.operands()->size() - 1)); 5731cb0ef41Sopenharmony_ci break; 5741cb0ef41Sopenharmony_ci case WasmInitExpr::kRttCanon: 5751cb0ef41Sopenharmony_ci STATIC_ASSERT((kExprRttCanon >> 8) == kGCPrefix); 5761cb0ef41Sopenharmony_ci buffer->write_u8(kGCPrefix); 5771cb0ef41Sopenharmony_ci buffer->write_u8(static_cast<uint8_t>(kExprRttCanon)); 5781cb0ef41Sopenharmony_ci buffer->write_i32v(static_cast<int32_t>(init.immediate().index)); 5791cb0ef41Sopenharmony_ci break; 5801cb0ef41Sopenharmony_ci } 5811cb0ef41Sopenharmony_ci} 5821cb0ef41Sopenharmony_ci 5831cb0ef41Sopenharmony_civoid WriteInitializerExpression(ZoneBuffer* buffer, const WasmInitExpr& init, 5841cb0ef41Sopenharmony_ci ValueType type) { 5851cb0ef41Sopenharmony_ci WriteInitializerExpressionWithEnd(buffer, init, type); 5861cb0ef41Sopenharmony_ci buffer->write_u8(kExprEnd); 5871cb0ef41Sopenharmony_ci} 5881cb0ef41Sopenharmony_ci} // namespace 5891cb0ef41Sopenharmony_ci 5901cb0ef41Sopenharmony_civoid WasmModuleBuilder::WriteTo(ZoneBuffer* buffer) const { 5911cb0ef41Sopenharmony_ci // == Emit magic ============================================================= 5921cb0ef41Sopenharmony_ci buffer->write_u32(kWasmMagic); 5931cb0ef41Sopenharmony_ci buffer->write_u32(kWasmVersion); 5941cb0ef41Sopenharmony_ci 5951cb0ef41Sopenharmony_ci // == Emit types ============================================================= 5961cb0ef41Sopenharmony_ci if (types_.size() > 0) { 5971cb0ef41Sopenharmony_ci size_t start = EmitSection(kTypeSectionCode, buffer); 5981cb0ef41Sopenharmony_ci size_t type_count = types_.size(); 5991cb0ef41Sopenharmony_ci for (auto pair : recursive_groups_) { 6001cb0ef41Sopenharmony_ci // Every rec. group counts as one type entry. 6011cb0ef41Sopenharmony_ci type_count -= pair.second - 1; 6021cb0ef41Sopenharmony_ci } 6031cb0ef41Sopenharmony_ci 6041cb0ef41Sopenharmony_ci buffer->write_size(type_count); 6051cb0ef41Sopenharmony_ci 6061cb0ef41Sopenharmony_ci for (uint32_t i = 0; i < types_.size(); i++) { 6071cb0ef41Sopenharmony_ci auto recursive_group = recursive_groups_.find(i); 6081cb0ef41Sopenharmony_ci 6091cb0ef41Sopenharmony_ci if (recursive_group != recursive_groups_.end()) { 6101cb0ef41Sopenharmony_ci buffer->write_u8(kWasmRecursiveTypeGroupCode); 6111cb0ef41Sopenharmony_ci buffer->write_u32v(recursive_group->second); 6121cb0ef41Sopenharmony_ci } 6131cb0ef41Sopenharmony_ci 6141cb0ef41Sopenharmony_ci const TypeDefinition& type = types_[i]; 6151cb0ef41Sopenharmony_ci 6161cb0ef41Sopenharmony_ci if (type.supertype != kNoSuperType) { 6171cb0ef41Sopenharmony_ci buffer->write_u8(kWasmSubtypeCode); 6181cb0ef41Sopenharmony_ci buffer->write_u8(1); // The supertype count is always 1. 6191cb0ef41Sopenharmony_ci buffer->write_u32v(type.supertype); 6201cb0ef41Sopenharmony_ci } 6211cb0ef41Sopenharmony_ci switch (type.kind) { 6221cb0ef41Sopenharmony_ci case TypeDefinition::kFunction: { 6231cb0ef41Sopenharmony_ci const FunctionSig* sig = type.function_sig; 6241cb0ef41Sopenharmony_ci buffer->write_u8(kWasmFunctionTypeCode); 6251cb0ef41Sopenharmony_ci buffer->write_size(sig->parameter_count()); 6261cb0ef41Sopenharmony_ci for (auto param : sig->parameters()) { 6271cb0ef41Sopenharmony_ci WriteValueType(buffer, param); 6281cb0ef41Sopenharmony_ci } 6291cb0ef41Sopenharmony_ci buffer->write_size(sig->return_count()); 6301cb0ef41Sopenharmony_ci for (auto ret : sig->returns()) { 6311cb0ef41Sopenharmony_ci WriteValueType(buffer, ret); 6321cb0ef41Sopenharmony_ci } 6331cb0ef41Sopenharmony_ci break; 6341cb0ef41Sopenharmony_ci } 6351cb0ef41Sopenharmony_ci case TypeDefinition::kStruct: { 6361cb0ef41Sopenharmony_ci const StructType* struct_type = type.struct_type; 6371cb0ef41Sopenharmony_ci buffer->write_u8(kWasmStructTypeCode); 6381cb0ef41Sopenharmony_ci buffer->write_size(struct_type->field_count()); 6391cb0ef41Sopenharmony_ci for (uint32_t i = 0; i < struct_type->field_count(); i++) { 6401cb0ef41Sopenharmony_ci WriteValueType(buffer, struct_type->field(i)); 6411cb0ef41Sopenharmony_ci buffer->write_u8(struct_type->mutability(i) ? 1 : 0); 6421cb0ef41Sopenharmony_ci } 6431cb0ef41Sopenharmony_ci break; 6441cb0ef41Sopenharmony_ci } 6451cb0ef41Sopenharmony_ci case TypeDefinition::kArray: { 6461cb0ef41Sopenharmony_ci const ArrayType* array_type = type.array_type; 6471cb0ef41Sopenharmony_ci buffer->write_u8(kWasmArrayTypeCode); 6481cb0ef41Sopenharmony_ci WriteValueType(buffer, array_type->element_type()); 6491cb0ef41Sopenharmony_ci buffer->write_u8(array_type->mutability() ? 1 : 0); 6501cb0ef41Sopenharmony_ci break; 6511cb0ef41Sopenharmony_ci } 6521cb0ef41Sopenharmony_ci } 6531cb0ef41Sopenharmony_ci } 6541cb0ef41Sopenharmony_ci FixupSection(buffer, start); 6551cb0ef41Sopenharmony_ci } 6561cb0ef41Sopenharmony_ci 6571cb0ef41Sopenharmony_ci // == Emit imports =========================================================== 6581cb0ef41Sopenharmony_ci if (global_imports_.size() + function_imports_.size() > 0) { 6591cb0ef41Sopenharmony_ci size_t start = EmitSection(kImportSectionCode, buffer); 6601cb0ef41Sopenharmony_ci buffer->write_size(global_imports_.size() + function_imports_.size()); 6611cb0ef41Sopenharmony_ci for (auto import : global_imports_) { 6621cb0ef41Sopenharmony_ci buffer->write_string(import.module); // module name 6631cb0ef41Sopenharmony_ci buffer->write_string(import.name); // field name 6641cb0ef41Sopenharmony_ci buffer->write_u8(kExternalGlobal); 6651cb0ef41Sopenharmony_ci buffer->write_u8(import.type_code); 6661cb0ef41Sopenharmony_ci buffer->write_u8(import.mutability ? 1 : 0); 6671cb0ef41Sopenharmony_ci } 6681cb0ef41Sopenharmony_ci for (auto import : function_imports_) { 6691cb0ef41Sopenharmony_ci buffer->write_string(import.module); // module name 6701cb0ef41Sopenharmony_ci buffer->write_string(import.name); // field name 6711cb0ef41Sopenharmony_ci buffer->write_u8(kExternalFunction); 6721cb0ef41Sopenharmony_ci buffer->write_u32v(import.sig_index); 6731cb0ef41Sopenharmony_ci } 6741cb0ef41Sopenharmony_ci FixupSection(buffer, start); 6751cb0ef41Sopenharmony_ci } 6761cb0ef41Sopenharmony_ci 6771cb0ef41Sopenharmony_ci // == Emit function signatures =============================================== 6781cb0ef41Sopenharmony_ci uint32_t num_function_names = 0; 6791cb0ef41Sopenharmony_ci if (functions_.size() > 0) { 6801cb0ef41Sopenharmony_ci size_t start = EmitSection(kFunctionSectionCode, buffer); 6811cb0ef41Sopenharmony_ci buffer->write_size(functions_.size()); 6821cb0ef41Sopenharmony_ci for (auto* function : functions_) { 6831cb0ef41Sopenharmony_ci function->WriteSignature(buffer); 6841cb0ef41Sopenharmony_ci if (!function->name_.empty()) ++num_function_names; 6851cb0ef41Sopenharmony_ci } 6861cb0ef41Sopenharmony_ci FixupSection(buffer, start); 6871cb0ef41Sopenharmony_ci } 6881cb0ef41Sopenharmony_ci 6891cb0ef41Sopenharmony_ci // == Emit tables ============================================================ 6901cb0ef41Sopenharmony_ci if (tables_.size() > 0) { 6911cb0ef41Sopenharmony_ci size_t start = EmitSection(kTableSectionCode, buffer); 6921cb0ef41Sopenharmony_ci buffer->write_size(tables_.size()); 6931cb0ef41Sopenharmony_ci for (const WasmTable& table : tables_) { 6941cb0ef41Sopenharmony_ci WriteValueType(buffer, table.type); 6951cb0ef41Sopenharmony_ci buffer->write_u8(table.has_maximum ? kWithMaximum : kNoMaximum); 6961cb0ef41Sopenharmony_ci buffer->write_size(table.min_size); 6971cb0ef41Sopenharmony_ci if (table.has_maximum) buffer->write_size(table.max_size); 6981cb0ef41Sopenharmony_ci if (table.init.kind() != WasmInitExpr::kNone) { 6991cb0ef41Sopenharmony_ci WriteInitializerExpression(buffer, table.init, table.type); 7001cb0ef41Sopenharmony_ci } 7011cb0ef41Sopenharmony_ci } 7021cb0ef41Sopenharmony_ci FixupSection(buffer, start); 7031cb0ef41Sopenharmony_ci } 7041cb0ef41Sopenharmony_ci 7051cb0ef41Sopenharmony_ci // == Emit memory declaration ================================================ 7061cb0ef41Sopenharmony_ci { 7071cb0ef41Sopenharmony_ci size_t start = EmitSection(kMemorySectionCode, buffer); 7081cb0ef41Sopenharmony_ci buffer->write_u8(1); // memory count 7091cb0ef41Sopenharmony_ci if (has_shared_memory_) { 7101cb0ef41Sopenharmony_ci buffer->write_u8(has_max_memory_size_ ? kSharedWithMaximum 7111cb0ef41Sopenharmony_ci : kSharedNoMaximum); 7121cb0ef41Sopenharmony_ci } else { 7131cb0ef41Sopenharmony_ci buffer->write_u8(has_max_memory_size_ ? kWithMaximum : kNoMaximum); 7141cb0ef41Sopenharmony_ci } 7151cb0ef41Sopenharmony_ci buffer->write_u32v(min_memory_size_); 7161cb0ef41Sopenharmony_ci if (has_max_memory_size_) { 7171cb0ef41Sopenharmony_ci buffer->write_u32v(max_memory_size_); 7181cb0ef41Sopenharmony_ci } 7191cb0ef41Sopenharmony_ci FixupSection(buffer, start); 7201cb0ef41Sopenharmony_ci } 7211cb0ef41Sopenharmony_ci 7221cb0ef41Sopenharmony_ci // Emit event section. 7231cb0ef41Sopenharmony_ci if (exceptions_.size() > 0) { 7241cb0ef41Sopenharmony_ci size_t start = EmitSection(kTagSectionCode, buffer); 7251cb0ef41Sopenharmony_ci buffer->write_size(exceptions_.size()); 7261cb0ef41Sopenharmony_ci for (int type : exceptions_) { 7271cb0ef41Sopenharmony_ci buffer->write_u32v(kExceptionAttribute); 7281cb0ef41Sopenharmony_ci buffer->write_u32v(type); 7291cb0ef41Sopenharmony_ci } 7301cb0ef41Sopenharmony_ci FixupSection(buffer, start); 7311cb0ef41Sopenharmony_ci } 7321cb0ef41Sopenharmony_ci 7331cb0ef41Sopenharmony_ci // == Emit globals =========================================================== 7341cb0ef41Sopenharmony_ci if (globals_.size() > 0) { 7351cb0ef41Sopenharmony_ci size_t start = EmitSection(kGlobalSectionCode, buffer); 7361cb0ef41Sopenharmony_ci buffer->write_size(globals_.size()); 7371cb0ef41Sopenharmony_ci 7381cb0ef41Sopenharmony_ci for (const WasmGlobal& global : globals_) { 7391cb0ef41Sopenharmony_ci WriteValueType(buffer, global.type); 7401cb0ef41Sopenharmony_ci buffer->write_u8(global.mutability ? 1 : 0); 7411cb0ef41Sopenharmony_ci WriteInitializerExpression(buffer, global.init, global.type); 7421cb0ef41Sopenharmony_ci } 7431cb0ef41Sopenharmony_ci FixupSection(buffer, start); 7441cb0ef41Sopenharmony_ci } 7451cb0ef41Sopenharmony_ci 7461cb0ef41Sopenharmony_ci // == emit exports =========================================================== 7471cb0ef41Sopenharmony_ci if (exports_.size() > 0) { 7481cb0ef41Sopenharmony_ci size_t start = EmitSection(kExportSectionCode, buffer); 7491cb0ef41Sopenharmony_ci buffer->write_size(exports_.size()); 7501cb0ef41Sopenharmony_ci for (auto ex : exports_) { 7511cb0ef41Sopenharmony_ci buffer->write_string(ex.name); 7521cb0ef41Sopenharmony_ci buffer->write_u8(ex.kind); 7531cb0ef41Sopenharmony_ci switch (ex.kind) { 7541cb0ef41Sopenharmony_ci case kExternalFunction: 7551cb0ef41Sopenharmony_ci buffer->write_size(ex.index + function_imports_.size()); 7561cb0ef41Sopenharmony_ci break; 7571cb0ef41Sopenharmony_ci case kExternalGlobal: 7581cb0ef41Sopenharmony_ci buffer->write_size(ex.index + global_imports_.size()); 7591cb0ef41Sopenharmony_ci break; 7601cb0ef41Sopenharmony_ci case kExternalMemory: 7611cb0ef41Sopenharmony_ci case kExternalTable: 7621cb0ef41Sopenharmony_ci // The WasmModuleBuilder doesn't support importing tables or memories 7631cb0ef41Sopenharmony_ci // yet, so there is no index offset to add. 7641cb0ef41Sopenharmony_ci buffer->write_size(ex.index); 7651cb0ef41Sopenharmony_ci break; 7661cb0ef41Sopenharmony_ci case kExternalTag: 7671cb0ef41Sopenharmony_ci UNREACHABLE(); 7681cb0ef41Sopenharmony_ci } 7691cb0ef41Sopenharmony_ci } 7701cb0ef41Sopenharmony_ci FixupSection(buffer, start); 7711cb0ef41Sopenharmony_ci } 7721cb0ef41Sopenharmony_ci 7731cb0ef41Sopenharmony_ci // == emit start function index ============================================== 7741cb0ef41Sopenharmony_ci if (start_function_index_ >= 0) { 7751cb0ef41Sopenharmony_ci size_t start = EmitSection(kStartSectionCode, buffer); 7761cb0ef41Sopenharmony_ci buffer->write_size(start_function_index_ + function_imports_.size()); 7771cb0ef41Sopenharmony_ci FixupSection(buffer, start); 7781cb0ef41Sopenharmony_ci } 7791cb0ef41Sopenharmony_ci 7801cb0ef41Sopenharmony_ci // == emit element segments ================================================== 7811cb0ef41Sopenharmony_ci if (element_segments_.size() > 0) { 7821cb0ef41Sopenharmony_ci size_t start = EmitSection(kElementSectionCode, buffer); 7831cb0ef41Sopenharmony_ci buffer->write_size(element_segments_.size()); 7841cb0ef41Sopenharmony_ci for (const WasmElemSegment& segment : element_segments_) { 7851cb0ef41Sopenharmony_ci bool is_active = segment.status == WasmElemSegment::kStatusActive; 7861cb0ef41Sopenharmony_ci // We pick the most general syntax, i.e., we always explicitly emit the 7871cb0ef41Sopenharmony_ci // table index and the type, and use the expressions-as-elements syntax. 7881cb0ef41Sopenharmony_ci // The initial byte is one of 0x05, 0x06, and 0x07. 7891cb0ef41Sopenharmony_ci uint8_t kind_mask = 7901cb0ef41Sopenharmony_ci segment.status == WasmElemSegment::kStatusActive 7911cb0ef41Sopenharmony_ci ? 0b10 7921cb0ef41Sopenharmony_ci : segment.status == WasmElemSegment::kStatusDeclarative ? 0b11 7931cb0ef41Sopenharmony_ci : 0b01; 7941cb0ef41Sopenharmony_ci uint8_t expressions_as_elements_mask = 0b100; 7951cb0ef41Sopenharmony_ci buffer->write_u8(kind_mask | expressions_as_elements_mask); 7961cb0ef41Sopenharmony_ci if (is_active) { 7971cb0ef41Sopenharmony_ci buffer->write_u32v(segment.table_index); 7981cb0ef41Sopenharmony_ci WriteInitializerExpression(buffer, segment.offset, segment.type); 7991cb0ef41Sopenharmony_ci } 8001cb0ef41Sopenharmony_ci WriteValueType(buffer, segment.type); 8011cb0ef41Sopenharmony_ci buffer->write_size(segment.entries.size()); 8021cb0ef41Sopenharmony_ci for (const WasmElemSegment::Entry entry : segment.entries) { 8031cb0ef41Sopenharmony_ci uint8_t opcode = 8041cb0ef41Sopenharmony_ci entry.kind == WasmElemSegment::Entry::kGlobalGetEntry 8051cb0ef41Sopenharmony_ci ? kExprGlobalGet 8061cb0ef41Sopenharmony_ci : entry.kind == WasmElemSegment::Entry::kRefFuncEntry 8071cb0ef41Sopenharmony_ci ? kExprRefFunc 8081cb0ef41Sopenharmony_ci : kExprRefNull; 8091cb0ef41Sopenharmony_ci bool needs_function_offset = 8101cb0ef41Sopenharmony_ci segment.indexing_mode == 8111cb0ef41Sopenharmony_ci WasmElemSegment::kRelativeToDeclaredFunctions && 8121cb0ef41Sopenharmony_ci entry.kind == WasmElemSegment::Entry::kRefFuncEntry; 8131cb0ef41Sopenharmony_ci uint32_t index = 8141cb0ef41Sopenharmony_ci entry.index + (needs_function_offset 8151cb0ef41Sopenharmony_ci ? static_cast<uint32_t>(function_imports_.size()) 8161cb0ef41Sopenharmony_ci : 0); 8171cb0ef41Sopenharmony_ci buffer->write_u8(opcode); 8181cb0ef41Sopenharmony_ci buffer->write_u32v(index); 8191cb0ef41Sopenharmony_ci buffer->write_u8(kExprEnd); 8201cb0ef41Sopenharmony_ci } 8211cb0ef41Sopenharmony_ci } 8221cb0ef41Sopenharmony_ci FixupSection(buffer, start); 8231cb0ef41Sopenharmony_ci } 8241cb0ef41Sopenharmony_ci 8251cb0ef41Sopenharmony_ci // == emit compilation hints section ========================================= 8261cb0ef41Sopenharmony_ci bool emit_compilation_hints = false; 8271cb0ef41Sopenharmony_ci for (auto* fn : functions_) { 8281cb0ef41Sopenharmony_ci if (fn->hint_ != kNoCompilationHint) { 8291cb0ef41Sopenharmony_ci emit_compilation_hints = true; 8301cb0ef41Sopenharmony_ci break; 8311cb0ef41Sopenharmony_ci } 8321cb0ef41Sopenharmony_ci } 8331cb0ef41Sopenharmony_ci if (emit_compilation_hints) { 8341cb0ef41Sopenharmony_ci // Emit the section code. 8351cb0ef41Sopenharmony_ci buffer->write_u8(kUnknownSectionCode); 8361cb0ef41Sopenharmony_ci // Emit a placeholder for section length. 8371cb0ef41Sopenharmony_ci size_t start = buffer->reserve_u32v(); 8381cb0ef41Sopenharmony_ci // Emit custom section name. 8391cb0ef41Sopenharmony_ci buffer->write_string(base::CStrVector("compilationHints")); 8401cb0ef41Sopenharmony_ci // Emit hint count. 8411cb0ef41Sopenharmony_ci buffer->write_size(functions_.size()); 8421cb0ef41Sopenharmony_ci // Emit hint bytes. 8431cb0ef41Sopenharmony_ci for (auto* fn : functions_) { 8441cb0ef41Sopenharmony_ci uint8_t hint_byte = 8451cb0ef41Sopenharmony_ci fn->hint_ != kNoCompilationHint ? fn->hint_ : kDefaultCompilationHint; 8461cb0ef41Sopenharmony_ci buffer->write_u8(hint_byte); 8471cb0ef41Sopenharmony_ci } 8481cb0ef41Sopenharmony_ci FixupSection(buffer, start); 8491cb0ef41Sopenharmony_ci } 8501cb0ef41Sopenharmony_ci 8511cb0ef41Sopenharmony_ci // == emit code ============================================================== 8521cb0ef41Sopenharmony_ci if (functions_.size() > 0) { 8531cb0ef41Sopenharmony_ci size_t start = EmitSection(kCodeSectionCode, buffer); 8541cb0ef41Sopenharmony_ci buffer->write_size(functions_.size()); 8551cb0ef41Sopenharmony_ci for (auto* function : functions_) { 8561cb0ef41Sopenharmony_ci function->WriteBody(buffer); 8571cb0ef41Sopenharmony_ci } 8581cb0ef41Sopenharmony_ci FixupSection(buffer, start); 8591cb0ef41Sopenharmony_ci } 8601cb0ef41Sopenharmony_ci 8611cb0ef41Sopenharmony_ci // == emit data segments ===================================================== 8621cb0ef41Sopenharmony_ci if (data_segments_.size() > 0) { 8631cb0ef41Sopenharmony_ci size_t start = EmitSection(kDataSectionCode, buffer); 8641cb0ef41Sopenharmony_ci buffer->write_size(data_segments_.size()); 8651cb0ef41Sopenharmony_ci 8661cb0ef41Sopenharmony_ci for (auto segment : data_segments_) { 8671cb0ef41Sopenharmony_ci buffer->write_u8(0); // linear memory segment 8681cb0ef41Sopenharmony_ci buffer->write_u8(kExprI32Const); // initializer expression for dest 8691cb0ef41Sopenharmony_ci buffer->write_u32v(segment.dest); 8701cb0ef41Sopenharmony_ci buffer->write_u8(kExprEnd); 8711cb0ef41Sopenharmony_ci buffer->write_u32v(static_cast<uint32_t>(segment.data.size())); 8721cb0ef41Sopenharmony_ci buffer->write(&segment.data[0], segment.data.size()); 8731cb0ef41Sopenharmony_ci } 8741cb0ef41Sopenharmony_ci FixupSection(buffer, start); 8751cb0ef41Sopenharmony_ci } 8761cb0ef41Sopenharmony_ci 8771cb0ef41Sopenharmony_ci // == Emit names ============================================================= 8781cb0ef41Sopenharmony_ci if (num_function_names > 0 || !function_imports_.empty()) { 8791cb0ef41Sopenharmony_ci // Emit the section code. 8801cb0ef41Sopenharmony_ci buffer->write_u8(kUnknownSectionCode); 8811cb0ef41Sopenharmony_ci // Emit a placeholder for the length. 8821cb0ef41Sopenharmony_ci size_t start = buffer->reserve_u32v(); 8831cb0ef41Sopenharmony_ci // Emit the section string. 8841cb0ef41Sopenharmony_ci buffer->write_string(base::CStrVector("name")); 8851cb0ef41Sopenharmony_ci // Emit a subsection for the function names. 8861cb0ef41Sopenharmony_ci buffer->write_u8(NameSectionKindCode::kFunctionCode); 8871cb0ef41Sopenharmony_ci // Emit a placeholder for the subsection length. 8881cb0ef41Sopenharmony_ci size_t functions_start = buffer->reserve_u32v(); 8891cb0ef41Sopenharmony_ci // Emit the function names. 8901cb0ef41Sopenharmony_ci // Imports are always named. 8911cb0ef41Sopenharmony_ci uint32_t num_imports = static_cast<uint32_t>(function_imports_.size()); 8921cb0ef41Sopenharmony_ci buffer->write_size(num_imports + num_function_names); 8931cb0ef41Sopenharmony_ci uint32_t function_index = 0; 8941cb0ef41Sopenharmony_ci for (; function_index < num_imports; ++function_index) { 8951cb0ef41Sopenharmony_ci const WasmFunctionImport* import = &function_imports_[function_index]; 8961cb0ef41Sopenharmony_ci DCHECK(!import->name.empty()); 8971cb0ef41Sopenharmony_ci buffer->write_u32v(function_index); 8981cb0ef41Sopenharmony_ci buffer->write_string(import->name); 8991cb0ef41Sopenharmony_ci } 9001cb0ef41Sopenharmony_ci if (num_function_names > 0) { 9011cb0ef41Sopenharmony_ci for (auto* function : functions_) { 9021cb0ef41Sopenharmony_ci DCHECK_EQ(function_index, 9031cb0ef41Sopenharmony_ci function->func_index() + function_imports_.size()); 9041cb0ef41Sopenharmony_ci if (!function->name_.empty()) { 9051cb0ef41Sopenharmony_ci buffer->write_u32v(function_index); 9061cb0ef41Sopenharmony_ci buffer->write_string(function->name_); 9071cb0ef41Sopenharmony_ci } 9081cb0ef41Sopenharmony_ci ++function_index; 9091cb0ef41Sopenharmony_ci } 9101cb0ef41Sopenharmony_ci } 9111cb0ef41Sopenharmony_ci FixupSection(buffer, functions_start); 9121cb0ef41Sopenharmony_ci FixupSection(buffer, start); 9131cb0ef41Sopenharmony_ci } 9141cb0ef41Sopenharmony_ci} 9151cb0ef41Sopenharmony_ci 9161cb0ef41Sopenharmony_civoid WasmModuleBuilder::WriteAsmJsOffsetTable(ZoneBuffer* buffer) const { 9171cb0ef41Sopenharmony_ci // == Emit asm.js offset table =============================================== 9181cb0ef41Sopenharmony_ci buffer->write_size(functions_.size()); 9191cb0ef41Sopenharmony_ci // Emit the offset table per function. 9201cb0ef41Sopenharmony_ci for (auto* function : functions_) { 9211cb0ef41Sopenharmony_ci function->WriteAsmWasmOffsetTable(buffer); 9221cb0ef41Sopenharmony_ci } 9231cb0ef41Sopenharmony_ci} 9241cb0ef41Sopenharmony_ci} // namespace wasm 9251cb0ef41Sopenharmony_ci} // namespace internal 9261cb0ef41Sopenharmony_ci} // namespace v8 927