diff options
author | Alon Zakai <alonzakai@gmail.com> | 2015-12-29 21:14:29 -0500 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2015-12-29 22:16:58 -0800 |
commit | 0421bd0c27ea57c7c5c9bc3b1ce6f71f8ce240dc (patch) | |
tree | c0676a6bd3a1ac204cf344bfdff7264e39eb8e8e /src | |
parent | 358f8d614e34c240a089ea02d08da47da4393d7b (diff) | |
download | binaryen-0421bd0c27ea57c7c5c9bc3b1ce6f71f8ce240dc.tar.gz binaryen-0421bd0c27ea57c7c5c9bc3b1ce6f71f8ce240dc.tar.bz2 binaryen-0421bd0c27ea57c7c5c9bc3b1ce6f71f8ce240dc.zip |
start work on binary format, per v8 spec
Diffstat (limited to 'src')
-rw-r--r-- | src/wasm-binary.h | 200 |
1 files changed, 200 insertions, 0 deletions
diff --git a/src/wasm-binary.h b/src/wasm-binary.h new file mode 100644 index 000000000..9b81cffe8 --- /dev/null +++ b/src/wasm-binary.h @@ -0,0 +1,200 @@ +/* + * Copyright 2015 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. + */ + +// +// Parses and emits WebAssembly binary code +// + +#ifndef wasm_wasm_binary_h +#define wasm_wasm_binary_h + +#include <ostream> + +#include "wasm.h" +#include "shared-constants.h" + +namespace wasm { + +enum Section { + Memory = 0, + Signatures = 1, + Functions = 2, + DataSegments = 4, + FunctionTable = 5, + End = 6 +}; + +enum FunctionEntry { + Named = 1, + Import = 2, + Locals = 4, + Export = 8 +}; + +char binaryWasmType(WasmType type) { + switch (type) { + case none: return 0; + case i32: return 1; + case i64: return 2; + case f32: return 3; + case f64: return 4; + default: abort(); + } +} + +class WasmBinaryWriter : public WasmVisitor<void> { + Module* wasm; + ostream& o; + +public: + WasmBinaryWriter(Module* wasm, ostream& o) : wasm(wasm), o(o) {} + + void write() { + writeMemory(); + writeSignatures(); + writeFunctions(); + writeDataSegments(); + writeFunctionTable(); + writeEnd(); + } + + writeMemory() { + o << Section::Memory << char(log2(wasm.memory.initial)) << + char(log2(wasm.memory.max)) << + char(1); // export memory + } + + writeSignatures() { + o << Section::Signatures << LEB128(wasm.functionTypes.size()); + for (auto type : wasm.functionTypes) { + o << char(type->params.size()); + o << binaryWasmType(type->result); + for (auto param : type->params) { + o << binaryWasmType(param); + } + } + } + + int16_t functionTypeIndex(Name type) { + // TODO: optimize + for (size_t i = 0; i < wasm.functionTypes.size(); i++) { + if (wasm.functionTypes[i].name == type) return i; + } + abort(); + } + + std::map<Name, size_t> mappedLocals; // local name => index in compact form of [all int32s][all int64s]etc + std::map<WasmType, size_t> numLocalsByType; // type => number of locals of that type in the compact form + + void mapLocals(Function* function) { + for (auto& local : function->locals) { + numLocalsByType[local.type]++; + } + std::map<WasmType, size_t> currLocalsByType; + for (auto& local : function->locals) { + size_t index = 0; + Name name = local.name; + WasmType type = local.type; + currLocalsByType[type]++; // increment now for simplicity, must decremebt it in returns + if (type == i32) { + mappedLocals[name] = index + currLocalsByType[i32] - 1; + break; + } + index += numLocalsByType[i32]; + if (type == i64) { + mappedLocals[name] = index + currLocalsByType[i64] - 1; + break; + } + index += numLocalsByType[i64]; + if (type == f32) { + mappedLocals[name] = index + currLocalsByType[f32] - 1; + break; + } + index += numLocalsByType[f32]; + if (type == f64) { + mappedLocals[name] = index + currLocalsByType[f64] - 1; + break; + } + } + } + + std::vector<char> encodeAST(Function* function) { + } + + writeFunctions() { + size_t total = wasm.imports.size() + wasm.functions.size(); + o << Section::Functions << LEB128(total); + for (size_t i = 0; i < total; i++) { + Import* import = i < wasm.imports.size() ? wasm.imports[i] : nullptr; + Function* function = i >= wasm.imports.size() ? wasm.functions[i - wasm.imports.size()] : nullptr; + Name name, type; + if (import) { + name = import->name; + type = import->type.name; + } else { + name = function->name; + type = function->type; + } + o << functionTypeIndex(type); + o << char(FunctionEntry::Named | + (FunctionEntry::Import * !!import) | + (FunctionEntry::Locals * (function && function->locals.size() > 0) | + (FunctionEntry::Export) * (wasm.exportsMap[name].count(name) > 0))); + // TODO: name. how can we do an offset? into what section? and how do we know it now? + if (function && function->locals.size() > 0) { + mapLocals(function); + o << uint16_t(numLocalsByType[i32]) + << uint16_t(numLocalsByType[i64]) + << uint16_t(numLocalsByType[f32]) + << uint16_t(numLocalsByType[f64]); + } + if (function) { + auto ast = encodeAST(function); + o << uint16_t(ast.size()); + for (auto c : ast) { + o << c; + } + } + } + } + + writeDataSegments() { + } + + writeFunctionTable() { + } + + writeEnd() { + o << Section::End; + } +}; + +class WasmBinaryBuilder { + AllocatingModule& wasm; + MixedArena& allocator; + istream& i; +public: + WasmBinaryBuilder(AllocatingModule& wasm, istream& i) : wasm(wasm), allocator(wasm.allocator), i(i) {} + + void read() { + // + } +}; + +} // namespace wasm + +#endif // wasm_wasm_binary_h + |