preproc: generate .size in script_data sections (#9233)

This commit is contained in:
Martin Griffin 2026-03-19 10:42:51 +00:00 committed by GitHub
parent ccb9c4d294
commit 4af2bd3207
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 99 additions and 19 deletions

View File

@ -529,7 +529,7 @@ ifneq ($(NODEP),1)
endif
$(DATA_ASM_BUILDDIR)/%.o: $(DATA_ASM_SUBDIR)/%.s
$(PREPROC) $< charmap.txt | $(CPP) $(CPPFLAGS) $(INCLUDE_SCANINC_ARGS) - | $(PREPROC) -ie $< charmap.txt | $(AS) $(ASFLAGS) -o $@
$(PREPROC) -s $< charmap.txt | $(CPP) $(CPPFLAGS) $(INCLUDE_SCANINC_ARGS) - | $(PREPROC) -ie $< charmap.txt | $(AS) $(ASFLAGS) -o $@
$(DATA_ASM_BUILDDIR)/%.d: $(DATA_ASM_SUBDIR)/%.s
$(SCANINC) -M $@ $(INCLUDE_SCANINC_ARGS) -I "" $<

View File

@ -160,9 +160,9 @@ Directive AsmFile::GetDirective()
return Directive::Unknown;
}
// Checks if we're at label that ends with '::'.
// Returns the name if so and an empty string if not.
std::string AsmFile::GetGlobalLabel()
// Checks if we're at label and if so, returns its symbol and scope.
// Returns 'label::none' if not.
Label AsmFile::GetLabel()
{
long start = m_pos;
long pos = m_pos;
@ -175,14 +175,57 @@ std::string AsmFile::GetGlobalLabel()
pos++;
}
if (m_buffer[pos] == ':' && m_buffer[pos + 1] == ':')
if (m_buffer[pos] == ':')
{
m_pos = pos + 2;
ExpectEmptyRestOfLine();
return std::string(&m_buffer[start], pos - start);
std::string symbol(&m_buffer[start], pos - start);
if (m_buffer[pos + 1] == ':')
{
m_pos = pos + 2;
ExpectEmptyRestOfLine();
return Label(symbol, Label::global);
}
else
{
m_pos = pos + 1;
return Label(symbol, Label::local);
}
}
return std::string();
return Label("", Label::none);
}
std::string AsmFile::PeekSection()
{
long oldPos = m_pos;
std::string section;
SkipWhitespace();
// TODO: Support 'pushsection', 'popsection', '.previous'.
if (CheckForDirective(".bss"))
{
section = ".bss";
}
else if (CheckForDirective(".data"))
{
section = ".data";
}
else if (CheckForDirective(".rodata"))
{
section = ".rodata";
}
else if (CheckForDirective(".text"))
{
section = ".text";
}
else if (CheckForDirective(".section"))
{
SkipWhitespace();
section = ReadIdentifier();
}
m_pos = oldPos;
return section;
}
// Skips tabs and spaces.

View File

@ -35,6 +35,17 @@ enum class Directive
Unknown
};
struct Label
{
std::string symbol;
enum Type { none, global, local } type;
Label() : symbol(""), type(none) {}
Label(const Label&) = default;
Label(std::string symbol_, Type type_) : symbol(symbol_), type(type_) {}
explicit operator bool() { return !symbol.empty() && type != none; }
};
class AsmFile
{
public:
@ -43,7 +54,8 @@ public:
AsmFile(const AsmFile&) = delete;
~AsmFile();
Directive GetDirective();
std::string GetGlobalLabel();
Label GetLabel();
std::string PeekSection();
std::string ReadPath();
int ReadString(unsigned char* s);
int ReadBraille(unsigned char* s);
@ -60,6 +72,7 @@ private:
long m_lineNum;
long m_lineStart;
std::string m_filename;
bool m_scriptData;
bool ConsumeComma();
int ReadPadLength();

View File

@ -51,9 +51,11 @@ void PrintAsmBytes(unsigned char *s, int length)
}
}
void PreprocAsmFile(std::string filename, bool isStdin, bool doEnum)
void PreprocAsmFile(std::string filename, bool isStdin, bool doEnum, bool doSize)
{
std::stack<AsmFile> stack;
Label prevLabel;
bool inScriptData = false;
stack.push(AsmFile(filename, isStdin, doEnum));
std::printf("# 1 \"%s\"\n", filename.c_str());
@ -62,6 +64,11 @@ void PreprocAsmFile(std::string filename, bool isStdin, bool doEnum)
{
while (stack.top().IsAtEnd())
{
const char *ps = prevLabel.symbol.c_str();
if (doSize && inScriptData && prevLabel)
std::printf(".ifdef %s ; .size %s, . - %s ; .endif\n", ps, ps, ps);
prevLabel = Label();
stack.pop();
if (stack.empty())
@ -100,15 +107,28 @@ void PreprocAsmFile(std::string filename, bool isStdin, bool doEnum)
}
case Directive::Unknown:
{
std::string globalLabel = stack.top().GetGlobalLabel();
Label label = stack.top().GetLabel();
if (globalLabel.length() != 0)
if (label)
{
const char *s = globalLabel.c_str();
std::printf("%s: ; .global %s\n", s, s);
const char *s = label.symbol.c_str();
const char *ps = prevLabel.symbol.c_str();
if (doSize && inScriptData && prevLabel)
std::printf(".ifdef %s ; .size %s, . - %s ; .endif ; ", ps, ps, ps);
if (label.type == Label::global)
std::printf(".global %s\n%s:\n", s, s);
prevLabel = label;
}
else
{
std::string section = stack.top().PeekSection();
if (section == "script_data")
inScriptData = true;
else if (section != "")
inScriptData = false;
stack.top().OutputLine();
}
@ -147,7 +167,7 @@ const char* GetFileExtension(const char* filename)
static void UsageAndExit(const char *program)
{
std::fprintf(stderr, "Usage: %s [-i] [-e] SRC_FILE CHARMAP_FILE\nwhere -i denotes if input is from stdin\n -e enables enum handling\n", program);
std::fprintf(stderr, "Usage: %s [-i] [-e] [-s] SRC_FILE CHARMAP_FILE\nwhere -i denotes if input is from stdin\n -e enables enum handling\n -s enables '.size' handling\n", program);
std::exit(EXIT_FAILURE);
}
@ -158,9 +178,10 @@ int main(int argc, char **argv)
const char *charmap = NULL;
bool isStdin = false;
bool doEnum = false;
bool doSize = false;
/* preproc [-i] [-e] SRC_FILE CHARMAP_FILE */
while ((opt = getopt(argc, argv, "ie")) != -1)
/* preproc [-i] [-e] [-s] SRC_FILE CHARMAP_FILE */
while ((opt = getopt(argc, argv, "ies")) != -1)
{
switch (opt)
{
@ -170,6 +191,9 @@ int main(int argc, char **argv)
case 'e':
doEnum = true;
break;
case 's':
doSize = true;
break;
default:
UsageAndExit(argv[0]);
break;
@ -196,7 +220,7 @@ int main(int argc, char **argv)
if ((extension[0] == 's') && extension[1] == 0)
{
PreprocAsmFile(source, isStdin, doEnum);
PreprocAsmFile(source, isStdin, doEnum, doSize);
}
else if ((extension[0] == 'c' || extension[0] == 'i') && extension[1] == 0)
{