blob: 599b42b2217cd5983489f674836a845ca8e420c7 [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 Ueyama11842532018-02-16 20:38:00 +000022void wasm::debugWrite(uint64_t Offset, const Twine &Msg) {
Nicola Zaghene7245b42018-05-15 13:36:20 +000023 LLVM_DEBUG(dbgs() << format(" | %08lld: ", Offset) << Msg << "\n");
Sam Cleggc94d3932017-11-17 18:14:09 +000024}
25
Sam Cleggea397f62018-03-01 00:42:57 +000026void wasm::writeUleb128(raw_ostream &OS, uint32_t Number, const Twine &Msg) {
Rui Ueyama11842532018-02-16 20:38:00 +000027 debugWrite(OS.tell(), Msg + "[" + utohexstr(Number) + "]");
Sam Cleggc94d3932017-11-17 18:14:09 +000028 encodeULEB128(Number, OS);
29}
30
Sam Cleggea397f62018-03-01 00:42:57 +000031void wasm::writeSleb128(raw_ostream &OS, int32_t Number, const Twine &Msg) {
Rui Ueyama11842532018-02-16 20:38:00 +000032 debugWrite(OS.tell(), Msg + "[" + utohexstr(Number) + "]");
Sam Cleggc94d3932017-11-17 18:14:09 +000033 encodeSLEB128(Number, OS);
34}
35
Rui Ueyama7b9ed652018-02-16 19:53:29 +000036void wasm::writeBytes(raw_ostream &OS, const char *Bytes, size_t Count,
Sam Cleggea397f62018-03-01 00:42:57 +000037 const Twine &Msg) {
Rui Ueyama11842532018-02-16 20:38:00 +000038 debugWrite(OS.tell(), Msg + " [data[" + Twine(Count) + "]]");
Rui Ueyama7b9ed652018-02-16 19:53:29 +000039 OS.write(Bytes, Count);
Sam Cleggc94d3932017-11-17 18:14:09 +000040}
41
Sam Cleggea397f62018-03-01 00:42:57 +000042void wasm::writeStr(raw_ostream &OS, StringRef String, const Twine &Msg) {
Rui Ueyama11842532018-02-16 20:38:00 +000043 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
Sam Cleggea397f62018-03-01 00:42:57 +000049void wasm::writeU8(raw_ostream &OS, uint8_t Byte, const Twine &Msg) {
50 debugWrite(OS.tell(), Msg + " [0x" + utohexstr(Byte) + "]");
51 OS << Byte;
52}
Sam Cleggc94d3932017-11-17 18:14:09 +000053
Sam Cleggea397f62018-03-01 00:42:57 +000054void wasm::writeU32(raw_ostream &OS, uint32_t Number, const Twine &Msg) {
55 debugWrite(OS.tell(), Msg + "[0x" + utohexstr(Number) + "]");
Peter Collingbournee3f65292018-05-18 19:46:24 +000056 support::endian::write(OS, Number, support::little);
Sam Cleggc94d3932017-11-17 18:14:09 +000057}
58
Derek Schuff371842b2018-10-03 22:25:32 +000059void wasm::writeValueType(raw_ostream &OS, ValType Type, const Twine &Msg) {
60 writeU8(OS, static_cast<uint8_t>(Type),
Sam Cleggc1a3b9d2018-11-01 01:08:37 +000061 Msg + "[type: " + toString(Type) + "]");
Sam Cleggc94d3932017-11-17 18:14:09 +000062}
63
64void wasm::writeSig(raw_ostream &OS, const WasmSignature &Sig) {
Sam Clegg8518e7d2018-03-01 18:06:39 +000065 writeU8(OS, WASM_TYPE_FUNC, "signature type");
Derek Schuff371842b2018-10-03 22:25:32 +000066 writeUleb128(OS, Sig.Params.size(), "param Count");
67 for (ValType ParamType : Sig.Params) {
Sam Cleggc94d3932017-11-17 18:14:09 +000068 writeValueType(OS, ParamType, "param type");
69 }
Derek Schuff371842b2018-10-03 22:25:32 +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
76void wasm::writeInitExpr(raw_ostream &OS, const WasmInitExpr &InitExpr) {
77 writeU8(OS, InitExpr.Opcode, "opcode");
78 switch (InitExpr.Opcode) {
79 case WASM_OPCODE_I32_CONST:
80 writeSleb128(OS, InitExpr.Value.Int32, "literal (i32)");
81 break;
82 case WASM_OPCODE_I64_CONST:
83 writeSleb128(OS, InitExpr.Value.Int64, "literal (i64)");
84 break;
Thomas Lively25ff8932019-01-08 06:25:55 +000085 case WASM_OPCODE_GLOBAL_GET:
Sam Cleggc94d3932017-11-17 18:14:09 +000086 writeUleb128(OS, InitExpr.Value.Global, "literal (global index)");
87 break;
88 default:
89 fatal("unknown opcode in init expr: " + Twine(InitExpr.Opcode));
Sam Cleggc94d3932017-11-17 18:14:09 +000090 }
91 writeU8(OS, WASM_OPCODE_END, "opcode:end");
92}
93
94void wasm::writeLimits(raw_ostream &OS, const WasmLimits &Limits) {
Sam Clegg8518e7d2018-03-01 18:06:39 +000095 writeU8(OS, Limits.Flags, "limits flags");
Sam Cleggc94d3932017-11-17 18:14:09 +000096 writeUleb128(OS, Limits.Initial, "limits initial");
97 if (Limits.Flags & WASM_LIMITS_FLAG_HAS_MAX)
98 writeUleb128(OS, Limits.Maximum, "limits max");
99}
100
Sam Clegg1a9b7b92018-01-31 19:54:34 +0000101void wasm::writeGlobalType(raw_ostream &OS, const WasmGlobalType &Type) {
Derek Schuff371842b2018-10-03 22:25:32 +0000102 // TODO: Update WasmGlobalType to use ValType and remove this cast.
103 writeValueType(OS, ValType(Type.Type), "global type");
Sam Clegg8518e7d2018-03-01 18:06:39 +0000104 writeU8(OS, Type.Mutable, "global mutable");
Sam Clegg1a9b7b92018-01-31 19:54:34 +0000105}
106
Sam Cleggc94d3932017-11-17 18:14:09 +0000107void wasm::writeGlobal(raw_ostream &OS, const WasmGlobal &Global) {
Sam Clegg1a9b7b92018-01-31 19:54:34 +0000108 writeGlobalType(OS, Global.Type);
Sam Cleggc94d3932017-11-17 18:14:09 +0000109 writeInitExpr(OS, Global.InitExpr);
110}
111
Heejin Ahne915a712018-12-08 06:17:43 +0000112void wasm::writeEventType(raw_ostream &OS, const WasmEventType &Type) {
113 writeUleb128(OS, Type.Attribute, "event attribute");
114 writeUleb128(OS, Type.SigIndex, "sig index");
115}
116
117void wasm::writeEvent(raw_ostream &OS, const WasmEvent &Event) {
118 writeEventType(OS, Event.Type);
119}
120
Nicholas Wilson874eedd2018-03-27 17:38:51 +0000121void wasm::writeTableType(raw_ostream &OS, const llvm::wasm::WasmTable &Type) {
Thomas Lively25ff8932019-01-08 06:25:55 +0000122 writeU8(OS, WASM_TYPE_FUNCREF, "table type");
Nicholas Wilson874eedd2018-03-27 17:38:51 +0000123 writeLimits(OS, Type.Limits);
124}
125
Sam Cleggc94d3932017-11-17 18:14:09 +0000126void wasm::writeImport(raw_ostream &OS, const WasmImport &Import) {
127 writeStr(OS, Import.Module, "import module name");
128 writeStr(OS, Import.Field, "import field name");
129 writeU8(OS, Import.Kind, "import kind");
130 switch (Import.Kind) {
131 case WASM_EXTERNAL_FUNCTION:
132 writeUleb128(OS, Import.SigIndex, "import sig index");
133 break;
134 case WASM_EXTERNAL_GLOBAL:
Sam Clegg1a9b7b92018-01-31 19:54:34 +0000135 writeGlobalType(OS, Import.Global);
Sam Cleggc94d3932017-11-17 18:14:09 +0000136 break;
Heejin Ahne915a712018-12-08 06:17:43 +0000137 case WASM_EXTERNAL_EVENT:
138 writeEventType(OS, Import.Event);
139 break;
Sam Cleggc94d3932017-11-17 18:14:09 +0000140 case WASM_EXTERNAL_MEMORY:
141 writeLimits(OS, Import.Memory);
142 break;
Nicholas Wilson874eedd2018-03-27 17:38:51 +0000143 case WASM_EXTERNAL_TABLE:
144 writeTableType(OS, Import.Table);
145 break;
Sam Cleggc94d3932017-11-17 18:14:09 +0000146 default:
147 fatal("unsupported import type: " + Twine(Import.Kind));
Sam Cleggc94d3932017-11-17 18:14:09 +0000148 }
149}
150
151void wasm::writeExport(raw_ostream &OS, const WasmExport &Export) {
152 writeStr(OS, Export.Name, "export name");
153 writeU8(OS, Export.Kind, "export kind");
154 switch (Export.Kind) {
155 case WASM_EXTERNAL_FUNCTION:
156 writeUleb128(OS, Export.Index, "function index");
157 break;
158 case WASM_EXTERNAL_GLOBAL:
159 writeUleb128(OS, Export.Index, "global index");
160 break;
161 case WASM_EXTERNAL_MEMORY:
162 writeUleb128(OS, Export.Index, "memory index");
163 break;
Nicholas Wilson874eedd2018-03-27 17:38:51 +0000164 case WASM_EXTERNAL_TABLE:
165 writeUleb128(OS, Export.Index, "table index");
166 break;
Sam Cleggc94d3932017-11-17 18:14:09 +0000167 default:
168 fatal("unsupported export type: " + Twine(Export.Kind));
Sam Cleggc94d3932017-11-17 18:14:09 +0000169 }
170}
Sam Cleggc94d3932017-11-17 18:14:09 +0000171} // namespace lld
Sam Cleggb8621592017-11-30 01:40:08 +0000172
173std::string lld::toString(ValType Type) {
174 switch (Type) {
175 case ValType::I32:
Sam Cleggc1a3b9d2018-11-01 01:08:37 +0000176 return "i32";
Sam Cleggb8621592017-11-30 01:40:08 +0000177 case ValType::I64:
Sam Cleggc1a3b9d2018-11-01 01:08:37 +0000178 return "i64";
Sam Cleggb8621592017-11-30 01:40:08 +0000179 case ValType::F32:
Sam Cleggc1a3b9d2018-11-01 01:08:37 +0000180 return "f32";
Sam Cleggb8621592017-11-30 01:40:08 +0000181 case ValType::F64:
Sam Cleggc1a3b9d2018-11-01 01:08:37 +0000182 return "f64";
Thomas Livelyd661e262018-09-20 22:07:18 +0000183 case ValType::V128:
Sam Cleggc1a3b9d2018-11-01 01:08:37 +0000184 return "v128";
Heejin Ahn2dce27d2018-03-08 04:06:57 +0000185 case ValType::EXCEPT_REF:
186 return "except_ref";
Sam Cleggb8621592017-11-30 01:40:08 +0000187 }
188 llvm_unreachable("Invalid wasm::ValType");
189}
190
191std::string lld::toString(const WasmSignature &Sig) {
192 SmallString<128> S("(");
Derek Schuff371842b2018-10-03 22:25:32 +0000193 for (ValType Type : Sig.Params) {
Sam Cleggb8621592017-11-30 01:40:08 +0000194 if (S.size() != 1)
195 S += ", ";
Derek Schuff371842b2018-10-03 22:25:32 +0000196 S += toString(Type);
Sam Cleggb8621592017-11-30 01:40:08 +0000197 }
198 S += ") -> ";
Derek Schuff371842b2018-10-03 22:25:32 +0000199 if (Sig.Returns.size() == 0)
Sam Cleggb8621592017-11-30 01:40:08 +0000200 S += "void";
201 else
Derek Schuff371842b2018-10-03 22:25:32 +0000202 S += toString(Sig.Returns[0]);
Sam Cleggb8621592017-11-30 01:40:08 +0000203 return S.str();
204}
Sam Clegg93102972018-02-23 05:08:53 +0000205
Heejin Ahne915a712018-12-08 06:17:43 +0000206std::string lld::toString(const WasmGlobalType &Type) {
207 return (Type.Mutable ? "var " : "const ") +
208 toString(static_cast<ValType>(Type.Type));
209}
210
211std::string lld::toString(const WasmEventType &Type) {
212 if (Type.Attribute == WASM_EVENT_ATTRIBUTE_EXCEPTION)
213 return "exception";
214 return "unknown";
Sam Clegg93102972018-02-23 05:08:53 +0000215}