| /* | |
| * Copyright 2023 WebAssembly Community Group participants | |
| * | |
| * Licensed under the Apache License, Version 2.0 (the "License"); | |
| * you may not use this file except in compliance with the License. | |
| * You may obtain a copy of the License at | |
| * | |
| * http://www.apache.org/licenses/LICENSE-2.0 | |
| * | |
| * Unless required by applicable law or agreed to in writing, software | |
| * distributed under the License is distributed on an "AS IS" BASIS, | |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| * See the License for the specific language governing permissions and | |
| * limitations under the License. | |
| */ | |
| // | |
| // Emits the data segments to a file. The file contains data from address base | |
| // onwards (we must pass in base, as we can't tell it from the wasm - the | |
| // first segment may start after a run of zeros, but we need those zeros in | |
| // the file. | |
| // | |
| #include "pass.h" | |
| #include "support/file.h" | |
| #include "wasm-features.h" | |
| #include "wasm.h" | |
| namespace wasm { | |
| struct SeparateDataSegments : public Pass { | |
| bool modifiesBinaryenIR() override { return false; } | |
| void run(Module* module) override { | |
| std::string outfileName = | |
| getArgument("separate-data-segments", | |
| "SeparateDataSegments usage: wasm-opt " | |
| "--separate-data-segments@FILENAME"); | |
| Output outfile(outfileName, Flags::Binary); | |
| std::string baseStr = | |
| getArgument("separate-data-segments-global-base", | |
| "SeparateDataSegments usage: wasm-opt " | |
| "--pass-arg=separate-data-segments-global-base@NUMBER"); | |
| Address base = std::stoi(baseStr); | |
| size_t lastEnd = 0; | |
| for (auto& seg : module->dataSegments) { | |
| if (seg->isPassive()) { | |
| Fatal() << "separating passive segments not implemented"; | |
| } | |
| if (!seg->offset->is<Const>()) { | |
| Fatal() << "separating relocatable segments not implemented"; | |
| } | |
| size_t offset = seg->offset->cast<Const>()->value.getInteger(); | |
| offset -= base; | |
| size_t fill = offset - lastEnd; | |
| if (fill > 0) { | |
| std::vector<char> buf(fill); | |
| outfile.write(buf.data(), fill); | |
| } | |
| outfile.write(seg->data.data(), seg->data.size()); | |
| lastEnd = offset + seg->data.size(); | |
| } | |
| module->dataSegments.clear(); | |
| // Remove the start/stop symbols that the PostEmscripten uses to remove | |
| // em_asm/em_js data. Since we just removed all the data segments from the | |
| // file there is nothing more for that pass to do. | |
| // TODO(sbc): Fix the ordering so that the removal the EM_ASM/EM_JS data | |
| // comes before this pass. | |
| module->removeExport("__start_em_asm"); | |
| module->removeExport("__stop_em_asm"); | |
| module->removeExport("__start_em_js"); | |
| module->removeExport("__stop_em_js"); | |
| } | |
| }; | |
| Pass* createSeparateDataSegmentsPass() { return new SeparateDataSegments(); } | |
| } // namespace wasm |