blob: bad221241be531f94cc34d4f3f0beeb497e9f4cd [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 {
21
Rui Ueyama136d27a2019-07-11 05:40:30 +000022void wasm::debugWrite(uint64_t offset, const Twine &msg) {
23 LLVM_DEBUG(dbgs() << format(" | %08lld: ", offset) << msg << "\n");
Sam Cleggc94d3932017-11-17 18:14:09 +000024}
25
Rui Ueyama136d27a2019-07-11 05:40:30 +000026void wasm::writeUleb128(raw_ostream &os, uint32_t number, const Twine &msg) {
27 debugWrite(os.tell(), msg + "[" + utohexstr(number) + "]");
28 encodeULEB128(number, os);
Sam Cleggc94d3932017-11-17 18:14:09 +000029}
30
Rui Ueyama136d27a2019-07-11 05:40:30 +000031void wasm::writeSleb128(raw_ostream &os, int32_t number, const Twine &msg) {
32 debugWrite(os.tell(), msg + "[" + utohexstr(number) + "]");
33 encodeSLEB128(number, os);
Sam Cleggc94d3932017-11-17 18:14:09 +000034}
35
Rui Ueyama136d27a2019-07-11 05:40:30 +000036void wasm::writeBytes(raw_ostream &os, const char *bytes, size_t count,
37 const Twine &msg) {
38 debugWrite(os.tell(), msg + " [data[" + Twine(count) + "]]");
39 os.write(bytes, count);
Sam Cleggc94d3932017-11-17 18:14:09 +000040}
41
Rui Ueyama136d27a2019-07-11 05:40:30 +000042void wasm::writeStr(raw_ostream &os, StringRef string, const Twine &msg) {
43 debugWrite(os.tell(),
44 msg + " [str[" + Twine(string.size()) + "]: " + string + "]");
45 encodeULEB128(string.size(), os);
46 os.write(string.data(), string.size());
Sam Cleggc94d3932017-11-17 18:14:09 +000047}
48
Rui Ueyama136d27a2019-07-11 05:40:30 +000049void wasm::writeU8(raw_ostream &os, uint8_t byte, const Twine &msg) {
50 debugWrite(os.tell(), msg + " [0x" + utohexstr(byte) + "]");
51 os << byte;
Sam Cleggea397f62018-03-01 00:42:57 +000052}
Sam Cleggc94d3932017-11-17 18:14:09 +000053
Rui Ueyama136d27a2019-07-11 05:40:30 +000054void wasm::writeU32(raw_ostream &os, uint32_t number, const Twine &msg) {
55 debugWrite(os.tell(), msg + "[0x" + utohexstr(number) + "]");
56 support::endian::write(os, number, support::little);
Sam Cleggc94d3932017-11-17 18:14:09 +000057}
58
Rui Ueyama136d27a2019-07-11 05:40:30 +000059void wasm::writeValueType(raw_ostream &os, ValType type, const Twine &msg) {
60 writeU8(os, static_cast<uint8_t>(type),
61 msg + "[type: " + toString(type) + "]");
Sam Cleggc94d3932017-11-17 18:14:09 +000062}
63
Rui Ueyama136d27a2019-07-11 05:40:30 +000064void wasm::writeSig(raw_ostream &os, const WasmSignature &sig) {
65 writeU8(os, WASM_TYPE_FUNC, "signature type");
66 writeUleb128(os, sig.Params.size(), "param Count");
67 for (ValType paramType : sig.Params) {
68 writeValueType(os, paramType, "param type");
Sam Cleggc94d3932017-11-17 18:14:09 +000069 }
Rui Ueyama136d27a2019-07-11 05:40:30 +000070 writeUleb128(os, sig.Returns.size(), "result Count");
71 if (sig.Returns.size()) {
72 writeValueType(os, sig.Returns[0], "result type");
Sam Cleggc94d3932017-11-17 18:14:09 +000073 }
74}
75
Thomas Lively09768c52019-09-04 19:50:39 +000076void wasm::writeI32Const(raw_ostream &os, int32_t number, const Twine &msg) {
77 writeU8(os, WASM_OPCODE_I32_CONST, "i32.const");
78 writeSleb128(os, number, msg);
79}
80
81void wasm::writeI64Const(raw_ostream &os, int32_t number, const Twine &msg) {
82 writeU8(os, WASM_OPCODE_I64_CONST, "i64.const");
83 writeSleb128(os, number, msg);
84}
85
86void wasm::writeMemArg(raw_ostream &os, uint32_t alignment, uint32_t offset) {
87 writeUleb128(os, alignment, "alignment");
88 writeUleb128(os, offset, "offset");
89}
90
Rui Ueyama136d27a2019-07-11 05:40:30 +000091void wasm::writeInitExpr(raw_ostream &os, const WasmInitExpr &initExpr) {
92 writeU8(os, initExpr.Opcode, "opcode");
93 switch (initExpr.Opcode) {
Sam Cleggc94d3932017-11-17 18:14:09 +000094 case WASM_OPCODE_I32_CONST:
Rui Ueyama136d27a2019-07-11 05:40:30 +000095 writeSleb128(os, initExpr.Value.Int32, "literal (i32)");
Sam Cleggc94d3932017-11-17 18:14:09 +000096 break;
97 case WASM_OPCODE_I64_CONST:
Rui Ueyama136d27a2019-07-11 05:40:30 +000098 writeSleb128(os, initExpr.Value.Int64, "literal (i64)");
Sam Cleggc94d3932017-11-17 18:14:09 +000099 break;
Thomas Lively25ff8932019-01-08 06:25:55 +0000100 case WASM_OPCODE_GLOBAL_GET:
Rui Ueyama136d27a2019-07-11 05:40:30 +0000101 writeUleb128(os, initExpr.Value.Global, "literal (global index)");
Sam Cleggc94d3932017-11-17 18:14:09 +0000102 break;
103 default:
Rui Ueyama136d27a2019-07-11 05:40:30 +0000104 fatal("unknown opcode in init expr: " + Twine(initExpr.Opcode));
Sam Cleggc94d3932017-11-17 18:14:09 +0000105 }
Rui Ueyama136d27a2019-07-11 05:40:30 +0000106 writeU8(os, WASM_OPCODE_END, "opcode:end");
Sam Cleggc94d3932017-11-17 18:14:09 +0000107}
108
Rui Ueyama136d27a2019-07-11 05:40:30 +0000109void wasm::writeLimits(raw_ostream &os, const WasmLimits &limits) {
110 writeU8(os, limits.Flags, "limits flags");
111 writeUleb128(os, limits.Initial, "limits initial");
112 if (limits.Flags & WASM_LIMITS_FLAG_HAS_MAX)
113 writeUleb128(os, limits.Maximum, "limits max");
Sam Cleggc94d3932017-11-17 18:14:09 +0000114}
115
Rui Ueyama136d27a2019-07-11 05:40:30 +0000116void wasm::writeGlobalType(raw_ostream &os, const WasmGlobalType &type) {
Derek Schuff371842b2018-10-03 22:25:32 +0000117 // TODO: Update WasmGlobalType to use ValType and remove this cast.
Rui Ueyama136d27a2019-07-11 05:40:30 +0000118 writeValueType(os, ValType(type.Type), "global type");
119 writeU8(os, type.Mutable, "global mutable");
Sam Clegg1a9b7b92018-01-31 19:54:34 +0000120}
121
Rui Ueyama136d27a2019-07-11 05:40:30 +0000122void wasm::writeGlobal(raw_ostream &os, const WasmGlobal &global) {
123 writeGlobalType(os, global.Type);
124 writeInitExpr(os, global.InitExpr);
Sam Cleggc94d3932017-11-17 18:14:09 +0000125}
126
Rui Ueyama136d27a2019-07-11 05:40:30 +0000127void wasm::writeEventType(raw_ostream &os, const WasmEventType &type) {
128 writeUleb128(os, type.Attribute, "event attribute");
129 writeUleb128(os, type.SigIndex, "sig index");
Heejin Ahne915a712018-12-08 06:17:43 +0000130}
131
Rui Ueyama136d27a2019-07-11 05:40:30 +0000132void wasm::writeEvent(raw_ostream &os, const WasmEvent &event) {
133 writeEventType(os, event.Type);
Heejin Ahne915a712018-12-08 06:17:43 +0000134}
135
Rui Ueyama136d27a2019-07-11 05:40:30 +0000136void wasm::writeTableType(raw_ostream &os, const llvm::wasm::WasmTable &type) {
137 writeU8(os, WASM_TYPE_FUNCREF, "table type");
138 writeLimits(os, type.Limits);
Nicholas Wilson874eedd2018-03-27 17:38:51 +0000139}
140
Rui Ueyama136d27a2019-07-11 05:40:30 +0000141void wasm::writeImport(raw_ostream &os, const WasmImport &import) {
142 writeStr(os, import.Module, "import module name");
143 writeStr(os, import.Field, "import field name");
144 writeU8(os, import.Kind, "import kind");
145 switch (import.Kind) {
Sam Cleggc94d3932017-11-17 18:14:09 +0000146 case WASM_EXTERNAL_FUNCTION:
Rui Ueyama136d27a2019-07-11 05:40:30 +0000147 writeUleb128(os, import.SigIndex, "import sig index");
Sam Cleggc94d3932017-11-17 18:14:09 +0000148 break;
149 case WASM_EXTERNAL_GLOBAL:
Rui Ueyama136d27a2019-07-11 05:40:30 +0000150 writeGlobalType(os, import.Global);
Sam Cleggc94d3932017-11-17 18:14:09 +0000151 break;
Heejin Ahne915a712018-12-08 06:17:43 +0000152 case WASM_EXTERNAL_EVENT:
Rui Ueyama136d27a2019-07-11 05:40:30 +0000153 writeEventType(os, import.Event);
Heejin Ahne915a712018-12-08 06:17:43 +0000154 break;
Sam Cleggc94d3932017-11-17 18:14:09 +0000155 case WASM_EXTERNAL_MEMORY:
Rui Ueyama136d27a2019-07-11 05:40:30 +0000156 writeLimits(os, import.Memory);
Sam Cleggc94d3932017-11-17 18:14:09 +0000157 break;
Nicholas Wilson874eedd2018-03-27 17:38:51 +0000158 case WASM_EXTERNAL_TABLE:
Rui Ueyama136d27a2019-07-11 05:40:30 +0000159 writeTableType(os, import.Table);
Nicholas Wilson874eedd2018-03-27 17:38:51 +0000160 break;
Sam Cleggc94d3932017-11-17 18:14:09 +0000161 default:
Rui Ueyama136d27a2019-07-11 05:40:30 +0000162 fatal("unsupported import type: " + Twine(import.Kind));
Sam Cleggc94d3932017-11-17 18:14:09 +0000163 }
164}
165
Rui Ueyama136d27a2019-07-11 05:40:30 +0000166void wasm::writeExport(raw_ostream &os, const WasmExport &export_) {
167 writeStr(os, export_.Name, "export name");
168 writeU8(os, export_.Kind, "export kind");
169 switch (export_.Kind) {
Sam Cleggc94d3932017-11-17 18:14:09 +0000170 case WASM_EXTERNAL_FUNCTION:
Rui Ueyama136d27a2019-07-11 05:40:30 +0000171 writeUleb128(os, export_.Index, "function index");
Sam Cleggc94d3932017-11-17 18:14:09 +0000172 break;
173 case WASM_EXTERNAL_GLOBAL:
Rui Ueyama136d27a2019-07-11 05:40:30 +0000174 writeUleb128(os, export_.Index, "global index");
Sam Cleggc94d3932017-11-17 18:14:09 +0000175 break;
176 case WASM_EXTERNAL_MEMORY:
Rui Ueyama136d27a2019-07-11 05:40:30 +0000177 writeUleb128(os, export_.Index, "memory index");
Sam Cleggc94d3932017-11-17 18:14:09 +0000178 break;
Nicholas Wilson874eedd2018-03-27 17:38:51 +0000179 case WASM_EXTERNAL_TABLE:
Rui Ueyama136d27a2019-07-11 05:40:30 +0000180 writeUleb128(os, export_.Index, "table index");
Nicholas Wilson874eedd2018-03-27 17:38:51 +0000181 break;
Sam Cleggc94d3932017-11-17 18:14:09 +0000182 default:
Rui Ueyama136d27a2019-07-11 05:40:30 +0000183 fatal("unsupported export type: " + Twine(export_.Kind));
Sam Cleggc94d3932017-11-17 18:14:09 +0000184 }
185}
Sam Cleggc94d3932017-11-17 18:14:09 +0000186} // namespace lld
Sam Cleggb8621592017-11-30 01:40:08 +0000187
Rui Ueyama136d27a2019-07-11 05:40:30 +0000188std::string lld::toString(ValType type) {
189 switch (type) {
Sam Cleggb8621592017-11-30 01:40:08 +0000190 case ValType::I32:
Sam Cleggc1a3b9d2018-11-01 01:08:37 +0000191 return "i32";
Sam Cleggb8621592017-11-30 01:40:08 +0000192 case ValType::I64:
Sam Cleggc1a3b9d2018-11-01 01:08:37 +0000193 return "i64";
Sam Cleggb8621592017-11-30 01:40:08 +0000194 case ValType::F32:
Sam Cleggc1a3b9d2018-11-01 01:08:37 +0000195 return "f32";
Sam Cleggb8621592017-11-30 01:40:08 +0000196 case ValType::F64:
Sam Cleggc1a3b9d2018-11-01 01:08:37 +0000197 return "f64";
Thomas Livelyd661e262018-09-20 22:07:18 +0000198 case ValType::V128:
Sam Cleggc1a3b9d2018-11-01 01:08:37 +0000199 return "v128";
Heejin Ahn9f96a582019-07-15 22:49:25 +0000200 case ValType::EXNREF:
201 return "exnref";
Sam Cleggb8621592017-11-30 01:40:08 +0000202 }
203 llvm_unreachable("Invalid wasm::ValType");
204}
205
Rui Ueyama136d27a2019-07-11 05:40:30 +0000206std::string lld::toString(const WasmSignature &sig) {
207 SmallString<128> s("(");
208 for (ValType type : sig.Params) {
209 if (s.size() != 1)
210 s += ", ";
211 s += toString(type);
Sam Cleggb8621592017-11-30 01:40:08 +0000212 }
Rui Ueyama136d27a2019-07-11 05:40:30 +0000213 s += ") -> ";
214 if (sig.Returns.empty())
215 s += "void";
Sam Cleggb8621592017-11-30 01:40:08 +0000216 else
Rui Ueyama136d27a2019-07-11 05:40:30 +0000217 s += toString(sig.Returns[0]);
218 return s.str();
Sam Cleggb8621592017-11-30 01:40:08 +0000219}
Sam Clegg93102972018-02-23 05:08:53 +0000220
Rui Ueyama136d27a2019-07-11 05:40:30 +0000221std::string lld::toString(const WasmGlobalType &type) {
222 return (type.Mutable ? "var " : "const ") +
223 toString(static_cast<ValType>(type.Type));
Heejin Ahne915a712018-12-08 06:17:43 +0000224}
225
Rui Ueyama136d27a2019-07-11 05:40:30 +0000226std::string lld::toString(const WasmEventType &type) {
227 if (type.Attribute == WASM_EVENT_ATTRIBUTE_EXCEPTION)
Heejin Ahne915a712018-12-08 06:17:43 +0000228 return "exception";
229 return "unknown";
Sam Clegg93102972018-02-23 05:08:53 +0000230}