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:
Rangi
2025-07-09 12:13:01 -04:00
committed by GitHub
parent 5e43ece578
commit 41ab5dff5a
19 changed files with 343 additions and 13 deletions

View File

@@ -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 &sect = 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++);
}