Coverage Report

Created: 2018-10-20 12:32

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/tools/lld/wasm/InputChunks.h
Line
Count
Source (jump to first uncovered line)
1
//===- InputChunks.h --------------------------------------------*- C++ -*-===//
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
// An InputChunks represents an indivisible opaque region of a input wasm file.
11
// i.e. a single wasm data segment or a single wasm function.
12
//
13
// They are written directly to the mmap'd output file after which relocations
14
// are applied.  Because each Chunk is independent they can be written in
15
// parallel.
16
//
17
// Chunks are also unit on which garbage collection (--gc-sections) operates.
18
//
19
//===----------------------------------------------------------------------===//
20
21
#ifndef LLD_WASM_INPUT_CHUNKS_H
22
#define LLD_WASM_INPUT_CHUNKS_H
23
24
#include "Config.h"
25
#include "InputFiles.h"
26
#include "lld/Common/ErrorHandler.h"
27
#include "llvm/Object/Wasm.h"
28
29
using llvm::object::WasmSection;
30
using llvm::object::WasmSegment;
31
using llvm::wasm::WasmFunction;
32
using llvm::wasm::WasmRelocation;
33
using llvm::wasm::WasmSignature;
34
35
namespace llvm {
36
class raw_ostream;
37
}
38
39
namespace lld {
40
namespace wasm {
41
42
class ObjFile;
43
class OutputSegment;
44
45
class InputChunk {
46
public:
47
  enum Kind { DataSegment, Function, SyntheticFunction, Section };
48
49
0
  Kind kind() const { return SectionKind; }
50
51
176
  virtual uint32_t getSize() const { return data().size(); }
52
80
  virtual uint32_t getInputSize() const { return getSize(); };
53
54
  virtual void writeTo(uint8_t *SectionStart) const;
55
56
812
  ArrayRef<WasmRelocation> getRelocations() const { return Relocations; }
57
846
  void setRelocations(ArrayRef<WasmRelocation> Rs) { Relocations = Rs; }
58
59
  virtual StringRef getName() const = 0;
60
  virtual StringRef getDebugName() const = 0;
61
  virtual uint32_t getComdat() const = 0;
62
  StringRef getComdatName() const;
63
  virtual uint32_t getInputSectionOffset() const = 0;
64
65
222
  size_t NumRelocations() const { return Relocations.size(); }
66
  void writeRelocations(llvm::raw_ostream &OS) const;
67
68
  ObjFile *File;
69
  int32_t OutputOffset = 0;
70
71
  // Signals that the section is part of the output.  The garbage collector,
72
  // and COMDAT handling can set a sections' Live bit.
73
  // If GC is disabled, all sections start out as live by default.
74
  unsigned Live : 1;
75
76
protected:
77
  InputChunk(ObjFile *F, Kind K)
78
957
      : File(F), Live(!Config->GcSections), SectionKind(K) {}
79
957
  virtual ~InputChunk() = default;
80
  virtual ArrayRef<uint8_t> data() const = 0;
81
82
  // Verifies the existing data at relocation targets matches our expectations.
83
  // This is performed only debug builds as an extra sanity check.
84
  void verifyRelocTargets() const;
85
86
  ArrayRef<WasmRelocation> Relocations;
87
  Kind SectionKind;
88
};
89
90
// Represents a WebAssembly data segment which can be included as part of
91
// an output data segments.  Note that in WebAssembly, unlike ELF and other
92
// formats, used the term "data segment" to refer to the continous regions of
93
// memory that make on the data section. See:
94
// https://webassembly.github.io/spec/syntax/modules.html#syntax-data
95
//
96
// For example, by default, clang will produce a separate data section for
97
// each global variable.
98
class InputSegment : public InputChunk {
99
public:
100
  InputSegment(const WasmSegment &Seg, ObjFile *F)
101
80
      : InputChunk(F, InputChunk::DataSegment), Segment(Seg) {}
102
103
0
  static bool classof(const InputChunk *C) { return C->kind() == DataSegment; }
104
105
140
  uint32_t getAlignment() const { return Segment.Data.Alignment; }
106
71
  StringRef getName() const override { return Segment.Data.Name; }
107
0
  StringRef getDebugName() const override { return StringRef(); }
108
99
  uint32_t getComdat() const override { return Segment.Data.Comdat; }
109
187
  uint32_t getInputSectionOffset() const override {
110
187
    return Segment.SectionOffset;
111
187
  }
112
113
  const OutputSegment *OutputSeg = nullptr;
114
  int32_t OutputSegmentOffset = 0;
115
116
protected:
117
290
  ArrayRef<uint8_t> data() const override { return Segment.Data.Content; }
118
119
  const WasmSegment &Segment;
120
};
121
122
// Represents a single wasm function within and input file.  These are
123
// combined to create the final output CODE section.
124
class InputFunction : public InputChunk {
125
public:
126
  InputFunction(const WasmSignature &S, const WasmFunction *Func, ObjFile *F)
127
550
      : InputChunk(F, InputChunk::Function), Signature(S), Function(Func) {}
128
129
0
  static bool classof(const InputChunk *C) {
130
0
    return C->kind() == InputChunk::Function ||
131
0
           C->kind() == InputChunk::SyntheticFunction;
132
0
  }
133
134
  void writeTo(uint8_t *SectionStart) const override;
135
1.53k
  StringRef getName() const override { return Function->SymbolName; }
136
383
  StringRef getDebugName() const override { return Function->DebugName; }
137
640
  uint32_t getComdat() const override { return Function->Comdat; }
138
0
  uint32_t getFunctionInputOffset() const { return getInputSectionOffset(); }
139
11
  uint32_t getFunctionCodeOffset() const { return Function->CodeOffset; }
140
478
  uint32_t getSize() const override {
141
478
    if (Config->CompressRelocations && 
File5
) {
142
4
      assert(CompressedSize);
143
4
      return CompressedSize;
144
4
    }
145
474
    return data().size();
146
474
  }
147
439
  uint32_t getInputSize() const override { return Function->Size; }
148
942
  uint32_t getFunctionIndex() const { return FunctionIndex.getValue(); }
149
39
  bool hasFunctionIndex() const { return FunctionIndex.hasValue(); }
150
  void setFunctionIndex(uint32_t Index);
151
2.47k
  uint32_t getInputSectionOffset() const override {
152
2.47k
    return Function->CodeSectionOffset;
153
2.47k
  }
154
50
  uint32_t getTableIndex() const { return TableIndex.getValue(); }
155
79
  bool hasTableIndex() const { return TableIndex.hasValue(); }
156
  void setTableIndex(uint32_t Index);
157
158
  // The size of a given input function can depend on the values of the
159
  // LEB relocations within it.  This finalizeContents method is called after
160
  // all the symbol values have be calcualted but before getSize() is ever
161
  // called.
162
  void calculateSize();
163
164
  const WasmSignature &Signature;
165
166
protected:
167
1.15k
  ArrayRef<uint8_t> data() const override {
168
1.15k
    assert(!Config->CompressRelocations);
169
1.15k
    return File->CodeSection->Content.slice(getInputSectionOffset(),
170
1.15k
                                            Function->Size);
171
1.15k
  }
172
173
  const WasmFunction *Function;
174
  llvm::Optional<uint32_t> FunctionIndex;
175
  llvm::Optional<uint32_t> TableIndex;
176
  uint32_t CompressedFuncSize = 0;
177
  uint32_t CompressedSize = 0;
178
};
179
180
class SyntheticFunction : public InputFunction {
181
public:
182
  SyntheticFunction(const WasmSignature &S, StringRef Name,
183
                    StringRef DebugName = {})
184
111
      : InputFunction(S, nullptr, nullptr), Name(Name), DebugName(DebugName) {
185
111
    SectionKind = InputChunk::SyntheticFunction;
186
111
  }
187
188
0
  static bool classof(const InputChunk *C) {
189
0
    return C->kind() == InputChunk::SyntheticFunction;
190
0
  }
191
192
327
  StringRef getName() const override { return Name; }
193
89
  StringRef getDebugName() const override { return DebugName; }
194
0
  uint32_t getComdat() const override { return UINT32_MAX; }
195
196
89
  void setBody(ArrayRef<uint8_t> Body_) { Body = Body_; }
197
198
protected:
199
259
  ArrayRef<uint8_t> data() const override { return Body; }
200
201
  StringRef Name;
202
  StringRef DebugName;
203
  ArrayRef<uint8_t> Body;
204
};
205
206
// Represents a single Wasm Section within an input file.
207
class InputSection : public InputChunk {
208
public:
209
  InputSection(const WasmSection &S, ObjFile *F)
210
327
      : InputChunk(F, InputChunk::Section), Section(S) {
211
327
    assert(Section.Type == llvm::wasm::WASM_SEC_CUSTOM);
212
327
  }
213
214
286
  StringRef getName() const override { return Section.Name; }
215
0
  StringRef getDebugName() const override { return StringRef(); }
216
0
  uint32_t getComdat() const override { return UINT32_MAX; }
217
218
protected:
219
78
  ArrayRef<uint8_t> data() const override { return Section.Content; }
220
221
  // Offset within the input section.  This is only zero since this chunk
222
  // type represents an entire input section, not part of one.
223
14
  uint32_t getInputSectionOffset() const override { return 0; }
224
225
  const WasmSection &Section;
226
};
227
228
} // namespace wasm
229
230
std::string toString(const wasm::InputChunk *);
231
} // namespace lld
232
233
#endif // LLD_WASM_INPUT_CHUNKS_H