blob: a92da743d9662f7397fe5c20495509f01a309ee5 [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;
20using namespace lld::wasm;
21
Derek Schuff371842b2018-10-03 22:25:32 +000022static const char *valueTypeToString(ValType Type) {
Sam Cleggc94d3932017-11-17 18:14:09 +000023 switch (Type) {
Derek Schuff371842b2018-10-03 22:25:32 +000024 case wasm::ValType::I32:
Sam Cleggc94d3932017-11-17 18:14:09 +000025 return "i32";
Derek Schuff371842b2018-10-03 22:25:32 +000026 case wasm::ValType::I64:
Sam Cleggc94d3932017-11-17 18:14:09 +000027 return "i64";
Derek Schuff371842b2018-10-03 22:25:32 +000028 case wasm::ValType::F32:
Sam Cleggc94d3932017-11-17 18:14:09 +000029 return "f32";
Derek Schuff371842b2018-10-03 22:25:32 +000030 case wasm::ValType::F64:
Sam Cleggc94d3932017-11-17 18:14:09 +000031 return "f64";
32 default:
33 llvm_unreachable("invalid value type");
34 }
35}
36
37namespace lld {
38
Rui Ueyama11842532018-02-16 20:38:00 +000039void wasm::debugWrite(uint64_t Offset, const Twine &Msg) {
Nicola Zaghene7245b42018-05-15 13:36:20 +000040 LLVM_DEBUG(dbgs() << format(" | %08lld: ", Offset) << Msg << "\n");
Sam Cleggc94d3932017-11-17 18:14:09 +000041}
42
Sam Cleggea397f62018-03-01 00:42:57 +000043void wasm::writeUleb128(raw_ostream &OS, uint32_t Number, const Twine &Msg) {
Rui Ueyama11842532018-02-16 20:38:00 +000044 debugWrite(OS.tell(), Msg + "[" + utohexstr(Number) + "]");
Sam Cleggc94d3932017-11-17 18:14:09 +000045 encodeULEB128(Number, OS);
46}
47
Sam Cleggea397f62018-03-01 00:42:57 +000048void wasm::writeSleb128(raw_ostream &OS, int32_t Number, const Twine &Msg) {
Rui Ueyama11842532018-02-16 20:38:00 +000049 debugWrite(OS.tell(), Msg + "[" + utohexstr(Number) + "]");
Sam Cleggc94d3932017-11-17 18:14:09 +000050 encodeSLEB128(Number, OS);
51}
52
Rui Ueyama7b9ed652018-02-16 19:53:29 +000053void wasm::writeBytes(raw_ostream &OS, const char *Bytes, size_t Count,
Sam Cleggea397f62018-03-01 00:42:57 +000054 const Twine &Msg) {
Rui Ueyama11842532018-02-16 20:38:00 +000055 debugWrite(OS.tell(), Msg + " [data[" + Twine(Count) + "]]");
Rui Ueyama7b9ed652018-02-16 19:53:29 +000056 OS.write(Bytes, Count);
Sam Cleggc94d3932017-11-17 18:14:09 +000057}
58
Sam Cleggea397f62018-03-01 00:42:57 +000059void wasm::writeStr(raw_ostream &OS, StringRef String, const Twine &Msg) {
Rui Ueyama11842532018-02-16 20:38:00 +000060 debugWrite(OS.tell(),
61 Msg + " [str[" + Twine(String.size()) + "]: " + String + "]");
62 encodeULEB128(String.size(), OS);
63 OS.write(String.data(), String.size());
Sam Cleggc94d3932017-11-17 18:14:09 +000064}
65
Sam Cleggea397f62018-03-01 00:42:57 +000066void wasm::writeU8(raw_ostream &OS, uint8_t Byte, const Twine &Msg) {
67 debugWrite(OS.tell(), Msg + " [0x" + utohexstr(Byte) + "]");
68 OS << Byte;
69}
Sam Cleggc94d3932017-11-17 18:14:09 +000070
Sam Cleggea397f62018-03-01 00:42:57 +000071void wasm::writeU32(raw_ostream &OS, uint32_t Number, const Twine &Msg) {
72 debugWrite(OS.tell(), Msg + "[0x" + utohexstr(Number) + "]");
Peter Collingbournee3f65292018-05-18 19:46:24 +000073 support::endian::write(OS, Number, support::little);
Sam Cleggc94d3932017-11-17 18:14:09 +000074}
75
Derek Schuff371842b2018-10-03 22:25:32 +000076void wasm::writeValueType(raw_ostream &OS, ValType Type, const Twine &Msg) {
77 writeU8(OS, static_cast<uint8_t>(Type),
78 Msg + "[type: " + valueTypeToString(Type) + "]");
Sam Cleggc94d3932017-11-17 18:14:09 +000079}
80
81void wasm::writeSig(raw_ostream &OS, const WasmSignature &Sig) {
Sam Clegg8518e7d2018-03-01 18:06:39 +000082 writeU8(OS, WASM_TYPE_FUNC, "signature type");
Derek Schuff371842b2018-10-03 22:25:32 +000083 writeUleb128(OS, Sig.Params.size(), "param Count");
84 for (ValType ParamType : Sig.Params) {
Sam Cleggc94d3932017-11-17 18:14:09 +000085 writeValueType(OS, ParamType, "param type");
86 }
Derek Schuff371842b2018-10-03 22:25:32 +000087 writeUleb128(OS, Sig.Returns.size(), "result Count");
88 if (Sig.Returns.size()) {
89 writeValueType(OS, Sig.Returns[0], "result type");
Sam Cleggc94d3932017-11-17 18:14:09 +000090 }
91}
92
93void wasm::writeInitExpr(raw_ostream &OS, const WasmInitExpr &InitExpr) {
94 writeU8(OS, InitExpr.Opcode, "opcode");
95 switch (InitExpr.Opcode) {
96 case WASM_OPCODE_I32_CONST:
97 writeSleb128(OS, InitExpr.Value.Int32, "literal (i32)");
98 break;
99 case WASM_OPCODE_I64_CONST:
100 writeSleb128(OS, InitExpr.Value.Int64, "literal (i64)");
101 break;
102 case WASM_OPCODE_GET_GLOBAL:
103 writeUleb128(OS, InitExpr.Value.Global, "literal (global index)");
104 break;
105 default:
106 fatal("unknown opcode in init expr: " + Twine(InitExpr.Opcode));
Sam Cleggc94d3932017-11-17 18:14:09 +0000107 }
108 writeU8(OS, WASM_OPCODE_END, "opcode:end");
109}
110
111void wasm::writeLimits(raw_ostream &OS, const WasmLimits &Limits) {
Sam Clegg8518e7d2018-03-01 18:06:39 +0000112 writeU8(OS, Limits.Flags, "limits flags");
Sam Cleggc94d3932017-11-17 18:14:09 +0000113 writeUleb128(OS, Limits.Initial, "limits initial");
114 if (Limits.Flags & WASM_LIMITS_FLAG_HAS_MAX)
115 writeUleb128(OS, Limits.Maximum, "limits max");
116}
117
Sam Clegg1a9b7b92018-01-31 19:54:34 +0000118void wasm::writeGlobalType(raw_ostream &OS, const WasmGlobalType &Type) {
Derek Schuff371842b2018-10-03 22:25:32 +0000119 // TODO: Update WasmGlobalType to use ValType and remove this cast.
120 writeValueType(OS, ValType(Type.Type), "global type");
Sam Clegg8518e7d2018-03-01 18:06:39 +0000121 writeU8(OS, Type.Mutable, "global mutable");
Sam Clegg1a9b7b92018-01-31 19:54:34 +0000122}
123
Sam Cleggc94d3932017-11-17 18:14:09 +0000124void wasm::writeGlobal(raw_ostream &OS, const WasmGlobal &Global) {
Sam Clegg1a9b7b92018-01-31 19:54:34 +0000125 writeGlobalType(OS, Global.Type);
Sam Cleggc94d3932017-11-17 18:14:09 +0000126 writeInitExpr(OS, Global.InitExpr);
127}
128
Nicholas Wilson874eedd2018-03-27 17:38:51 +0000129void wasm::writeTableType(raw_ostream &OS, const llvm::wasm::WasmTable &Type) {
130 writeU8(OS, WASM_TYPE_ANYFUNC, "table type");
131 writeLimits(OS, Type.Limits);
132}
133
Sam Cleggc94d3932017-11-17 18:14:09 +0000134void wasm::writeImport(raw_ostream &OS, const WasmImport &Import) {
135 writeStr(OS, Import.Module, "import module name");
136 writeStr(OS, Import.Field, "import field name");
137 writeU8(OS, Import.Kind, "import kind");
138 switch (Import.Kind) {
139 case WASM_EXTERNAL_FUNCTION:
140 writeUleb128(OS, Import.SigIndex, "import sig index");
141 break;
142 case WASM_EXTERNAL_GLOBAL:
Sam Clegg1a9b7b92018-01-31 19:54:34 +0000143 writeGlobalType(OS, Import.Global);
Sam Cleggc94d3932017-11-17 18:14:09 +0000144 break;
145 case WASM_EXTERNAL_MEMORY:
146 writeLimits(OS, Import.Memory);
147 break;
Nicholas Wilson874eedd2018-03-27 17:38:51 +0000148 case WASM_EXTERNAL_TABLE:
149 writeTableType(OS, Import.Table);
150 break;
Sam Cleggc94d3932017-11-17 18:14:09 +0000151 default:
152 fatal("unsupported import type: " + Twine(Import.Kind));
Sam Cleggc94d3932017-11-17 18:14:09 +0000153 }
154}
155
156void wasm::writeExport(raw_ostream &OS, const WasmExport &Export) {
157 writeStr(OS, Export.Name, "export name");
158 writeU8(OS, Export.Kind, "export kind");
159 switch (Export.Kind) {
160 case WASM_EXTERNAL_FUNCTION:
161 writeUleb128(OS, Export.Index, "function index");
162 break;
163 case WASM_EXTERNAL_GLOBAL:
164 writeUleb128(OS, Export.Index, "global index");
165 break;
166 case WASM_EXTERNAL_MEMORY:
167 writeUleb128(OS, Export.Index, "memory index");
168 break;
Nicholas Wilson874eedd2018-03-27 17:38:51 +0000169 case WASM_EXTERNAL_TABLE:
170 writeUleb128(OS, Export.Index, "table index");
171 break;
Sam Cleggc94d3932017-11-17 18:14:09 +0000172 default:
173 fatal("unsupported export type: " + Twine(Export.Kind));
Sam Cleggc94d3932017-11-17 18:14:09 +0000174 }
175}
Sam Cleggc94d3932017-11-17 18:14:09 +0000176} // namespace lld
Sam Cleggb8621592017-11-30 01:40:08 +0000177
178std::string lld::toString(ValType Type) {
179 switch (Type) {
180 case ValType::I32:
181 return "I32";
182 case ValType::I64:
183 return "I64";
184 case ValType::F32:
185 return "F32";
186 case ValType::F64:
187 return "F64";
Thomas Livelyd661e262018-09-20 22:07:18 +0000188 case ValType::V128:
189 return "V128";
Heejin Ahn2dce27d2018-03-08 04:06:57 +0000190 case ValType::EXCEPT_REF:
191 return "except_ref";
Sam Cleggb8621592017-11-30 01:40:08 +0000192 }
193 llvm_unreachable("Invalid wasm::ValType");
194}
195
196std::string lld::toString(const WasmSignature &Sig) {
197 SmallString<128> S("(");
Derek Schuff371842b2018-10-03 22:25:32 +0000198 for (ValType Type : Sig.Params) {
Sam Cleggb8621592017-11-30 01:40:08 +0000199 if (S.size() != 1)
200 S += ", ";
Derek Schuff371842b2018-10-03 22:25:32 +0000201 S += toString(Type);
Sam Cleggb8621592017-11-30 01:40:08 +0000202 }
203 S += ") -> ";
Derek Schuff371842b2018-10-03 22:25:32 +0000204 if (Sig.Returns.size() == 0)
Sam Cleggb8621592017-11-30 01:40:08 +0000205 S += "void";
206 else
Derek Schuff371842b2018-10-03 22:25:32 +0000207 S += toString(Sig.Returns[0]);
Sam Cleggb8621592017-11-30 01:40:08 +0000208 return S.str();
209}
Sam Clegg93102972018-02-23 05:08:53 +0000210
211std::string lld::toString(const WasmGlobalType &Sig) {
Nicholas Wilson36f14f42018-03-02 14:54:34 +0000212 return (Sig.Mutable ? "var " : "const ") +
Nicholas Wilsondbd90bf2018-03-07 13:28:16 +0000213 toString(static_cast<ValType>(Sig.Type));
Sam Clegg93102972018-02-23 05:08:53 +0000214}