5 #include "src/wasm/wasm-text.h" 7 #include "src/debug/interface-types.h" 8 #include "src/objects-inl.h" 9 #include "src/ostreams.h" 10 #include "src/vector.h" 11 #include "src/wasm/function-body-decoder-impl.h" 12 #include "src/wasm/function-body-decoder.h" 13 #include "src/wasm/wasm-module.h" 14 #include "src/wasm/wasm-opcodes.h" 15 #include "src/zone/zone.h" 22 bool IsValidFunctionName(
const Vector<const char> &name) {
23 if (name.is_empty())
return false;
24 const char *special_chars =
"_.+-*/\\^~=<>!?@#$%&|:'`";
26 bool valid_char = (c >=
'0' && c <= '9') || (c >=
'a' && c <=
'z') ||
27 (c >=
'A' && c <=
'Z') || strchr(special_chars, c);
28 if (!valid_char)
return false;
35 void PrintWasmText(
const WasmModule* module,
const ModuleWireBytes& wire_bytes,
36 uint32_t func_index, std::ostream& os,
37 debug::WasmDisassembly::OffsetTable* offset_table) {
38 DCHECK_NOT_NULL(module);
39 DCHECK_GT(module->functions.size(), func_index);
40 const WasmFunction *fun = &module->functions[func_index];
42 AccountingAllocator allocator;
43 Zone zone(&allocator, ZONE_NAME);
45 int control_depth = 1;
49 WasmName fun_name = wire_bytes.GetNameOrNull(fun, module);
50 if (IsValidFunctionName(fun_name)) {
52 os.write(fun_name.start(), fun_name.length());
54 if (fun->sig->parameter_count()) {
56 for (
auto param : fun->sig->parameters())
57 os <<
' ' << ValueTypes::TypeName(param);
60 if (fun->sig->return_count()) {
62 for (
auto ret : fun->sig->returns()) os <<
' ' << ValueTypes::TypeName(ret);
69 BodyLocalDecls decls(&zone);
70 Vector<const byte> func_bytes = wire_bytes.GetFunctionBytes(fun);
71 BytecodeIterator
i(func_bytes.begin(), func_bytes.end(), &decls);
72 DCHECK_LT(func_bytes.begin(),
i.pc());
73 if (!decls.type_list.empty()) {
75 for (
const ValueType &v : decls.type_list) {
76 os <<
' ' << ValueTypes::TypeName(v);
82 for (;
i.has_next();
i.next()) {
83 WasmOpcode opcode =
i.current();
84 if (opcode == kExprElse || opcode == kExprEnd) --control_depth;
86 DCHECK_LE(0, control_depth);
87 const int kMaxIndentation = 64;
88 int indentation = std::min(kMaxIndentation, 2 * control_depth);
90 offset_table->emplace_back(
i.pc_offset(), line_nr, indentation);
94 const char padding[kMaxIndentation + 1] =
96 os.write(padding, indentation);
103 BlockTypeImmediate<Decoder::kNoValidate> imm(kAllWasmFeatures, &
i,
105 os << WasmOpcodes::OpcodeName(opcode);
106 if (imm.type == kWasmVar) {
107 os <<
" (type " << imm.sig_index <<
")";
108 }
else if (imm.out_arity() > 0) {
109 os <<
" " << ValueTypes::TypeName(imm.out_type(0));
116 BreakDepthImmediate<Decoder::kNoValidate> imm(&
i,
i.pc());
117 os << WasmOpcodes::OpcodeName(opcode) <<
' ' << imm.depth;
128 BranchTableImmediate<Decoder::kNoValidate> imm(&
i,
i.pc());
129 BranchTableIterator<Decoder::kNoValidate> iterator(&
i, imm);
131 while (iterator.has_next()) os <<
' ' << iterator.next();
134 case kExprCallIndirect: {
135 CallIndirectImmediate<Decoder::kNoValidate> imm(&
i,
i.pc());
136 DCHECK_EQ(0, imm.table_index);
137 os <<
"call_indirect " << imm.sig_index;
140 case kExprCallFunction: {
141 CallFunctionImmediate<Decoder::kNoValidate> imm(&
i,
i.pc());
142 os <<
"call " << imm.index;
147 case kExprTeeLocal: {
148 LocalIndexImmediate<Decoder::kNoValidate> imm(&
i,
i.pc());
149 os << WasmOpcodes::OpcodeName(opcode) <<
' ' << imm.index;
154 ExceptionIndexImmediate<Decoder::kNoValidate> imm(&
i,
i.pc());
155 os << WasmOpcodes::OpcodeName(opcode) <<
' ' << imm.index;
159 case kExprSetGlobal: {
160 GlobalIndexImmediate<Decoder::kNoValidate> imm(&
i,
i.pc());
161 os << WasmOpcodes::OpcodeName(opcode) <<
' ' << imm.index;
164 #define CASE_CONST(type, str, cast_type) \ 165 case kExpr##type##Const: { \ 166 Imm##type##Immediate<Decoder::kNoValidate> imm(&i, i.pc()); \ 167 os << #str ".const " << static_cast<cast_type>(imm.value); \ 170 CASE_CONST(I32, i32, int32_t)
172 CASE_CONST(F32, f32,
float)
173 CASE_CONST(F64, f64,
double)
176 #define CASE_OPCODE(opcode, _, __) case kExpr##opcode: 177 FOREACH_LOAD_MEM_OPCODE(CASE_OPCODE)
178 FOREACH_STORE_MEM_OPCODE(CASE_OPCODE) {
179 MemoryAccessImmediate<Decoder::kNoValidate> imm(&
i,
i.pc(),
181 os << WasmOpcodes::OpcodeName(opcode) <<
" offset=" << imm.offset
182 <<
" align=" << (1ULL << imm.alignment);
186 FOREACH_SIMPLE_OPCODE(CASE_OPCODE)
187 case kExprUnreachable:
190 case kExprMemorySize:
191 case kExprMemoryGrow:
194 os << WasmOpcodes::OpcodeName(opcode);
196 case kAtomicPrefix: {
197 WasmOpcode atomic_opcode =
i.prefixed_opcode();
198 switch (atomic_opcode) {
199 FOREACH_ATOMIC_OPCODE(CASE_OPCODE) {
200 MemoryAccessImmediate<Decoder::kNoValidate> imm(&
i,
i.pc(),
202 os << WasmOpcodes::OpcodeName(atomic_opcode)
203 <<
" offset=" << imm.offset
204 <<
" align=" << (1ULL << imm.alignment);
216 FOREACH_ASMJS_COMPAT_OPCODE(CASE_OPCODE)
219 FOREACH_SIMD_0_OPERAND_OPCODE(CASE_OPCODE)
220 FOREACH_SIMD_1_OPERAND_OPCODE(CASE_OPCODE)
221 FOREACH_SIMD_MASK_OPERAND_OPCODE(CASE_OPCODE)
222 FOREACH_SIMD_MEM_OPCODE(CASE_OPCODE)
223 os << WasmOpcodes::OpcodeName(opcode);
234 DCHECK_EQ(0, control_depth);