Bug 1882714 [wpt PR 44850] - Update wpt metadata, a=testonly
[gecko.git] / third_party / wasm2c / src / ir-util.cc
blobee9262cc0c55058edd4392f92fa46b32f3329748
1 /*
2 * Copyright 2016 WebAssembly Community Group participants
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #include "wabt/ir-util.h"
19 #include <algorithm>
20 #include <array>
21 #include <cassert>
22 #include <cinttypes>
23 #include <cstdarg>
24 #include <cstdio>
25 #include <iterator>
26 #include <map>
27 #include <string>
28 #include <vector>
30 #include "wabt/cast.h"
31 #include "wabt/common.h"
32 #include "wabt/expr-visitor.h"
33 #include "wabt/ir-util.h"
34 #include "wabt/ir.h"
35 #include "wabt/literal.h"
36 #include "wabt/stream.h"
38 #define WABT_TRACING 0
39 #include "wabt/tracing.h"
41 using namespace wabt;
43 const Label* ModuleContext::GetLabel(const Var& var) const {
44 if (var.is_name()) {
45 for (Index i = GetLabelStackSize(); i > 0; --i) {
46 auto label = &label_stack_[i - 1];
47 if (label->name == var.name()) {
48 return label;
51 } else if (var.index() < GetLabelStackSize()) {
52 auto label = &label_stack_[GetLabelStackSize() - var.index() - 1];
53 return label;
55 return nullptr;
58 Index ModuleContext::GetLabelArity(const Var& var) const {
59 auto label = GetLabel(var);
60 if (!label) {
61 return 0;
64 return label->label_type == LabelType::Loop ? label->param_types.size()
65 : label->result_types.size();
68 Index ModuleContext::GetFuncParamCount(const Var& var) const {
69 const Func* func = module.GetFunc(var);
70 return func ? func->GetNumParams() : 0;
73 Index ModuleContext::GetFuncResultCount(const Var& var) const {
74 const Func* func = module.GetFunc(var);
75 return func ? func->GetNumResults() : 0;
78 void ModuleContext::BeginBlock(LabelType label_type, const Block& block) {
79 label_stack_.emplace_back(label_type, block.label, block.decl.sig.param_types,
80 block.decl.sig.result_types);
83 void ModuleContext::EndBlock() {
84 label_stack_.pop_back();
87 void ModuleContext::BeginFunc(const Func& func) {
88 label_stack_.clear();
89 label_stack_.emplace_back(LabelType::Func, std::string(), TypeVector(),
90 func.decl.sig.result_types);
91 current_func_ = &func;
94 void ModuleContext::EndFunc() {
95 current_func_ = nullptr;
98 ModuleContext::Arities ModuleContext::GetExprArity(const Expr& expr) const {
99 switch (expr.type()) {
100 case ExprType::AtomicNotify:
101 case ExprType::AtomicRmw:
102 case ExprType::Binary:
103 case ExprType::Compare:
104 case ExprType::TableGrow:
105 return {2, 1};
107 case ExprType::AtomicStore:
108 case ExprType::Store:
109 case ExprType::TableSet:
110 return {2, 0};
112 case ExprType::Block:
113 return {0, cast<BlockExpr>(&expr)->block.decl.sig.GetNumResults()};
115 case ExprType::Br:
116 return {GetLabelArity(cast<BrExpr>(&expr)->var), 1, true};
118 case ExprType::BrIf: {
119 Index arity = GetLabelArity(cast<BrIfExpr>(&expr)->var);
120 return {arity + 1, arity};
123 case ExprType::BrTable:
124 return {GetLabelArity(cast<BrTableExpr>(&expr)->default_target) + 1, 1,
125 true};
127 case ExprType::Call: {
128 const Var& var = cast<CallExpr>(&expr)->var;
129 return {GetFuncParamCount(var), GetFuncResultCount(var)};
132 case ExprType::ReturnCall: {
133 const Var& var = cast<ReturnCallExpr>(&expr)->var;
134 return {GetFuncParamCount(var), GetFuncResultCount(var), true};
137 case ExprType::CallIndirect: {
138 const auto* ci_expr = cast<CallIndirectExpr>(&expr);
139 return {ci_expr->decl.GetNumParams() + 1, ci_expr->decl.GetNumResults()};
142 case ExprType::CallRef: {
143 const Var& var = cast<CallRefExpr>(&expr)->function_type_index;
144 return {GetFuncParamCount(var) + 1, GetFuncResultCount(var)};
147 case ExprType::ReturnCallIndirect: {
148 const auto* rci_expr = cast<ReturnCallIndirectExpr>(&expr);
149 return {rci_expr->decl.GetNumParams() + 1, rci_expr->decl.GetNumResults(),
150 true};
153 case ExprType::Const:
154 case ExprType::GlobalGet:
155 case ExprType::LocalGet:
156 case ExprType::MemorySize:
157 case ExprType::TableSize:
158 case ExprType::RefNull:
159 case ExprType::RefFunc:
160 return {0, 1};
162 case ExprType::Unreachable:
163 return {0, 1, true};
165 case ExprType::DataDrop:
166 case ExprType::ElemDrop:
167 case ExprType::AtomicFence:
168 case ExprType::CodeMetadata:
169 return {0, 0};
171 case ExprType::MemoryInit:
172 case ExprType::TableInit:
173 case ExprType::MemoryFill:
174 case ExprType::MemoryCopy:
175 case ExprType::TableCopy:
176 case ExprType::TableFill:
177 return {3, 0};
179 case ExprType::AtomicLoad:
180 case ExprType::Convert:
181 case ExprType::Load:
182 case ExprType::LocalTee:
183 case ExprType::MemoryGrow:
184 case ExprType::Unary:
185 case ExprType::TableGet:
186 case ExprType::RefIsNull:
187 case ExprType::LoadSplat:
188 case ExprType::LoadZero:
189 return {1, 1};
191 case ExprType::Drop:
192 case ExprType::GlobalSet:
193 case ExprType::LocalSet:
194 return {1, 0};
196 case ExprType::If:
197 return {1, cast<IfExpr>(&expr)->true_.decl.sig.GetNumResults()};
199 case ExprType::Loop:
200 return {0, cast<LoopExpr>(&expr)->block.decl.sig.GetNumResults()};
202 case ExprType::Nop:
203 return {0, 0};
205 case ExprType::Return:
206 return {static_cast<Index>(current_func_->decl.sig.result_types.size()),
207 1, true};
209 case ExprType::Rethrow:
210 return {0, 0, true};
212 case ExprType::AtomicRmwCmpxchg:
213 case ExprType::AtomicWait:
214 case ExprType::Select:
215 return {3, 1};
217 case ExprType::Throw: {
218 auto throw_ = cast<ThrowExpr>(&expr);
219 Index operand_count = 0;
220 if (Tag* tag = module.GetTag(throw_->var)) {
221 operand_count = tag->decl.sig.param_types.size();
223 return {operand_count, 0, true};
226 case ExprType::Try:
227 return {0, cast<TryExpr>(&expr)->block.decl.sig.GetNumResults()};
229 case ExprType::Ternary:
230 return {3, 1};
232 case ExprType::SimdLaneOp: {
233 const Opcode opcode = cast<SimdLaneOpExpr>(&expr)->opcode;
234 switch (opcode) {
235 case Opcode::I8X16ExtractLaneS:
236 case Opcode::I8X16ExtractLaneU:
237 case Opcode::I16X8ExtractLaneS:
238 case Opcode::I16X8ExtractLaneU:
239 case Opcode::I32X4ExtractLane:
240 case Opcode::I64X2ExtractLane:
241 case Opcode::F32X4ExtractLane:
242 case Opcode::F64X2ExtractLane:
243 return {1, 1};
245 case Opcode::I8X16ReplaceLane:
246 case Opcode::I16X8ReplaceLane:
247 case Opcode::I32X4ReplaceLane:
248 case Opcode::I64X2ReplaceLane:
249 case Opcode::F32X4ReplaceLane:
250 case Opcode::F64X2ReplaceLane:
251 return {2, 1};
253 default:
254 fprintf(stderr, "Invalid Opcode for expr type: %s\n",
255 GetExprTypeName(expr));
256 assert(0);
257 return {0, 0};
261 case ExprType::SimdLoadLane:
262 case ExprType::SimdStoreLane: {
263 return {2, 1};
266 case ExprType::SimdShuffleOp:
267 return {2, 1};
270 WABT_UNREACHABLE;