mirror of
https://github.com/gbdev/rgbds.git
synced 2025-11-21 02:32:06 +00:00
Implement [[ fragment literals ]] (#1614)
This feature is referred to as "code/data literals" in ASMotor, and simply as "literals" in some older assemblers like MIDAS for the PDP-10. RGBASM already had the "section fragments" feature for keeping disparate contents together when linked, so these worked naturally as "fragment literals".
This commit is contained in:
@@ -22,6 +22,8 @@
|
||||
#include "asm/symbol.hpp"
|
||||
#include "asm/warning.hpp"
|
||||
|
||||
using namespace std::literals;
|
||||
|
||||
uint8_t fillByte;
|
||||
|
||||
struct UnionStackEntry {
|
||||
@@ -311,6 +313,32 @@ static Section *createSection(
|
||||
return §
|
||||
}
|
||||
|
||||
// Create a new section fragment literal, not yet in the list.
|
||||
static Section *createSectionFragmentLiteral(Section const &parent) {
|
||||
// Add the new section to the list, but do not update the map
|
||||
Section § = sectionList.emplace_back();
|
||||
assume(sectionMap.find(parent.name) != sectionMap.end());
|
||||
|
||||
sect.name = parent.name;
|
||||
sect.type = parent.type;
|
||||
sect.modifier = SECTION_FRAGMENT;
|
||||
sect.src = fstk_GetFileStack();
|
||||
sect.fileLine = lexer_GetLineNo();
|
||||
sect.size = 0;
|
||||
sect.org = UINT32_MAX;
|
||||
sect.bank = parent.bank == 0 ? UINT32_MAX : parent.bank;
|
||||
sect.align = 0;
|
||||
sect.alignOfs = 0;
|
||||
|
||||
out_RegisterNode(sect.src);
|
||||
|
||||
// Section fragment literals must be ROM sections.
|
||||
assume(sect_HasData(sect.type));
|
||||
sect.data.resize(sectionTypeInfo[sect.type].size);
|
||||
|
||||
return §
|
||||
}
|
||||
|
||||
// Find a section by name and type. If it doesn't exist, create it.
|
||||
static Section *getSection(
|
||||
std::string const &name,
|
||||
@@ -1067,3 +1095,40 @@ void sect_EndSection() {
|
||||
currentSection = nullptr;
|
||||
sym_ResetCurrentLabelScopes();
|
||||
}
|
||||
|
||||
std::string sect_PushSectionFragmentLiteral() {
|
||||
static uint64_t nextFragmentLiteralID = 0;
|
||||
|
||||
// Like `requireCodeSection` but fatal
|
||||
if (!currentSection) {
|
||||
fatal("Cannot output fragment literals outside of a SECTION");
|
||||
}
|
||||
if (!sect_HasData(currentSection->type)) {
|
||||
fatal(
|
||||
"Section '%s' cannot contain fragment literals (not ROM0 or ROMX)",
|
||||
currentSection->name.c_str()
|
||||
);
|
||||
}
|
||||
|
||||
if (currentLoadSection) {
|
||||
fatal("`LOAD` blocks cannot contain fragment literals");
|
||||
}
|
||||
if (currentSection->modifier == SECTION_UNION) {
|
||||
fatal("`SECTION UNION` cannot contain fragment literals");
|
||||
}
|
||||
|
||||
// A section containing a fragment literal has to become a fragment too
|
||||
currentSection->modifier = SECTION_FRAGMENT;
|
||||
|
||||
Section *parent = currentSection;
|
||||
sect_PushSection(); // Resets `currentSection`
|
||||
|
||||
Section *sect = createSectionFragmentLiteral(*parent);
|
||||
|
||||
changeSection();
|
||||
curOffset = sect->size;
|
||||
currentSection = sect;
|
||||
|
||||
// Return a symbol ID to use for the address of this section fragment
|
||||
return "$"s + std::to_string(nextFragmentLiteralID++);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user