moar
diff --git a/src/asm2wasm.h b/src/asm2wasm.h
index 77be6aa..219d36c 100644
--- a/src/asm2wasm.h
+++ b/src/asm2wasm.h
@@ -515,7 +515,7 @@
   Block* blockify(Expression* expression) {
     if (expression->is<Block>() && !expression->cast<Block>()->name.is()) return expression->dynCast<Block>();
     auto ret = allocator.alloc<Block>();
-    ret->list.push_back(expression);
+    ret->list.push_back(expression, allocator);
     ret->finalize();
     return ret;
   }
@@ -532,8 +532,8 @@
       case BinaryOp::DivUInt64: call->target = I64U_DIV; break;
       default: WASM_UNREACHABLE();
     }
-    call->operands.push_back(left);
-    call->operands.push_back(right);
+    call->operands.push_back(left, allocator);
+    call->operands.push_back(right, allocator);
     call->type = i64;
     static std::set<Name> addedFunctions;
     if (addedFunctions.count(call->target) == 0) {
@@ -958,7 +958,7 @@
           // add a new param
           auto val = parent->allocator.alloc<Const>();
           val->type = val->value.type = type->params[i];
-          curr->operands.push_back(val);
+          curr->operands.push_back(val, parent->allocator);
         } else if (curr->operands[i]->type != type->params[i]) {
           // if the param is used, then we have overloading here and the combined type must be f64;
           // if this is an unreachable param, then it doesn't matter.
@@ -1119,8 +1119,8 @@
           x64 = Builder::addVar(func, "x64", i64),
           y64 = Builder::addVar(func, "y64", i64);
     auto* body = allocator.alloc<Block>();
-    body->list.push_back(builder.makeSetLocal(x64, I64Utilities::recreateI64(builder, xl, xh)));
-    body->list.push_back(builder.makeSetLocal(y64, I64Utilities::recreateI64(builder, yl, yh)));
+    body->list.push_back(builder.makeSetLocal(x64, I64Utilities::recreateI64(builder, xl, xh)), allocator);
+    body->list.push_back(builder.makeSetLocal(y64, I64Utilities::recreateI64(builder, yl, yh)), allocator);
     body->list.push_back(
       builder.makeIf(
         builder.makeGetLocal(r, i32),
@@ -1134,7 +1134,7 @@
           ),
           i64
         )
-      )
+      ), allocator
     );
     body->list.push_back(
       builder.makeSetLocal(
@@ -1144,15 +1144,15 @@
           builder.makeGetLocal(x64, i64),
           builder.makeGetLocal(y64, i64)
         )
-      )
+      ), allocator
     );
     body->list.push_back(
       builder.makeSetGlobal(
         tempRet0,
         I64Utilities::getI64High(builder, x64)
-      )
+      ), allocator
     );
-    body->list.push_back(I64Utilities::getI64Low(builder, x64));
+    body->list.push_back(I64Utilities::getI64Low(builder, x64), allocator);
     body->finalize();
     func->body = body;
   }
@@ -1301,8 +1301,8 @@
         // WebAssembly does not have floating-point remainder, we have to emit a call to a special import of ours
         CallImport *call = allocator.alloc<CallImport>();
         call->target = F64_REM;
-        call->operands.push_back(ret->left);
-        call->operands.push_back(ret->right);
+        call->operands.push_back(ret->left, allocator);
+        call->operands.push_back(ret->right, allocator);
         call->type = f64;
         static bool addedImport = false;
         if (!addedImport) {
@@ -1327,8 +1327,8 @@
           case BinaryOp::DivUInt32: call->target = I32U_DIV; break;
           default: WASM_UNREACHABLE();
         }
-        call->operands.push_back(ret->left);
-        call->operands.push_back(ret->right);
+        call->operands.push_back(ret->left, allocator);
+        call->operands.push_back(ret->right, allocator);
         call->type = i32;
         static std::set<Name> addedImport;
         if (addedImport.count(call->target) == 0) {
@@ -1473,7 +1473,7 @@
               conv->type = WasmType::f64;
               input = conv;
             }
-            ret->operands.push_back(input);
+            ret->operands.push_back(input, allocator);
             ret->type = i32;
             static bool addedImport = false;
             if (!addedImport) {
@@ -1578,7 +1578,7 @@
             isNegative->right = builder.makeConst(Literal(0));
             isNegative->finalize();
             auto block = allocator.alloc<Block>();
-            block->list.push_back(set);
+            block->list.push_back(set, allocator);
             auto flip = allocator.alloc<Binary>();
             flip->op = SubInt32;
             flip->left = builder.makeConst(Literal(0));
@@ -1589,7 +1589,7 @@
             select->ifFalse = get();
             select->condition = isNegative;
             select->type = i32;
-            block->list.push_back(select);
+            block->list.push_back(select, allocator);
             block->finalize();
             return block;
           } else if (value->type == f32 || value->type == f64) {
@@ -1769,7 +1769,7 @@
           ret = specific;
         }
         for (unsigned i = firstOperand; i < args->size(); i++) {
-          operands->push_back(process(args[i]));
+          operands->push_back(process(args[i]), allocator);
         }
         if (tableCall) {
           auto specific = ret->dynCast<CallIndirect>();
@@ -1792,7 +1792,7 @@
       ret->target = process(target[2]); // TODO: as an optimization, we could look through the mask
       Ref args = ast[2];
       for (unsigned i = 0; i < args->size(); i++) {
-        ret->operands.push_back(process(args[i]));
+        ret->operands.push_back(process(args[i]), allocator);
       }
       auto* fullType = getFunctionType(astStackHelper.getParent(), ret->operands);
       ret->fullType = fullType->name;
@@ -1828,7 +1828,7 @@
         } else {
           block = allocator.alloc<Block>();
           block->name = name;
-          block->list.push_back(ret);
+          block->list.push_back(ret, allocator);
           block->finalize();
           ret = block;
         }
@@ -1871,8 +1871,8 @@
         condition->ifTrue = breakOut;
         condition->finalize();
         auto body = allocator.alloc<Block>();
-        body->list.push_back(condition);
-        body->list.push_back(process(ast[2]));
+        body->list.push_back(condition, allocator);
+        body->list.push_back(process(ast[2]), allocator);
         body->finalize();
         ret->body = body;
       }
@@ -1880,7 +1880,7 @@
       Block* block = builder.blockifyWithName(ret->body, out);
       auto continuer = allocator.alloc<Break>();
       continuer->name = ret->name;
-      block->list.push_back(continuer);
+      block->list.push_back(continuer, allocator);
       block->finalize();
       ret->body = block;
       ret->finalize();
@@ -1913,9 +1913,9 @@
         breakSeeker.walk(child);
         if (breakSeeker.found == 0) {
           auto block = allocator.alloc<Block>();
-          block->list.push_back(child);
+          block->list.push_back(child, allocator);
           if (isConcreteWasmType(child->type)) {
-            block->list.push_back(builder.makeNop()); // ensure a nop at the end, so the block has guaranteed none type and no values fall through
+            block->list.push_back(builder.makeNop(), allocator); // ensure a nop at the end, so the block has guaranteed none type and no values fall through
           }
           block->name = stop;
           block->finalize();
@@ -1983,9 +1983,9 @@
       condition->ifTrue = breakOut;
       condition->finalize();
       auto body = allocator.alloc<Block>();
-      body->list.push_back(condition);
-      body->list.push_back(process(fbody));
-      body->list.push_back(process(finc));
+      body->list.push_back(condition, allocator);
+      body->list.push_back(process(fbody), allocator);
+      body->list.push_back(process(finc), allocator);
       body->finalize();
       ret->body = body;
       // loops do not automatically loop, add a branch back
@@ -2000,8 +2000,8 @@
       nameMapper.popLabelName(out);
       Block *outer = allocator.alloc<Block>();
       // add an outer block for the init as well
-      outer->list.push_back(process(finit));
-      outer->list.push_back(ret);
+      outer->list.push_back(process(finit), allocator);
+      outer->list.push_back(ret, allocator);
       outer->finalize();
       return outer;
     } else if (what == LABEL) {
@@ -2072,8 +2072,8 @@
         }
       }
       auto ret = allocator.alloc<Block>();
-      ret->list.push_back(process(ast[1]));
-      ret->list.push_back(process(ast[2]));
+      ret->list.push_back(process(ast[1]), allocator);
+      ret->list.push_back(process(ast[2]), allocator);
       ret->finalize();
       return ret;
     } else if (what == SWITCH) {
@@ -2133,7 +2133,7 @@
           br->condition = builder.makeUnary(UnaryOp::WrapInt64, offsetor); // TODO: check this fits in 32 bits
         }
 
-        top->list.push_back(br);
+        top->list.push_back(br, allocator);
         top->finalize();
 
         for (unsigned i = 0; i < cases->size(); i++) {
@@ -2152,14 +2152,14 @@
             uint64_t index_s = index;
             name = nameMapper.pushLabelName("switch-case");
             if (br->targets.size() <= index_s) {
-              br->targets.resize(index_s + 1);
+              br->targets.resize(index_s + 1, allocator);
             }
             br->targets[index_s] = name;
           }
           auto next = allocator.alloc<Block>();
           top->name = name;
-          next->list.push_back(top);
-          next->list.push_back(case_);
+          next->list.push_back(top, allocator);
+          next->list.push_back(case_, allocator);
           next->finalize();
           top = next;
           nameMapper.popLabelName(name);
@@ -2178,7 +2178,7 @@
       } else {
         // we can't switch, make an if-chain instead of br_table
         auto var = Builder::addVar(function, br->condition->type);
-        top->list.push_back(builder.makeSetLocal(var, br->condition));
+        top->list.push_back(builder.makeSetLocal(var, br->condition), allocator);
         auto* brHolder = top;
         If* chain = nullptr;
         If* first = nullptr;
@@ -2207,8 +2207,8 @@
           }
           auto next = allocator.alloc<Block>();
           top->name = name;
-          next->list.push_back(top);
-          next->list.push_back(case_);
+          next->list.push_back(top, allocator);
+          next->list.push_back(case_, allocator);
           next->finalize();
           top = next;
           nameMapper.popLabelName(name);
@@ -2224,7 +2224,7 @@
 
         first->ifFalse = builder.makeBreak(br->default_);
 
-        brHolder->list.push_back(chain);
+        brHolder->list.push_back(chain, allocator);
         brHolder->finalize();
       }
 
@@ -2261,7 +2261,7 @@
     if (size == 1) return process(ast[from]);
     auto block = allocator.alloc<Block>();
     for (unsigned i = from; i < ast->size(); i++) {
-      block->list.push_back(process(ast[i]));
+      block->list.push_back(process(ast[i]), allocator);
     }
     block->finalize();
     return block;
diff --git a/src/ast_utils.h b/src/ast_utils.h
index d51a01d..fb5bf50 100644
--- a/src/ast_utils.h
+++ b/src/ast_utils.h
@@ -233,16 +233,6 @@
     convert<InputType, Nop>(target);
   }
 
-  // Convert a node that allocates
-  template<typename InputType, typename OutputType>
-  static OutputType* convert(InputType *input, MixedArena& allocator) {
-    assert(sizeof(OutputType) <= sizeof(InputType));
-    input->~InputType(); // arena-allocaed, so no destructor, but avoid UB.
-    OutputType* output = (OutputType*)(input);
-    new (output) OutputType(allocator);
-    return output;
-  }
-
   template<typename T>
   static Expression* flexibleCopy(Expression* original, Module& wasm, T& custom) {
     struct Copier : public Visitor<Copier, Expression*> {
diff --git a/src/binaryen-c.cpp b/src/binaryen-c.cpp
index c618f9d..a026da4 100644
--- a/src/binaryen-c.cpp
+++ b/src/binaryen-c.cpp
@@ -300,10 +300,11 @@
 BinaryenOp BinaryenHasFeature(void) { return HasFeature; }
 
 BinaryenExpressionRef BinaryenBlock(BinaryenModuleRef module, const char* name, BinaryenExpressionRef* children, BinaryenIndex numChildren) {
-  auto* ret = ((Module*)module)->allocator.alloc<Block>();
+  auto& allocator = ((Module*)module)->allocator;
+  auto* ret = allocator.alloc<Block>();
   if (name) ret->name = name;
   for (BinaryenIndex i = 0; i < numChildren; i++) {
-    ret->list.push_back((Expression*)children[i]);
+    ret->list.push_back((Expression*)children[i], allocator);
   }
   ret->finalize();
 
@@ -362,7 +363,8 @@
   return static_cast<Expression*>(ret);
 }
 BinaryenExpressionRef BinaryenSwitch(BinaryenModuleRef module, const char **names, BinaryenIndex numNames, const char* defaultName, BinaryenExpressionRef condition, BinaryenExpressionRef value) {
-  auto* ret = ((Module*)module)->allocator.alloc<Switch>();
+  auto& allocator = ((Module*)module)->allocator;
+  auto* ret = allocator.alloc<Switch>();
 
   if (tracing) {
     std::cout << "  {\n";
@@ -379,7 +381,7 @@
   }
 
   for (BinaryenIndex i = 0; i < numNames; i++) {
-    ret->targets.push_back(names[i]);
+    ret->targets.push_back(names[i], allocator);
   }
   ret->default_ = defaultName;
   ret->condition = (Expression*)condition;
@@ -388,7 +390,8 @@
   return static_cast<Expression*>(ret);
 }
 BinaryenExpressionRef BinaryenCall(BinaryenModuleRef module, const char *target, BinaryenExpressionRef* operands, BinaryenIndex numOperands, BinaryenType returnType) {
-  auto* ret = ((Module*)module)->allocator.alloc<Call>();
+  auto& allocator = ((Module*)module)->allocator;
+  auto* ret = allocator.alloc<Call>();
 
   if (tracing) {
     std::cout << "  {\n";
@@ -406,14 +409,15 @@
 
   ret->target = target;
   for (BinaryenIndex i = 0; i < numOperands; i++) {
-    ret->operands.push_back((Expression*)operands[i]);
+    ret->operands.push_back((Expression*)operands[i], allocator);
   }
   ret->type = WasmType(returnType);
   ret->finalize();
   return static_cast<Expression*>(ret);
 }
 BinaryenExpressionRef BinaryenCallImport(BinaryenModuleRef module, const char *target, BinaryenExpressionRef* operands, BinaryenIndex numOperands, BinaryenType returnType) {
-  auto* ret = ((Module*)module)->allocator.alloc<CallImport>();
+  auto& allocator = ((Module*)module)->allocator;
+  auto* ret = allocator.alloc<CallImport>();
 
   if (tracing) {
     std::cout << "  {\n";
@@ -431,7 +435,7 @@
 
   ret->target = target;
   for (BinaryenIndex i = 0; i < numOperands; i++) {
-    ret->operands.push_back((Expression*)operands[i]);
+    ret->operands.push_back((Expression*)operands[i], allocator);
   }
   ret->type = WasmType(returnType);
   ret->finalize();
@@ -439,7 +443,8 @@
 }
 BinaryenExpressionRef BinaryenCallIndirect(BinaryenModuleRef module, BinaryenExpressionRef target, BinaryenExpressionRef* operands, BinaryenIndex numOperands, const char* type) {
   auto* wasm = (Module*)module;
-  auto* ret = wasm->allocator.alloc<CallIndirect>();
+  auto& allocator = wasm->allocator;
+  auto* ret = allocator.alloc<CallIndirect>();
 
   if (tracing) {
     std::cout << "  {\n";
@@ -457,7 +462,7 @@
 
   ret->target = (Expression*)target;
   for (BinaryenIndex i = 0; i < numOperands; i++) {
-    ret->operands.push_back((Expression*)operands[i]);
+    ret->operands.push_back((Expression*)operands[i], allocator);
   }
   ret->fullType = type;
   ret->type = wasm->getFunctionType(ret->fullType)->result;
@@ -625,11 +630,12 @@
     std::cout << "  TODO: host...\n";
   }
 
-  auto* ret = ((Module*)module)->allocator.alloc<Host>();
+  auto& allocator = ((Module*)module)->allocator;
+  auto* ret = allocator.alloc<Host>();
   ret->op = HostOp(op);
   if (name) ret->nameOperand = name;
   for (BinaryenIndex i = 0; i < numOperands; i++) {
-    ret->operands.push_back((Expression*)operands[i]);
+    ret->operands.push_back((Expression*)operands[i], allocator);
   }
   ret->finalize();
   return static_cast<Expression*>(ret);
diff --git a/src/cfg/Relooper.cpp b/src/cfg/Relooper.cpp
index d412c7b..51a59d0 100644
--- a/src/cfg/Relooper.cpp
+++ b/src/cfg/Relooper.cpp
@@ -58,7 +58,7 @@
       Shape* Body = iter.second;
       Curr->name = Builder.getBlockBreakName(Id);
       auto* Outer = Builder.makeBlock(Curr);
-      Outer->list.push_back(Body->Render(Builder, InLoop));
+      Outer->list.push_back(Body->Render(Builder, InLoop), Builder.allocator);
       Outer->finalize(); // TODO: not really necessary
       Curr = Outer;
     }
@@ -106,13 +106,13 @@
 
 wasm::Expression* Branch::Render(RelooperBuilder& Builder, Block *Target, bool SetLabel) {
   auto* Ret = Builder.makeBlock();
-  if (Code) Ret->list.push_back(Code);
-  if (SetLabel) Ret->list.push_back(Builder.makeSetLabel(Target->Id));
+  if (Code) Ret->list.push_back(Code, Builder.allocator);
+  if (SetLabel) Ret->list.push_back(Builder.makeSetLabel(Target->Id), Builder.allocator);
   if (Type == Break) {
-    Ret->list.push_back(Builder.makeBlockBreak(Target->Id));
+    Ret->list.push_back(Builder.makeBlockBreak(Target->Id), Builder.allocator);
   } else if (Type == Continue) {
     assert(Ancestor);
-    Ret->list.push_back(Builder.makeShapeContinue(Ancestor->Id));
+    Ret->list.push_back(Builder.makeShapeContinue(Ancestor->Id), Builder.allocator);
   }
   Ret->finalize();
   return Ret;
@@ -144,9 +144,9 @@
 wasm::Expression* Block::Render(RelooperBuilder& Builder, bool InLoop) {
   auto* Ret = Builder.makeBlock();
   if (IsCheckedMultipleEntry && InLoop) {
-    Ret->list.push_back(Builder.makeSetLabel(0));
+    Ret->list.push_back(Builder.makeSetLabel(0), Builder.allocator);
   }
-  if (Code) Ret->list.push_back(Code);
+  if (Code) Ret->list.push_back(Code, Builder.allocator);
 
   if (!ProcessedBranchesOut.size()) {
     Ret->finalize();
@@ -306,10 +306,10 @@
       // generate a block to branch to, if we have content
       if (CurrContent) {
         auto* NextOuter = Builder.makeBlock();
-        NextOuter->list.push_back(Outer);
+        NextOuter->list.push_back(Outer, Builder.allocator);
         Outer->name = CurrName; // breaking on Outer leads to the content in NextOuter
-        NextOuter->list.push_back(CurrContent);
-        NextOuter->list.push_back(Builder.makeBreak(SwitchLeave));
+        NextOuter->list.push_back(CurrContent, Builder.allocator);
+        NextOuter->list.push_back(Builder.makeBreak(SwitchLeave), Builder.allocator);
         // prepare for more nesting
         Outer = NextOuter;
       } else {
@@ -331,12 +331,12 @@
     }
     // finish up the whole pattern
     Outer->name = SwitchLeave;
-    Inner->list.push_back(Builder.makeSwitch(Table, SwitchDefault, SwitchCondition));
+    Inner->list.push_back(Builder.makeSwitch(Table, SwitchDefault, SwitchCondition), Builder.allocator);
     Root = Outer;
   }
 
   if (Root) {
-    Ret->list.push_back(Root);
+    Ret->list.push_back(Root, Builder.allocator);
   }
   Ret->finalize();
 
diff --git a/src/mixed_arena.h b/src/mixed_arena.h
index 081d5ec..5bf94e5 100644
--- a/src/mixed_arena.h
+++ b/src/mixed_arena.h
@@ -168,7 +168,7 @@
 public:
   ArenaVector() {}
   ArenaVector(ArenaVector<T>&& other) {
-    *this = other;
+    *this = std::move(other);
   }
 
   T& operator[](size_t index) const {
@@ -222,10 +222,6 @@
     usedElements = size;
   }
 
-  void operator=(ArenaVector<T>& other) {
-    set(other);
-  }
-
   void operator=(ArenaVector<T>&& other) {
     data = other.data;
     usedElements = other.usedElements;
diff --git a/src/passes/DeadCodeElimination.cpp b/src/passes/DeadCodeElimination.cpp
index 878384d..f7fe617 100644
--- a/src/passes/DeadCodeElimination.cpp
+++ b/src/passes/DeadCodeElimination.cpp
@@ -121,7 +121,7 @@
         // it would leave an element with type none as the last, that could be a problem,
         // see https://github.com/WebAssembly/spec/issues/355
         if (!(isConcreteWasmType(block->type) && block->list[i]->type == none)) {
-          block->list.resize(i + 1, self->getModule()->allocator);
+          block->list.resize(i + 1, self->getAllocator());
           // note that we do *not* finalize here. it is incorrect to re-finalize a block
           // after removing elements, as it may no longer have branches to it that would
           // determine its type, so re-finalizing would just wipe out an existing type
@@ -247,9 +247,9 @@
     for (Index i = 0; i < curr->operands.size(); i++) {
       if (isDead(curr->operands[i])) {
         if (i > 0) {
-          auto* block = getModule()->allocator.alloc<Block>();
+          auto* block = getAllocator().alloc<Block>();
           Index newSize = i + 1;
-          block->list.resize(newSize, getModule()->allocator);
+          block->list.resize(newSize, getAllocator());
           Index j = 0;
           for (; j < newSize; j++) {
             block->list[j] = drop(curr->operands[j]);
@@ -275,11 +275,11 @@
   void visitCallIndirect(CallIndirect* curr) {
     if (handleCall(curr) != curr) return;
     if (isDead(curr->target)) {
-      auto* block = getModule()->allocator.alloc<Block>();
+      auto* block = getAllocator().alloc<Block>();
       for (auto* operand : curr->operands) {
-        block->list.push_back(drop(operand), getModule()->allocator);
+        block->list.push_back(drop(operand), getAllocator());
       }
-      block->list.push_back(curr->target, getModule()->allocator);
+      block->list.push_back(curr->target, getAllocator());
       block->finalize();
       replaceCurrent(block);
     }
@@ -303,8 +303,8 @@
       return;
     }
     if (isDead(curr->value)) {
-      auto* block = getModule()->allocator.alloc<Block>();
-      block->list.resize(2, getModule()->allocator);
+      auto* block = getAllocator().alloc<Block>();
+      block->list.resize(2, getAllocator());
       block->list[0] = drop(curr->ptr);
       block->list[1] = curr->value;
       block->finalize();
@@ -324,8 +324,8 @@
       return;
     }
     if (isDead(curr->right)) {
-      auto* block = getModule()->allocator.alloc<Block>();
-      block->list.resize(2, getModule()->allocator);
+      auto* block = getAllocator().alloc<Block>();
+      block->list.resize(2, getAllocator());
       block->list[0] = drop(curr->left);
       block->list[1] = curr->right;
       block->finalize();
@@ -339,8 +339,8 @@
       return;
     }
     if (isDead(curr->ifFalse)) {
-      auto* block = getModule()->allocator.alloc<Block>();
-      block->list.resize(2, getModule()->allocator);
+      auto* block = getAllocator().alloc<Block>();
+      block->list.resize(2, getAllocator());
       block->list[0] = drop(curr->ifTrue);
       block->list[1] = curr->ifFalse;
       block->finalize();
@@ -348,8 +348,8 @@
       return;
     }
     if (isDead(curr->condition)) {
-      auto* block = getModule()->allocator.alloc<Block>();
-      block->list.resize(3, getModule()->allocator);
+      auto* block = getAllocator().alloc<Block>();
+      block->list.resize(3, getAllocator());
       block->list[0] = drop(curr->ifTrue);
       block->list[1] = drop(curr->ifFalse);
       block->list[2] = curr->condition;
diff --git a/src/passes/LegalizeJSInterface.cpp b/src/passes/LegalizeJSInterface.cpp
index 6e07015..6e33fae 100644
--- a/src/passes/LegalizeJSInterface.cpp
+++ b/src/passes/LegalizeJSInterface.cpp
@@ -124,14 +124,14 @@
 
     for (auto param : func->params) {
       if (param == i64) {
-        call->operands.push_back(I64Utilities::recreateI64(builder, legal->params.size(), legal->params.size() + 1));
+        call->operands.push_back(I64Utilities::recreateI64(builder, legal->params.size(), legal->params.size() + 1), module->allocator);
         legal->params.push_back(i32);
         legal->params.push_back(i32);
       } else if (param == f32) {
-        call->operands.push_back(builder.makeUnary(DemoteFloat64, builder.makeGetLocal(legal->params.size(), f64)));
+        call->operands.push_back(builder.makeUnary(DemoteFloat64, builder.makeGetLocal(legal->params.size(), f64)), module->allocator);
         legal->params.push_back(f64);
       } else {
-        call->operands.push_back(builder.makeGetLocal(legal->params.size(), param));
+        call->operands.push_back(builder.makeGetLocal(legal->params.size(), param), module->allocator);
         legal->params.push_back(param);
       }
     }
@@ -140,13 +140,13 @@
       legal->result = i32;
       auto index = builder.addVar(legal, Name(), i64);
       auto* block = builder.makeBlock();
-      block->list.push_back(builder.makeSetLocal(index, call));
+      block->list.push_back(builder.makeSetLocal(index, call), module->allocator);
       ensureTempRet0(module);
       block->list.push_back(builder.makeSetGlobal(
         TEMP_RET_0,
         I64Utilities::getI64High(builder, index)
-      ));
-      block->list.push_back(I64Utilities::getI64Low(builder, index));
+      ), module->allocator);
+      block->list.push_back(I64Utilities::getI64Low(builder, index), module->allocator);
       block->finalize();
       legal->body = block;
     } else if (func->result == f32) {
@@ -184,15 +184,15 @@
 
     for (auto param : im->functionType->params) {
       if (param == i64) {
-        call->operands.push_back(I64Utilities::getI64Low(builder, func->params.size()));
-        call->operands.push_back(I64Utilities::getI64High(builder, func->params.size()));
+        call->operands.push_back(I64Utilities::getI64Low(builder, func->params.size()), module->allocator);
+        call->operands.push_back(I64Utilities::getI64High(builder, func->params.size()), module->allocator);
         type->params.push_back(i32);
         type->params.push_back(i32);
       } else if (param == f32) {
-        call->operands.push_back(builder.makeUnary(PromoteFloat32, builder.makeGetLocal(func->params.size(), f32)));
+        call->operands.push_back(builder.makeUnary(PromoteFloat32, builder.makeGetLocal(func->params.size(), f32)), module->allocator);
         type->params.push_back(f64);
       } else {
-        call->operands.push_back(builder.makeGetLocal(func->params.size(), param));
+        call->operands.push_back(builder.makeGetLocal(func->params.size(), param), module->allocator);
         type->params.push_back(param);
       }
       func->params.push_back(param);
diff --git a/src/passes/MergeBlocks.cpp b/src/passes/MergeBlocks.cpp
index 467ffb4..072f86e 100644
--- a/src/passes/MergeBlocks.cpp
+++ b/src/passes/MergeBlocks.cpp
@@ -180,17 +180,17 @@
       }
       if (!child) continue;
       if (child->name.is()) continue; // named blocks can have breaks to them (and certainly do, if we ran RemoveUnusedNames and RemoveUnusedBrs)
-      ExpressionList merged(module->allocator);
+      ExpressionList merged;
       for (size_t j = 0; j < i; j++) {
-        merged.push_back(curr->list[j]);
+        merged.push_back(curr->list[j], module->allocator);
       }
       for (auto item : child->list) {
-        merged.push_back(item);
+        merged.push_back(item, module->allocator);
       }
       for (size_t j = i + 1; j < curr->list.size(); j++) {
-        merged.push_back(curr->list[j]);
+        merged.push_back(curr->list[j], module->allocator);
       }
-      curr->list = merged;
+      curr->list.set(merged, module->allocator);
       more = true;
       changed = true;
       break;
@@ -234,9 +234,9 @@
           assert(outer->list.back() == curr);
           outer->list.pop_back();
           for (Index i = 0; i < block->list.size() - 1; i++) {
-            outer->list.push_back(block->list[i]);
+            outer->list.push_back(block->list[i], getAllocator());
           }
-          outer->list.push_back(curr);
+          outer->list.push_back(curr, getAllocator());
         }
       }
     }
diff --git a/src/passes/RemoveUnusedBrs.cpp b/src/passes/RemoveUnusedBrs.cpp
index 69a7c4f..3ccdb07 100644
--- a/src/passes/RemoveUnusedBrs.cpp
+++ b/src/passes/RemoveUnusedBrs.cpp
@@ -115,7 +115,7 @@
         }
         // drop a nop at the end of a block, which prevents a value flowing
         while (block->list.size() > 0 && block->list.back()->is<Nop>()) {
-          block->list.resize(block->list.size() - 1);
+          block->list.resize(block->list.size() - 1, self->getAllocator());
           self->anotherCycle = true;
         }
       }
@@ -411,7 +411,7 @@
             ifTrueBreak->condition = iff->condition;
             ifTrueBreak->finalize();
             list[i] = Builder(*getModule()).dropIfConcretelyTyped(ifTrueBreak);
-            ExpressionManipulator::spliceIntoBlock(curr, i + 1, iff->ifFalse);
+            ExpressionManipulator::spliceIntoBlock(curr, i + 1, iff->ifFalse, getAllocator());
             continue;
           }
           // otherwise, perhaps we can flip the if
@@ -420,7 +420,7 @@
             ifFalseBreak->condition = Builder(*getModule()).makeUnary(EqZInt32, iff->condition);
             ifFalseBreak->finalize();
             list[i] = Builder(*getModule()).dropIfConcretelyTyped(ifFalseBreak);
-            ExpressionManipulator::spliceIntoBlock(curr, i + 1, iff->ifTrue);
+            ExpressionManipulator::spliceIntoBlock(curr, i + 1, iff->ifTrue, getAllocator());
             continue;
           }
         }
diff --git a/src/passes/SimplifyLocals.cpp b/src/passes/SimplifyLocals.cpp
index 6509c9d..6f2f527 100644
--- a/src/passes/SimplifyLocals.cpp
+++ b/src/passes/SimplifyLocals.cpp
@@ -352,7 +352,7 @@
       if (br->condition) {
         br->value = set;
         set->setTee(true);
-        *breakSetLocalPointer = getModule()->allocator.alloc<Nop>();
+        *breakSetLocalPointer = getAllocator().alloc<Nop>();
         // in addition, as this is a conditional br that now has a value, it now returns a value, so it must be dropped
         br->finalize();
         *brp = Builder(*getModule()).makeDrop(br);
@@ -456,7 +456,7 @@
       // enlarge blocks that were marked, for the next round
       if (blocksToEnlarge.size() > 0) {
         for (auto* block : blocksToEnlarge) {
-          block->list.push_back(getModule()->allocator.alloc<Nop>());
+          block->list.push_back(getAllocator().alloc<Nop>(), getAllocator());
         }
         blocksToEnlarge.clear();
         anotherCycle = true;
@@ -467,12 +467,12 @@
           auto ifTrue = Builder(*getModule()).blockify(iff->ifTrue);
           iff->ifTrue = ifTrue;
           if (ifTrue->list.size() == 0 || !ifTrue->list.back()->is<Nop>()) {
-            ifTrue->list.push_back(getModule()->allocator.alloc<Nop>());
+            ifTrue->list.push_back(getAllocator().alloc<Nop>(), getAllocator());
           }
           auto ifFalse = Builder(*getModule()).blockify(iff->ifFalse);
           iff->ifFalse = ifFalse;
           if (ifFalse->list.size() == 0 || !ifFalse->list.back()->is<Nop>()) {
-            ifFalse->list.push_back(getModule()->allocator.alloc<Nop>());
+            ifFalse->list.push_back(getAllocator().alloc<Nop>(), getAllocator());
           }
         }
         ifsToEnlarge.clear();
diff --git a/src/passes/Vacuum.cpp b/src/passes/Vacuum.cpp
index 8d9bb42..6906624 100644
--- a/src/passes/Vacuum.cpp
+++ b/src/passes/Vacuum.cpp
@@ -158,10 +158,10 @@
         Switch* sw = list[z - skip]->dynCast<Switch>();
         if ((br && !br->condition) || sw) {
           auto* last = list.back();
-          list.resize(z - skip + 1);
+          list.resize(z - skip + 1, getAllocator());
           // if we removed the last one, and it was a return value, it must be returned
           if (list.back() != last && isConcreteWasmType(last->type)) {
-            list.push_back(last);
+            list.push_back(last, getAllocator());
           }
           needResize = false;
           break;
@@ -169,7 +169,7 @@
       }
     }
     if (needResize) {
-      list.resize(size - skip);
+      list.resize(size - skip, getAllocator());
     }
     if (!curr->name.is()) {
       if (list.size() == 1) {
diff --git a/src/s2wasm.h b/src/s2wasm.h
index faa31ae..a6068ad 100644
--- a/src/s2wasm.h
+++ b/src/s2wasm.h
@@ -740,12 +740,12 @@
     // parse body
     func->body = allocator->alloc<Block>();
     std::vector<Expression*> bstack;
-    auto addToBlock = [&bstack](Expression* curr) {
+    auto addToBlock = [&bstack, this](Expression* curr) {
       Expression* last = bstack.back();
       if (last->is<Loop>()) {
         last = last->cast<Loop>()->body;
       }
-      last->cast<Block>()->list.push_back(curr);
+      last->cast<Block>()->list.push_back(curr, *allocator);
     };
     bstack.push_back(func->body);
     std::vector<Expression*> estack;
@@ -874,7 +874,7 @@
       Name assign = getAssign();
       auto curr = allocator->alloc<Host>();
       curr->op = op;
-      curr->operands.push_back(getInput());
+      curr->operands.push_back(getInput(), *allocator);
       curr->finalize();
       setOutput(curr, assign);
     };
@@ -976,7 +976,7 @@
           int num = getNumInputs();
           auto inputs = getInputs(num);
           for (int i = 0; i < num; i++) {
-            curr->operands.push_back(inputs[i]);
+            curr->operands.push_back(inputs[i], *allocator);
           }
         }
         Name target = linkerObj->resolveAlias(
@@ -1203,7 +1203,7 @@
         auto curr = allocator->alloc<Switch>();
         curr->condition = getInput();
         while (skipComma()) {
-          curr->targets.push_back(getBranchLabel(getInt()));
+          curr->targets.push_back(getBranchLabel(getInt()), *allocator);
         }
         assert(curr->targets.size() > 0);
         curr->default_ = curr->targets.back();
diff --git a/src/wasm-builder.h b/src/wasm-builder.h
index ac43a4b..e7d473d 100644
--- a/src/wasm-builder.h
+++ b/src/wasm-builder.h
@@ -33,12 +33,12 @@
 // General AST node builder
 
 class Builder {
-  MixedArena& allocator;
-
 public:
   Builder(MixedArena& allocator) : allocator(allocator) {}
   Builder(Module& wasm) : allocator(wasm.allocator) {}
 
+  MixedArena& allocator;
+
   // make* functions, create nodes
 
   Function* makeFunction(Name name,
diff --git a/src/wasm-linker.cpp b/src/wasm-linker.cpp
index 757fc88..037dfa1 100644
--- a/src/wasm-linker.cpp
+++ b/src/wasm-linker.cpp
@@ -84,7 +84,7 @@
       auto type = call->type;
       auto operands = std::move(call->operands);
       auto target = call->target;
-      CallImport* newCall = ExpressionManipulator::convert<Call, CallImport>(call, out.wasm.allocator);
+      CallImport* newCall = ExpressionManipulator::convert<Call, CallImport>(call);
       newCall->type = type;
       newCall->operands = std::move(operands);
       newCall->target = target;
@@ -241,7 +241,7 @@
       auto* call = builder.makeCall(startFunction, args, target->result);
       Expression* e = call;
       if (target->result != none) e = builder.makeDrop(call);
-      block->list.push_back(e);
+      block->list.push_back(e, builder.allocator);
       block->finalize();
     }
   }
diff --git a/src/wasm-traversal.h b/src/wasm-traversal.h
index 0b8097f..bf89166 100644
--- a/src/wasm-traversal.h
+++ b/src/wasm-traversal.h
@@ -170,6 +170,11 @@
     return currFunction;
   }
 
+  // Convenience function to get the allocator
+  MixedArena& getAllocator() {
+    return currModule->allocator;
+  }
+
   // Walk starting
 
   void walkFunction(Function* func) {