blob: d0733d847814f080610299dca03d545c5f18b9f3 [file] [log] [blame]
Sam Cleggc94d3932017-11-17 18:14:09 +00001//===- WriterUtils.cpp ----------------------------------------------------===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Sam Cleggc94d3932017-11-17 18:14:09 +00006//
7//===----------------------------------------------------------------------===//
8
9#include "WriterUtils.h"
Sam Cleggc94d3932017-11-17 18:14:09 +000010#include "lld/Common/ErrorHandler.h"
Sam Cleggc94d3932017-11-17 18:14:09 +000011#include "llvm/Support/Debug.h"
12#include "llvm/Support/EndianStream.h"
Sam Cleggc94d3932017-11-17 18:14:09 +000013#include "llvm/Support/LEB128.h"
14
15#define DEBUG_TYPE "lld"
16
17using namespace llvm;
18using namespace llvm::wasm;
Sam Cleggc94d3932017-11-17 18:14:09 +000019
Sam Cleggc94d3932017-11-17 18:14:09 +000020namespace lld {
Fangrui Song33c59ab2019-10-10 05:25:39 +000021std::string toString(ValType type) {
22 switch (type) {
23 case ValType::I32:
24 return "i32";
25 case ValType::I64:
26 return "i64";
27 case ValType::F32:
28 return "f32";
29 case ValType::F64:
30 return "f64";
31 case ValType::V128:
32 return "v128";
33 case ValType::EXNREF:
34 return "exnref";
35 }
36 llvm_unreachable("Invalid wasm::ValType");
37}
Sam Cleggc94d3932017-11-17 18:14:09 +000038
Fangrui Song33c59ab2019-10-10 05:25:39 +000039std::string toString(const WasmSignature &sig) {
40 SmallString<128> s("(");
41 for (ValType type : sig.Params) {
42 if (s.size() != 1)
43 s += ", ";
44 s += toString(type);
45 }
46 s += ") -> ";
47 if (sig.Returns.empty())
48 s += "void";
49 else
50 s += toString(sig.Returns[0]);
Benjamin Krameradcd0262020-01-28 20:23:46 +010051 return std::string(s.str());
Fangrui Song33c59ab2019-10-10 05:25:39 +000052}
53
54std::string toString(const WasmGlobalType &type) {
55 return (type.Mutable ? "var " : "const ") +
56 toString(static_cast<ValType>(type.Type));
57}
58
59std::string toString(const WasmEventType &type) {
60 if (type.Attribute == WASM_EVENT_ATTRIBUTE_EXCEPTION)
61 return "exception";
62 return "unknown";
63}
64
65namespace wasm {
66void debugWrite(uint64_t offset, const Twine &msg) {
Rui Ueyama136d27a2019-07-11 05:40:30 +000067 LLVM_DEBUG(dbgs() << format(" | %08lld: ", offset) << msg << "\n");
Sam Cleggc94d3932017-11-17 18:14:09 +000068}
69
Fangrui Song33c59ab2019-10-10 05:25:39 +000070void writeUleb128(raw_ostream &os, uint32_t number, const Twine &msg) {
Rui Ueyama136d27a2019-07-11 05:40:30 +000071 debugWrite(os.tell(), msg + "[" + utohexstr(number) + "]");
72 encodeULEB128(number, os);
Sam Cleggc94d3932017-11-17 18:14:09 +000073}
74
Fangrui Song33c59ab2019-10-10 05:25:39 +000075void writeSleb128(raw_ostream &os, int32_t number, const Twine &msg) {
Rui Ueyama136d27a2019-07-11 05:40:30 +000076 debugWrite(os.tell(), msg + "[" + utohexstr(number) + "]");
77 encodeSLEB128(number, os);
Sam Cleggc94d3932017-11-17 18:14:09 +000078}
79
Fangrui Song33c59ab2019-10-10 05:25:39 +000080void writeBytes(raw_ostream &os, const char *bytes, size_t count,
Rui Ueyama136d27a2019-07-11 05:40:30 +000081 const Twine &msg) {
82 debugWrite(os.tell(), msg + " [data[" + Twine(count) + "]]");
83 os.write(bytes, count);
Sam Cleggc94d3932017-11-17 18:14:09 +000084}
85
Fangrui Song33c59ab2019-10-10 05:25:39 +000086void writeStr(raw_ostream &os, StringRef string, const Twine &msg) {
Rui Ueyama136d27a2019-07-11 05:40:30 +000087 debugWrite(os.tell(),
88 msg + " [str[" + Twine(string.size()) + "]: " + string + "]");
89 encodeULEB128(string.size(), os);
90 os.write(string.data(), string.size());
Sam Cleggc94d3932017-11-17 18:14:09 +000091}
92
Fangrui Song33c59ab2019-10-10 05:25:39 +000093void writeU8(raw_ostream &os, uint8_t byte, const Twine &msg) {
Rui Ueyama136d27a2019-07-11 05:40:30 +000094 debugWrite(os.tell(), msg + " [0x" + utohexstr(byte) + "]");
95 os << byte;
Sam Cleggea397f62018-03-01 00:42:57 +000096}
Sam Cleggc94d3932017-11-17 18:14:09 +000097
Fangrui Song33c59ab2019-10-10 05:25:39 +000098void writeU32(raw_ostream &os, uint32_t number, const Twine &msg) {
Rui Ueyama136d27a2019-07-11 05:40:30 +000099 debugWrite(os.tell(), msg + "[0x" + utohexstr(number) + "]");
100 support::endian::write(os, number, support::little);
Sam Cleggc94d3932017-11-17 18:14:09 +0000101}
102
Fangrui Song33c59ab2019-10-10 05:25:39 +0000103void writeValueType(raw_ostream &os, ValType type, const Twine &msg) {
Rui Ueyama136d27a2019-07-11 05:40:30 +0000104 writeU8(os, static_cast<uint8_t>(type),
105 msg + "[type: " + toString(type) + "]");
Sam Cleggc94d3932017-11-17 18:14:09 +0000106}
107
Fangrui Song33c59ab2019-10-10 05:25:39 +0000108void writeSig(raw_ostream &os, const WasmSignature &sig) {
Rui Ueyama136d27a2019-07-11 05:40:30 +0000109 writeU8(os, WASM_TYPE_FUNC, "signature type");
110 writeUleb128(os, sig.Params.size(), "param Count");
111 for (ValType paramType : sig.Params) {
112 writeValueType(os, paramType, "param type");
Sam Cleggc94d3932017-11-17 18:14:09 +0000113 }
Rui Ueyama136d27a2019-07-11 05:40:30 +0000114 writeUleb128(os, sig.Returns.size(), "result Count");
115 if (sig.Returns.size()) {
116 writeValueType(os, sig.Returns[0], "result type");
Sam Cleggc94d3932017-11-17 18:14:09 +0000117 }
118}
119
Fangrui Song33c59ab2019-10-10 05:25:39 +0000120void writeI32Const(raw_ostream &os, int32_t number, const Twine &msg) {
Thomas Lively09768c52019-09-04 19:50:39 +0000121 writeU8(os, WASM_OPCODE_I32_CONST, "i32.const");
122 writeSleb128(os, number, msg);
123}
124
Fangrui Song33c59ab2019-10-10 05:25:39 +0000125void writeI64Const(raw_ostream &os, int32_t number, const Twine &msg) {
Thomas Lively09768c52019-09-04 19:50:39 +0000126 writeU8(os, WASM_OPCODE_I64_CONST, "i64.const");
127 writeSleb128(os, number, msg);
128}
129
Fangrui Song33c59ab2019-10-10 05:25:39 +0000130void writeMemArg(raw_ostream &os, uint32_t alignment, uint32_t offset) {
Thomas Lively09768c52019-09-04 19:50:39 +0000131 writeUleb128(os, alignment, "alignment");
132 writeUleb128(os, offset, "offset");
133}
134
Fangrui Song33c59ab2019-10-10 05:25:39 +0000135void writeInitExpr(raw_ostream &os, const WasmInitExpr &initExpr) {
Rui Ueyama136d27a2019-07-11 05:40:30 +0000136 writeU8(os, initExpr.Opcode, "opcode");
137 switch (initExpr.Opcode) {
Sam Cleggc94d3932017-11-17 18:14:09 +0000138 case WASM_OPCODE_I32_CONST:
Rui Ueyama136d27a2019-07-11 05:40:30 +0000139 writeSleb128(os, initExpr.Value.Int32, "literal (i32)");
Sam Cleggc94d3932017-11-17 18:14:09 +0000140 break;
141 case WASM_OPCODE_I64_CONST:
Rui Ueyama136d27a2019-07-11 05:40:30 +0000142 writeSleb128(os, initExpr.Value.Int64, "literal (i64)");
Sam Cleggc94d3932017-11-17 18:14:09 +0000143 break;
Thomas Lively25ff8932019-01-08 06:25:55 +0000144 case WASM_OPCODE_GLOBAL_GET:
Rui Ueyama136d27a2019-07-11 05:40:30 +0000145 writeUleb128(os, initExpr.Value.Global, "literal (global index)");
Sam Cleggc94d3932017-11-17 18:14:09 +0000146 break;
147 default:
Rui Ueyama136d27a2019-07-11 05:40:30 +0000148 fatal("unknown opcode in init expr: " + Twine(initExpr.Opcode));
Sam Cleggc94d3932017-11-17 18:14:09 +0000149 }
Rui Ueyama136d27a2019-07-11 05:40:30 +0000150 writeU8(os, WASM_OPCODE_END, "opcode:end");
Sam Cleggc94d3932017-11-17 18:14:09 +0000151}
152
Fangrui Song33c59ab2019-10-10 05:25:39 +0000153void writeLimits(raw_ostream &os, const WasmLimits &limits) {
Rui Ueyama136d27a2019-07-11 05:40:30 +0000154 writeU8(os, limits.Flags, "limits flags");
155 writeUleb128(os, limits.Initial, "limits initial");
156 if (limits.Flags & WASM_LIMITS_FLAG_HAS_MAX)
157 writeUleb128(os, limits.Maximum, "limits max");
Sam Cleggc94d3932017-11-17 18:14:09 +0000158}
159
Fangrui Song33c59ab2019-10-10 05:25:39 +0000160void writeGlobalType(raw_ostream &os, const WasmGlobalType &type) {
Derek Schuff371842b2018-10-03 22:25:32 +0000161 // TODO: Update WasmGlobalType to use ValType and remove this cast.
Rui Ueyama136d27a2019-07-11 05:40:30 +0000162 writeValueType(os, ValType(type.Type), "global type");
163 writeU8(os, type.Mutable, "global mutable");
Sam Clegg1a9b7b92018-01-31 19:54:34 +0000164}
165
Fangrui Song33c59ab2019-10-10 05:25:39 +0000166void writeGlobal(raw_ostream &os, const WasmGlobal &global) {
Rui Ueyama136d27a2019-07-11 05:40:30 +0000167 writeGlobalType(os, global.Type);
168 writeInitExpr(os, global.InitExpr);
Sam Cleggc94d3932017-11-17 18:14:09 +0000169}
170
Fangrui Song33c59ab2019-10-10 05:25:39 +0000171void writeEventType(raw_ostream &os, const WasmEventType &type) {
Rui Ueyama136d27a2019-07-11 05:40:30 +0000172 writeUleb128(os, type.Attribute, "event attribute");
173 writeUleb128(os, type.SigIndex, "sig index");
Heejin Ahne915a712018-12-08 06:17:43 +0000174}
175
Fangrui Song33c59ab2019-10-10 05:25:39 +0000176void writeEvent(raw_ostream &os, const WasmEvent &event) {
Rui Ueyama136d27a2019-07-11 05:40:30 +0000177 writeEventType(os, event.Type);
Heejin Ahne915a712018-12-08 06:17:43 +0000178}
179
Fangrui Song33c59ab2019-10-10 05:25:39 +0000180void writeTableType(raw_ostream &os, const llvm::wasm::WasmTable &type) {
Rui Ueyama136d27a2019-07-11 05:40:30 +0000181 writeU8(os, WASM_TYPE_FUNCREF, "table type");
182 writeLimits(os, type.Limits);
Nicholas Wilson874eedd2018-03-27 17:38:51 +0000183}
184
Fangrui Song33c59ab2019-10-10 05:25:39 +0000185void writeImport(raw_ostream &os, const WasmImport &import) {
Rui Ueyama136d27a2019-07-11 05:40:30 +0000186 writeStr(os, import.Module, "import module name");
187 writeStr(os, import.Field, "import field name");
188 writeU8(os, import.Kind, "import kind");
189 switch (import.Kind) {
Sam Cleggc94d3932017-11-17 18:14:09 +0000190 case WASM_EXTERNAL_FUNCTION:
Rui Ueyama136d27a2019-07-11 05:40:30 +0000191 writeUleb128(os, import.SigIndex, "import sig index");
Sam Cleggc94d3932017-11-17 18:14:09 +0000192 break;
193 case WASM_EXTERNAL_GLOBAL:
Rui Ueyama136d27a2019-07-11 05:40:30 +0000194 writeGlobalType(os, import.Global);
Sam Cleggc94d3932017-11-17 18:14:09 +0000195 break;
Heejin Ahne915a712018-12-08 06:17:43 +0000196 case WASM_EXTERNAL_EVENT:
Rui Ueyama136d27a2019-07-11 05:40:30 +0000197 writeEventType(os, import.Event);
Heejin Ahne915a712018-12-08 06:17:43 +0000198 break;
Sam Cleggc94d3932017-11-17 18:14:09 +0000199 case WASM_EXTERNAL_MEMORY:
Rui Ueyama136d27a2019-07-11 05:40:30 +0000200 writeLimits(os, import.Memory);
Sam Cleggc94d3932017-11-17 18:14:09 +0000201 break;
Nicholas Wilson874eedd2018-03-27 17:38:51 +0000202 case WASM_EXTERNAL_TABLE:
Rui Ueyama136d27a2019-07-11 05:40:30 +0000203 writeTableType(os, import.Table);
Nicholas Wilson874eedd2018-03-27 17:38:51 +0000204 break;
Sam Cleggc94d3932017-11-17 18:14:09 +0000205 default:
Rui Ueyama136d27a2019-07-11 05:40:30 +0000206 fatal("unsupported import type: " + Twine(import.Kind));
Sam Cleggc94d3932017-11-17 18:14:09 +0000207 }
208}
209
Fangrui Song33c59ab2019-10-10 05:25:39 +0000210void writeExport(raw_ostream &os, const WasmExport &export_) {
Rui Ueyama136d27a2019-07-11 05:40:30 +0000211 writeStr(os, export_.Name, "export name");
212 writeU8(os, export_.Kind, "export kind");
213 switch (export_.Kind) {
Sam Cleggc94d3932017-11-17 18:14:09 +0000214 case WASM_EXTERNAL_FUNCTION:
Rui Ueyama136d27a2019-07-11 05:40:30 +0000215 writeUleb128(os, export_.Index, "function index");
Sam Cleggc94d3932017-11-17 18:14:09 +0000216 break;
217 case WASM_EXTERNAL_GLOBAL:
Rui Ueyama136d27a2019-07-11 05:40:30 +0000218 writeUleb128(os, export_.Index, "global index");
Sam Cleggc94d3932017-11-17 18:14:09 +0000219 break;
220 case WASM_EXTERNAL_MEMORY:
Rui Ueyama136d27a2019-07-11 05:40:30 +0000221 writeUleb128(os, export_.Index, "memory index");
Sam Cleggc94d3932017-11-17 18:14:09 +0000222 break;
Nicholas Wilson874eedd2018-03-27 17:38:51 +0000223 case WASM_EXTERNAL_TABLE:
Rui Ueyama136d27a2019-07-11 05:40:30 +0000224 writeUleb128(os, export_.Index, "table index");
Nicholas Wilson874eedd2018-03-27 17:38:51 +0000225 break;
Sam Cleggc94d3932017-11-17 18:14:09 +0000226 default:
Rui Ueyama136d27a2019-07-11 05:40:30 +0000227 fatal("unsupported export type: " + Twine(export_.Kind));
Sam Cleggc94d3932017-11-17 18:14:09 +0000228 }
229}
Fangrui Song33c59ab2019-10-10 05:25:39 +0000230
231} // namespace wasm
Sam Cleggc94d3932017-11-17 18:14:09 +0000232} // namespace lld