diff options
Diffstat (limited to 'src/ir/possible-constant.h')
-rw-r--r-- | src/ir/possible-constant.h | 38 |
1 files changed, 35 insertions, 3 deletions
diff --git a/src/ir/possible-constant.h b/src/ir/possible-constant.h index 24f236a3c..c75669dab 100644 --- a/src/ir/possible-constant.h +++ b/src/ir/possible-constant.h @@ -19,6 +19,7 @@ #include <variant> +#include "ir/properties.h" #include "wasm-builder.h" #include "wasm.h" @@ -47,9 +48,29 @@ private: public: PossibleConstantValues() : value(None()) {} - // Note a written value as we see it, and update our internal knowledge based - // on it and all previous values noted. This can be called using either a - // Literal or a Name, so it uses a template. + // Notes the contents of an expression and update our internal knowledge based + // on it and all previous values noted. + void note(Expression* expr, Module& wasm) { + // If this is a constant literal value, note that. + if (Properties::isConstantExpression(expr)) { + note(Properties::getLiteral(expr)); + return; + } + + // If this is an immutable global that we get, note that. + if (auto* get = expr->dynCast<GlobalGet>()) { + auto* global = wasm.getGlobal(get->name); + if (global->mutable_ == Immutable) { + note(get->name); + return; + } + } + + // Otherwise, this is not something we can reason about. + noteUnknown(); + } + + // Note either a Literal or a Name. template<typename T> void note(T curr) { if (std::get_if<None>(&value)) { // This is the first value. @@ -120,6 +141,17 @@ public: return std::get<Name>(value); } + // Assuming we have a single value, make an expression containing that value. + Expression* makeExpression(Module& wasm) { + Builder builder(wasm); + if (isConstantLiteral()) { + return builder.makeConstantExpression(getConstantLiteral()); + } else { + auto name = getConstantGlobal(); + return builder.makeGlobalGet(name, wasm.getGlobal(name)->type); + } + } + // Returns whether we have ever noted a value. bool hasNoted() const { return !std::get_if<None>(&value); } |