summaryrefslogtreecommitdiff
path: root/src/ir/utils.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/ir/utils.h')
-rw-r--r--src/ir/utils.h118
1 files changed, 50 insertions, 68 deletions
diff --git a/src/ir/utils.h b/src/ir/utils.h
index c91698124..9be8947a1 100644
--- a/src/ir/utils.h
+++ b/src/ir/utils.h
@@ -17,22 +17,21 @@
#ifndef wasm_ir_utils_h
#define wasm_ir_utils_h
-#include "wasm.h"
-#include "wasm-traversal.h"
-#include "wasm-builder.h"
-#include "pass.h"
#include "ir/branch-utils.h"
+#include "pass.h"
+#include "wasm-builder.h"
+#include "wasm-traversal.h"
+#include "wasm.h"
namespace wasm {
// Measure the size of an AST
-struct Measurer : public PostWalker<Measurer, UnifiedExpressionVisitor<Measurer>> {
+struct Measurer
+ : public PostWalker<Measurer, UnifiedExpressionVisitor<Measurer>> {
Index size = 0;
- void visitExpression(Expression* curr) {
- size++;
- }
+ void visitExpression(Expression* curr) { size++; }
static Index measure(Expression* tree) {
Measurer measurer;
@@ -43,26 +42,24 @@ struct Measurer : public PostWalker<Measurer, UnifiedExpressionVisitor<Measurer>
struct ExpressionAnalyzer {
// Given a stack of expressions, checks if the topmost is used as a result.
- // For example, if the parent is a block and the node is before the last position,
- // it is not used.
+ // For example, if the parent is a block and the node is before the last
+ // position, it is not used.
static bool isResultUsed(ExpressionStack& stack, Function* func);
// Checks if a value is dropped.
static bool isResultDropped(ExpressionStack& stack);
- // Checks if a break is a simple - no condition, no value, just a plain branching
- static bool isSimple(Break* curr) {
- return !curr->condition && !curr->value;
- }
+ // Checks if a break is a simple - no condition, no value, just a plain
+ // branching
+ static bool isSimple(Break* curr) { return !curr->condition && !curr->value; }
using ExprComparer = std::function<bool(Expression*, Expression*)>;
- static bool flexibleEqual(Expression* left, Expression* right, ExprComparer comparer);
+ static bool
+ flexibleEqual(Expression* left, Expression* right, ExprComparer comparer);
// Compares two expressions for equivalence.
static bool equal(Expression* left, Expression* right) {
- auto comparer = [](Expression* left, Expression* right) {
- return false;
- };
+ auto comparer = [](Expression* left, Expression* right) { return false; };
return flexibleEqual(left, right, comparer);
}
@@ -79,7 +76,8 @@ struct ExpressionAnalyzer {
return flexibleEqual(left, right, comparer);
}
- // hash an expression, ignoring superficial details like specific internal names
+ // hash an expression, ignoring superficial details like specific internal
+ // names
static HashType hash(Expression* curr);
};
@@ -100,15 +98,16 @@ struct ExpressionAnalyzer {
// exist, but the breaks don't declare the type, rather everything
// depends on the block. To avoid looking at the parent or something
// else, just remove such un-taken branches.
-struct ReFinalize : public WalkerPass<PostWalker<ReFinalize, OverriddenVisitor<ReFinalize>>> {
+struct ReFinalize
+ : public WalkerPass<PostWalker<ReFinalize, OverriddenVisitor<ReFinalize>>> {
bool isFunctionParallel() override { return true; }
Pass* create() override { return new ReFinalize; }
ReFinalize() { name = "refinalize"; }
- // block finalization is O(bad) if we do each block by itself, so do it in bulk,
- // tracking break value types so we just do a linear pass
+ // block finalization is O(bad) if we do each block by itself, so do it in
+ // bulk, tracking break value types so we just do a linear pass
std::map<Name, Type> breakValues;
@@ -220,10 +219,10 @@ struct ReFinalizeNode : public OverriddenVisitor<ReFinalizeNode> {
}
};
-// Adds drop() operations where necessary. This lets you not worry about adding drop when
-// generating code.
-// This also refinalizes before and after, as dropping can change types, and depends
-// on types being cleaned up - no unnecessary block/if/loop types (see refinalize)
+// Adds drop() operations where necessary. This lets you not worry about adding
+// drop when generating code. This also refinalizes before and after, as
+// dropping can change types, and depends on types being cleaned up - no
+// unnecessary block/if/loop types (see refinalize)
// TODO: optimize that, interleave them
struct AutoDrop : public WalkerPass<ExpressionStackWalker<AutoDrop>> {
bool isFunctionParallel() override { return true; }
@@ -236,7 +235,8 @@ struct AutoDrop : public WalkerPass<ExpressionStackWalker<AutoDrop>> {
bool acted = false;
if (isConcreteType(child->type)) {
expressionStack.push_back(child);
- if (!ExpressionAnalyzer::isResultUsed(expressionStack, getFunction()) && !ExpressionAnalyzer::isResultDropped(expressionStack)) {
+ if (!ExpressionAnalyzer::isResultUsed(expressionStack, getFunction()) &&
+ !ExpressionAnalyzer::isResultDropped(expressionStack)) {
child = Builder(*getModule()).makeDrop(child);
acted = true;
}
@@ -245,12 +245,11 @@ struct AutoDrop : public WalkerPass<ExpressionStackWalker<AutoDrop>> {
return acted;
}
- void reFinalize() {
- ReFinalizeNode::updateStack(expressionStack);
- }
+ void reFinalize() { ReFinalizeNode::updateStack(expressionStack); }
void visitBlock(Block* curr) {
- if (curr->list.size() == 0) return;
+ if (curr->list.size() == 0)
+ return;
for (Index i = 0; i < curr->list.size() - 1; i++) {
auto* child = curr->list[i];
if (isConcreteType(child->type)) {
@@ -265,9 +264,11 @@ struct AutoDrop : public WalkerPass<ExpressionStackWalker<AutoDrop>> {
void visitIf(If* curr) {
bool acted = false;
- if (maybeDrop(curr->ifTrue)) acted = true;
+ if (maybeDrop(curr->ifTrue))
+ acted = true;
if (curr->ifFalse) {
- if (maybeDrop(curr->ifFalse)) acted = true;
+ if (maybeDrop(curr->ifFalse))
+ acted = true;
}
if (acted) {
reFinalize();
@@ -286,50 +287,31 @@ struct AutoDrop : public WalkerPass<ExpressionStackWalker<AutoDrop>> {
};
struct I64Utilities {
- static Expression* recreateI64(Builder& builder, Expression* low, Expression* high) {
- return
- builder.makeBinary(
- OrInt64,
- builder.makeUnary(
- ExtendUInt32,
- low
- ),
- builder.makeBinary(
- ShlInt64,
- builder.makeUnary(
- ExtendUInt32,
- high
- ),
- builder.makeConst(Literal(int64_t(32)))
- )
- )
- ;
+ static Expression*
+ recreateI64(Builder& builder, Expression* low, Expression* high) {
+ return builder.makeBinary(
+ OrInt64,
+ builder.makeUnary(ExtendUInt32, low),
+ builder.makeBinary(ShlInt64,
+ builder.makeUnary(ExtendUInt32, high),
+ builder.makeConst(Literal(int64_t(32)))));
};
static Expression* recreateI64(Builder& builder, Index low, Index high) {
- return recreateI64(builder, builder.makeGetLocal(low, i32), builder.makeGetLocal(high, i32));
+ return recreateI64(
+ builder, builder.makeGetLocal(low, i32), builder.makeGetLocal(high, i32));
};
static Expression* getI64High(Builder& builder, Index index) {
- return
- builder.makeUnary(
- WrapInt64,
- builder.makeBinary(
- ShrUInt64,
- builder.makeGetLocal(index, i64),
- builder.makeConst(Literal(int64_t(32)))
- )
- )
- ;
+ return builder.makeUnary(
+ WrapInt64,
+ builder.makeBinary(ShrUInt64,
+ builder.makeGetLocal(index, i64),
+ builder.makeConst(Literal(int64_t(32)))));
}
static Expression* getI64Low(Builder& builder, Index index) {
- return
- builder.makeUnary(
- WrapInt64,
- builder.makeGetLocal(index, i64)
- )
- ;
+ return builder.makeUnary(WrapInt64, builder.makeGetLocal(index, i64));
}
};