blob: ac3a19fc04dd0da6371216fcfbe66dab25a7f732 [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 Clegg8518e7d2018-03-01 18:06:39 +000022static const char *valueTypeToString(uint8_t Type) {
Sam Cleggc94d3932017-11-17 18:14:09 +000023 switch (Type) {
24 case WASM_TYPE_I32:
25 return "i32";
26 case WASM_TYPE_I64:
27 return "i64";
28 case WASM_TYPE_F32:
29 return "f32";
30 case WASM_TYPE_F64:
31 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) {
40 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) + "]");
Sam Cleggc94d3932017-11-17 18:14:09 +000073 support::endian::Writer<support::little>(OS).write(Number);
74}
75
Sam Clegg8518e7d2018-03-01 18:06:39 +000076void wasm::writeValueType(raw_ostream &OS, uint8_t Type, const Twine &Msg) {
77 writeU8(OS, Type, Msg + "[type: " + valueTypeToString(Type) + "]");
Sam Cleggc94d3932017-11-17 18:14:09 +000078}
79
80void wasm::writeSig(raw_ostream &OS, const WasmSignature &Sig) {
Sam Clegg8518e7d2018-03-01 18:06:39 +000081 writeU8(OS, WASM_TYPE_FUNC, "signature type");
Rui Ueyama7b9ed652018-02-16 19:53:29 +000082 writeUleb128(OS, Sig.ParamTypes.size(), "param Count");
Sam Clegg8518e7d2018-03-01 18:06:39 +000083 for (uint8_t ParamType : Sig.ParamTypes) {
Sam Cleggc94d3932017-11-17 18:14:09 +000084 writeValueType(OS, ParamType, "param type");
85 }
86 if (Sig.ReturnType == WASM_TYPE_NORESULT) {
Rui Ueyama7b9ed652018-02-16 19:53:29 +000087 writeUleb128(OS, 0, "result Count");
Sam Cleggc94d3932017-11-17 18:14:09 +000088 } else {
Rui Ueyama7b9ed652018-02-16 19:53:29 +000089 writeUleb128(OS, 1, "result Count");
Sam Cleggc94d3932017-11-17 18:14:09 +000090 writeValueType(OS, Sig.ReturnType, "result type");
91 }
92}
93
94void wasm::writeInitExpr(raw_ostream &OS, const WasmInitExpr &InitExpr) {
95 writeU8(OS, InitExpr.Opcode, "opcode");
96 switch (InitExpr.Opcode) {
97 case WASM_OPCODE_I32_CONST:
98 writeSleb128(OS, InitExpr.Value.Int32, "literal (i32)");
99 break;
100 case WASM_OPCODE_I64_CONST:
101 writeSleb128(OS, InitExpr.Value.Int64, "literal (i64)");
102 break;
103 case WASM_OPCODE_GET_GLOBAL:
104 writeUleb128(OS, InitExpr.Value.Global, "literal (global index)");
105 break;
106 default:
107 fatal("unknown opcode in init expr: " + Twine(InitExpr.Opcode));
Sam Cleggc94d3932017-11-17 18:14:09 +0000108 }
109 writeU8(OS, WASM_OPCODE_END, "opcode:end");
110}
111
112void wasm::writeLimits(raw_ostream &OS, const WasmLimits &Limits) {
Sam Clegg8518e7d2018-03-01 18:06:39 +0000113 writeU8(OS, Limits.Flags, "limits flags");
Sam Cleggc94d3932017-11-17 18:14:09 +0000114 writeUleb128(OS, Limits.Initial, "limits initial");
115 if (Limits.Flags & WASM_LIMITS_FLAG_HAS_MAX)
116 writeUleb128(OS, Limits.Maximum, "limits max");
117}
118
Sam Clegg1a9b7b92018-01-31 19:54:34 +0000119void wasm::writeGlobalType(raw_ostream &OS, const WasmGlobalType &Type) {
120 writeValueType(OS, 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
129void wasm::writeImport(raw_ostream &OS, const WasmImport &Import) {
130 writeStr(OS, Import.Module, "import module name");
131 writeStr(OS, Import.Field, "import field name");
132 writeU8(OS, Import.Kind, "import kind");
133 switch (Import.Kind) {
134 case WASM_EXTERNAL_FUNCTION:
135 writeUleb128(OS, Import.SigIndex, "import sig index");
136 break;
137 case WASM_EXTERNAL_GLOBAL:
Sam Clegg1a9b7b92018-01-31 19:54:34 +0000138 writeGlobalType(OS, Import.Global);
Sam Cleggc94d3932017-11-17 18:14:09 +0000139 break;
140 case WASM_EXTERNAL_MEMORY:
141 writeLimits(OS, Import.Memory);
142 break;
143 default:
144 fatal("unsupported import type: " + Twine(Import.Kind));
Sam Cleggc94d3932017-11-17 18:14:09 +0000145 }
146}
147
148void wasm::writeExport(raw_ostream &OS, const WasmExport &Export) {
149 writeStr(OS, Export.Name, "export name");
150 writeU8(OS, Export.Kind, "export kind");
151 switch (Export.Kind) {
152 case WASM_EXTERNAL_FUNCTION:
153 writeUleb128(OS, Export.Index, "function index");
154 break;
155 case WASM_EXTERNAL_GLOBAL:
156 writeUleb128(OS, Export.Index, "global index");
157 break;
158 case WASM_EXTERNAL_MEMORY:
159 writeUleb128(OS, Export.Index, "memory index");
160 break;
161 default:
162 fatal("unsupported export type: " + Twine(Export.Kind));
Sam Cleggc94d3932017-11-17 18:14:09 +0000163 }
164}
Sam Cleggc94d3932017-11-17 18:14:09 +0000165} // namespace lld
Sam Cleggb8621592017-11-30 01:40:08 +0000166
167std::string lld::toString(ValType Type) {
168 switch (Type) {
169 case ValType::I32:
170 return "I32";
171 case ValType::I64:
172 return "I64";
173 case ValType::F32:
174 return "F32";
175 case ValType::F64:
176 return "F64";
Heejin Ahn2dce27d2018-03-08 04:06:57 +0000177 case ValType::EXCEPT_REF:
178 return "except_ref";
Sam Cleggb8621592017-11-30 01:40:08 +0000179 }
180 llvm_unreachable("Invalid wasm::ValType");
181}
182
183std::string lld::toString(const WasmSignature &Sig) {
184 SmallString<128> S("(");
185 for (uint32_t Type : Sig.ParamTypes) {
186 if (S.size() != 1)
187 S += ", ";
188 S += toString(static_cast<ValType>(Type));
189 }
190 S += ") -> ";
191 if (Sig.ReturnType == WASM_TYPE_NORESULT)
192 S += "void";
193 else
194 S += toString(static_cast<ValType>(Sig.ReturnType));
195 return S.str();
196}
Sam Clegg93102972018-02-23 05:08:53 +0000197
198std::string lld::toString(const WasmGlobalType &Sig) {
Nicholas Wilson36f14f42018-03-02 14:54:34 +0000199 return (Sig.Mutable ? "var " : "const ") +
Nicholas Wilsondbd90bf2018-03-07 13:28:16 +0000200 toString(static_cast<ValType>(Sig.Type));
Sam Clegg93102972018-02-23 05:08:53 +0000201}