summaryrefslogtreecommitdiff
path: root/src/ast_utils.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/ast_utils.h')
-rw-r--r--src/ast_utils.h23
1 files changed, 20 insertions, 3 deletions
diff --git a/src/ast_utils.h b/src/ast_utils.h
index 55499d808..66dbf039a 100644
--- a/src/ast_utils.h
+++ b/src/ast_utils.h
@@ -49,6 +49,11 @@ struct BreakSeeker : public PostWalker<BreakSeeker, Visitor<BreakSeeker>> {
// TODO: optimize
struct EffectAnalyzer : public PostWalker<EffectAnalyzer, Visitor<EffectAnalyzer>> {
+ EffectAnalyzer() {}
+ EffectAnalyzer(Expression *ast) {
+ walk(ast);
+ }
+
bool branches = false;
bool calls = false;
std::set<Index> localsRead;
@@ -115,9 +120,21 @@ struct EffectAnalyzer : public PostWalker<EffectAnalyzer, Visitor<EffectAnalyzer
};
struct ExpressionManipulator {
- // Nop is the smallest node, so we can always nop-ify another node in our arena
- static void nop(Expression* target) {
- *static_cast<Nop*>(target) = Nop();
+ // Re-use a node's memory. This helps avoid allocation when optimizing.
+ template<typename InputType, typename OutputType>
+ static OutputType* convert(InputType *input) {
+ static_assert(sizeof(OutputType) <= sizeof(InputType),
+ "Can only convert to a smaller size Expression node");
+ input->~InputType(); // arena-allocaed, so no destructor, but avoid UB.
+ OutputType* output = (OutputType*)(input);
+ new (output) OutputType;
+ return output;
+ }
+
+ // Convenience method for nop, which is a common conversion
+ template<typename InputType>
+ static void nop(InputType* target) {
+ convert<InputType, Nop>(target);
}
};