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 endif
$(DATA_ASM_BUILDDIR)/%.o: $(DATA_ASM_SUBDIR)/%.s $(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 $(DATA_ASM_BUILDDIR)/%.d: $(DATA_ASM_SUBDIR)/%.s
$(SCANINC) -M $@ $(INCLUDE_SCANINC_ARGS) -I "" $< $(SCANINC) -M $@ $(INCLUDE_SCANINC_ARGS) -I "" $<

View File

@ -160,9 +160,9 @@ Directive AsmFile::GetDirective()
return Directive::Unknown; return Directive::Unknown;
} }
// Checks if we're at label that ends with '::'. // Checks if we're at label and if so, returns its symbol and scope.
// Returns the name if so and an empty string if not. // Returns 'label::none' if not.
std::string AsmFile::GetGlobalLabel() Label AsmFile::GetLabel()
{ {
long start = m_pos; long start = m_pos;
long pos = m_pos; long pos = m_pos;
@ -175,14 +175,57 @@ std::string AsmFile::GetGlobalLabel()
pos++; pos++;
} }
if (m_buffer[pos] == ':' && m_buffer[pos + 1] == ':') if (m_buffer[pos] == ':')
{ {
m_pos = pos + 2; std::string symbol(&m_buffer[start], pos - start);
ExpectEmptyRestOfLine(); if (m_buffer[pos + 1] == ':')
return std::string(&m_buffer[start], pos - start); {
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. // Skips tabs and spaces.

View File

@ -35,6 +35,17 @@ enum class Directive
Unknown 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 class AsmFile
{ {
public: public:
@ -43,7 +54,8 @@ public:
AsmFile(const AsmFile&) = delete; AsmFile(const AsmFile&) = delete;
~AsmFile(); ~AsmFile();
Directive GetDirective(); Directive GetDirective();
std::string GetGlobalLabel(); Label GetLabel();
std::string PeekSection();
std::string ReadPath(); std::string ReadPath();
int ReadString(unsigned char* s); int ReadString(unsigned char* s);
int ReadBraille(unsigned char* s); int ReadBraille(unsigned char* s);
@ -60,6 +72,7 @@ private:
long m_lineNum; long m_lineNum;
long m_lineStart; long m_lineStart;
std::string m_filename; std::string m_filename;
bool m_scriptData;
bool ConsumeComma(); bool ConsumeComma();
int ReadPadLength(); 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; std::stack<AsmFile> stack;
Label prevLabel;
bool inScriptData = false;
stack.push(AsmFile(filename, isStdin, doEnum)); stack.push(AsmFile(filename, isStdin, doEnum));
std::printf("# 1 \"%s\"\n", filename.c_str()); 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()) 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(); stack.pop();
if (stack.empty()) if (stack.empty())
@ -100,15 +107,28 @@ void PreprocAsmFile(std::string filename, bool isStdin, bool doEnum)
} }
case Directive::Unknown: 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(); const char *s = label.symbol.c_str();
std::printf("%s: ; .global %s\n", s, s); 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 else
{ {
std::string section = stack.top().PeekSection();
if (section == "script_data")
inScriptData = true;
else if (section != "")
inScriptData = false;
stack.top().OutputLine(); stack.top().OutputLine();
} }
@ -147,7 +167,7 @@ const char* GetFileExtension(const char* filename)
static void UsageAndExit(const char *program) 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); std::exit(EXIT_FAILURE);
} }
@ -158,9 +178,10 @@ int main(int argc, char **argv)
const char *charmap = NULL; const char *charmap = NULL;
bool isStdin = false; bool isStdin = false;
bool doEnum = false; bool doEnum = false;
bool doSize = false;
/* preproc [-i] [-e] SRC_FILE CHARMAP_FILE */ /* preproc [-i] [-e] [-s] SRC_FILE CHARMAP_FILE */
while ((opt = getopt(argc, argv, "ie")) != -1) while ((opt = getopt(argc, argv, "ies")) != -1)
{ {
switch (opt) switch (opt)
{ {
@ -170,6 +191,9 @@ int main(int argc, char **argv)
case 'e': case 'e':
doEnum = true; doEnum = true;
break; break;
case 's':
doSize = true;
break;
default: default:
UsageAndExit(argv[0]); UsageAndExit(argv[0]);
break; break;
@ -196,7 +220,7 @@ int main(int argc, char **argv)
if ((extension[0] == 's') && extension[1] == 0) 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) else if ((extension[0] == 'c' || extension[0] == 'i') && extension[1] == 0)
{ {