| /* |
| * 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 |