Coverage Report

Created: 2018-01-17 17:22

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/tools/lld/wasm/WriterUtils.cpp
Line
Count
Source (jump to first uncovered line)
1
//===- 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"
11
12
#include "lld/Common/ErrorHandler.h"
13
14
#include "llvm/Support/Debug.h"
15
#include "llvm/Support/EndianStream.h"
16
#include "llvm/Support/FormatVariadic.h"
17
#include "llvm/Support/LEB128.h"
18
19
#define DEBUG_TYPE "lld"
20
21
using namespace llvm;
22
using namespace llvm::wasm;
23
using namespace lld::wasm;
24
25
0
static const char *valueTypeToString(int32_t Type) {
26
0
  switch (Type) {
27
0
  case WASM_TYPE_I32:
28
0
    return "i32";
29
0
  case WASM_TYPE_I64:
30
0
    return "i64";
31
0
  case WASM_TYPE_F32:
32
0
    return "f32";
33
0
  case WASM_TYPE_F64:
34
0
    return "f64";
35
0
  default:
36
0
    llvm_unreachable("invalid value type");
37
0
  }
38
0
}
39
40
namespace lld {
41
42
0
void wasm::debugWrite(uint64_t offset, Twine msg) {
43
0
  DEBUG(dbgs() << format("  | %08" PRIx64 ": ", offset) << msg << "\n");
44
0
}
45
46
0
void wasm::writeUleb128(raw_ostream &OS, uint32_t Number, const char *msg) {
47
0
  if (msg)
48
0
    debugWrite(OS.tell(), msg + formatv(" [{0:x}]", Number));
49
0
  encodeULEB128(Number, OS);
50
0
}
51
52
0
void wasm::writeSleb128(raw_ostream &OS, int32_t Number, const char *msg) {
53
0
  if (msg)
54
0
    debugWrite(OS.tell(), msg + formatv(" [{0:x}]", Number));
55
0
  encodeSLEB128(Number, OS);
56
0
}
57
58
void wasm::writeBytes(raw_ostream &OS, const char *bytes, size_t count,
59
0
                      const char *msg) {
60
0
  if (msg)
61
0
    debugWrite(OS.tell(), msg + formatv(" [data[{0}]]", count));
62
0
  OS.write(bytes, count);
63
0
}
64
65
0
void wasm::writeStr(raw_ostream &OS, const StringRef String, const char *msg) {
66
0
  if (msg)
67
0
    debugWrite(OS.tell(),
68
0
               msg + formatv(" [str[{0}]: {1}]", String.size(), String));
69
0
  writeUleb128(OS, String.size(), nullptr);
70
0
  writeBytes(OS, String.data(), String.size());
71
0
}
72
73
0
void wasm::writeU8(raw_ostream &OS, uint8_t byte, const char *msg) {
74
0
  OS << byte;
75
0
}
76
77
0
void wasm::writeU32(raw_ostream &OS, uint32_t Number, const char *msg) {
78
0
  debugWrite(OS.tell(), msg + formatv("[{0:x}]", Number));
79
0
  support::endian::Writer<support::little>(OS).write(Number);
80
0
}
81
82
0
void wasm::writeValueType(raw_ostream &OS, int32_t Type, const char *msg) {
83
0
  debugWrite(OS.tell(), msg + formatv("[type: {0}]", valueTypeToString(Type)));
84
0
  writeSleb128(OS, Type, nullptr);
85
0
}
86
87
0
void wasm::writeSig(raw_ostream &OS, const WasmSignature &Sig) {
88
0
  writeSleb128(OS, WASM_TYPE_FUNC, "signature type");
89
0
  writeUleb128(OS, Sig.ParamTypes.size(), "param count");
90
0
  for (int32_t ParamType : Sig.ParamTypes) {
91
0
    writeValueType(OS, ParamType, "param type");
92
0
  }
93
0
  if (Sig.ReturnType == WASM_TYPE_NORESULT) {
94
0
    writeUleb128(OS, 0, "result count");
95
0
  } else {
96
0
    writeUleb128(OS, 1, "result count");
97
0
    writeValueType(OS, Sig.ReturnType, "result type");
98
0
  }
99
0
}
100
101
0
void wasm::writeInitExpr(raw_ostream &OS, const WasmInitExpr &InitExpr) {
102
0
  writeU8(OS, InitExpr.Opcode, "opcode");
103
0
  switch (InitExpr.Opcode) {
104
0
  case WASM_OPCODE_I32_CONST:
105
0
    writeSleb128(OS, InitExpr.Value.Int32, "literal (i32)");
106
0
    break;
107
0
  case WASM_OPCODE_I64_CONST:
108
0
    writeSleb128(OS, InitExpr.Value.Int64, "literal (i64)");
109
0
    break;
110
0
  case WASM_OPCODE_GET_GLOBAL:
111
0
    writeUleb128(OS, InitExpr.Value.Global, "literal (global index)");
112
0
    break;
113
0
  default:
114
0
    fatal("unknown opcode in init expr: " + Twine(InitExpr.Opcode));
115
0
  }
116
0
  writeU8(OS, WASM_OPCODE_END, "opcode:end");
117
0
}
118
119
0
void wasm::writeLimits(raw_ostream &OS, const WasmLimits &Limits) {
120
0
  writeUleb128(OS, Limits.Flags, "limits flags");
121
0
  writeUleb128(OS, Limits.Initial, "limits initial");
122
0
  if (Limits.Flags & WASM_LIMITS_FLAG_HAS_MAX)
123
0
    writeUleb128(OS, Limits.Maximum, "limits max");
124
0
}
125
126
0
void wasm::writeGlobal(raw_ostream &OS, const WasmGlobal &Global) {
127
0
  writeValueType(OS, Global.Type, "global type");
128
0
  writeUleb128(OS, Global.Mutable, "global mutable");
129
0
  writeInitExpr(OS, Global.InitExpr);
130
0
}
131
132
0
void wasm::writeImport(raw_ostream &OS, const WasmImport &Import) {
133
0
  writeStr(OS, Import.Module, "import module name");
134
0
  writeStr(OS, Import.Field, "import field name");
135
0
  writeU8(OS, Import.Kind, "import kind");
136
0
  switch (Import.Kind) {
137
0
  case WASM_EXTERNAL_FUNCTION:
138
0
    writeUleb128(OS, Import.SigIndex, "import sig index");
139
0
    break;
140
0
  case WASM_EXTERNAL_GLOBAL:
141
0
    writeValueType(OS, Import.Global.Type, "import global type");
142
0
    writeUleb128(OS, Import.Global.Mutable, "import global mutable");
143
0
    break;
144
0
  case WASM_EXTERNAL_MEMORY:
145
0
    writeLimits(OS, Import.Memory);
146
0
    break;
147
0
  default:
148
0
    fatal("unsupported import type: " + Twine(Import.Kind));
149
0
  }
150
0
}
151
152
0
void wasm::writeExport(raw_ostream &OS, const WasmExport &Export) {
153
0
  writeStr(OS, Export.Name, "export name");
154
0
  writeU8(OS, Export.Kind, "export kind");
155
0
  switch (Export.Kind) {
156
0
  case WASM_EXTERNAL_FUNCTION:
157
0
    writeUleb128(OS, Export.Index, "function index");
158
0
    break;
159
0
  case WASM_EXTERNAL_GLOBAL:
160
0
    writeUleb128(OS, Export.Index, "global index");
161
0
    break;
162
0
  case WASM_EXTERNAL_MEMORY:
163
0
    writeUleb128(OS, Export.Index, "memory index");
164
0
    break;
165
0
  default:
166
0
    fatal("unsupported export type: " + Twine(Export.Kind));
167
0
  }
168
0
}
169
170
0
void wasm::writeReloc(raw_ostream &OS, const OutputRelocation &Reloc) {
171
0
  writeUleb128(OS, Reloc.Reloc.Type, "reloc type");
172
0
  writeUleb128(OS, Reloc.Reloc.Offset, "reloc offset");
173
0
  writeUleb128(OS, Reloc.NewIndex, "reloc index");
174
0
175
0
  switch (Reloc.Reloc.Type) {
176
0
  case R_WEBASSEMBLY_MEMORY_ADDR_LEB:
177
0
  case R_WEBASSEMBLY_MEMORY_ADDR_SLEB:
178
0
  case R_WEBASSEMBLY_MEMORY_ADDR_I32:
179
0
    writeUleb128(OS, Reloc.Reloc.Addend, "reloc addend");
180
0
    break;
181
0
  default:
182
0
    break;
183
0
  }
184
0
}
185
186
} // namespace lld
187
188
0
std::string lld::toString(ValType Type) {
189
0
  switch (Type) {
190
0
  case ValType::I32:
191
0
    return "I32";
192
0
  case ValType::I64:
193
0
    return "I64";
194
0
  case ValType::F32:
195
0
    return "F32";
196
0
  case ValType::F64:
197
0
    return "F64";
198
0
  }
199
0
  llvm_unreachable("Invalid wasm::ValType");
200
0
}
201
202
0
std::string lld::toString(const WasmSignature &Sig) {
203
0
  SmallString<128> S("(");
204
0
  for (uint32_t Type : Sig.ParamTypes) {
205
0
    if (S.size() != 1)
206
0
      S += ", ";
207
0
    S += toString(static_cast<ValType>(Type));
208
0
  }
209
0
  S += ") -> ";
210
0
  if (Sig.ReturnType == WASM_TYPE_NORESULT)
211
0
    S += "void";
212
0
  else
213
0
    S += toString(static_cast<ValType>(Sig.ReturnType));
214
0
  return S.str();
215
0
}