[JITLink] Add support of R_X86_64_32S relocation
[llvm-project.git] / lld / wasm / WriterUtils.cpp
blob17e7c17cf1f5952ca01c09402949bbfdb8eb8063
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/Support/Debug.h"
12 #include "llvm/Support/EndianStream.h"
13 #include "llvm/Support/LEB128.h"
15 #define DEBUG_TYPE "lld"
17 using namespace llvm;
18 using namespace llvm::wasm;
20 namespace lld {
21 std::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::FUNCREF:
34 return "funcref";
35 case ValType::EXTERNREF:
36 return "externref";
38 llvm_unreachable("Invalid wasm::ValType");
41 std::string toString(const WasmSignature &sig) {
42 SmallString<128> s("(");
43 for (ValType type : sig.Params) {
44 if (s.size() != 1)
45 s += ", ";
46 s += toString(type);
48 s += ") -> ";
49 if (sig.Returns.empty())
50 s += "void";
51 else
52 s += toString(sig.Returns[0]);
53 return std::string(s.str());
56 std::string toString(const WasmGlobalType &type) {
57 return (type.Mutable ? "var " : "const ") +
58 toString(static_cast<ValType>(type.Type));
61 std::string toString(const WasmTagType &type) {
62 if (type.Attribute == WASM_TAG_ATTRIBUTE_EXCEPTION)
63 return "exception";
64 return "unknown";
67 static std::string toString(const llvm::wasm::WasmLimits &limits) {
68 std::string ret;
69 ret += "flags=0x" + std::to_string(limits.Flags);
70 ret += "; min=" + std::to_string(limits.Minimum);
71 if (limits.Flags & WASM_LIMITS_FLAG_HAS_MAX)
72 ret += "; max=" + std::to_string(limits.Maximum);
73 return ret;
76 std::string toString(const WasmTableType &type) {
77 SmallString<128> ret("");
78 return "type=" + toString(static_cast<ValType>(type.ElemType)) +
79 "; limits=[" + toString(type.Limits) + "]";
82 namespace wasm {
83 void debugWrite(uint64_t offset, const Twine &msg) {
84 LLVM_DEBUG(dbgs() << format(" | %08lld: ", offset) << msg << "\n");
87 void writeUleb128(raw_ostream &os, uint64_t number, const Twine &msg) {
88 debugWrite(os.tell(), msg + "[" + utohexstr(number) + "]");
89 encodeULEB128(number, os);
92 void writeSleb128(raw_ostream &os, int64_t number, const Twine &msg) {
93 debugWrite(os.tell(), msg + "[" + utohexstr(number) + "]");
94 encodeSLEB128(number, os);
97 void writeBytes(raw_ostream &os, const char *bytes, size_t count,
98 const Twine &msg) {
99 debugWrite(os.tell(), msg + " [data[" + Twine(count) + "]]");
100 os.write(bytes, count);
103 void writeStr(raw_ostream &os, StringRef string, const Twine &msg) {
104 debugWrite(os.tell(),
105 msg + " [str[" + Twine(string.size()) + "]: " + string + "]");
106 encodeULEB128(string.size(), os);
107 os.write(string.data(), string.size());
110 void writeU8(raw_ostream &os, uint8_t byte, const Twine &msg) {
111 debugWrite(os.tell(), msg + " [0x" + utohexstr(byte) + "]");
112 os << byte;
115 void writeU32(raw_ostream &os, uint32_t number, const Twine &msg) {
116 debugWrite(os.tell(), msg + "[0x" + utohexstr(number) + "]");
117 support::endian::write(os, number, support::little);
120 void writeU64(raw_ostream &os, uint64_t number, const Twine &msg) {
121 debugWrite(os.tell(), msg + "[0x" + utohexstr(number) + "]");
122 support::endian::write(os, number, support::little);
125 void writeValueType(raw_ostream &os, ValType type, const Twine &msg) {
126 writeU8(os, static_cast<uint8_t>(type),
127 msg + "[type: " + toString(type) + "]");
130 void writeSig(raw_ostream &os, const WasmSignature &sig) {
131 writeU8(os, WASM_TYPE_FUNC, "signature type");
132 writeUleb128(os, sig.Params.size(), "param Count");
133 for (ValType paramType : sig.Params) {
134 writeValueType(os, paramType, "param type");
136 writeUleb128(os, sig.Returns.size(), "result Count");
137 for (ValType returnType : sig.Returns) {
138 writeValueType(os, returnType, "result type");
142 void writeI32Const(raw_ostream &os, int32_t number, const Twine &msg) {
143 writeU8(os, WASM_OPCODE_I32_CONST, "i32.const");
144 writeSleb128(os, number, msg);
147 void writeI64Const(raw_ostream &os, int64_t number, const Twine &msg) {
148 writeU8(os, WASM_OPCODE_I64_CONST, "i64.const");
149 writeSleb128(os, number, msg);
152 void writePtrConst(raw_ostream &os, int64_t number, bool is64,
153 const Twine &msg) {
154 if (is64)
155 writeI64Const(os, number, msg);
156 else
157 writeI32Const(os, static_cast<int32_t>(number), msg);
160 void writeMemArg(raw_ostream &os, uint32_t alignment, uint64_t offset) {
161 writeUleb128(os, alignment, "alignment");
162 writeUleb128(os, offset, "offset");
165 void writeInitExpr(raw_ostream &os, const WasmInitExpr &initExpr) {
166 writeU8(os, initExpr.Opcode, "opcode");
167 switch (initExpr.Opcode) {
168 case WASM_OPCODE_I32_CONST:
169 writeSleb128(os, initExpr.Value.Int32, "literal (i32)");
170 break;
171 case WASM_OPCODE_I64_CONST:
172 writeSleb128(os, initExpr.Value.Int64, "literal (i64)");
173 break;
174 case WASM_OPCODE_F32_CONST:
175 writeU32(os, initExpr.Value.Float32, "literal (f32)");
176 break;
177 case WASM_OPCODE_F64_CONST:
178 writeU64(os, initExpr.Value.Float64, "literal (f64)");
179 break;
180 case WASM_OPCODE_GLOBAL_GET:
181 writeUleb128(os, initExpr.Value.Global, "literal (global index)");
182 break;
183 case WASM_OPCODE_REF_NULL:
184 writeValueType(os, ValType::EXTERNREF, "literal (externref type)");
185 break;
186 default:
187 fatal("unknown opcode in init expr: " + Twine(initExpr.Opcode));
189 writeU8(os, WASM_OPCODE_END, "opcode:end");
192 void writeLimits(raw_ostream &os, const WasmLimits &limits) {
193 writeU8(os, limits.Flags, "limits flags");
194 writeUleb128(os, limits.Minimum, "limits min");
195 if (limits.Flags & WASM_LIMITS_FLAG_HAS_MAX)
196 writeUleb128(os, limits.Maximum, "limits max");
199 void writeGlobalType(raw_ostream &os, const WasmGlobalType &type) {
200 // TODO: Update WasmGlobalType to use ValType and remove this cast.
201 writeValueType(os, ValType(type.Type), "global type");
202 writeU8(os, type.Mutable, "global mutable");
205 void writeTagType(raw_ostream &os, const WasmTagType &type) {
206 writeUleb128(os, type.Attribute, "tag attribute");
207 writeUleb128(os, type.SigIndex, "sig index");
210 void writeTag(raw_ostream &os, const WasmTag &tag) {
211 writeTagType(os, tag.Type);
214 void writeTableType(raw_ostream &os, const WasmTableType &type) {
215 writeValueType(os, ValType(type.ElemType), "table type");
216 writeLimits(os, type.Limits);
219 void writeImport(raw_ostream &os, const WasmImport &import) {
220 writeStr(os, import.Module, "import module name");
221 writeStr(os, import.Field, "import field name");
222 writeU8(os, import.Kind, "import kind");
223 switch (import.Kind) {
224 case WASM_EXTERNAL_FUNCTION:
225 writeUleb128(os, import.SigIndex, "import sig index");
226 break;
227 case WASM_EXTERNAL_GLOBAL:
228 writeGlobalType(os, import.Global);
229 break;
230 case WASM_EXTERNAL_TAG:
231 writeTagType(os, import.Tag);
232 break;
233 case WASM_EXTERNAL_MEMORY:
234 writeLimits(os, import.Memory);
235 break;
236 case WASM_EXTERNAL_TABLE:
237 writeTableType(os, import.Table);
238 break;
239 default:
240 fatal("unsupported import type: " + Twine(import.Kind));
244 void writeExport(raw_ostream &os, const WasmExport &export_) {
245 writeStr(os, export_.Name, "export name");
246 writeU8(os, export_.Kind, "export kind");
247 switch (export_.Kind) {
248 case WASM_EXTERNAL_FUNCTION:
249 writeUleb128(os, export_.Index, "function index");
250 break;
251 case WASM_EXTERNAL_GLOBAL:
252 writeUleb128(os, export_.Index, "global index");
253 break;
254 case WASM_EXTERNAL_TAG:
255 writeUleb128(os, export_.Index, "tag index");
256 break;
257 case WASM_EXTERNAL_MEMORY:
258 writeUleb128(os, export_.Index, "memory index");
259 break;
260 case WASM_EXTERNAL_TABLE:
261 writeUleb128(os, export_.Index, "table index");
262 break;
263 default:
264 fatal("unsupported export type: " + Twine(export_.Kind));
268 } // namespace wasm
269 } // namespace lld