From 4af2bd320702e3ade8771722c98e0bce880aa13b Mon Sep 17 00:00:00 2001 From: Martin Griffin Date: Thu, 19 Mar 2026 10:42:51 +0000 Subject: [PATCH] preproc: generate .size in script_data sections (#9233) --- Makefile | 2 +- tools/preproc/asm_file.cpp | 59 ++++++++++++++++++++++++++++++++------ tools/preproc/asm_file.h | 15 +++++++++- tools/preproc/preproc.cpp | 42 +++++++++++++++++++++------ 4 files changed, 99 insertions(+), 19 deletions(-) diff --git a/Makefile b/Makefile index be29b2ea1e..c699272399 100644 --- a/Makefile +++ b/Makefile @@ -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 "" $< diff --git a/tools/preproc/asm_file.cpp b/tools/preproc/asm_file.cpp index 6cfc4cbdb3..6daf0d841a 100644 --- a/tools/preproc/asm_file.cpp +++ b/tools/preproc/asm_file.cpp @@ -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. diff --git a/tools/preproc/asm_file.h b/tools/preproc/asm_file.h index 9cab32a97f..fe75c1a939 100644 --- a/tools/preproc/asm_file.h +++ b/tools/preproc/asm_file.h @@ -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(); diff --git a/tools/preproc/preproc.cpp b/tools/preproc/preproc.cpp index ac9496d701..57ea7f9d39 100644 --- a/tools/preproc/preproc.cpp +++ b/tools/preproc/preproc.cpp @@ -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 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) {