1/*
2 * Copyright 2021 WebAssembly Community Group participants
3 *
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
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
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.
15 */
16
17#include "ir/properties.h"
18#include "wasm-traversal.h"
19
20namespace wasm::Properties {
21
22bool isGenerative(Expression* curr, FeatureSet features) {
23 // Practically no wasm instructions are generative. Exceptions occur only in
24 // GC atm.
25 if (!features.hasGC()) {
26 return false;
27 }
28
29 struct Scanner : public PostWalker<Scanner> {
30 bool generative = false;
31 void visitStructNew(StructNew* curr) { generative = true; }
32 void visitArrayNew(ArrayNew* curr) { generative = true; }
33 void visitArrayNewFixed(ArrayNewFixed* curr) { generative = true; }
34 } scanner;
35 scanner.walk(curr);
36 return scanner.generative;
37}
38
39// Checks an expression in a shallow manner (i.e., does not check children) as
40// to whether it is valid in a wasm constant expression.
41static bool isValidInConstantExpression(Module& wasm, Expression* expr) {
42 if (isSingleConstantExpression(curr: expr) || expr->is<StructNew>() ||
43 expr->is<ArrayNew>() || expr->is<ArrayNewFixed>() || expr->is<I31New>() ||
44 expr->is<StringConst>()) {
45 return true;
46 }
47
48 if (auto* refAs = expr->dynCast<RefAs>()) {
49 if (refAs->op == ExternExternalize || refAs->op == ExternInternalize) {
50 return true;
51 }
52 }
53
54 if (auto* get = expr->dynCast<GlobalGet>()) {
55 auto* g = wasm.getGlobalOrNull(name: get->name);
56 // This is called from the validator, so we have to handle non-existent
57 // globals gracefully.
58 if (!g) {
59 return false;
60 }
61 // Only gets of immutable globals are constant.
62 if (g->mutable_) {
63 return false;
64 }
65 // Only imported globals are available in constant expressions unless GC is
66 // enabled.
67 return g->imported() || wasm.features.hasGC();
68 // TODO: Check that there are no cycles between globals.
69 }
70
71 if (wasm.features.hasExtendedConst()) {
72 if (auto* bin = expr->dynCast<Binary>()) {
73 if (bin->op == AddInt64 || bin->op == SubInt64 || bin->op == MulInt64 ||
74 bin->op == AddInt32 || bin->op == SubInt32 || bin->op == MulInt32) {
75 return true;
76 }
77 }
78 }
79
80 return false;
81}
82
83bool isValidConstantExpression(Module& wasm, Expression* expr) {
84 struct Walker : public PostWalker<Walker, UnifiedExpressionVisitor<Walker>> {
85 bool valid = true;
86 void visitExpression(Expression* curr) {
87 if (!isValidInConstantExpression(*getModule(), curr)) {
88 valid = false;
89 }
90 }
91 } walker;
92 walker.setModule(&wasm);
93 walker.walk(expr);
94 return walker.valid;
95}
96
97} // namespace wasm::Properties
98

source code of dart_sdk/third_party/binaryen/src/src/ir/properties.cpp