blob: 477c7cb6e21fdad10888a1c5149fde90738eda8f [file] [log] [blame]
Michael J. Spencer773a8fb2011-12-18 08:27:59 +00001//===- Core/SymbolTable.cpp - Main Symbol Table ---------------------------===//
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 "lld/Core/SymbolTable.h"
Nick Kledzik6bc04c62012-02-22 21:56:59 +000011#include "lld/Core/AbsoluteAtom.h"
Michael J. Spencer4586fbc2013-01-22 20:49:42 +000012#include "lld/Core/Atom.h"
Michael J. Spencercfd029f2012-03-28 19:04:02 +000013#include "lld/Core/DefinedAtom.h"
Michael J. Spencer773a8fb2011-12-18 08:27:59 +000014#include "lld/Core/File.h"
Michael J. Spencere6203a52012-04-03 18:39:40 +000015#include "lld/Core/LLVM.h"
Michael J. Spencer773a8fb2011-12-18 08:27:59 +000016#include "lld/Core/Resolver.h"
Michael J. Spencercfd029f2012-03-28 19:04:02 +000017#include "lld/Core/SharedLibraryAtom.h"
Rui Ueyama0ca149f2013-08-06 22:31:59 +000018#include "lld/Core/LinkingContext.h"
Michael J. Spencercfd029f2012-03-28 19:04:02 +000019#include "lld/Core/UndefinedAtom.h"
Michael J. Spencer773a8fb2011-12-18 08:27:59 +000020
Nick Kledzikbfedfc12012-01-09 20:18:15 +000021#include "llvm/ADT/ArrayRef.h"
Michael J. Spencercfd029f2012-03-28 19:04:02 +000022#include "llvm/ADT/DenseMapInfo.h"
Michael J. Spencer67f25272013-03-20 22:18:22 +000023#include "llvm/ADT/Hashing.h"
Michael J. Spencercfd029f2012-03-28 19:04:02 +000024#include "llvm/Support/ErrorHandling.h"
Nick Kledzikbb963df2012-04-18 21:55:06 +000025#include "llvm/Support/raw_ostream.h"
Michael J. Spencer773a8fb2011-12-18 08:27:59 +000026
27#include <algorithm>
28#include <cassert>
Michael J. Spencercfd029f2012-03-28 19:04:02 +000029#include <cstdlib>
Michael J. Spencer773a8fb2011-12-18 08:27:59 +000030#include <vector>
31
32namespace lld {
Simon Atanasyan07000872014-09-08 09:43:38 +000033SymbolTable::SymbolTable(LinkingContext &context) : _context(context) {}
Nick Kledzik38eec3d2011-12-22 02:38:01 +000034
Rui Ueyama2a522512014-05-14 17:29:27 +000035bool SymbolTable::add(const UndefinedAtom &atom) { return addByName(atom); }
Nick Kledzikf4fb2c52012-01-11 01:06:19 +000036
Rui Ueyama2a522512014-05-14 17:29:27 +000037bool SymbolTable::add(const SharedLibraryAtom &atom) { return addByName(atom); }
Michael J. Spencer765792d2012-04-03 18:40:27 +000038
Rui Ueyama2a522512014-05-14 17:29:27 +000039bool SymbolTable::add(const AbsoluteAtom &atom) { return addByName(atom); }
Nick Kledzik6bc04c62012-02-22 21:56:59 +000040
Rui Ueyama2a522512014-05-14 17:29:27 +000041bool SymbolTable::add(const DefinedAtom &atom) {
Shankar Easwaran8962feb2013-03-14 16:09:49 +000042 if (!atom.name().empty() &&
Rui Ueyama8b08c372013-11-25 17:09:29 +000043 atom.scope() != DefinedAtom::scopeTranslationUnit) {
Nick Kledzik233f5372013-01-15 00:17:57 +000044 // Named atoms cannot be merged by content.
45 assert(atom.merge() != DefinedAtom::mergeByContent);
46 // Track named atoms that are not scoped to file (static).
Rui Ueyama2a522512014-05-14 17:29:27 +000047 return addByName(atom);
Rui Ueyama8b08c372013-11-25 17:09:29 +000048 }
49 if (atom.merge() == DefinedAtom::mergeByContent) {
Nick Kledzik233f5372013-01-15 00:17:57 +000050 // Named atoms cannot be merged by content.
51 assert(atom.name().empty());
Nick Kledzik388f3d02014-05-28 01:16:35 +000052 // Currently only read-only constants can be merged.
53 if (atom.permissions() == DefinedAtom::permR__)
54 return addByContent(atom);
55 // TODO: support mergeByContent of data atoms by comparing content & fixups.
Michael J. Spencer773a8fb2011-12-18 08:27:59 +000056 }
Rui Ueyama2a522512014-05-14 17:29:27 +000057 return false;
Michael J. Spencer773a8fb2011-12-18 08:27:59 +000058}
59
Shankar Easwaran7ac2a3d2014-03-26 16:37:13 +000060const Atom *SymbolTable::findGroup(StringRef sym) {
61 NameToAtom::iterator pos = _groupTable.find(sym);
62 if (pos == _groupTable.end())
63 return nullptr;
64 return pos->second;
65}
66
67bool SymbolTable::addGroup(const DefinedAtom &da) {
68 StringRef name = da.name();
69 assert(!name.empty());
70 const Atom *existing = findGroup(name);
71 if (existing == nullptr) {
72 _groupTable[name] = &da;
73 return true;
74 }
75 _replacedAtoms[&da] = existing;
76 return false;
77}
78
Michael J. Spencer773a8fb2011-12-18 08:27:59 +000079enum NameCollisionResolution {
80 NCR_First,
81 NCR_Second,
Nick Kledzik6bc04c62012-02-22 21:56:59 +000082 NCR_DupDef,
83 NCR_DupUndef,
84 NCR_DupShLib,
Michael J. Spencer773a8fb2011-12-18 08:27:59 +000085 NCR_Error
86};
87
Nick Kledzikf4fb2c52012-01-11 01:06:19 +000088static NameCollisionResolution cases[4][4] = {
89 //regular absolute undef sharedLib
Michael J. Spencer773a8fb2011-12-18 08:27:59 +000090 {
91 // first is regular
Nick Kledzik6bc04c62012-02-22 21:56:59 +000092 NCR_DupDef, NCR_Error, NCR_First, NCR_First
Michael J. Spencer773a8fb2011-12-18 08:27:59 +000093 },
94 {
95 // first is absolute
Nick Kledzikf4fb2c52012-01-11 01:06:19 +000096 NCR_Error, NCR_Error, NCR_First, NCR_First
Michael J. Spencer773a8fb2011-12-18 08:27:59 +000097 },
98 {
99 // first is undef
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000100 NCR_Second, NCR_Second, NCR_DupUndef, NCR_Second
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000101 },
102 {
103 // first is sharedLib
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000104 NCR_Second, NCR_Second, NCR_First, NCR_DupShLib
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000105 }
106};
107
108static NameCollisionResolution collide(Atom::Definition first,
109 Atom::Definition second) {
110 return cases[first][second];
111}
112
Nick Kledzikf4fb2c52012-01-11 01:06:19 +0000113enum MergeResolution {
114 MCR_First,
115 MCR_Second,
116 MCR_Largest,
Rui Ueyamac79dd2f2014-03-07 23:05:10 +0000117 MCR_SameSize,
Nick Kledzikf4fb2c52012-01-11 01:06:19 +0000118 MCR_Error
119};
120
Rui Ueyama7ad72eb2014-03-18 19:37:50 +0000121static MergeResolution mergeCases[][6] = {
122 // no tentative weak weakAddress sameNameAndSize largest
123 {MCR_Error, MCR_First, MCR_First, MCR_First, MCR_SameSize, MCR_Largest}, // no
124 {MCR_Second, MCR_Largest, MCR_Second, MCR_Second, MCR_SameSize, MCR_Largest}, // tentative
125 {MCR_Second, MCR_First, MCR_First, MCR_Second, MCR_SameSize, MCR_Largest}, // weak
126 {MCR_Second, MCR_First, MCR_First, MCR_First, MCR_SameSize, MCR_Largest}, // weakAddress
127 {MCR_SameSize, MCR_SameSize, MCR_SameSize, MCR_SameSize, MCR_SameSize, MCR_SameSize}, // sameSize
128 {MCR_Largest, MCR_Largest, MCR_Largest, MCR_Largest, MCR_SameSize, MCR_Largest}, // largest
Nick Kledzikf4fb2c52012-01-11 01:06:19 +0000129};
130
Michael J. Spencer765792d2012-04-03 18:40:27 +0000131static MergeResolution mergeSelect(DefinedAtom::Merge first,
Nick Kledzikf4fb2c52012-01-11 01:06:19 +0000132 DefinedAtom::Merge second) {
Rui Ueyama7caea312014-03-08 00:44:01 +0000133 assert(first != DefinedAtom::mergeByContent);
134 assert(second != DefinedAtom::mergeByContent);
Nick Kledzikf4fb2c52012-01-11 01:06:19 +0000135 return mergeCases[first][second];
136}
137
Rui Ueyama331f4822014-04-04 18:34:40 +0000138static const DefinedAtom *followReference(const DefinedAtom *atom,
139 uint32_t kind) {
140 for (const Reference *r : *atom)
141 if (r->kindNamespace() == Reference::KindNamespace::all &&
142 r->kindArch() == Reference::KindArch::all &&
143 r->kindValue() == kind)
144 return cast<const DefinedAtom>(r->target());
145 return nullptr;
146}
147
148static uint64_t getSizeFollowReferences(const DefinedAtom *atom,
149 uint32_t kind) {
Rui Ueyama7ad72eb2014-03-18 19:37:50 +0000150 uint64_t size = 0;
Rui Ueyama331f4822014-04-04 18:34:40 +0000151 for (;;) {
152 atom = followReference(atom, kind);
153 if (!atom)
154 return size;
155 size += atom->size();
Rui Ueyama7ad72eb2014-03-18 19:37:50 +0000156 }
Rui Ueyama7ad72eb2014-03-18 19:37:50 +0000157}
158
159// Returns the size of the section containing the given atom. Atoms in the same
160// section are connected by layout-before and layout-after edges, so this
161// function traverses them to get the total size of atoms in the same section.
162static uint64_t sectionSize(const DefinedAtom *atom) {
163 return atom->size()
164 + getSizeFollowReferences(atom, lld::Reference::kindLayoutBefore)
165 + getSizeFollowReferences(atom, lld::Reference::kindLayoutAfter);
166}
167
Rui Ueyama2a522512014-05-14 17:29:27 +0000168bool SymbolTable::addByName(const Atom &newAtom) {
Michael J. Spencere6203a52012-04-03 18:39:40 +0000169 StringRef name = newAtom.name();
Nick Kledzik233f5372013-01-15 00:17:57 +0000170 assert(!name.empty());
Shankar Easwaran7ac2a3d2014-03-26 16:37:13 +0000171 const Atom *existing = findByName(name);
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000172 if (existing == nullptr) {
Nick Kledzik7735a7d2012-01-04 23:58:17 +0000173 // Name is not in symbol table yet, add it associate with this atom.
Nick Kledzikbb38f7b2014-08-20 20:46:28 +0000174 _context.notifySymbolTableAdd(&newAtom);
Nick Kledzik38eec3d2011-12-22 02:38:01 +0000175 _nameTable[name] = &newAtom;
Rui Ueyama2a522512014-05-14 17:29:27 +0000176 return true;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000177 }
Rui Ueyamaf347e752013-11-13 23:22:00 +0000178
Rui Ueyama2a522512014-05-14 17:29:27 +0000179 // Do nothing if the same object is added more than once.
180 if (existing == &newAtom)
181 return false;
182
Rui Ueyamaf347e752013-11-13 23:22:00 +0000183 // Name is already in symbol table and associated with another atom.
184 bool useNew = true;
185 switch (collide(existing->definition(), newAtom.definition())) {
186 case NCR_First:
187 useNew = false;
188 break;
189 case NCR_Second:
190 useNew = true;
191 break;
192 case NCR_DupDef:
Rui Ueyama0abf6132014-10-14 21:42:08 +0000193 switch (mergeSelect(cast<DefinedAtom>(existing)->merge(),
194 cast<DefinedAtom>(&newAtom)->merge())) {
Rui Ueyama5a3804f2013-11-25 17:09:25 +0000195 case MCR_First:
196 useNew = false;
197 break;
198 case MCR_Second:
199 useNew = true;
200 break;
Rui Ueyama7ad72eb2014-03-18 19:37:50 +0000201 case MCR_Largest: {
202 uint64_t existingSize = sectionSize((DefinedAtom*)existing);
203 uint64_t newSize = sectionSize((DefinedAtom*)&newAtom);
204 useNew = (newSize >= existingSize);
Rui Ueyama5a3804f2013-11-25 17:09:25 +0000205 break;
Rui Ueyama7ad72eb2014-03-18 19:37:50 +0000206 }
Rui Ueyamac79dd2f2014-03-07 23:05:10 +0000207 case MCR_SameSize: {
Rui Ueyama7ad72eb2014-03-18 19:37:50 +0000208 uint64_t existingSize = sectionSize((DefinedAtom*)existing);
209 uint64_t newSize = sectionSize((DefinedAtom*)&newAtom);
210 if (existingSize == newSize) {
Rui Ueyamac79dd2f2014-03-07 23:05:10 +0000211 useNew = true;
212 break;
213 }
214 llvm::errs() << "Size mismatch: "
Rui Ueyama7ad72eb2014-03-18 19:37:50 +0000215 << existing->name() << " (" << existingSize << ") "
216 << newAtom.name() << " (" << newSize << ")\n";
Rui Ueyamac79dd2f2014-03-07 23:05:10 +0000217 // fallthrough
218 }
Rui Ueyama5a3804f2013-11-25 17:09:25 +0000219 case MCR_Error:
Rui Ueyamaa9a51292014-03-28 16:26:38 +0000220 if (!_context.getAllowDuplicates()) {
221 llvm::errs() << "Duplicate symbols: "
222 << existing->name()
223 << ":"
224 << existing->file().path()
225 << " and "
226 << newAtom.name()
227 << ":"
228 << newAtom.file().path()
229 << "\n";
230 llvm::report_fatal_error("duplicate symbol error");
231 }
232 useNew = false;
Rui Ueyama5a3804f2013-11-25 17:09:25 +0000233 break;
Rui Ueyamaf347e752013-11-13 23:22:00 +0000234 }
235 break;
236 case NCR_DupUndef: {
Rui Ueyama01cc7182014-04-04 18:21:51 +0000237 const UndefinedAtom* existingUndef = cast<UndefinedAtom>(existing);
238 const UndefinedAtom* newUndef = cast<UndefinedAtom>(&newAtom);
Rui Ueyamab4dca7f2013-11-15 03:12:24 +0000239
240 bool sameCanBeNull = (existingUndef->canBeNull() == newUndef->canBeNull());
241 if (!sameCanBeNull &&
242 _context.warnIfCoalesableAtomsHaveDifferentCanBeNull()) {
243 llvm::errs() << "lld warning: undefined symbol "
244 << existingUndef->name()
245 << " has different weakness in "
246 << existingUndef->file().path()
247 << " and in " << newUndef->file().path() << "\n";
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000248 }
Rui Ueyamab4dca7f2013-11-15 03:12:24 +0000249
250 const UndefinedAtom *existingFallback = existingUndef->fallback();
251 const UndefinedAtom *newFallback = newUndef->fallback();
252 bool hasDifferentFallback =
253 (existingFallback && newFallback &&
254 existingFallback->name() != newFallback->name());
255 if (hasDifferentFallback) {
256 llvm::errs() << "lld warning: undefined symbol "
257 << existingUndef->name() << " has different fallback: "
258 << existingFallback->name() << " in "
259 << existingUndef->file().path() << " and "
260 << newFallback->name() << " in "
261 << newUndef->file().path() << "\n";
262 }
263
264 bool hasNewFallback = newUndef->fallback();
265 if (sameCanBeNull)
266 useNew = hasNewFallback;
267 else
268 useNew = (newUndef->canBeNull() < existingUndef->canBeNull());
Rui Ueyamaf347e752013-11-13 23:22:00 +0000269 break;
Rui Ueyamab4dca7f2013-11-15 03:12:24 +0000270 }
Rui Ueyamaf347e752013-11-13 23:22:00 +0000271 case NCR_DupShLib: {
Rui Ueyama01cc7182014-04-04 18:21:51 +0000272 const SharedLibraryAtom *curShLib = cast<SharedLibraryAtom>(existing);
273 const SharedLibraryAtom *newShLib = cast<SharedLibraryAtom>(&newAtom);
Rui Ueyamafb7936d2014-04-04 18:12:27 +0000274 bool sameNullness =
275 (curShLib->canBeNullAtRuntime() == newShLib->canBeNullAtRuntime());
276 bool sameName = curShLib->loadName().equals(newShLib->loadName());
Rui Ueyamae8af3e42014-04-04 18:21:53 +0000277 if (sameName && !sameNullness &&
278 _context.warnIfCoalesableAtomsHaveDifferentCanBeNull()) {
279 // FIXME: need diagonstics interface for writing warning messages
280 llvm::errs() << "lld warning: shared library symbol "
281 << curShLib->name() << " has different weakness in "
282 << curShLib->file().path() << " and in "
283 << newShLib->file().path();
Nick Kledzik7735a7d2012-01-04 23:58:17 +0000284 }
Rui Ueyamae8af3e42014-04-04 18:21:53 +0000285 if (!sameName && _context.warnIfCoalesableAtomsHaveDifferentLoadName()) {
286 // FIXME: need diagonstics interface for writing warning messages
287 llvm::errs() << "lld warning: shared library symbol "
288 << curShLib->name() << " has different load path in "
289 << curShLib->file().path() << " and in "
290 << newShLib->file().path();
291 }
292 useNew = false;
Rui Ueyamaf347e752013-11-13 23:22:00 +0000293 break;
Rui Ueyamafb7936d2014-04-04 18:12:27 +0000294 }
Rui Ueyamabcccb5d2013-11-13 23:23:38 +0000295 case NCR_Error:
296 llvm::errs() << "SymbolTable: error while merging " << name << "\n";
Rui Ueyama9310e012013-11-14 06:39:31 +0000297 llvm::report_fatal_error("duplicate symbol error");
298 break;
Rui Ueyamaf347e752013-11-13 23:22:00 +0000299 }
Rui Ueyamabcccb5d2013-11-13 23:23:38 +0000300
Nick Kledzikbb38f7b2014-08-20 20:46:28 +0000301 // Give context a chance to change which is kept.
302 _context.notifySymbolTableCoalesce(existing, &newAtom, useNew);
303
Rui Ueyamaf347e752013-11-13 23:22:00 +0000304 if (useNew) {
305 // Update name table to use new atom.
306 _nameTable[name] = &newAtom;
307 // Add existing atom to replacement table.
308 _replacedAtoms[existing] = &newAtom;
309 } else {
310 // New atom is not being used. Add it to replacement table.
311 _replacedAtoms[&newAtom] = existing;
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000312 }
Rui Ueyama2a522512014-05-14 17:29:27 +0000313 return false;
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000314}
315
Michael J. Spencer67f25272013-03-20 22:18:22 +0000316unsigned SymbolTable::AtomMappingInfo::getHashValue(const DefinedAtom *atom) {
317 auto content = atom->rawContent();
318 return llvm::hash_combine(atom->size(),
319 atom->contentType(),
320 llvm::hash_combine_range(content.begin(),
321 content.end()));
Nick Kledzikbfedfc12012-01-09 20:18:15 +0000322}
323
Michael J. Spencer765792d2012-04-03 18:40:27 +0000324bool SymbolTable::AtomMappingInfo::isEqual(const DefinedAtom * const l,
Michael J. Spencer67f25272013-03-20 22:18:22 +0000325 const DefinedAtom * const r) {
Rui Ueyamaf347e752013-11-13 23:22:00 +0000326 if (l == r)
Nick Kledzikbfedfc12012-01-09 20:18:15 +0000327 return true;
Rui Ueyamaf347e752013-11-13 23:22:00 +0000328 if (l == getEmptyKey())
Nick Kledzikbfedfc12012-01-09 20:18:15 +0000329 return false;
Rui Ueyamaf347e752013-11-13 23:22:00 +0000330 if (r == getEmptyKey())
Nick Kledzikbfedfc12012-01-09 20:18:15 +0000331 return false;
Rui Ueyamaf347e752013-11-13 23:22:00 +0000332 if (l == getTombstoneKey())
Nick Kledzikbfedfc12012-01-09 20:18:15 +0000333 return false;
Rui Ueyamaf347e752013-11-13 23:22:00 +0000334 if (r == getTombstoneKey())
Nick Kledzikbfedfc12012-01-09 20:18:15 +0000335 return false;
Rui Ueyamaf347e752013-11-13 23:22:00 +0000336 if (l->contentType() != r->contentType())
Nick Kledzikbfedfc12012-01-09 20:18:15 +0000337 return false;
Rui Ueyamaf347e752013-11-13 23:22:00 +0000338 if (l->size() != r->size())
Nick Kledzikbfedfc12012-01-09 20:18:15 +0000339 return false;
Nick Kledzik32d0d092014-10-02 17:22:05 +0000340 if (l->sectionChoice() != r->sectionChoice())
341 return false;
342 if (l->sectionChoice() == DefinedAtom::sectionCustomRequired) {
343 if (!l->customSectionName().equals(r->customSectionName()))
344 return false;
345 }
Michael J. Spencere6203a52012-04-03 18:39:40 +0000346 ArrayRef<uint8_t> lc = l->rawContent();
347 ArrayRef<uint8_t> rc = r->rawContent();
Michael J. Spencer67f25272013-03-20 22:18:22 +0000348 return memcmp(lc.data(), rc.data(), lc.size()) == 0;
Nick Kledzikbfedfc12012-01-09 20:18:15 +0000349}
350
Rui Ueyama2a522512014-05-14 17:29:27 +0000351bool SymbolTable::addByContent(const DefinedAtom &newAtom) {
Nick Kledzikbfedfc12012-01-09 20:18:15 +0000352 AtomContentSet::iterator pos = _contentTable.find(&newAtom);
Rui Ueyamaf347e752013-11-13 23:22:00 +0000353 if (pos == _contentTable.end()) {
Nick Kledzikbfedfc12012-01-09 20:18:15 +0000354 _contentTable.insert(&newAtom);
Rui Ueyama2a522512014-05-14 17:29:27 +0000355 return true;
Nick Kledzikbfedfc12012-01-09 20:18:15 +0000356 }
357 const Atom* existing = *pos;
Rui Ueyamaf347e752013-11-13 23:22:00 +0000358 // New atom is not being used. Add it to replacement table.
359 _replacedAtoms[&newAtom] = existing;
Rui Ueyama2a522512014-05-14 17:29:27 +0000360 return false;
Nick Kledzikbfedfc12012-01-09 20:18:15 +0000361}
362
Michael J. Spencere6203a52012-04-03 18:39:40 +0000363const Atom *SymbolTable::findByName(StringRef sym) {
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000364 NameToAtom::iterator pos = _nameTable.find(sym);
365 if (pos == _nameTable.end())
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000366 return nullptr;
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000367 return pos->second;
368}
369
Michael J. Spencere6203a52012-04-03 18:39:40 +0000370bool SymbolTable::isDefined(StringRef sym) {
Rui Ueyama71c02022014-04-03 22:43:42 +0000371 if (const Atom *atom = findByName(sym))
Rui Ueyama0abf6132014-10-14 21:42:08 +0000372 return !isa<UndefinedAtom>(atom);
Rui Ueyama71c02022014-04-03 22:43:42 +0000373 return false;
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000374}
375
Rui Ueyamae5416ec2013-09-12 19:14:05 +0000376void SymbolTable::addReplacement(const Atom *replaced,
377 const Atom *replacement) {
378 _replacedAtoms[replaced] = replacement;
379}
380
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000381const Atom *SymbolTable::replacement(const Atom *atom) {
Rui Ueyama1c3486a2014-04-03 22:58:41 +0000382 // Find the replacement for a given atom. Atoms in _replacedAtoms
383 // may be chained, so find the last one.
Rui Ueyama4f010d22014-04-03 22:36:55 +0000384 for (;;) {
385 AtomToAtom::iterator pos = _replacedAtoms.find(atom);
386 if (pos == _replacedAtoms.end())
387 return atom;
Rui Ueyama4f010d22014-04-03 22:36:55 +0000388 atom = pos->second;
389 }
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000390}
391
Rui Ueyama733b45f2014-06-05 07:37:29 +0000392bool SymbolTable::isCoalescedAway(const Atom *atom) {
393 return _replacedAtoms.count(atom) > 0;
394}
395
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000396unsigned int SymbolTable::size() {
397 return _nameTable.size();
398}
399
Rui Ueyama8dc9f0a2014-04-04 00:15:52 +0000400std::vector<const UndefinedAtom *> SymbolTable::undefines() {
401 std::vector<const UndefinedAtom *> ret;
Rui Ueyama17e899c2013-11-25 17:09:27 +0000402 for (auto it : _nameTable) {
403 const Atom *atom = it.second;
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000404 assert(atom != nullptr);
Rui Ueyama839fb2f2014-08-22 02:00:58 +0000405 if (const auto *undef = dyn_cast<const UndefinedAtom>(atom))
406 if (_replacedAtoms.count(undef) == 0)
407 ret.push_back(undef);
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000408 }
Rui Ueyama8dc9f0a2014-04-04 00:15:52 +0000409 return ret;
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000410}
411
Rui Ueyama8dc9f0a2014-04-04 00:15:52 +0000412std::vector<StringRef> SymbolTable::tentativeDefinitions() {
413 std::vector<StringRef> ret;
Nick Kledzik20e652d2012-04-20 01:24:37 +0000414 for (auto entry : _nameTable) {
415 const Atom *atom = entry.second;
416 StringRef name = entry.first;
417 assert(atom != nullptr);
Rui Ueyamaf347e752013-11-13 23:22:00 +0000418 if (const DefinedAtom *defAtom = dyn_cast<DefinedAtom>(atom))
419 if (defAtom->merge() == DefinedAtom::mergeAsTentative)
Rui Ueyama8dc9f0a2014-04-04 00:15:52 +0000420 ret.push_back(name);
Nick Kledzik20e652d2012-04-20 01:24:37 +0000421 }
Rui Ueyama8dc9f0a2014-04-04 00:15:52 +0000422 return ret;
Nick Kledzik20e652d2012-04-20 01:24:37 +0000423}
Rui Ueyama8dc9f0a2014-04-04 00:15:52 +0000424
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000425} // namespace lld