1//===- lib/MC/MCSection.cpp - Machine Code Section Representation ---------===//
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/MCSection.h"
10#include "llvm/ADT/SmallVector.h"
11#include "llvm/Config/llvm-config.h"
12#include "llvm/MC/MCContext.h"
13#include "llvm/MC/MCSymbol.h"
14#include "llvm/Support/Compiler.h"
15#include "llvm/Support/ErrorHandling.h"
16#include "llvm/Support/raw_ostream.h"
17#include <utility>
18
19using namespace llvm;
20
21MCSection::MCSection(StringRef Name, bool IsText, bool IsBss, MCSymbol *Begin)
22 : Begin(Begin), HasInstructions(false), IsRegistered(false), IsText(IsText),
23 IsBss(IsBss), Name(Name) {
24 DummyFragment.setParent(this);
25}
26
27MCSymbol *MCSection::getEndSymbol(MCContext &Ctx) {
28 if (!End)
29 End = Ctx.createTempSymbol(Name: "sec_end");
30 return End;
31}
32
33bool MCSection::hasEnded() const { return End && End->isInSection(); }
34
35#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
36LLVM_DUMP_METHOD void MCSection::dump(
37 DenseMap<const MCFragment *, SmallVector<const MCSymbol *, 0>> *FragToSyms)
38 const {
39 raw_ostream &OS = errs();
40
41 OS << "MCSection Name:" << getName();
42 if (isLinkerRelaxable())
43 OS << " FirstLinkerRelaxable:" << firstLinkerRelaxable();
44 for (auto &F : *this) {
45 OS << '\n';
46 F.dump();
47 if (!FragToSyms)
48 continue;
49 auto It = FragToSyms->find(&F);
50 if (It == FragToSyms->end())
51 continue;
52 for (auto *Sym : It->second) {
53 OS << "\n Symbol @" << Sym->getOffset() << ' ' << Sym->getName();
54 if (Sym->isTemporary())
55 OS << " Temporary";
56 }
57 }
58}
59#endif
60
61void MCFragment::setVarContents(ArrayRef<char> Contents) {
62 auto &S = getParent()->ContentStorage;
63 if (VarContentStart + Contents.size() > VarContentEnd) {
64 VarContentStart = S.size();
65 S.resize_for_overwrite(N: S.size() + Contents.size());
66 }
67 VarContentEnd = VarContentStart + Contents.size();
68 llvm::copy(Range&: Contents, Out: S.begin() + VarContentStart);
69}
70
71void MCFragment::addFixup(MCFixup Fixup) { appendFixups(Fixups: {Fixup}); }
72
73void MCFragment::moveFixupsToEnd() {
74 auto &S = getParent()->FixupStorage;
75 if (LLVM_UNLIKELY(FixupEnd != S.size())) {
76 // Move the elements to the end. Reserve space to avoid invalidating
77 // S.begin()+I for `append`.
78 auto Size = FixupEnd - FixupStart;
79 auto I = std::exchange(obj&: FixupStart, new_val: S.size());
80 S.reserve(N: S.size() + Size);
81 S.append(in_start: S.begin() + I, in_end: S.begin() + I + Size);
82 }
83}
84
85void MCFragment::appendFixups(ArrayRef<MCFixup> Fixups) {
86 moveFixupsToEnd();
87
88 auto &S = getParent()->FixupStorage;
89 S.append(in_start: Fixups.begin(), in_end: Fixups.end());
90 FixupEnd = S.size();
91}
92
93void MCFragment::insertRelocFixups(ArrayRef<MCFixup> Fixups) {
94 moveFixupsToEnd();
95
96 // See MCAssembler::layout() for the rule being followed here.
97 auto &S = getParent()->FixupStorage;
98 S.insert(I: std::upper_bound(first: S.begin() + FixupStart, last: S.end(), val: Fixups[0],
99 comp: [](MCFixup F1, MCFixup F2) {
100 return F1.getOffset() < F2.getOffset();
101 }),
102 From: Fixups.begin(), To: Fixups.end());
103 FixupEnd = S.size();
104}
105
106void MCFragment::setVarFixups(ArrayRef<MCFixup> Fixups) {
107 assert(Fixups.size() < 256 &&
108 "variable-size tail cannot have more than 256 fixups");
109 auto &S = getParent()->FixupStorage;
110 if (Fixups.size() > VarFixupSize) {
111 VarFixupStart = S.size();
112 S.resize_for_overwrite(N: S.size() + Fixups.size());
113 }
114 VarFixupSize = Fixups.size();
115 // Source fixup offsets are relative to the variable part's start. Add the
116 // fixed part size to make them relative to the fixed part's start.
117 std::transform(first: Fixups.begin(), last: Fixups.end(), result: S.begin() + VarFixupStart,
118 unary_op: [Fixed = getFixedSize()](MCFixup F) {
119 F.setOffset(Fixed + F.getOffset());
120 return F;
121 });
122}
123