summaryrefslogtreecommitdiff
path: root/src/ir/module-utils.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/ir/module-utils.cpp')
-rw-r--r--src/ir/module-utils.cpp60
1 files changed, 56 insertions, 4 deletions
diff --git a/src/ir/module-utils.cpp b/src/ir/module-utils.cpp
index c2f48eec8..fdee4f869 100644
--- a/src/ir/module-utils.cpp
+++ b/src/ir/module-utils.cpp
@@ -15,6 +15,7 @@
*/
#include "module-utils.h"
+#include "ir/debug.h"
#include "ir/intrinsics.h"
#include "ir/manipulation.h"
#include "ir/properties.h"
@@ -23,17 +24,46 @@
namespace wasm::ModuleUtils {
+// Update the file name indices when moving a set of debug locations from one
+// module to another.
+static void updateLocationSet(std::set<Function::DebugLocation>& locations,
+ std::vector<Index>& fileIndexMap) {
+ std::set<Function::DebugLocation> updatedLocations;
+
+ for (auto iter : locations) {
+ iter.fileIndex = fileIndexMap[iter.fileIndex];
+ updatedLocations.insert(iter);
+ }
+ locations.clear();
+ std::swap(locations, updatedLocations);
+}
+
// Copies a function into a module. If newName is provided it is used as the
-// name of the function (otherwise the original name is copied).
-Function* copyFunction(Function* func, Module& out, Name newName) {
+// name of the function (otherwise the original name is copied). If fileIndexMap
+// is specified, it is used to rename source map filename indices when copying
+// the function from one module to another one.
+Function* copyFunction(Function* func,
+ Module& out,
+ Name newName,
+ std::optional<std::vector<Index>> fileIndexMap) {
auto ret = std::make_unique<Function>();
ret->name = newName.is() ? newName : func->name;
ret->type = func->type;
ret->vars = func->vars;
ret->localNames = func->localNames;
ret->localIndices = func->localIndices;
- ret->debugLocations = func->debugLocations;
ret->body = ExpressionManipulator::copy(func->body, out);
+ debug::copyDebugInfo(func->body, ret->body, func, ret.get());
+ ret->prologLocation = func->prologLocation;
+ ret->epilogLocation = func->epilogLocation;
+ // Update file indices if needed
+ if (fileIndexMap) {
+ for (auto& iter : ret->debugLocations) {
+ iter.second.fileIndex = (*fileIndexMap)[iter.second.fileIndex];
+ }
+ updateLocationSet(ret->prologLocation, *fileIndexMap);
+ updateLocationSet(ret->epilogLocation, *fileIndexMap);
+ }
ret->module = func->module;
ret->base = func->base;
ret->noFullInline = func->noFullInline;
@@ -136,8 +166,30 @@ DataSegment* copyDataSegment(const DataSegment* segment, Module& out) {
// Copies named toplevel module items (things of kind ModuleItemKind). See
// copyModule() for something that also copies exports, the start function, etc.
void copyModuleItems(const Module& in, Module& out) {
+ // If the source module has some debug information, we first compute how
+ // to map file name indices from this modules to file name indices in
+ // the target module.
+ std::optional<std::vector<Index>> fileIndexMap;
+ if (!in.debugInfoFileNames.empty()) {
+ std::unordered_map<std::string, Index> debugInfoFileIndices;
+ for (Index i = 0; i < out.debugInfoFileNames.size(); i++) {
+ debugInfoFileIndices[out.debugInfoFileNames[i]] = i;
+ }
+ fileIndexMap.emplace();
+ for (Index i = 0; i < in.debugInfoFileNames.size(); i++) {
+ std::string file = in.debugInfoFileNames[i];
+ auto iter = debugInfoFileIndices.find(file);
+ if (iter == debugInfoFileIndices.end()) {
+ Index index = out.debugInfoFileNames.size();
+ out.debugInfoFileNames.push_back(file);
+ debugInfoFileIndices[file] = index;
+ }
+ fileIndexMap->push_back(debugInfoFileIndices[file]);
+ }
+ }
+
for (auto& curr : in.functions) {
- copyFunction(curr.get(), out);
+ copyFunction(curr.get(), out, Name(), fileIndexMap);
}
for (auto& curr : in.globals) {
copyGlobal(curr.get(), out);