blob: 80bfc091612199db85cf93aa6555c27cd17d809e [file] [log] [blame]
Sam Cleggc94d3932017-11-17 18:14:09 +00001//===- WriterUtils.cpp ----------------------------------------------------===//
2//
3// The LLVM Linker
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "WriterUtils.h"
Sam Cleggc94d3932017-11-17 18:14:09 +000011#include "lld/Common/ErrorHandler.h"
Sam Cleggc94d3932017-11-17 18:14:09 +000012#include "llvm/Support/Debug.h"
13#include "llvm/Support/EndianStream.h"
Sam Cleggc94d3932017-11-17 18:14:09 +000014#include "llvm/Support/LEB128.h"
15
16#define DEBUG_TYPE "lld"
17
18using namespace llvm;
19using namespace llvm::wasm;
Sam Cleggc94d3932017-11-17 18:14:09 +000020
Sam Cleggc94d3932017-11-17 18:14:09 +000021namespace lld {
22
Rui Ueyama11842532018-02-16 20:38:00 +000023void wasm::debugWrite(uint64_t Offset, const Twine &Msg) {
Nicola Zaghene7245b42018-05-15 13:36:20 +000024 LLVM_DEBUG(dbgs() << format(" | %08lld: ", Offset) << Msg << "\n");
Sam Cleggc94d3932017-11-17 18:14:09 +000025}
26
Sam Cleggea397f62018-03-01 00:42:57 +000027void wasm::writeUleb128(raw_ostream &OS, uint32_t Number, const Twine &Msg) {
Rui Ueyama11842532018-02-16 20:38:00 +000028 debugWrite(OS.tell(), Msg + "[" + utohexstr(Number) + "]");
Sam Cleggc94d3932017-11-17 18:14:09 +000029 encodeULEB128(Number, OS);
30}
31
Sam Cleggea397f62018-03-01 00:42:57 +000032void wasm::writeSleb128(raw_ostream &OS, int32_t Number, const Twine &Msg) {
Rui Ueyama11842532018-02-16 20:38:00 +000033 debugWrite(OS.tell(), Msg + "[" + utohexstr(Number) + "]");
Sam Cleggc94d3932017-11-17 18:14:09 +000034 encodeSLEB128(Number, OS);
35}
36
Rui Ueyama7b9ed652018-02-16 19:53:29 +000037void wasm::writeBytes(raw_ostream &OS, const char *Bytes, size_t Count,
Sam Cleggea397f62018-03-01 00:42:57 +000038 const Twine &Msg) {
Rui Ueyama11842532018-02-16 20:38:00 +000039 debugWrite(OS.tell(), Msg + " [data[" + Twine(Count) + "]]");
Rui Ueyama7b9ed652018-02-16 19:53:29 +000040 OS.write(Bytes, Count);
Sam Cleggc94d3932017-11-17 18:14:09 +000041}
42
Sam Cleggea397f62018-03-01 00:42:57 +000043void wasm::writeStr(raw_ostream &OS, StringRef String, const Twine &Msg) {
Rui Ueyama11842532018-02-16 20:38:00 +000044 debugWrite(OS.tell(),
45 Msg + " [str[" + Twine(String.size()) + "]: " + String + "]");
46 encodeULEB128(String.size(), OS);
47 OS.write(String.data(), String.size());
Sam Cleggc94d3932017-11-17 18:14:09 +000048}
49
Sam Cleggea397f62018-03-01 00:42:57 +000050void wasm::writeU8(raw_ostream &OS, uint8_t Byte, const Twine &Msg) {
51 debugWrite(OS.tell(), Msg + " [0x" + utohexstr(Byte) + "]");
52 OS << Byte;
53}
Sam Cleggc94d3932017-11-17 18:14:09 +000054
Sam Cleggea397f62018-03-01 00:42:57 +000055void wasm::writeU32(raw_ostream &OS, uint32_t Number, const Twine &Msg) {
56 debugWrite(OS.tell(), Msg + "[0x" + utohexstr(Number) + "]");
Peter Collingbournee3f65292018-05-18 19:46:24 +000057 support::endian::write(OS, Number, support::little);
Sam Cleggc94d3932017-11-17 18:14:09 +000058}
59
Derek Schuff371842b2018-10-03 22:25:32 +000060void wasm::writeValueType(raw_ostream &OS, ValType Type, const Twine &Msg) {
61 writeU8(OS, static_cast<uint8_t>(Type),
Sam Cleggc1a3b9d2018-11-01 01:08:37 +000062 Msg + "[type: " + toString(Type) + "]");
Sam Cleggc94d3932017-11-17 18:14:09 +000063}
64
65void wasm::writeSig(raw_ostream &OS, const WasmSignature &Sig) {
Sam Clegg8518e7d2018-03-01 18:06:39 +000066 writeU8(OS, WASM_TYPE_FUNC, "signature type");
Derek Schuff371842b2018-10-03 22:25:32 +000067 writeUleb128(OS, Sig.Params.size(), "param Count");
68 for (ValType ParamType : Sig.Params) {
Sam Cleggc94d3932017-11-17 18:14:09 +000069 writeValueType(OS, ParamType, "param type");
70 }
Derek Schuff371842b2018-10-03 22:25:32 +000071 writeUleb128(OS, Sig.Returns.size(), "result Count");
72 if (Sig.Returns.size()) {
73 writeValueType(OS, Sig.Returns[0], "result type");
Sam Cleggc94d3932017-11-17 18:14:09 +000074 }
75}
76
77void wasm::writeInitExpr(raw_ostream &OS, const WasmInitExpr &InitExpr) {
78 writeU8(OS, InitExpr.Opcode, "opcode");
79 switch (InitExpr.Opcode) {
80 case WASM_OPCODE_I32_CONST:
81 writeSleb128(OS, InitExpr.Value.Int32, "literal (i32)");
82 break;
83 case WASM_OPCODE_I64_CONST:
84 writeSleb128(OS, InitExpr.Value.Int64, "literal (i64)");
85 break;
Thomas Lively25ff8932019-01-08 06:25:55 +000086 case WASM_OPCODE_GLOBAL_GET:
Sam Cleggc94d3932017-11-17 18:14:09 +000087 writeUleb128(OS, InitExpr.Value.Global, "literal (global index)");
88 break;
89 default:
90 fatal("unknown opcode in init expr: " + Twine(InitExpr.Opcode));
Sam Cleggc94d3932017-11-17 18:14:09 +000091 }
92 writeU8(OS, WASM_OPCODE_END, "opcode:end");
93}
94
95void wasm::writeLimits(raw_ostream &OS, const WasmLimits &Limits) {
Sam Clegg8518e7d2018-03-01 18:06:39 +000096 writeU8(OS, Limits.Flags, "limits flags");
Sam Cleggc94d3932017-11-17 18:14:09 +000097 writeUleb128(OS, Limits.Initial, "limits initial");
98 if (Limits.Flags & WASM_LIMITS_FLAG_HAS_MAX)
99 writeUleb128(OS, Limits.Maximum, "limits max");
100}
101
Sam Clegg1a9b7b92018-01-31 19:54:34 +0000102void wasm::writeGlobalType(raw_ostream &OS, const WasmGlobalType &Type) {
Derek Schuff371842b2018-10-03 22:25:32 +0000103 // TODO: Update WasmGlobalType to use ValType and remove this cast.
104 writeValueType(OS, ValType(Type.Type), "global type");
Sam Clegg8518e7d2018-03-01 18:06:39 +0000105 writeU8(OS, Type.Mutable, "global mutable");
Sam Clegg1a9b7b92018-01-31 19:54:34 +0000106}
107
Sam Cleggc94d3932017-11-17 18:14:09 +0000108void wasm::writeGlobal(raw_ostream &OS, const WasmGlobal &Global) {
Sam Clegg1a9b7b92018-01-31 19:54:34 +0000109 writeGlobalType(OS, Global.Type);
Sam Cleggc94d3932017-11-17 18:14:09 +0000110 writeInitExpr(OS, Global.InitExpr);
111}
112
Heejin Ahne915a712018-12-08 06:17:43 +0000113void wasm::writeEventType(raw_ostream &OS, const WasmEventType &Type) {
114 writeUleb128(OS, Type.Attribute, "event attribute");
115 writeUleb128(OS, Type.SigIndex, "sig index");
116}
117
118void wasm::writeEvent(raw_ostream &OS, const WasmEvent &Event) {
119 writeEventType(OS, Event.Type);
120}
121
Nicholas Wilson874eedd2018-03-27 17:38:51 +0000122void wasm::writeTableType(raw_ostream &OS, const llvm::wasm::WasmTable &Type) {
Thomas Lively25ff8932019-01-08 06:25:55 +0000123 writeU8(OS, WASM_TYPE_FUNCREF, "table type");
Nicholas Wilson874eedd2018-03-27 17:38:51 +0000124 writeLimits(OS, Type.Limits);
125}
126
Sam Cleggc94d3932017-11-17 18:14:09 +0000127void wasm::writeImport(raw_ostream &OS, const WasmImport &Import) {
128 writeStr(OS, Import.Module, "import module name");
129 writeStr(OS, Import.Field, "import field name");
130 writeU8(OS, Import.Kind, "import kind");
131 switch (Import.Kind) {
132 case WASM_EXTERNAL_FUNCTION:
133 writeUleb128(OS, Import.SigIndex, "import sig index");
134 break;
135 case WASM_EXTERNAL_GLOBAL:
Sam Clegg1a9b7b92018-01-31 19:54:34 +0000136 writeGlobalType(OS, Import.Global);
Sam Cleggc94d3932017-11-17 18:14:09 +0000137 break;
Heejin Ahne915a712018-12-08 06:17:43 +0000138 case WASM_EXTERNAL_EVENT:
139 writeEventType(OS, Import.Event);
140 break;
Sam Cleggc94d3932017-11-17 18:14:09 +0000141 case WASM_EXTERNAL_MEMORY:
142 writeLimits(OS, Import.Memory);
143 break;
Nicholas Wilson874eedd2018-03-27 17:38:51 +0000144 case WASM_EXTERNAL_TABLE:
145 writeTableType(OS, Import.Table);
146 break;
Sam Cleggc94d3932017-11-17 18:14:09 +0000147 default:
148 fatal("unsupported import type: " + Twine(Import.Kind));
Sam Cleggc94d3932017-11-17 18:14:09 +0000149 }
150}
151
152void wasm::writeExport(raw_ostream &OS, const WasmExport &Export) {
153 writeStr(OS, Export.Name, "export name");
154 writeU8(OS, Export.Kind, "export kind");
155 switch (Export.Kind) {
156 case WASM_EXTERNAL_FUNCTION:
157 writeUleb128(OS, Export.Index, "function index");
158 break;
159 case WASM_EXTERNAL_GLOBAL:
160 writeUleb128(OS, Export.Index, "global index");
161 break;
162 case WASM_EXTERNAL_MEMORY:
163 writeUleb128(OS, Export.Index, "memory index");
164 break;
Nicholas Wilson874eedd2018-03-27 17:38:51 +0000165 case WASM_EXTERNAL_TABLE:
166 writeUleb128(OS, Export.Index, "table index");
167 break;
Sam Cleggc94d3932017-11-17 18:14:09 +0000168 default:
169 fatal("unsupported export type: " + Twine(Export.Kind));
Sam Cleggc94d3932017-11-17 18:14:09 +0000170 }
171}
Sam Cleggc94d3932017-11-17 18:14:09 +0000172} // namespace lld
Sam Cleggb8621592017-11-30 01:40:08 +0000173
174std::string lld::toString(ValType Type) {
175 switch (Type) {
176 case ValType::I32:
Sam Cleggc1a3b9d2018-11-01 01:08:37 +0000177 return "i32";
Sam Cleggb8621592017-11-30 01:40:08 +0000178 case ValType::I64:
Sam Cleggc1a3b9d2018-11-01 01:08:37 +0000179 return "i64";
Sam Cleggb8621592017-11-30 01:40:08 +0000180 case ValType::F32:
Sam Cleggc1a3b9d2018-11-01 01:08:37 +0000181 return "f32";
Sam Cleggb8621592017-11-30 01:40:08 +0000182 case ValType::F64:
Sam Cleggc1a3b9d2018-11-01 01:08:37 +0000183 return "f64";
Thomas Livelyd661e262018-09-20 22:07:18 +0000184 case ValType::V128:
Sam Cleggc1a3b9d2018-11-01 01:08:37 +0000185 return "v128";
Heejin Ahn2dce27d2018-03-08 04:06:57 +0000186 case ValType::EXCEPT_REF:
187 return "except_ref";
Sam Cleggb8621592017-11-30 01:40:08 +0000188 }
189 llvm_unreachable("Invalid wasm::ValType");
190}
191
192std::string lld::toString(const WasmSignature &Sig) {
193 SmallString<128> S("(");
Derek Schuff371842b2018-10-03 22:25:32 +0000194 for (ValType Type : Sig.Params) {
Sam Cleggb8621592017-11-30 01:40:08 +0000195 if (S.size() != 1)
196 S += ", ";
Derek Schuff371842b2018-10-03 22:25:32 +0000197 S += toString(Type);
Sam Cleggb8621592017-11-30 01:40:08 +0000198 }
199 S += ") -> ";
Derek Schuff371842b2018-10-03 22:25:32 +0000200 if (Sig.Returns.size() == 0)
Sam Cleggb8621592017-11-30 01:40:08 +0000201 S += "void";
202 else
Derek Schuff371842b2018-10-03 22:25:32 +0000203 S += toString(Sig.Returns[0]);
Sam Cleggb8621592017-11-30 01:40:08 +0000204 return S.str();
205}
Sam Clegg93102972018-02-23 05:08:53 +0000206
Heejin Ahne915a712018-12-08 06:17:43 +0000207std::string lld::toString(const WasmGlobalType &Type) {
208 return (Type.Mutable ? "var " : "const ") +
209 toString(static_cast<ValType>(Type.Type));
210}
211
212std::string lld::toString(const WasmEventType &Type) {
213 if (Type.Attribute == WASM_EVENT_ATTRIBUTE_EXCEPTION)
214 return "exception";
215 return "unknown";
Sam Clegg93102972018-02-23 05:08:53 +0000216}