Files
rgbds/src/link/symbol.cpp
Rangi 3d155d5695 Some refactoring and cleanup (#1806)
* Use clang-tidy `misc-include-cleaner` for IWYU `#include` cleanup

* Use `std::optional<size_t>` instead of `ssize_t`

* Rename some functions in linkdefs.hpp

* Fix header order
2025-08-20 16:09:04 -04:00

93 lines
2.4 KiB
C++

// SPDX-License-Identifier: MIT
#include "link/symbol.hpp"
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <unordered_map>
#include <utility>
#include <variant>
#include <vector>
#include "helpers.hpp" // assume
#include "linkdefs.hpp"
#include "link/fstack.hpp"
#include "link/section.hpp"
#include "link/warning.hpp"
static std::unordered_map<std::string, Symbol *> symbols;
static std::unordered_map<std::string, std::vector<Symbol *>> localSymbols;
void sym_ForEach(void (*callback)(Symbol &)) {
for (auto &it : symbols) {
callback(*it.second);
}
}
void sym_AddSymbol(Symbol &symbol) {
if (symbol.type != SYMTYPE_EXPORT) {
if (symbol.type != SYMTYPE_IMPORT) {
localSymbols[symbol.name].push_back(&symbol);
}
return;
}
Symbol *other = sym_GetSymbol(symbol.name);
int32_t *symValue =
std::holds_alternative<int32_t>(symbol.data) ? &std::get<int32_t>(symbol.data) : nullptr;
int32_t *otherValue = other && std::holds_alternative<int32_t>(other->data)
? &std::get<int32_t>(other->data)
: nullptr;
// Check if the symbol already exists with a different value
if (other && !(symValue && otherValue && *symValue == *otherValue)) {
std::string symDef = symValue ? std::to_string(*symValue) : "a label";
std::string otherDef = otherValue ? std::to_string(*otherValue) : "another label";
fatalTwoAt(
symbol,
*other,
"`%s` is defined as %s, but also as %s",
symbol.name.c_str(),
symDef.c_str(),
otherDef.c_str()
);
}
// If not, add it (potentially replacing the previous same-value symbol)
symbols[symbol.name] = &symbol;
}
Symbol *sym_GetSymbol(std::string const &name) {
auto search = symbols.find(name);
return search != symbols.end() ? search->second : nullptr;
}
void sym_TraceLocalAliasedSymbols(std::string const &name) {
std::vector<Symbol *> const &locals = localSymbols[name];
if (locals.empty()) {
return;
}
bool plural = locals.size() != 1;
fprintf(
stderr,
" %zu symbol%s with that name %s defined but not exported:\n",
locals.size(),
plural ? "s" : "",
plural ? "are" : "is"
);
int count = 0;
for (Symbol *local : locals) {
assume(local->src);
local->src->printBacktrace(local->lineNo);
if (++count == 3 && locals.size() > 3) {
fprintf(stderr, " ...and %zu more\n", locals.size() - 3);
break;
}
}
}