mirror of
https://github.com/gbdev/rgbds.git
synced 2025-11-23 11:32:07 +00:00
RGBLINK lists local symbols when encountering an unknown symbol reference (#1496)
This commit is contained in:
@@ -49,4 +49,6 @@ void sym_AddSymbol(Symbol &symbol);
|
|||||||
*/
|
*/
|
||||||
Symbol *sym_GetSymbol(std::string const &name);
|
Symbol *sym_GetSymbol(std::string const &name);
|
||||||
|
|
||||||
|
void sym_DumpLocalAliasedSymbols(std::string const &name);
|
||||||
|
|
||||||
#endif // RGBDS_LINK_SYMBOL_HPP
|
#endif // RGBDS_LINK_SYMBOL_HPP
|
||||||
|
|||||||
@@ -564,8 +564,7 @@ void obj_ReadFile(char const *fileName, unsigned int fileID) {
|
|||||||
|
|
||||||
readSymbol(file, symbol, fileName, nodes[fileID]);
|
readSymbol(file, symbol, fileName, nodes[fileID]);
|
||||||
|
|
||||||
if (symbol.type == SYMTYPE_EXPORT)
|
sym_AddSymbol(symbol);
|
||||||
sym_AddSymbol(symbol);
|
|
||||||
if (symbol.data.holds<Label>())
|
if (symbol.data.holds<Label>())
|
||||||
nbSymPerSect[symbol.data.get<Label>().sectionID]++;
|
nbSymPerSect[symbol.data.get<Label>().sectionID]++;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -388,6 +388,7 @@ static int32_t computeRPNExpr(Patch const &patch, std::vector<Symbol> const &fil
|
|||||||
"Unknown symbol \"%s\"",
|
"Unknown symbol \"%s\"",
|
||||||
fileSymbols[value].name.c_str()
|
fileSymbols[value].name.c_str()
|
||||||
);
|
);
|
||||||
|
sym_DumpLocalAliasedSymbols(fileSymbols[value].name);
|
||||||
isError = true;
|
isError = true;
|
||||||
} else if (symbol->data.holds<Label>()) {
|
} else if (symbol->data.holds<Label>()) {
|
||||||
Label const &label = symbol->data.get<Label>();
|
Label const &label = symbol->data.get<Label>();
|
||||||
|
|||||||
@@ -382,6 +382,7 @@ void sdobj_ReadFile(FileStackNode const &where, FILE *file, std::vector<Symbol>
|
|||||||
// Expected format: /[DR]ef[0-9A-F]+/i
|
// Expected format: /[DR]ef[0-9A-F]+/i
|
||||||
if (token[0] == 'R' || token[0] == 'r') {
|
if (token[0] == 'R' || token[0] == 'r') {
|
||||||
symbol.type = SYMTYPE_IMPORT;
|
symbol.type = SYMTYPE_IMPORT;
|
||||||
|
sym_AddSymbol(symbol);
|
||||||
// TODO: hard error if the rest is not zero
|
// TODO: hard error if the rest is not zero
|
||||||
} else if (token[0] != 'D' && token[0] != 'd') {
|
} else if (token[0] != 'D' && token[0] != 'd') {
|
||||||
fatal(&where, lineNo, "'S' line is neither \"Def\" nor \"Ref\"");
|
fatal(&where, lineNo, "'S' line is neither \"Def\" nor \"Ref\"");
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "helpers.hpp" // assume
|
#include "helpers.hpp" // assume
|
||||||
|
|
||||||
@@ -11,6 +12,7 @@
|
|||||||
#include "link/section.hpp"
|
#include "link/section.hpp"
|
||||||
|
|
||||||
std::unordered_map<std::string, Symbol *> symbols;
|
std::unordered_map<std::string, Symbol *> symbols;
|
||||||
|
std::unordered_map<std::string, std::vector<Symbol *>> localSymbols;
|
||||||
|
|
||||||
void sym_ForEach(void (*callback)(Symbol &)) {
|
void sym_ForEach(void (*callback)(Symbol &)) {
|
||||||
for (auto &it : symbols)
|
for (auto &it : symbols)
|
||||||
@@ -18,6 +20,12 @@ void sym_ForEach(void (*callback)(Symbol &)) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void sym_AddSymbol(Symbol &symbol) {
|
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);
|
Symbol *other = sym_GetSymbol(symbol.name);
|
||||||
int32_t *symValue = symbol.data.holds<int32_t>() ? &symbol.data.get<int32_t>() : nullptr;
|
int32_t *symValue = symbol.data.holds<int32_t>() ? &symbol.data.get<int32_t>() : nullptr;
|
||||||
int32_t *otherValue =
|
int32_t *otherValue =
|
||||||
@@ -41,3 +49,30 @@ Symbol *sym_GetSymbol(std::string const &name) {
|
|||||||
auto search = symbols.find(name);
|
auto search = symbols.find(name);
|
||||||
return search != symbols.end() ? search->second : nullptr;
|
return search != symbols.end() ? search->second : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void sym_DumpLocalAliasedSymbols(std::string const &name) {
|
||||||
|
std::vector<Symbol *> const &locals = localSymbols[name];
|
||||||
|
int count = 0;
|
||||||
|
for (Symbol *local : locals) {
|
||||||
|
if (count++ == 3) {
|
||||||
|
size_t remaining = locals.size() - 3;
|
||||||
|
bool plural = remaining != 1;
|
||||||
|
fprintf(
|
||||||
|
stderr,
|
||||||
|
" ...and %zu more symbol%s with that name %s defined but not exported\n",
|
||||||
|
remaining,
|
||||||
|
plural ? "s" : "",
|
||||||
|
plural ? "are" : "is"
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
fprintf(
|
||||||
|
stderr,
|
||||||
|
" A %s with that name is defined but not exported at ",
|
||||||
|
local->data.holds<Label>() ? "label" : "constant"
|
||||||
|
);
|
||||||
|
assume(local->src);
|
||||||
|
local->src->dump(local->lineNo);
|
||||||
|
putc('\n', stderr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
2
test/link/symbols/unknown/a.asm
Normal file
2
test/link/symbols/unknown/a.asm
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
section "a", rom0
|
||||||
|
ld hl, Label
|
||||||
2
test/link/symbols/unknown/b.asm
Normal file
2
test/link/symbols/unknown/b.asm
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
section "b", rom0
|
||||||
|
Label:
|
||||||
1
test/link/symbols/unknown/c.asm
Normal file
1
test/link/symbols/unknown/c.asm
Normal file
@@ -0,0 +1 @@
|
|||||||
|
def Label equ 42
|
||||||
1
test/link/symbols/unknown/d.asm
Normal file
1
test/link/symbols/unknown/d.asm
Normal file
@@ -0,0 +1 @@
|
|||||||
|
def Label = 123
|
||||||
2
test/link/symbols/unknown/e.asm
Normal file
2
test/link/symbols/unknown/e.asm
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
section "e", wram0
|
||||||
|
Label:
|
||||||
6
test/link/symbols/unknown/out.err
Normal file
6
test/link/symbols/unknown/out.err
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
error: symbols/unknown/a.asm(2): Unknown symbol "Label"
|
||||||
|
A label with that name is defined but not exported at symbols/unknown/b.asm(2)
|
||||||
|
A constant with that name is defined but not exported at symbols/unknown/c.asm(1)
|
||||||
|
A constant with that name is defined but not exported at symbols/unknown/d.asm(1)
|
||||||
|
...and 1 more symbol with that name is defined but not exported
|
||||||
|
Linking failed with 1 error
|
||||||
@@ -8,10 +8,11 @@ gbtemp="$(mktemp)"
|
|||||||
gbtemp2="$(mktemp)"
|
gbtemp2="$(mktemp)"
|
||||||
outtemp="$(mktemp)"
|
outtemp="$(mktemp)"
|
||||||
outtemp2="$(mktemp)"
|
outtemp2="$(mktemp)"
|
||||||
|
outtemp3="$(mktemp)"
|
||||||
|
|
||||||
# Immediate expansion is the desired behavior.
|
# Immediate expansion is the desired behavior.
|
||||||
# shellcheck disable=SC2064
|
# shellcheck disable=SC2064
|
||||||
trap "rm -f ${otemp@Q} ${gbtemp@Q} ${gbtemp2@Q} ${outtemp@Q} ${outtemp2@Q}" EXIT
|
trap "rm -f ${otemp@Q} ${gbtemp@Q} ${gbtemp2@Q} ${outtemp@Q} ${outtemp2@Q} ${outtemp3@Q}" EXIT
|
||||||
|
|
||||||
tests=0
|
tests=0
|
||||||
failed=0
|
failed=0
|
||||||
@@ -316,7 +317,7 @@ for i in section-union/*.asm; do
|
|||||||
evaluateTest
|
evaluateTest
|
||||||
done
|
done
|
||||||
|
|
||||||
test="symbols"
|
test="symbols/good"
|
||||||
startTest
|
startTest
|
||||||
"$RGBASM" -o "$otemp" "$test"/a.asm
|
"$RGBASM" -o "$otemp" "$test"/a.asm
|
||||||
"$RGBASM" -o "$gbtemp2" "$test"/b.asm
|
"$RGBASM" -o "$gbtemp2" "$test"/b.asm
|
||||||
@@ -327,6 +328,18 @@ tryDiff "$test"/ref.out.sym "$outtemp2"
|
|||||||
tryCmpRom "$test"/ref.out.bin
|
tryCmpRom "$test"/ref.out.bin
|
||||||
evaluateTest
|
evaluateTest
|
||||||
|
|
||||||
|
test="symbols/unknown"
|
||||||
|
startTest
|
||||||
|
"$RGBASM" -o "$otemp" "$test"/a.asm
|
||||||
|
"$RGBASM" -o "$gbtemp" "$test"/b.asm
|
||||||
|
"$RGBASM" -o "$gbtemp2" "$test"/c.asm
|
||||||
|
"$RGBASM" -o "$outtemp" "$test"/d.asm
|
||||||
|
"$RGBASM" -o "$outtemp2" "$test"/e.asm
|
||||||
|
continueTest
|
||||||
|
rgblinkQuiet "$otemp" "$gbtemp" "$gbtemp2" "$outtemp" "$outtemp2" 2>"$outtemp3"
|
||||||
|
tryDiff "$test"/out.err "$outtemp3"
|
||||||
|
evaluateTest
|
||||||
|
|
||||||
if [[ "$failed" -eq 0 ]]; then
|
if [[ "$failed" -eq 0 ]]; then
|
||||||
echo "${bold}${green}All ${tests} tests passed!${rescolors}${resbold}"
|
echo "${bold}${green}All ${tests} tests passed!${rescolors}${resbold}"
|
||||||
else
|
else
|
||||||
|
|||||||
Reference in New Issue
Block a user