Improve some const correctness
diff --git a/src/ir/module-utils.cpp b/src/ir/module-utils.cpp
index b17d6c7..e921d23 100644
--- a/src/ir/module-utils.cpp
+++ b/src/ir/module-utils.cpp
@@ -408,7 +408,7 @@
 struct CodeScanner : PostWalker<CodeScanner> {
   TypeInfos& info;
 
-  CodeScanner(Module& wasm, TypeInfos& info) : info(info) { setModule(&wasm); }
+  CodeScanner(const Module& wasm, TypeInfos& info) : info(info) { setModule(const_cast<Module*>(&wasm)); }
 
   void visitCallIndirect(CallIndirect* curr) { info.note(curr->heapType); }
   void visitCallRef(CallRef* curr) { info.note(curr->target->type); }
@@ -479,20 +479,20 @@
   }
 };
 
-void classifyTypeVisibility(Module& wasm,
+void classifyTypeVisibility(const Module& wasm,
                             InsertOrderedMap<HeapType, HeapTypeInfo>& types,
                             WorldMode worldMode);
 
 } // anonymous namespace
 
 InsertOrderedMap<HeapType, HeapTypeInfo>
-collectHeapTypeInfo(Module& wasm,
+collectHeapTypeInfo(const Module& wasm,
                     WorldMode worldMode,
                     TypeInclusion inclusion,
                     VisibilityHandling visibility) {
   // Collect module-level info.
   TypeInfos info;
-  CodeScanner(wasm, info).walkModuleCode(&wasm);
+  CodeScanner(wasm, info).walkModuleCode(const_cast<Module*>(&wasm));
   for (auto& curr : wasm.globals) {
     info.note(curr->type);
   }
@@ -508,7 +508,7 @@
 
   // Collect info from functions in parallel.
   ModuleUtils::ParallelFunctionAnalysis<TypeInfos, Immutable, InsertOrderedMap>
-    analysis(wasm, [&](Function* func, TypeInfos& info) {
+    analysis(const_cast<Module&>(wasm), [&](Function* func, TypeInfos& info) {
       info.note(func->type);
       for (auto type : func->vars) {
         info.note(type);
@@ -604,7 +604,7 @@
 
 namespace {
 
-void classifyTypeVisibility(Module& wasm,
+void classifyTypeVisibility(const Module& wasm,
                             InsertOrderedMap<HeapType, HeapTypeInfo>& types,
                             WorldMode worldMode) {
   for (auto type : getPublicHeapTypes(wasm, worldMode)) {
@@ -685,7 +685,7 @@
 
 } // anonymous namespace
 
-std::vector<HeapType> collectHeapTypes(Module& wasm) {
+std::vector<HeapType> collectHeapTypes(const Module& wasm) {
   auto info = collectHeapTypeInfo(wasm, WorldMode::Open);
   std::vector<HeapType> types;
   types.reserve(info.size());
@@ -695,7 +695,7 @@
   return types;
 }
 
-std::vector<HeapType> getExposedPublicHeapTypes(Module& wasm) {
+std::vector<HeapType> getExposedPublicHeapTypes(const Module& wasm) {
   // Look at the types of imports and exports to get an initial set of public
   // types.
   std::vector<HeapType> publicTypes;
@@ -764,7 +764,7 @@
   return publicTypes;
 }
 
-std::vector<HeapType> getPublicHeapTypes(Module& wasm, WorldMode worldMode) {
+std::vector<HeapType> getPublicHeapTypes(const Module& wasm, WorldMode worldMode) {
   auto directlyExposed = getExposedPublicHeapTypes(wasm);
   auto transitivelyExposed = getTransitivelyReachable(
     directlyExposed, /*includeSupertypes=*/true, /*includeRecGroups=*/true);
@@ -778,7 +778,7 @@
   return publicTypes;
 }
 
-std::vector<HeapType> getPrivateHeapTypes(Module& wasm, WorldMode worldMode) {
+std::vector<HeapType> getPrivateHeapTypes(const Module& wasm, WorldMode worldMode) {
   auto info = collectHeapTypeInfo(wasm,
                                   worldMode,
                                   TypeInclusion::UsedIRTypes,
@@ -793,7 +793,7 @@
   return types;
 }
 
-IndexedHeapTypes getOptimizedIndexedHeapTypes(Module& wasm) {
+IndexedHeapTypes getOptimizedIndexedHeapTypes(const Module& wasm) {
   auto counts =
     collectHeapTypeInfo(wasm, WorldMode::Open, TypeInclusion::BinaryTypes);
 
diff --git a/src/ir/module-utils.h b/src/ir/module-utils.h
index 860672b..078e624 100644
--- a/src/ir/module-utils.h
+++ b/src/ir/module-utils.h
@@ -76,7 +76,7 @@
 
 // Convenient iteration over imported/non-imported module elements
 
-template<typename T> inline void iterImportedMemories(Module& wasm, T visitor) {
+template<typename T> inline void iterImportedMemories(const Module& wasm, T visitor) {
   for (auto& import : wasm.memories) {
     if (import->imported()) {
       visitor(import.get());
@@ -84,7 +84,7 @@
   }
 }
 
-template<typename T> inline void iterDefinedMemories(Module& wasm, T visitor) {
+template<typename T> inline void iterDefinedMemories(const Module& wasm, T visitor) {
   for (auto& import : wasm.memories) {
     if (!import->imported()) {
       visitor(import.get());
@@ -93,7 +93,7 @@
 }
 
 template<typename T>
-inline void iterMemorySegments(Module& wasm, Name memory, T visitor) {
+inline void iterMemorySegments(const Module& wasm, Name memory, T visitor) {
   for (auto& segment : wasm.dataSegments) {
     if (segment->isActive() && segment->memory == memory) {
       visitor(segment.get());
@@ -102,7 +102,7 @@
 }
 
 template<typename T>
-inline void iterActiveDataSegments(Module& wasm, T visitor) {
+inline void iterActiveDataSegments(const Module& wasm, T visitor) {
   for (auto& segment : wasm.dataSegments) {
     if (segment->isActive()) {
       visitor(segment.get());
@@ -110,7 +110,7 @@
   }
 }
 
-template<typename T> inline void iterImportedTables(Module& wasm, T visitor) {
+template<typename T> inline void iterImportedTables(const Module& wasm, T visitor) {
   for (auto& import : wasm.tables) {
     if (import->imported()) {
       visitor(import.get());
@@ -118,7 +118,7 @@
   }
 }
 
-template<typename T> inline void iterDefinedTables(Module& wasm, T visitor) {
+template<typename T> inline void iterDefinedTables(const Module& wasm, T visitor) {
   for (auto& import : wasm.tables) {
     if (!import->imported()) {
       visitor(import.get());
@@ -127,7 +127,7 @@
 }
 
 template<typename T>
-inline void iterTableSegments(Module& wasm, Name table, T visitor) {
+inline void iterTableSegments(const Module& wasm, Name table, T visitor) {
   // Just a precaution so that we don't iterate over passive elem segments by
   // accident
   assert(table.is() && "Table name must not be null");
@@ -140,7 +140,7 @@
 }
 
 template<typename T>
-inline void iterActiveElementSegments(Module& wasm, T visitor) {
+inline void iterActiveElementSegments(const Module& wasm, T visitor) {
   for (auto& segment : wasm.elementSegments) {
     if (segment->isActive()) {
       visitor(segment.get());
@@ -148,7 +148,7 @@
   }
 }
 
-template<typename T> inline void iterImportedGlobals(Module& wasm, T visitor) {
+template<typename T> inline void iterImportedGlobals(const Module& wasm, T visitor) {
   for (auto& import : wasm.globals) {
     if (import->imported()) {
       visitor(import.get());
@@ -156,7 +156,7 @@
   }
 }
 
-template<typename T> inline void iterDefinedGlobals(Module& wasm, T visitor) {
+template<typename T> inline void iterDefinedGlobals(const Module& wasm, T visitor) {
   for (auto& import : wasm.globals) {
     if (!import->imported()) {
       visitor(import.get());
@@ -165,7 +165,7 @@
 }
 
 template<typename T>
-inline void iterImportedFunctions(Module& wasm, T visitor) {
+inline void iterImportedFunctions(const Module& wasm, T visitor) {
   for (auto& import : wasm.functions) {
     if (import->imported()) {
       visitor(import.get());
@@ -173,7 +173,7 @@
   }
 }
 
-template<typename T> inline void iterDefinedFunctions(Module& wasm, T visitor) {
+template<typename T> inline void iterDefinedFunctions(const Module& wasm, T visitor) {
   for (auto& import : wasm.functions) {
     if (!import->imported()) {
       visitor(import.get());
@@ -181,7 +181,7 @@
   }
 }
 
-template<typename T> inline void iterImportedTags(Module& wasm, T visitor) {
+template<typename T> inline void iterImportedTags(const Module& wasm, T visitor) {
   for (auto& import : wasm.tags) {
     if (import->imported()) {
       visitor(import.get());
@@ -189,7 +189,7 @@
   }
 }
 
-template<typename T> inline void iterDefinedTags(Module& wasm, T visitor) {
+template<typename T> inline void iterDefinedTags(const Module& wasm, T visitor) {
   for (auto& import : wasm.tags) {
     if (!import->imported()) {
       visitor(import.get());
@@ -197,7 +197,7 @@
   }
 }
 
-template<typename T> inline void iterImports(Module& wasm, T visitor) {
+template<typename T> inline void iterImports(const Module& wasm, T visitor) {
   iterImportedMemories(wasm, visitor);
   iterImportedTables(wasm, visitor);
   iterImportedGlobals(wasm, visitor);
@@ -207,7 +207,7 @@
 
 // Iterates over all importable module items. The visitor provided should have
 // signature void(ExternalKind, Importable*).
-template<typename T> inline void iterImportable(Module& wasm, T visitor) {
+template<typename T> inline void iterImportable(const Module& wasm, T visitor) {
   for (auto& curr : wasm.functions) {
     if (curr->imported()) {
       visitor(ExternalKind::Function, curr.get());
@@ -237,7 +237,7 @@
 
 // Iterates over all module items. The visitor provided should have signature
 // void(ModuleItemKind, Named*).
-template<typename T> inline void iterModuleItems(Module& wasm, T visitor) {
+template<typename T> inline void iterModuleItems(const Module& wasm, T visitor) {
   for (auto& curr : wasm.functions) {
     visitor(ModuleItemKind::Function, curr.get());
   }
@@ -381,7 +381,7 @@
         Module* module;
         T& info;
         Func work;
-      } mapper(&wasm, info, work);
+      } mapper(const_cast<Module*>(&wasm), info, work);
       mapper.walk(func->body);
     });
 
@@ -471,27 +471,27 @@
 };
 
 InsertOrderedMap<HeapType, HeapTypeInfo> collectHeapTypeInfo(
-  Module& wasm,
+  const Module& wasm,
   WorldMode worldMode,
   TypeInclusion inclusion = TypeInclusion::AllTypes,
   VisibilityHandling visibility = VisibilityHandling::NoVisibility);
 
 // Helper function for collecting all the non-basic heap types used in the
 // module, i.e. the types that would appear in the type section.
-std::vector<HeapType> collectHeapTypes(Module& wasm);
+std::vector<HeapType> collectHeapTypes(const Module& wasm);
 
 // Get the types directly made public by imported or exported module items. For
 // example, the types of imported or exported globals or functions, but not
 // other types reachable from those types. Includes abstract heap types.
-std::vector<HeapType> getExposedPublicHeapTypes(Module& wasm);
+std::vector<HeapType> getExposedPublicHeapTypes(const Module& wasm);
 
 // Collect all the defined heap types visible on the module boundary that cannot
 // be changed, e.g. the defined types from getExposedPublicHeapTypes and those
 // they reach.
-std::vector<HeapType> getPublicHeapTypes(Module& wasm, WorldMode worldMode);
+std::vector<HeapType> getPublicHeapTypes(const Module& wasm, WorldMode worldMode);
 
 // All the defined heap types that are not public.
-std::vector<HeapType> getPrivateHeapTypes(Module& wasm, WorldMode worldMode);
+std::vector<HeapType> getPrivateHeapTypes(const Module& wasm, WorldMode worldMode);
 
 struct IndexedHeapTypes {
   std::vector<HeapType> types;
@@ -501,7 +501,7 @@
 // Similar to `collectHeapTypes`, but provides fast lookup of the index for each
 // type as well. Also orders the types to be valid and sorts the types by
 // frequency of use to minimize code size.
-IndexedHeapTypes getOptimizedIndexedHeapTypes(Module& wasm);
+IndexedHeapTypes getOptimizedIndexedHeapTypes(const Module& wasm);
 
 } // namespace wasm::ModuleUtils
 
diff --git a/src/ir/subtypes.h b/src/ir/subtypes.h
index 912d61f..ea12a62 100644
--- a/src/ir/subtypes.h
+++ b/src/ir/subtypes.h
@@ -34,7 +34,7 @@
     }
   }
 
-  SubTypes(Module& wasm) : SubTypes(ModuleUtils::collectHeapTypes(wasm)) {}
+  SubTypes(const Module& wasm) : SubTypes(ModuleUtils::collectHeapTypes(wasm)) {}
 
   const std::vector<HeapType>& getImmediateSubTypes(HeapType type) const {
     // When we return an empty result, use a canonical constant empty vec to