Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/Object/RecordStreamer.cpp
35233 views
1
//===-- RecordStreamer.cpp - Record asm defined and used symbols ----------===//
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 "RecordStreamer.h"
10
#include "llvm/IR/Mangler.h"
11
#include "llvm/IR/Module.h"
12
#include "llvm/MC/MCContext.h"
13
#include "llvm/MC/MCSymbol.h"
14
15
using namespace llvm;
16
17
void RecordStreamer::markDefined(const MCSymbol &Symbol) {
18
State &S = Symbols[Symbol.getName()];
19
switch (S) {
20
case DefinedGlobal:
21
case Global:
22
S = DefinedGlobal;
23
break;
24
case NeverSeen:
25
case Defined:
26
case Used:
27
S = Defined;
28
break;
29
case DefinedWeak:
30
break;
31
case UndefinedWeak:
32
S = DefinedWeak;
33
}
34
}
35
36
void RecordStreamer::markGlobal(const MCSymbol &Symbol,
37
MCSymbolAttr Attribute) {
38
State &S = Symbols[Symbol.getName()];
39
switch (S) {
40
case DefinedGlobal:
41
case Defined:
42
S = (Attribute == MCSA_Weak) ? DefinedWeak : DefinedGlobal;
43
break;
44
45
case NeverSeen:
46
case Global:
47
case Used:
48
S = (Attribute == MCSA_Weak) ? UndefinedWeak : Global;
49
break;
50
case UndefinedWeak:
51
case DefinedWeak:
52
break;
53
}
54
}
55
56
void RecordStreamer::markUsed(const MCSymbol &Symbol) {
57
State &S = Symbols[Symbol.getName()];
58
switch (S) {
59
case DefinedGlobal:
60
case Defined:
61
case Global:
62
case DefinedWeak:
63
case UndefinedWeak:
64
break;
65
66
case NeverSeen:
67
case Used:
68
S = Used;
69
break;
70
}
71
}
72
73
void RecordStreamer::visitUsedSymbol(const MCSymbol &Sym) { markUsed(Sym); }
74
75
RecordStreamer::RecordStreamer(MCContext &Context, const Module &M)
76
: MCStreamer(Context), M(M) {}
77
78
RecordStreamer::const_iterator RecordStreamer::begin() {
79
return Symbols.begin();
80
}
81
82
RecordStreamer::const_iterator RecordStreamer::end() { return Symbols.end(); }
83
84
void RecordStreamer::emitLabel(MCSymbol *Symbol, SMLoc Loc) {
85
MCStreamer::emitLabel(Symbol);
86
markDefined(*Symbol);
87
}
88
89
void RecordStreamer::emitAssignment(MCSymbol *Symbol, const MCExpr *Value) {
90
markDefined(*Symbol);
91
MCStreamer::emitAssignment(Symbol, Value);
92
}
93
94
bool RecordStreamer::emitSymbolAttribute(MCSymbol *Symbol,
95
MCSymbolAttr Attribute) {
96
if (Attribute == MCSA_Global || Attribute == MCSA_Weak)
97
markGlobal(*Symbol, Attribute);
98
if (Attribute == MCSA_LazyReference)
99
markUsed(*Symbol);
100
return true;
101
}
102
103
void RecordStreamer::emitZerofill(MCSection *Section, MCSymbol *Symbol,
104
uint64_t Size, Align ByteAlignment,
105
SMLoc Loc) {
106
markDefined(*Symbol);
107
}
108
109
void RecordStreamer::emitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
110
Align ByteAlignment) {
111
markDefined(*Symbol);
112
}
113
114
RecordStreamer::State RecordStreamer::getSymbolState(const MCSymbol *Sym) {
115
auto SI = Symbols.find(Sym->getName());
116
if (SI == Symbols.end())
117
return NeverSeen;
118
return SI->second;
119
}
120
121
void RecordStreamer::emitELFSymverDirective(const MCSymbol *OriginalSym,
122
StringRef Name,
123
bool KeepOriginalSym) {
124
SymverAliasMap[OriginalSym].push_back(Name);
125
}
126
127
iterator_range<RecordStreamer::const_symver_iterator>
128
RecordStreamer::symverAliases() {
129
return {SymverAliasMap.begin(), SymverAliasMap.end()};
130
}
131
132
void RecordStreamer::flushSymverDirectives() {
133
// Mapping from mangled name to GV.
134
StringMap<const GlobalValue *> MangledNameMap;
135
// The name in the assembler will be mangled, but the name in the IR
136
// might not, so we first compute a mapping from mangled name to GV.
137
Mangler Mang;
138
SmallString<64> MangledName;
139
for (const GlobalValue &GV : M.global_values()) {
140
if (!GV.hasName())
141
continue;
142
MangledName.clear();
143
MangledName.reserve(GV.getName().size() + 1);
144
Mang.getNameWithPrefix(MangledName, &GV, /*CannotUsePrivateLabel=*/false);
145
MangledNameMap[MangledName] = &GV;
146
}
147
148
// Walk all the recorded .symver aliases, and set up the binding
149
// for each alias.
150
for (auto &Symver : SymverAliasMap) {
151
const MCSymbol *Aliasee = Symver.first;
152
MCSymbolAttr Attr = MCSA_Invalid;
153
bool IsDefined = false;
154
155
// First check if the aliasee binding was recorded in the asm.
156
RecordStreamer::State state = getSymbolState(Aliasee);
157
switch (state) {
158
case RecordStreamer::Global:
159
case RecordStreamer::DefinedGlobal:
160
Attr = MCSA_Global;
161
break;
162
case RecordStreamer::UndefinedWeak:
163
case RecordStreamer::DefinedWeak:
164
Attr = MCSA_Weak;
165
break;
166
default:
167
break;
168
}
169
170
switch (state) {
171
case RecordStreamer::Defined:
172
case RecordStreamer::DefinedGlobal:
173
case RecordStreamer::DefinedWeak:
174
IsDefined = true;
175
break;
176
case RecordStreamer::NeverSeen:
177
case RecordStreamer::Global:
178
case RecordStreamer::Used:
179
case RecordStreamer::UndefinedWeak:
180
break;
181
}
182
183
if (Attr == MCSA_Invalid || !IsDefined) {
184
const GlobalValue *GV = M.getNamedValue(Aliasee->getName());
185
if (!GV) {
186
auto MI = MangledNameMap.find(Aliasee->getName());
187
if (MI != MangledNameMap.end())
188
GV = MI->second;
189
}
190
if (GV) {
191
// If we don't have a symbol attribute from assembly, then check if
192
// the aliasee was defined in the IR.
193
if (Attr == MCSA_Invalid) {
194
if (GV->hasExternalLinkage())
195
Attr = MCSA_Global;
196
else if (GV->hasLocalLinkage())
197
Attr = MCSA_Local;
198
else if (GV->isWeakForLinker())
199
Attr = MCSA_Weak;
200
}
201
IsDefined = IsDefined || !GV->isDeclarationForLinker();
202
}
203
}
204
205
// Set the detected binding on each alias with this aliasee.
206
for (auto AliasName : Symver.second) {
207
std::pair<StringRef, StringRef> Split = AliasName.split("@@@");
208
SmallString<128> NewName;
209
if (!Split.second.empty() && !Split.second.starts_with("@")) {
210
// Special processing for "@@@" according
211
// https://sourceware.org/binutils/docs/as/Symver.html
212
const char *Separator = IsDefined ? "@@" : "@";
213
AliasName =
214
(Split.first + Separator + Split.second).toStringRef(NewName);
215
}
216
MCSymbol *Alias = getContext().getOrCreateSymbol(AliasName);
217
// TODO: Handle "@@@". Depending on SymbolAttribute value it needs to be
218
// converted into @ or @@.
219
const MCExpr *Value = MCSymbolRefExpr::create(Aliasee, getContext());
220
if (IsDefined)
221
markDefined(*Alias);
222
// Don't use EmitAssignment override as it always marks alias as defined.
223
MCStreamer::emitAssignment(Alias, Value);
224
if (Attr != MCSA_Invalid)
225
emitSymbolAttribute(Alias, Attr);
226
}
227
}
228
}
229
230