blob: 6de48d91b85b8bf0a730450a83adcfa5fa92f4b7 [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
Sam Cleggc94d3932017-11-17 18:14:09 +000022namespace lld {
23
Rui Ueyama11842532018-02-16 20:38:00 +000024void wasm::debugWrite(uint64_t Offset, const Twine &Msg) {
Nicola Zaghene7245b42018-05-15 13:36:20 +000025 LLVM_DEBUG(dbgs() << format(" | %08lld: ", Offset) << Msg << "\n");
Sam Cleggc94d3932017-11-17 18:14:09 +000026}
27
Sam Cleggea397f62018-03-01 00:42:57 +000028void wasm::writeUleb128(raw_ostream &OS, uint32_t Number, const Twine &Msg) {
Rui Ueyama11842532018-02-16 20:38:00 +000029 debugWrite(OS.tell(), Msg + "[" + utohexstr(Number) + "]");
Sam Cleggc94d3932017-11-17 18:14:09 +000030 encodeULEB128(Number, OS);
31}
32
Sam Cleggea397f62018-03-01 00:42:57 +000033void wasm::writeSleb128(raw_ostream &OS, int32_t Number, const Twine &Msg) {
Rui Ueyama11842532018-02-16 20:38:00 +000034 debugWrite(OS.tell(), Msg + "[" + utohexstr(Number) + "]");
Sam Cleggc94d3932017-11-17 18:14:09 +000035 encodeSLEB128(Number, OS);
36}
37
Rui Ueyama7b9ed652018-02-16 19:53:29 +000038void wasm::writeBytes(raw_ostream &OS, const char *Bytes, size_t Count,
Sam Cleggea397f62018-03-01 00:42:57 +000039 const Twine &Msg) {
Rui Ueyama11842532018-02-16 20:38:00 +000040 debugWrite(OS.tell(), Msg + " [data[" + Twine(Count) + "]]");
Rui Ueyama7b9ed652018-02-16 19:53:29 +000041 OS.write(Bytes, Count);
Sam Cleggc94d3932017-11-17 18:14:09 +000042}
43
Sam Cleggea397f62018-03-01 00:42:57 +000044void wasm::writeStr(raw_ostream &OS, StringRef String, const Twine &Msg) {
Rui Ueyama11842532018-02-16 20:38:00 +000045 debugWrite(OS.tell(),
46 Msg + " [str[" + Twine(String.size()) + "]: " + String + "]");
47 encodeULEB128(String.size(), OS);
48 OS.write(String.data(), String.size());
Sam Cleggc94d3932017-11-17 18:14:09 +000049}
50
Sam Cleggea397f62018-03-01 00:42:57 +000051void wasm::writeU8(raw_ostream &OS, uint8_t Byte, const Twine &Msg) {
52 debugWrite(OS.tell(), Msg + " [0x" + utohexstr(Byte) + "]");
53 OS << Byte;
54}
Sam Cleggc94d3932017-11-17 18:14:09 +000055
Sam Cleggea397f62018-03-01 00:42:57 +000056void wasm::writeU32(raw_ostream &OS, uint32_t Number, const Twine &Msg) {
57 debugWrite(OS.tell(), Msg + "[0x" + utohexstr(Number) + "]");
Peter Collingbournee3f65292018-05-18 19:46:24 +000058 support::endian::write(OS, Number, support::little);
Sam Cleggc94d3932017-11-17 18:14:09 +000059}
60
Derek Schuff371842b2018-10-03 22:25:32 +000061void wasm::writeValueType(raw_ostream &OS, ValType Type, const Twine &Msg) {
62 writeU8(OS, static_cast<uint8_t>(Type),
Sam Cleggc1a3b9d2018-11-01 01:08:37 +000063 Msg + "[type: " + toString(Type) + "]");
Sam Cleggc94d3932017-11-17 18:14:09 +000064}
65
66void wasm::writeSig(raw_ostream &OS, const WasmSignature &Sig) {
Sam Clegg8518e7d2018-03-01 18:06:39 +000067 writeU8(OS, WASM_TYPE_FUNC, "signature type");
Derek Schuff371842b2018-10-03 22:25:32 +000068 writeUleb128(OS, Sig.Params.size(), "param Count");
69 for (ValType ParamType : Sig.Params) {
Sam Cleggc94d3932017-11-17 18:14:09 +000070 writeValueType(OS, ParamType, "param type");
71 }
Derek Schuff371842b2018-10-03 22:25:32 +000072 writeUleb128(OS, Sig.Returns.size(), "result Count");
73 if (Sig.Returns.size()) {
74 writeValueType(OS, Sig.Returns[0], "result type");
Sam Cleggc94d3932017-11-17 18:14:09 +000075 }
76}
77
78void wasm::writeInitExpr(raw_ostream &OS, const WasmInitExpr &InitExpr) {
79 writeU8(OS, InitExpr.Opcode, "opcode");
80 switch (InitExpr.Opcode) {
81 case WASM_OPCODE_I32_CONST:
82 writeSleb128(OS, InitExpr.Value.Int32, "literal (i32)");
83 break;
84 case WASM_OPCODE_I64_CONST:
85 writeSleb128(OS, InitExpr.Value.Int64, "literal (i64)");
86 break;
87 case WASM_OPCODE_GET_GLOBAL:
88 writeUleb128(OS, InitExpr.Value.Global, "literal (global index)");
89 break;
90 default:
91 fatal("unknown opcode in init expr: " + Twine(InitExpr.Opcode));
Sam Cleggc94d3932017-11-17 18:14:09 +000092 }
93 writeU8(OS, WASM_OPCODE_END, "opcode:end");
94}
95
96void wasm::writeLimits(raw_ostream &OS, const WasmLimits &Limits) {
Sam Clegg8518e7d2018-03-01 18:06:39 +000097 writeU8(OS, Limits.Flags, "limits flags");
Sam Cleggc94d3932017-11-17 18:14:09 +000098 writeUleb128(OS, Limits.Initial, "limits initial");
99 if (Limits.Flags & WASM_LIMITS_FLAG_HAS_MAX)
100 writeUleb128(OS, Limits.Maximum, "limits max");
101}
102
Sam Clegg1a9b7b92018-01-31 19:54:34 +0000103void wasm::writeGlobalType(raw_ostream &OS, const WasmGlobalType &Type) {
Derek Schuff371842b2018-10-03 22:25:32 +0000104 // TODO: Update WasmGlobalType to use ValType and remove this cast.
105 writeValueType(OS, ValType(Type.Type), "global type");
Sam Clegg8518e7d2018-03-01 18:06:39 +0000106 writeU8(OS, Type.Mutable, "global mutable");
Sam Clegg1a9b7b92018-01-31 19:54:34 +0000107}
108
Sam Cleggc94d3932017-11-17 18:14:09 +0000109void wasm::writeGlobal(raw_ostream &OS, const WasmGlobal &Global) {
Sam Clegg1a9b7b92018-01-31 19:54:34 +0000110 writeGlobalType(OS, Global.Type);
Sam Cleggc94d3932017-11-17 18:14:09 +0000111 writeInitExpr(OS, Global.InitExpr);
112}
113
Nicholas Wilson874eedd2018-03-27 17:38:51 +0000114void wasm::writeTableType(raw_ostream &OS, const llvm::wasm::WasmTable &Type) {
115 writeU8(OS, WASM_TYPE_ANYFUNC, "table type");
116 writeLimits(OS, Type.Limits);
117}
118
Sam Cleggc94d3932017-11-17 18:14:09 +0000119void wasm::writeImport(raw_ostream &OS, const WasmImport &Import) {
120 writeStr(OS, Import.Module, "import module name");
121 writeStr(OS, Import.Field, "import field name");
122 writeU8(OS, Import.Kind, "import kind");
123 switch (Import.Kind) {
124 case WASM_EXTERNAL_FUNCTION:
125 writeUleb128(OS, Import.SigIndex, "import sig index");
126 break;
127 case WASM_EXTERNAL_GLOBAL:
Sam Clegg1a9b7b92018-01-31 19:54:34 +0000128 writeGlobalType(OS, Import.Global);
Sam Cleggc94d3932017-11-17 18:14:09 +0000129 break;
130 case WASM_EXTERNAL_MEMORY:
131 writeLimits(OS, Import.Memory);
132 break;
Nicholas Wilson874eedd2018-03-27 17:38:51 +0000133 case WASM_EXTERNAL_TABLE:
134 writeTableType(OS, Import.Table);
135 break;
Sam Cleggc94d3932017-11-17 18:14:09 +0000136 default:
137 fatal("unsupported import type: " + Twine(Import.Kind));
Sam Cleggc94d3932017-11-17 18:14:09 +0000138 }
139}
140
141void wasm::writeExport(raw_ostream &OS, const WasmExport &Export) {
142 writeStr(OS, Export.Name, "export name");
143 writeU8(OS, Export.Kind, "export kind");
144 switch (Export.Kind) {
145 case WASM_EXTERNAL_FUNCTION:
146 writeUleb128(OS, Export.Index, "function index");
147 break;
148 case WASM_EXTERNAL_GLOBAL:
149 writeUleb128(OS, Export.Index, "global index");
150 break;
151 case WASM_EXTERNAL_MEMORY:
152 writeUleb128(OS, Export.Index, "memory index");
153 break;
Nicholas Wilson874eedd2018-03-27 17:38:51 +0000154 case WASM_EXTERNAL_TABLE:
155 writeUleb128(OS, Export.Index, "table index");
156 break;
Sam Cleggc94d3932017-11-17 18:14:09 +0000157 default:
158 fatal("unsupported export type: " + Twine(Export.Kind));
Sam Cleggc94d3932017-11-17 18:14:09 +0000159 }
160}
Sam Cleggc94d3932017-11-17 18:14:09 +0000161} // namespace lld
Sam Cleggb8621592017-11-30 01:40:08 +0000162
163std::string lld::toString(ValType Type) {
164 switch (Type) {
165 case ValType::I32:
Sam Cleggc1a3b9d2018-11-01 01:08:37 +0000166 return "i32";
Sam Cleggb8621592017-11-30 01:40:08 +0000167 case ValType::I64:
Sam Cleggc1a3b9d2018-11-01 01:08:37 +0000168 return "i64";
Sam Cleggb8621592017-11-30 01:40:08 +0000169 case ValType::F32:
Sam Cleggc1a3b9d2018-11-01 01:08:37 +0000170 return "f32";
Sam Cleggb8621592017-11-30 01:40:08 +0000171 case ValType::F64:
Sam Cleggc1a3b9d2018-11-01 01:08:37 +0000172 return "f64";
Thomas Livelyd661e262018-09-20 22:07:18 +0000173 case ValType::V128:
Sam Cleggc1a3b9d2018-11-01 01:08:37 +0000174 return "v128";
Heejin Ahn2dce27d2018-03-08 04:06:57 +0000175 case ValType::EXCEPT_REF:
176 return "except_ref";
Sam Cleggb8621592017-11-30 01:40:08 +0000177 }
178 llvm_unreachable("Invalid wasm::ValType");
179}
180
181std::string lld::toString(const WasmSignature &Sig) {
182 SmallString<128> S("(");
Derek Schuff371842b2018-10-03 22:25:32 +0000183 for (ValType Type : Sig.Params) {
Sam Cleggb8621592017-11-30 01:40:08 +0000184 if (S.size() != 1)
185 S += ", ";
Derek Schuff371842b2018-10-03 22:25:32 +0000186 S += toString(Type);
Sam Cleggb8621592017-11-30 01:40:08 +0000187 }
188 S += ") -> ";
Derek Schuff371842b2018-10-03 22:25:32 +0000189 if (Sig.Returns.size() == 0)
Sam Cleggb8621592017-11-30 01:40:08 +0000190 S += "void";
191 else
Derek Schuff371842b2018-10-03 22:25:32 +0000192 S += toString(Sig.Returns[0]);
Sam Cleggb8621592017-11-30 01:40:08 +0000193 return S.str();
194}
Sam Clegg93102972018-02-23 05:08:53 +0000195
196std::string lld::toString(const WasmGlobalType &Sig) {
Nicholas Wilson36f14f42018-03-02 14:54:34 +0000197 return (Sig.Mutable ? "var " : "const ") +
Nicholas Wilsondbd90bf2018-03-07 13:28:16 +0000198 toString(static_cast<ValType>(Sig.Type));
Sam Clegg93102972018-02-23 05:08:53 +0000199}