Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / lld / wasm / WriterUtils.cpp
blobcc8ed0b1de2371252128085371fde11ab469e443
1 //===- WriterUtils.cpp ----------------------------------------------------===//
2 //
3 // 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
6 //
7 //===----------------------------------------------------------------------===//
9 #include "WriterUtils.h"
10 #include "lld/Common/ErrorHandler.h"
11 #include "llvm/ADT/StringExtras.h"
12 #include "llvm/Support/Debug.h"
13 #include "llvm/Support/EndianStream.h"
14 #include "llvm/Support/LEB128.h"
16 #define DEBUG_TYPE "lld"
18 using namespace llvm;
19 using namespace llvm::wasm;
21 namespace lld {
22 std::string toString(ValType type) {
23 switch (type) {
24 case ValType::I32:
25 return "i32";
26 case ValType::I64:
27 return "i64";
28 case ValType::F32:
29 return "f32";
30 case ValType::F64:
31 return "f64";
32 case ValType::V128:
33 return "v128";
34 case ValType::FUNCREF:
35 return "funcref";
36 case ValType::EXTERNREF:
37 return "externref";
39 llvm_unreachable("Invalid wasm::ValType");
42 std::string toString(const WasmSignature &sig) {
43 SmallString<128> s("(");
44 for (ValType type : sig.Params) {
45 if (s.size() != 1)
46 s += ", ";
47 s += toString(type);
49 s += ") -> ";
50 if (sig.Returns.empty())
51 s += "void";
52 else
53 s += toString(sig.Returns[0]);
54 return std::string(s.str());
57 std::string toString(const WasmGlobalType &type) {
58 return (type.Mutable ? "var " : "const ") +
59 toString(static_cast<ValType>(type.Type));
62 static std::string toString(const llvm::wasm::WasmLimits &limits) {
63 std::string ret;
64 ret += "flags=0x" + std::to_string(limits.Flags);
65 ret += "; min=" + std::to_string(limits.Minimum);
66 if (limits.Flags & WASM_LIMITS_FLAG_HAS_MAX)
67 ret += "; max=" + std::to_string(limits.Maximum);
68 return ret;
71 std::string toString(const WasmTableType &type) {
72 SmallString<128> ret("");
73 return "type=" + toString(static_cast<ValType>(type.ElemType)) +
74 "; limits=[" + toString(type.Limits) + "]";
77 namespace wasm {
78 #ifdef LLVM_DEBUG
79 void debugWrite(uint64_t offset, const Twine &msg) {
80 LLVM_DEBUG(dbgs() << format(" | %08lld: ", offset) << msg << "\n");
82 #endif
84 void writeUleb128(raw_ostream &os, uint64_t number, const Twine &msg) {
85 debugWrite(os.tell(), msg + "[" + utohexstr(number) + "]");
86 encodeULEB128(number, os);
89 void writeSleb128(raw_ostream &os, int64_t number, const Twine &msg) {
90 debugWrite(os.tell(), msg + "[" + utohexstr(number) + "]");
91 encodeSLEB128(number, os);
94 void writeBytes(raw_ostream &os, const char *bytes, size_t count,
95 const Twine &msg) {
96 debugWrite(os.tell(), msg + " [data[" + Twine(count) + "]]");
97 os.write(bytes, count);
100 void writeStr(raw_ostream &os, StringRef string, const Twine &msg) {
101 debugWrite(os.tell(),
102 msg + " [str[" + Twine(string.size()) + "]: " + string + "]");
103 encodeULEB128(string.size(), os);
104 os.write(string.data(), string.size());
107 void writeU8(raw_ostream &os, uint8_t byte, const Twine &msg) {
108 debugWrite(os.tell(), msg + " [0x" + utohexstr(byte) + "]");
109 os << byte;
112 void writeU32(raw_ostream &os, uint32_t number, const Twine &msg) {
113 debugWrite(os.tell(), msg + "[0x" + utohexstr(number) + "]");
114 support::endian::write(os, number, llvm::endianness::little);
117 void writeU64(raw_ostream &os, uint64_t number, const Twine &msg) {
118 debugWrite(os.tell(), msg + "[0x" + utohexstr(number) + "]");
119 support::endian::write(os, number, llvm::endianness::little);
122 void writeValueType(raw_ostream &os, ValType type, const Twine &msg) {
123 writeU8(os, static_cast<uint8_t>(type),
124 msg + "[type: " + toString(type) + "]");
127 void writeSig(raw_ostream &os, const WasmSignature &sig) {
128 writeU8(os, WASM_TYPE_FUNC, "signature type");
129 writeUleb128(os, sig.Params.size(), "param Count");
130 for (ValType paramType : sig.Params) {
131 writeValueType(os, paramType, "param type");
133 writeUleb128(os, sig.Returns.size(), "result Count");
134 for (ValType returnType : sig.Returns) {
135 writeValueType(os, returnType, "result type");
139 void writeI32Const(raw_ostream &os, int32_t number, const Twine &msg) {
140 writeU8(os, WASM_OPCODE_I32_CONST, "i32.const");
141 writeSleb128(os, number, msg);
144 void writeI64Const(raw_ostream &os, int64_t number, const Twine &msg) {
145 writeU8(os, WASM_OPCODE_I64_CONST, "i64.const");
146 writeSleb128(os, number, msg);
149 void writePtrConst(raw_ostream &os, int64_t number, bool is64,
150 const Twine &msg) {
151 if (is64)
152 writeI64Const(os, number, msg);
153 else
154 writeI32Const(os, static_cast<int32_t>(number), msg);
157 void writeMemArg(raw_ostream &os, uint32_t alignment, uint64_t offset) {
158 writeUleb128(os, alignment, "alignment");
159 writeUleb128(os, offset, "offset");
162 void writeInitExpr(raw_ostream &os, const WasmInitExpr &initExpr) {
163 assert(!initExpr.Extended);
164 writeInitExprMVP(os, initExpr.Inst);
167 void writeInitExprMVP(raw_ostream &os, const WasmInitExprMVP &initExpr) {
168 writeU8(os, initExpr.Opcode, "opcode");
169 switch (initExpr.Opcode) {
170 case WASM_OPCODE_I32_CONST:
171 writeSleb128(os, initExpr.Value.Int32, "literal (i32)");
172 break;
173 case WASM_OPCODE_I64_CONST:
174 writeSleb128(os, initExpr.Value.Int64, "literal (i64)");
175 break;
176 case WASM_OPCODE_F32_CONST:
177 writeU32(os, initExpr.Value.Float32, "literal (f32)");
178 break;
179 case WASM_OPCODE_F64_CONST:
180 writeU64(os, initExpr.Value.Float64, "literal (f64)");
181 break;
182 case WASM_OPCODE_GLOBAL_GET:
183 writeUleb128(os, initExpr.Value.Global, "literal (global index)");
184 break;
185 case WASM_OPCODE_REF_NULL:
186 writeValueType(os, ValType::EXTERNREF, "literal (externref type)");
187 break;
188 default:
189 fatal("unknown opcode in init expr: " + Twine(initExpr.Opcode));
191 writeU8(os, WASM_OPCODE_END, "opcode:end");
194 void writeLimits(raw_ostream &os, const WasmLimits &limits) {
195 writeU8(os, limits.Flags, "limits flags");
196 writeUleb128(os, limits.Minimum, "limits min");
197 if (limits.Flags & WASM_LIMITS_FLAG_HAS_MAX)
198 writeUleb128(os, limits.Maximum, "limits max");
201 void writeGlobalType(raw_ostream &os, const WasmGlobalType &type) {
202 // TODO: Update WasmGlobalType to use ValType and remove this cast.
203 writeValueType(os, ValType(type.Type), "global type");
204 writeU8(os, type.Mutable, "global mutable");
207 void writeTableType(raw_ostream &os, const WasmTableType &type) {
208 writeValueType(os, ValType(type.ElemType), "table type");
209 writeLimits(os, type.Limits);
212 void writeImport(raw_ostream &os, const WasmImport &import) {
213 writeStr(os, import.Module, "import module name");
214 writeStr(os, import.Field, "import field name");
215 writeU8(os, import.Kind, "import kind");
216 switch (import.Kind) {
217 case WASM_EXTERNAL_FUNCTION:
218 writeUleb128(os, import.SigIndex, "import sig index");
219 break;
220 case WASM_EXTERNAL_GLOBAL:
221 writeGlobalType(os, import.Global);
222 break;
223 case WASM_EXTERNAL_TAG:
224 writeUleb128(os, 0, "tag attribute"); // Reserved "attribute" field
225 writeUleb128(os, import.SigIndex, "import sig index");
226 break;
227 case WASM_EXTERNAL_MEMORY:
228 writeLimits(os, import.Memory);
229 break;
230 case WASM_EXTERNAL_TABLE:
231 writeTableType(os, import.Table);
232 break;
233 default:
234 fatal("unsupported import type: " + Twine(import.Kind));
238 void writeExport(raw_ostream &os, const WasmExport &export_) {
239 writeStr(os, export_.Name, "export name");
240 writeU8(os, export_.Kind, "export kind");
241 switch (export_.Kind) {
242 case WASM_EXTERNAL_FUNCTION:
243 writeUleb128(os, export_.Index, "function index");
244 break;
245 case WASM_EXTERNAL_GLOBAL:
246 writeUleb128(os, export_.Index, "global index");
247 break;
248 case WASM_EXTERNAL_TAG:
249 writeUleb128(os, export_.Index, "tag index");
250 break;
251 case WASM_EXTERNAL_MEMORY:
252 writeUleb128(os, export_.Index, "memory index");
253 break;
254 case WASM_EXTERNAL_TABLE:
255 writeUleb128(os, export_.Index, "table index");
256 break;
257 default:
258 fatal("unsupported export type: " + Twine(export_.Kind));
262 } // namespace wasm
263 } // namespace lld