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"
30 #include "wabt/cast.h"
31 #include "wabt/common.h"
32 #include "wabt/expr-visitor.h"
33 #include "wabt/ir-util.h"
35 #include "wabt/literal.h"
36 #include "wabt/stream.h"
38 #define WABT_TRACING 0
39 #include "wabt/tracing.h"
43 const Label
* ModuleContext::GetLabel(const Var
& var
) const {
45 for (Index i
= GetLabelStackSize(); i
> 0; --i
) {
46 auto label
= &label_stack_
[i
- 1];
47 if (label
->name
== var
.name()) {
51 } else if (var
.index() < GetLabelStackSize()) {
52 auto label
= &label_stack_
[GetLabelStackSize() - var
.index() - 1];
58 Index
ModuleContext::GetLabelArity(const Var
& var
) const {
59 auto label
= GetLabel(var
);
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
) {
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
:
107 case ExprType::AtomicStore
:
108 case ExprType::Store
:
109 case ExprType::TableSet
:
112 case ExprType::Block
:
113 return {0, cast
<BlockExpr
>(&expr
)->block
.decl
.sig
.GetNumResults()};
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,
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(),
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
:
162 case ExprType::Unreachable
:
165 case ExprType::DataDrop
:
166 case ExprType::ElemDrop
:
167 case ExprType::AtomicFence
:
168 case ExprType::CodeMetadata
:
171 case ExprType::MemoryInit
:
172 case ExprType::TableInit
:
173 case ExprType::MemoryFill
:
174 case ExprType::MemoryCopy
:
175 case ExprType::TableCopy
:
176 case ExprType::TableFill
:
179 case ExprType::AtomicLoad
:
180 case ExprType::Convert
:
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
:
192 case ExprType::GlobalSet
:
193 case ExprType::LocalSet
:
197 return {1, cast
<IfExpr
>(&expr
)->true_
.decl
.sig
.GetNumResults()};
200 return {0, cast
<LoopExpr
>(&expr
)->block
.decl
.sig
.GetNumResults()};
205 case ExprType::Return
:
206 return {static_cast<Index
>(current_func_
->decl
.sig
.result_types
.size()),
209 case ExprType::Rethrow
:
212 case ExprType::AtomicRmwCmpxchg
:
213 case ExprType::AtomicWait
:
214 case ExprType::Select
:
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};
227 return {0, cast
<TryExpr
>(&expr
)->block
.decl
.sig
.GetNumResults()};
229 case ExprType::Ternary
:
232 case ExprType::SimdLaneOp
: {
233 const Opcode opcode
= cast
<SimdLaneOpExpr
>(&expr
)->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
:
245 case Opcode::I8X16ReplaceLane
:
246 case Opcode::I16X8ReplaceLane
:
247 case Opcode::I32X4ReplaceLane
:
248 case Opcode::I64X2ReplaceLane
:
249 case Opcode::F32X4ReplaceLane
:
250 case Opcode::F64X2ReplaceLane
:
254 fprintf(stderr
, "Invalid Opcode for expr type: %s\n",
255 GetExprTypeName(expr
));
261 case ExprType::SimdLoadLane
:
262 case ExprType::SimdStoreLane
: {
266 case ExprType::SimdShuffleOp
: