mirror of
https://github.com/gbdev/rgbds.git
synced 2025-11-20 10:12:06 +00:00
Compare commits
2 Commits
ca383c91ca
...
df5162edca
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
df5162edca | ||
|
|
2519d1e698 |
@@ -60,13 +60,4 @@
|
|||||||
#define _POSIX_C_SOURCE 200809L
|
#define _POSIX_C_SOURCE 200809L
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// gcc and clang have their own `musttail` attributes for tail recursion
|
|
||||||
#if defined(__clang__) && __has_cpp_attribute(clang::musttail)
|
|
||||||
#define MUSTTAIL [[clang::musttail]]
|
|
||||||
#elif defined(__GNUC__) && __has_cpp_attribute(gnu::musttail)
|
|
||||||
#define MUSTTAIL [[gnu::musttail]]
|
|
||||||
#else
|
|
||||||
#define MUSTTAIL
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // RGBDS_PLATFORM_HPP
|
#endif // RGBDS_PLATFORM_HPP
|
||||||
|
|||||||
@@ -154,6 +154,8 @@ of string constants:
|
|||||||
will be expanded in all of
|
will be expanded in all of
|
||||||
.Ql DEF({name}) ,
|
.Ql DEF({name}) ,
|
||||||
.Ql DEF {name} EQU/=/EQUS/etc ... ,
|
.Ql DEF {name} EQU/=/EQUS/etc ... ,
|
||||||
|
.Ql REDEF {name} EQU/=/EQUS/etc ... ,
|
||||||
|
.Ql FOR {name}, ... ,
|
||||||
.Ql PURGE {name} ,
|
.Ql PURGE {name} ,
|
||||||
and
|
and
|
||||||
.Ql MACRO {name} ,
|
.Ql MACRO {name} ,
|
||||||
@@ -1556,6 +1558,8 @@ in the C programming language.
|
|||||||
This expansion is disabled in a few contexts:
|
This expansion is disabled in a few contexts:
|
||||||
.Ql DEF(name) ,
|
.Ql DEF(name) ,
|
||||||
.Ql DEF name EQU/=/EQUS/etc ... ,
|
.Ql DEF name EQU/=/EQUS/etc ... ,
|
||||||
|
.Ql REDEF name EQU/=/EQUS/etc ... ,
|
||||||
|
.Ql FOR name, ... ,
|
||||||
.Ql PURGE name ,
|
.Ql PURGE name ,
|
||||||
and
|
and
|
||||||
.Ql MACRO name
|
.Ql MACRO name
|
||||||
|
|||||||
@@ -716,6 +716,7 @@ int LexerState::peekCharAhead() {
|
|||||||
static std::pair<Symbol const *, std::shared_ptr<std::string>> readInterpolation(size_t depth);
|
static std::pair<Symbol const *, std::shared_ptr<std::string>> readInterpolation(size_t depth);
|
||||||
|
|
||||||
static int peek() {
|
static int peek() {
|
||||||
|
for (;;) {
|
||||||
int c = lexerState->peekChar();
|
int c = lexerState->peekChar();
|
||||||
|
|
||||||
if (lexerState->expansionScanDistance > 0) {
|
if (lexerState->expansionScanDistance > 0) {
|
||||||
@@ -732,7 +733,6 @@ static int peek() {
|
|||||||
if (!isMacroChar(lexerState->peekCharAhead())) {
|
if (!isMacroChar(lexerState->peekCharAhead())) {
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If character is a macro arg char, do macro arg expansion
|
// If character is a macro arg char, do macro arg expansion
|
||||||
shiftChar();
|
shiftChar();
|
||||||
if (std::shared_ptr<std::string> str = readMacroArg(); str) {
|
if (std::shared_ptr<std::string> str = readMacroArg(); str) {
|
||||||
@@ -743,20 +743,19 @@ static int peek() {
|
|||||||
// https://en.wikipedia.org/wiki/Painted_blue
|
// https://en.wikipedia.org/wiki/Painted_blue
|
||||||
lexerState->expansionScanDistance += str->length();
|
lexerState->expansionScanDistance += str->length();
|
||||||
}
|
}
|
||||||
|
// Continue in the next iteration
|
||||||
MUSTTAIL return peek();
|
|
||||||
} else if (c == '{') {
|
} else if (c == '{') {
|
||||||
// If character is an open brace, do symbol interpolation
|
// If character is an open brace, do symbol interpolation
|
||||||
shiftChar();
|
shiftChar();
|
||||||
if (auto interp = readInterpolation(0); interp.first && interp.second) {
|
if (auto interp = readInterpolation(0); interp.first && interp.second) {
|
||||||
beginExpansion(interp.second, interp.first->name);
|
beginExpansion(interp.second, interp.first->name);
|
||||||
}
|
}
|
||||||
|
// Continue in the next iteration
|
||||||
MUSTTAIL return peek();
|
|
||||||
} else {
|
} else {
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void shiftChar() {
|
static void shiftChar() {
|
||||||
if (lexerState->capturing) {
|
if (lexerState->capturing) {
|
||||||
@@ -1943,8 +1942,6 @@ static Token yylex_NORMAL() {
|
|||||||
if (Symbol const *sym = sym_FindExactSymbol(std::get<std::string>(token.value));
|
if (Symbol const *sym = sym_FindExactSymbol(std::get<std::string>(token.value));
|
||||||
sym && sym->type == SYM_EQUS) {
|
sym && sym->type == SYM_EQUS) {
|
||||||
beginExpansion(sym->getEqus(), sym->name);
|
beginExpansion(sym->getEqus(), sym->name);
|
||||||
// We cannot do `MUSTTAIL return yylex_NORMAL();` because tail call optimization
|
|
||||||
// requires the return value to be "trivially destructible", and `Token` is not.
|
|
||||||
continue; // Restart, reading from the new buffer
|
continue; // Restart, reading from the new buffer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,6 @@
|
|||||||
#include "helpers.hpp"
|
#include "helpers.hpp"
|
||||||
#include "itertools.hpp"
|
#include "itertools.hpp"
|
||||||
#include "linkdefs.hpp"
|
#include "linkdefs.hpp"
|
||||||
#include "platform.hpp" // MUSTTAIL
|
|
||||||
#include "verbosity.hpp"
|
#include "verbosity.hpp"
|
||||||
|
|
||||||
#include "link/main.hpp"
|
#include "link/main.hpp"
|
||||||
@@ -119,6 +118,7 @@ static MemoryLocation getStartLocation(Section const §ion) {
|
|||||||
static std::optional<size_t> getPlacement(Section const §ion, MemoryLocation &location) {
|
static std::optional<size_t> getPlacement(Section const §ion, MemoryLocation &location) {
|
||||||
SectionTypeInfo const &typeInfo = sectionTypeInfo[section.type];
|
SectionTypeInfo const &typeInfo = sectionTypeInfo[section.type];
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
// Switch to the beginning of the next bank
|
// Switch to the beginning of the next bank
|
||||||
std::deque<FreeSpace> &bankMem = memory[section.type][location.bank - typeInfo.firstBank];
|
std::deque<FreeSpace> &bankMem = memory[section.type][location.bank - typeInfo.firstBank];
|
||||||
size_t spaceIdx = 0;
|
size_t spaceIdx = 0;
|
||||||
@@ -137,12 +137,11 @@ static std::optional<size_t> getPlacement(Section const §ion, MemoryLocation
|
|||||||
// Go to the next *possible* location
|
// Go to the next *possible* location
|
||||||
if (section.isAddressFixed) {
|
if (section.isAddressFixed) {
|
||||||
// If the address is fixed, there can be only one candidate block per bank;
|
// If the address is fixed, there can be only one candidate block per bank;
|
||||||
// if we already reached it, give up.
|
// if we already reached it, give up and try again in the next bank.
|
||||||
if (location.address < section.org) {
|
if (location.address >= section.org) {
|
||||||
location.address = section.org;
|
break;
|
||||||
} else {
|
|
||||||
break; // Try again in next bank
|
|
||||||
}
|
}
|
||||||
|
location.address = section.org;
|
||||||
} else if (section.isAlignFixed) {
|
} else if (section.isAlignFixed) {
|
||||||
// Move to next aligned location
|
// Move to next aligned location
|
||||||
// Move back to alignment boundary
|
// Move back to alignment boundary
|
||||||
@@ -204,7 +203,8 @@ static std::optional<size_t> getPlacement(Section const §ion, MemoryLocation
|
|||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
MUSTTAIL return getPlacement(section, location);
|
// Try again in the next iteration.
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string getSectionDescription(Section const §ion) {
|
static std::string getSectionDescription(Section const §ion) {
|
||||||
|
|||||||
Reference in New Issue
Block a user