Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/lib/MC/MCFragment.cpp
Line
Count
Source (jump to first uncovered line)
1
//===- lib/MC/MCFragment.cpp - Assembler Fragment Implementation ----------===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
9
#include "llvm/MC/MCFragment.h"
10
#include "llvm/ADT/SmallVector.h"
11
#include "llvm/ADT/StringExtras.h"
12
#include "llvm/ADT/Twine.h"
13
#include "llvm/Config/llvm-config.h"
14
#include "llvm/MC/MCAsmLayout.h"
15
#include "llvm/MC/MCAssembler.h"
16
#include "llvm/MC/MCContext.h"
17
#include "llvm/MC/MCExpr.h"
18
#include "llvm/MC/MCFixup.h"
19
#include "llvm/MC/MCSection.h"
20
#include "llvm/MC/MCSymbol.h"
21
#include "llvm/MC/MCValue.h"
22
#include "llvm/Support/Casting.h"
23
#include "llvm/Support/Compiler.h"
24
#include "llvm/Support/ErrorHandling.h"
25
#include "llvm/Support/raw_ostream.h"
26
#include <cassert>
27
#include <cstdint>
28
#include <utility>
29
30
using namespace llvm;
31
32
20.5k
MCAsmLayout::MCAsmLayout(MCAssembler &Asm) : Assembler(Asm) {
33
20.5k
  // Compute the section layout order. Virtual sections must go last.
34
20.5k
  for (MCSection &Sec : Asm)
35
557k
    if (!Sec.isVirtualSection())
36
552k
      SectionOrder.push_back(&Sec);
37
20.5k
  for (MCSection &Sec : Asm)
38
557k
    if (Sec.isVirtualSection())
39
4.99k
      SectionOrder.push_back(&Sec);
40
20.5k
}
41
42
28.0M
bool MCAsmLayout::isFragmentValid(const MCFragment *F) const {
43
28.0M
  const MCSection *Sec = F->getParent();
44
28.0M
  const MCFragment *LastValid = LastValidFragment.lookup(Sec);
45
28.0M
  if (!LastValid)
46
561k
    return false;
47
27.5M
  assert(LastValid->getParent() == Sec);
48
27.5M
  return F->getLayoutOrder() <= LastValid->getLayoutOrder();
49
27.5M
}
50
51
5.79k
void MCAsmLayout::invalidateFragmentsFrom(MCFragment *F) {
52
5.79k
  // If this fragment wasn't already valid, we don't need to do anything.
53
5.79k
  if (!isFragmentValid(F))
54
3.75k
    return;
55
2.03k
56
2.03k
  // Otherwise, reset the last valid fragment to the previous fragment
57
2.03k
  // (if this is the first fragment, it will be NULL).
58
2.03k
  LastValidFragment[F->getParent()] = F->getPrevNode();
59
2.03k
}
60
61
21.8M
void MCAsmLayout::ensureValid(const MCFragment *F) const {
62
21.8M
  MCSection *Sec = F->getParent();
63
21.8M
  MCSection::iterator I;
64
21.8M
  if (MCFragment *Cur = LastValidFragment[Sec])
65
21.3M
    I = ++MCSection::iterator(Cur);
66
557k
  else
67
557k
    I = Sec->begin();
68
21.8M
69
21.8M
  // Advance the layout position until the fragment is valid.
70
28.0M
  while (!isFragmentValid(F)) {
71
6.20M
    assert(I != Sec->end() && "Layout bookkeeping error");
72
6.20M
    const_cast<MCAsmLayout *>(this)->layoutFragment(&*I);
73
6.20M
    ++I;
74
6.20M
  }
75
21.8M
}
76
77
21.8M
uint64_t MCAsmLayout::getFragmentOffset(const MCFragment *F) const {
78
21.8M
  ensureValid(F);
79
21.8M
  assert(F->Offset != ~UINT64_C(0) && "Address not set!");
80
21.8M
  return F->Offset;
81
21.8M
}
82
83
// Simple getSymbolOffset helper for the non-variable case.
84
static bool getLabelOffset(const MCAsmLayout &Layout, const MCSymbol &S,
85
11.3M
                           bool ReportError, uint64_t &Val) {
86
11.3M
  if (!S.getFragment()) {
87
2.69k
    if (ReportError)
88
1
      report_fatal_error("unable to evaluate offset to undefined symbol '" +
89
1
                         S.getName() + "'");
90
2.69k
    return false;
91
2.69k
  }
92
11.3M
  Val = Layout.getFragmentOffset(S.getFragment()) + S.getOffset();
93
11.3M
  return true;
94
11.3M
}
95
96
static bool getSymbolOffsetImpl(const MCAsmLayout &Layout, const MCSymbol &S,
97
11.3M
                                bool ReportError, uint64_t &Val) {
98
11.3M
  if (!S.isVariable())
99
11.2M
    return getLabelOffset(Layout, S, ReportError, Val);
100
23.6k
101
23.6k
  // If SD is a variable, evaluate it.
102
23.6k
  MCValue Target;
103
23.6k
  if (!S.getVariableValue()->evaluateAsValue(Target, Layout))
104
0
    report_fatal_error("unable to evaluate offset for variable '" +
105
0
                       S.getName() + "'");
106
23.6k
107
23.6k
  uint64_t Offset = Target.getConstant();
108
23.6k
109
23.6k
  const MCSymbolRefExpr *A = Target.getSymA();
110
23.6k
  if (A) {
111
23.1k
    uint64_t ValA;
112
23.1k
    if (!getLabelOffset(Layout, A->getSymbol(), ReportError, ValA))
113
10
      return false;
114
23.0k
    Offset += ValA;
115
23.0k
  }
116
23.6k
117
23.6k
  const MCSymbolRefExpr *B = Target.getSymB();
118
23.6k
  if (B) {
119
22.6k
    uint64_t ValB;
120
22.6k
    if (!getLabelOffset(Layout, B->getSymbol(), ReportError, ValB))
121
0
      return false;
122
22.6k
    Offset -= ValB;
123
22.6k
  }
124
23.6k
125
23.6k
  Val = Offset;
126
23.6k
  return true;
127
23.6k
}
128
129
99.9k
bool MCAsmLayout::getSymbolOffset(const MCSymbol &S, uint64_t &Val) const {
130
99.9k
  return getSymbolOffsetImpl(*this, S, false, Val);
131
99.9k
}
132
133
11.2M
uint64_t MCAsmLayout::getSymbolOffset(const MCSymbol &S) const {
134
11.2M
  uint64_t Val;
135
11.2M
  getSymbolOffsetImpl(*this, S, true, Val);
136
11.2M
  return Val;
137
11.2M
}
138
139
100k
const MCSymbol *MCAsmLayout::getBaseSymbol(const MCSymbol &Symbol) const {
140
100k
  if (!Symbol.isVariable())
141
99.3k
    return &Symbol;
142
851
143
851
  const MCExpr *Expr = Symbol.getVariableValue();
144
851
  MCValue Value;
145
851
  if (!Expr->evaluateAsValue(Value, *this)) {
146
3
    Assembler.getContext().reportError(
147
3
        Expr->getLoc(), "expression could not be evaluated");
148
3
    return nullptr;
149
3
  }
150
848
151
848
  const MCSymbolRefExpr *RefB = Value.getSymB();
152
848
  if (RefB) {
153
2
    Assembler.getContext().reportError(
154
2
        Expr->getLoc(), Twine("symbol '") + RefB->getSymbol().getName() +
155
2
                     "' could not be evaluated in a subtraction expression");
156
2
    return nullptr;
157
2
  }
158
846
159
846
  const MCSymbolRefExpr *A = Value.getSymA();
160
846
  if (!A)
161
555
    return nullptr;
162
291
163
291
  const MCSymbol &ASym = A->getSymbol();
164
291
  const MCAssembler &Asm = getAssembler();
165
291
  if (ASym.isCommon()) {
166
4
    Asm.getContext().reportError(Expr->getLoc(),
167
4
                                 "Common symbol '" + ASym.getName() +
168
4
                                     "' cannot be used in assignment expr");
169
4
    return nullptr;
170
4
  }
171
287
172
287
  return &ASym;
173
287
}
174
175
507k
uint64_t MCAsmLayout::getSectionAddressSize(const MCSection *Sec) const {
176
507k
  // The size is the last fragment's end offset.
177
507k
  const MCFragment &F = Sec->getFragmentList().back();
178
507k
  return getFragmentOffset(&F) + getAssembler().computeFragmentSize(*this, F);
179
507k
}
180
181
73.1k
uint64_t MCAsmLayout::getSectionFileSize(const MCSection *Sec) const {
182
73.1k
  // Virtual sections have no file size.
183
73.1k
  if (Sec->isVirtualSection())
184
3.56k
    return 0;
185
69.5k
186
69.5k
  // Otherwise, the file size is the same as the address space size.
187
69.5k
  return getSectionAddressSize(Sec);
188
69.5k
}
189
190
uint64_t llvm::computeBundlePadding(const MCAssembler &Assembler,
191
                                    const MCEncodedFragment *F,
192
886
                                    uint64_t FOffset, uint64_t FSize) {
193
886
  uint64_t BundleSize = Assembler.getBundleAlignSize();
194
886
  assert(BundleSize > 0 &&
195
886
         "computeBundlePadding should only be called if bundling is enabled");
196
886
  uint64_t BundleMask = BundleSize - 1;
197
886
  uint64_t OffsetInBundle = FOffset & BundleMask;
198
886
  uint64_t EndOfFragment = OffsetInBundle + FSize;
199
886
200
886
  // There are two kinds of bundling restrictions:
201
886
  //
202
886
  // 1) For alignToBundleEnd(), add padding to ensure that the fragment will
203
886
  //    *end* on a bundle boundary.
204
886
  // 2) Otherwise, check if the fragment would cross a bundle boundary. If it
205
886
  //    would, add padding until the end of the bundle so that the fragment
206
886
  //    will start in a new one.
207
886
  if (F->alignToBundleEnd()) {
208
288
    // Three possibilities here:
209
288
    //
210
288
    // A) The fragment just happens to end at a bundle boundary, so we're good.
211
288
    // B) The fragment ends before the current bundle boundary: pad it just
212
288
    //    enough to reach the boundary.
213
288
    // C) The fragment ends after the current bundle boundary: pad it until it
214
288
    //    reaches the end of the next bundle boundary.
215
288
    //
216
288
    // Note: this code could be made shorter with some modulo trickery, but it's
217
288
    // intentionally kept in its more explicit form for simplicity.
218
288
    if (EndOfFragment == BundleSize)
219
18
      return 0;
220
270
    else if (EndOfFragment < BundleSize)
221
142
      return BundleSize - EndOfFragment;
222
128
    else { // EndOfFragment > BundleSize
223
128
      return 2 * BundleSize - EndOfFragment;
224
128
    }
225
598
  } else if (OffsetInBundle > 0 && 
EndOfFragment > BundleSize487
)
226
161
    return BundleSize - OffsetInBundle;
227
437
  else
228
437
    return 0;
229
886
}
230
231
/* *** */
232
233
7.19M
void ilist_alloc_traits<MCFragment>::deleteNode(MCFragment *V) { V->destroy(); }
234
235
10.4M
MCFragment::~MCFragment() = default;
236
237
MCFragment::MCFragment(FragmentType Kind, bool HasInstructions,
238
                       MCSection *Parent)
239
    : Kind(Kind), HasInstructions(HasInstructions), LayoutOrder(0),
240
10.4M
      Parent(Parent), Atom(nullptr), Offset(~UINT64_C(0)) {
241
10.4M
  if (Parent && 
!isDummy()3.12M
)
242
1.64k
    Parent->getFragmentList().push_back(this);
243
10.4M
}
244
245
7.19M
void MCFragment::destroy() {
246
7.19M
  // First check if we are the sentinal.
247
7.19M
  if (Kind == FragmentType(~0)) {
248
0
    delete this;
249
0
    return;
250
0
  }
251
7.19M
252
7.19M
  switch (Kind) {
253
7.19M
    case FT_Align:
254
488k
      delete cast<MCAlignFragment>(this);
255
488k
      return;
256
7.19M
    case FT_Data:
257
4.75M
      delete cast<MCDataFragment>(this);
258
4.75M
      return;
259
7.19M
    case FT_CompactEncodedInst:
260
135
      delete cast<MCCompactEncodedInstFragment>(this);
261
135
      return;
262
7.19M
    case FT_Fill:
263
609k
      delete cast<MCFillFragment>(this);
264
609k
      return;
265
7.19M
    case FT_Relaxable:
266
237k
      delete cast<MCRelaxableFragment>(this);
267
237k
      return;
268
7.19M
    case FT_Org:
269
19
      delete cast<MCOrgFragment>(this);
270
19
      return;
271
7.19M
    case FT_Dwarf:
272
965k
      delete cast<MCDwarfLineAddrFragment>(this);
273
965k
      return;
274
7.19M
    case FT_DwarfFrame:
275
131k
      delete cast<MCDwarfCallFrameFragment>(this);
276
131k
      return;
277
7.19M
    case FT_LEB:
278
4.82k
      delete cast<MCLEBFragment>(this);
279
4.82k
      return;
280
7.19M
    case FT_Padding:
281
0
      delete cast<MCPaddingFragment>(this);
282
0
      return;
283
7.19M
    case FT_SymbolId:
284
16
      delete cast<MCSymbolIdFragment>(this);
285
16
      return;
286
7.19M
    case FT_CVInlineLines:
287
33
      delete cast<MCCVInlineLineTableFragment>(this);
288
33
      return;
289
7.19M
    case FT_CVDefRange:
290
358
      delete cast<MCCVDefRangeFragment>(this);
291
358
      return;
292
7.19M
    case FT_Dummy:
293
0
      delete cast<MCDummyFragment>(this);
294
0
      return;
295
7.19M
  }
296
7.19M
}
297
298
// Debugging methods
299
300
namespace llvm {
301
302
0
raw_ostream &operator<<(raw_ostream &OS, const MCFixup &AF) {
303
0
  OS << "<MCFixup" << " Offset:" << AF.getOffset()
304
0
     << " Value:" << *AF.getValue()
305
0
     << " Kind:" << AF.getKind() << ">";
306
0
  return OS;
307
0
}
308
309
} // end namespace llvm
310
311
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
312
LLVM_DUMP_METHOD void MCFragment::dump() const {
313
  raw_ostream &OS = errs();
314
315
  OS << "<";
316
  switch (getKind()) {
317
  case MCFragment::FT_Align: OS << "MCAlignFragment"; break;
318
  case MCFragment::FT_Data:  OS << "MCDataFragment"; break;
319
  case MCFragment::FT_CompactEncodedInst:
320
    OS << "MCCompactEncodedInstFragment"; break;
321
  case MCFragment::FT_Fill:  OS << "MCFillFragment"; break;
322
  case MCFragment::FT_Relaxable:  OS << "MCRelaxableFragment"; break;
323
  case MCFragment::FT_Org:   OS << "MCOrgFragment"; break;
324
  case MCFragment::FT_Dwarf: OS << "MCDwarfFragment"; break;
325
  case MCFragment::FT_DwarfFrame: OS << "MCDwarfCallFrameFragment"; break;
326
  case MCFragment::FT_LEB:   OS << "MCLEBFragment"; break;
327
  case MCFragment::FT_Padding: OS << "MCPaddingFragment"; break;
328
  case MCFragment::FT_SymbolId:    OS << "MCSymbolIdFragment"; break;
329
  case MCFragment::FT_CVInlineLines: OS << "MCCVInlineLineTableFragment"; break;
330
  case MCFragment::FT_CVDefRange: OS << "MCCVDefRangeTableFragment"; break;
331
  case MCFragment::FT_Dummy: OS << "MCDummyFragment"; break;
332
  }
333
334
  OS << "<MCFragment " << (const void *)this << " LayoutOrder:" << LayoutOrder
335
     << " Offset:" << Offset << " HasInstructions:" << hasInstructions();
336
  if (const MCEncodedFragment *EF = dyn_cast<MCEncodedFragment>(this))
337
    OS << " BundlePadding:" << static_cast<unsigned>(EF->getBundlePadding());
338
  OS << ">";
339
340
  switch (getKind()) {
341
  case MCFragment::FT_Align: {
342
    const MCAlignFragment *AF = cast<MCAlignFragment>(this);
343
    if (AF->hasEmitNops())
344
      OS << " (emit nops)";
345
    OS << "\n       ";
346
    OS << " Alignment:" << AF->getAlignment()
347
       << " Value:" << AF->getValue() << " ValueSize:" << AF->getValueSize()
348
       << " MaxBytesToEmit:" << AF->getMaxBytesToEmit() << ">";
349
    break;
350
  }
351
  case MCFragment::FT_Data:  {
352
    const MCDataFragment *DF = cast<MCDataFragment>(this);
353
    OS << "\n       ";
354
    OS << " Contents:[";
355
    const SmallVectorImpl<char> &Contents = DF->getContents();
356
    for (unsigned i = 0, e = Contents.size(); i != e; ++i) {
357
      if (i) OS << ",";
358
      OS << hexdigit((Contents[i] >> 4) & 0xF) << hexdigit(Contents[i] & 0xF);
359
    }
360
    OS << "] (" << Contents.size() << " bytes)";
361
362
    if (DF->fixup_begin() != DF->fixup_end()) {
363
      OS << ",\n       ";
364
      OS << " Fixups:[";
365
      for (MCDataFragment::const_fixup_iterator it = DF->fixup_begin(),
366
             ie = DF->fixup_end(); it != ie; ++it) {
367
        if (it != DF->fixup_begin()) OS << ",\n                ";
368
        OS << *it;
369
      }
370
      OS << "]";
371
    }
372
    break;
373
  }
374
  case MCFragment::FT_CompactEncodedInst: {
375
    const MCCompactEncodedInstFragment *CEIF =
376
      cast<MCCompactEncodedInstFragment>(this);
377
    OS << "\n       ";
378
    OS << " Contents:[";
379
    const SmallVectorImpl<char> &Contents = CEIF->getContents();
380
    for (unsigned i = 0, e = Contents.size(); i != e; ++i) {
381
      if (i) OS << ",";
382
      OS << hexdigit((Contents[i] >> 4) & 0xF) << hexdigit(Contents[i] & 0xF);
383
    }
384
    OS << "] (" << Contents.size() << " bytes)";
385
    break;
386
  }
387
  case MCFragment::FT_Fill:  {
388
    const MCFillFragment *FF = cast<MCFillFragment>(this);
389
    OS << " Value:" << static_cast<unsigned>(FF->getValue())
390
       << " ValueSize:" << static_cast<unsigned>(FF->getValueSize())
391
       << " NumValues:" << FF->getNumValues();
392
    break;
393
  }
394
  case MCFragment::FT_Relaxable:  {
395
    const MCRelaxableFragment *F = cast<MCRelaxableFragment>(this);
396
    OS << "\n       ";
397
    OS << " Inst:";
398
    F->getInst().dump_pretty(OS);
399
    break;
400
  }
401
  case MCFragment::FT_Org:  {
402
    const MCOrgFragment *OF = cast<MCOrgFragment>(this);
403
    OS << "\n       ";
404
    OS << " Offset:" << OF->getOffset()
405
       << " Value:" << static_cast<unsigned>(OF->getValue());
406
    break;
407
  }
408
  case MCFragment::FT_Dwarf:  {
409
    const MCDwarfLineAddrFragment *OF = cast<MCDwarfLineAddrFragment>(this);
410
    OS << "\n       ";
411
    OS << " AddrDelta:" << OF->getAddrDelta()
412
       << " LineDelta:" << OF->getLineDelta();
413
    break;
414
  }
415
  case MCFragment::FT_DwarfFrame:  {
416
    const MCDwarfCallFrameFragment *CF = cast<MCDwarfCallFrameFragment>(this);
417
    OS << "\n       ";
418
    OS << " AddrDelta:" << CF->getAddrDelta();
419
    break;
420
  }
421
  case MCFragment::FT_LEB: {
422
    const MCLEBFragment *LF = cast<MCLEBFragment>(this);
423
    OS << "\n       ";
424
    OS << " Value:" << LF->getValue() << " Signed:" << LF->isSigned();
425
    break;
426
  }
427
  case MCFragment::FT_Padding: {
428
    const MCPaddingFragment *F = cast<MCPaddingFragment>(this);
429
    OS << "\n       ";
430
    OS << " PaddingPoliciesMask:" << F->getPaddingPoliciesMask()
431
       << " IsInsertionPoint:" << F->isInsertionPoint()
432
       << " Size:" << F->getSize();
433
    OS << "\n       ";
434
    OS << " Inst:";
435
    F->getInst().dump_pretty(OS);
436
    OS << " InstSize:" << F->getInstSize();
437
    OS << "\n       ";
438
    break;
439
  }
440
  case MCFragment::FT_SymbolId: {
441
    const MCSymbolIdFragment *F = cast<MCSymbolIdFragment>(this);
442
    OS << "\n       ";
443
    OS << " Sym:" << F->getSymbol();
444
    break;
445
  }
446
  case MCFragment::FT_CVInlineLines: {
447
    const auto *F = cast<MCCVInlineLineTableFragment>(this);
448
    OS << "\n       ";
449
    OS << " Sym:" << *F->getFnStartSym();
450
    break;
451
  }
452
  case MCFragment::FT_CVDefRange: {
453
    const auto *F = cast<MCCVDefRangeFragment>(this);
454
    OS << "\n       ";
455
    for (std::pair<const MCSymbol *, const MCSymbol *> RangeStartEnd :
456
         F->getRanges()) {
457
      OS << " RangeStart:" << RangeStartEnd.first;
458
      OS << " RangeEnd:" << RangeStartEnd.second;
459
    }
460
    break;
461
  }
462
  case MCFragment::FT_Dummy:
463
    break;
464
  }
465
  OS << ">";
466
}
467
#endif