Refactor structs to use methods instead of functions (#1322)

This commit is contained in:
Sylvie
2024-03-01 13:11:45 -05:00
committed by GitHub
parent e14ba664ea
commit 1ac3c0262f
18 changed files with 364 additions and 446 deletions

View File

@@ -21,6 +21,16 @@
#include "opmath.hpp"
// Init a RPN expression
static void initExpression(Expression *expr)
{
expr->reason = nullptr;
expr->isKnown = true;
expr->isSymbol = false;
expr->rpn = nullptr;
expr->rpnPatchSize = 0;
}
// Makes an expression "not known", also setting its error message
template<typename... Ts>
static void makeUnknown(Expression *expr, Ts ...parts)
@@ -46,28 +56,18 @@ static uint8_t *reserveSpace(Expression *expr, uint32_t size)
return &(*expr->rpn)[curSize];
}
// Init a RPN expression
static void rpn_Init(Expression *expr)
{
expr->reason = nullptr;
expr->isKnown = true;
expr->isSymbol = false;
expr->rpn = nullptr;
expr->rpnPatchSize = 0;
}
// Free the RPN expression
void rpn_Free(Expression *expr)
{
delete expr->rpn;
delete expr->reason;
rpn_Init(expr);
initExpression(expr);
}
// Add symbols, constants and operators to expression
void rpn_Number(Expression *expr, uint32_t i)
{
rpn_Init(expr);
initExpression(expr);
expr->val = i;
}
@@ -78,8 +78,8 @@ void rpn_Symbol(Expression *expr, char const *symName)
if (sym_IsPC(sym) && !sect_GetSymbolSection()) {
error("PC has no value outside a section\n");
rpn_Number(expr, 0);
} else if (!sym || !sym_IsConstant(sym)) {
rpn_Init(expr);
} else if (!sym || !sym->isConstant()) {
initExpression(expr);
expr->isSymbol = true;
if (sym_IsPC(sym))
@@ -100,7 +100,7 @@ void rpn_Symbol(Expression *expr, char const *symName)
void rpn_BankSelf(Expression *expr)
{
rpn_Init(expr);
initExpression(expr);
if (!currentSection) {
error("PC has no bank outside a section\n");
@@ -124,22 +124,23 @@ void rpn_BankSymbol(Expression *expr, char const *symName)
return;
}
rpn_Init(expr);
if (sym && !sym_IsLabel(sym)) {
initExpression(expr);
if (sym && !sym->isLabel()) {
error("BANK argument must be a label\n");
} else {
sym = sym_Ref(symName);
assert(sym); // If the symbol didn't exist, it should have been created
if (sym_GetSection(sym) && sym_GetSection(sym)->bank != (uint32_t)-1) {
if (sym->getSection() && sym->getSection()->bank != (uint32_t)-1) {
// Symbol's section is known and bank is fixed
expr->val = sym_GetSection(sym)->bank;
expr->val = sym->getSection()->bank;
} else {
makeUnknown(expr, "\"", symName, "\"'s bank is not known");
expr->rpnPatchSize += 5; // opcode + 4-byte sect ID
size_t nameLen = strlen(sym->name) + 1; // Room for NUL!
uint8_t *ptr = reserveSpace(expr, nameLen + 1);
*ptr++ = RPN_BANK_SYM;
memcpy(ptr, sym->name, nameLen);
}
@@ -148,7 +149,7 @@ void rpn_BankSymbol(Expression *expr, char const *symName)
void rpn_BankSection(Expression *expr, char const *sectionName)
{
rpn_Init(expr);
initExpression(expr);
Section *section = sect_FindSectionByName(sectionName);
@@ -168,11 +169,11 @@ void rpn_BankSection(Expression *expr, char const *sectionName)
void rpn_SizeOfSection(Expression *expr, char const *sectionName)
{
rpn_Init(expr);
initExpression(expr);
Section *section = sect_FindSectionByName(sectionName);
if (section && sect_IsSizeKnown(section)) {
if (section && section->isSizeKnown()) {
expr->val = section->size;
} else {
makeUnknown(expr, "Section \"", sectionName, "\"'s size is not known");
@@ -188,7 +189,7 @@ void rpn_SizeOfSection(Expression *expr, char const *sectionName)
void rpn_StartOfSection(Expression *expr, char const *sectionName)
{
rpn_Init(expr);
initExpression(expr);
Section *section = sect_FindSectionByName(sectionName);
@@ -208,7 +209,7 @@ void rpn_StartOfSection(Expression *expr, char const *sectionName)
void rpn_SizeOfSectionType(Expression *expr, enum SectionType type)
{
rpn_Init(expr);
initExpression(expr);
makeUnknown(expr, "Section type's size is not known");
uint8_t *ptr = reserveSpace(expr, 2);
@@ -220,7 +221,7 @@ void rpn_SizeOfSectionType(Expression *expr, enum SectionType type)
void rpn_StartOfSectionType(Expression *expr, enum SectionType type)
{
rpn_Init(expr);
initExpression(expr);
makeUnknown(expr, "Section type's start is not known");
uint8_t *ptr = reserveSpace(expr, 2);
@@ -235,7 +236,7 @@ void rpn_CheckHRAM(Expression *expr, const Expression *src)
*expr = *src;
expr->isSymbol = false;
if (!rpn_isKnown(expr)) {
if (!expr->isKnown) {
expr->rpnPatchSize++;
*reserveSpace(expr, 1) = RPN_HRAM;
} else if (expr->val >= 0xFF00 && expr->val <= 0xFFFF) {
@@ -250,7 +251,7 @@ void rpn_CheckRST(Expression *expr, const Expression *src)
{
*expr = *src;
if (rpn_isKnown(expr)) {
if (expr->isKnown) {
// A valid RST address must be masked with 0x38
if (expr->val & ~0x38)
error("Invalid address $%" PRIx32 " for RST\n", expr->val);
@@ -268,7 +269,7 @@ void rpn_CheckNBit(Expression const *expr, uint8_t n)
assert(n != 0); // That doesn't make sense
assert(n < CHAR_BIT * sizeof(int)); // Otherwise `1 << n` is UB
if (rpn_isKnown(expr)) {
if (expr->isKnown) {
int32_t val = expr->val;
if (val < -(1 << n) || val >= 1 << n)
@@ -278,13 +279,13 @@ void rpn_CheckNBit(Expression const *expr, uint8_t n)
}
}
int32_t rpn_GetConstVal(Expression const *expr)
int32_t Expression::getConstVal() const
{
if (!rpn_isKnown(expr)) {
error("Expected constant expression: %s\n", expr->reason->c_str());
if (!isKnown) {
error("Expected constant expression: %s\n", reason->c_str());
return 0;
}
return expr->val;
return val;
}
void rpn_LOGNOT(Expression *expr, const Expression *src)
@@ -292,7 +293,7 @@ void rpn_LOGNOT(Expression *expr, const Expression *src)
*expr = *src;
expr->isSymbol = false;
if (rpn_isKnown(expr)) {
if (expr->isKnown) {
expr->val = !expr->val;
} else {
expr->rpnPatchSize++;
@@ -300,31 +301,26 @@ void rpn_LOGNOT(Expression *expr, const Expression *src)
}
}
Symbol const *rpn_SymbolOf(Expression const *expr)
Symbol const *Expression::symbolOf() const
{
if (!rpn_isSymbol(expr))
if (!isSymbol)
return nullptr;
return sym_FindScopedSymbol((char const *)&(*expr->rpn)[1]);
return sym_FindScopedSymbol((char const *)&(*rpn)[1]);
}
bool rpn_IsDiffConstant(Expression const *src, Symbol const *sym)
bool Expression::isDiffConstant(Symbol const *sym) const
{
// Check if both expressions only refer to a single symbol
Symbol const *sym1 = rpn_SymbolOf(src);
Symbol const *sym1 = symbolOf();
if (!sym1 || !sym || sym1->type != SYM_LABEL || sym->type != SYM_LABEL)
return false;
Section const *section1 = sym_GetSection(sym1);
Section const *section2 = sym_GetSection(sym);
Section const *section1 = sym1->getSection();
Section const *section2 = sym->getSection();
return section1 && (section1 == section2);
}
static bool isDiffConstant(Expression const *src1, Expression const *src2)
{
return rpn_IsDiffConstant(src1, rpn_SymbolOf(src2));
}
/*
* Attempts to compute a constant binary AND from non-constant operands
* This is possible if one operand is a symbol belonging to an `ALIGN[N]` section, and the other is
@@ -334,33 +330,33 @@ static bool isDiffConstant(Expression const *src1, Expression const *src2)
*/
static int32_t tryConstMask(Expression const *lhs, Expression const *rhs)
{
Symbol const *sym = rpn_SymbolOf(lhs);
Symbol const *sym = lhs->symbolOf();
Expression const *expr = rhs;
if (!sym || !sym_GetSection(sym)) {
if (!sym || !sym->getSection()) {
// If the lhs isn't a symbol, try again the other way around
sym = rpn_SymbolOf(rhs);
sym = rhs->symbolOf();
expr = lhs;
if (!sym || !sym_GetSection(sym))
if (!sym || !sym->getSection())
return -1;
}
assert(sym_IsNumeric(sym));
assert(sym->isNumeric());
if (!rpn_isKnown(expr))
if (!expr->isKnown)
return -1;
// We can now safely use `expr->val`
Section const *sect = sym_GetSection(sym);
Section const *sect = sym->getSection();
int32_t unknownBits = (1 << 16) - (1 << sect->align); // The max alignment is 16
// The mask must ignore all unknown bits
if ((expr->val & unknownBits) != 0)
return -1;
// `sym_GetValue()` attempts to add the section's address,
// but that's "-1" because the section is floating (otherwise we wouldn't be here)
// `sym->getValue()` attempts to add the section's address, but that's "-1"
// because the section is floating (otherwise we wouldn't be here)
assert(sect->org == (uint32_t)-1);
int32_t symbolOfs = sym_GetValue(sym) + 1;
int32_t symbolOfs = sym->getValue() + 1;
return (symbolOfs + sect->alignOfs) & ~unknownBits;
}
@@ -371,9 +367,9 @@ void rpn_BinaryOp(enum RPNCommand op, Expression *expr, const Expression *src1,
int32_t constMaskVal;
// First, check if the expression is known
expr->isKnown = rpn_isKnown(src1) && rpn_isKnown(src2);
if (rpn_isKnown(expr)) {
rpn_Init(expr); // Init the expression to something sane
expr->isKnown = src1->isKnown && src2->isKnown;
if (expr->isKnown) {
initExpression(expr); // Init the expression to something sane
// If both expressions are known, just compute the value
uint32_t uleft = src1->val, uright = src2->val;
@@ -509,11 +505,11 @@ void rpn_BinaryOp(enum RPNCommand op, Expression *expr, const Expression *src1,
fatalerror("%d is not a binary operator\n", op);
}
} else if (op == RPN_SUB && isDiffConstant(src1, src2)) {
Symbol const *symbol1 = rpn_SymbolOf(src1);
Symbol const *symbol2 = rpn_SymbolOf(src2);
} else if (op == RPN_SUB && src1->isDiffConstant(src2->symbolOf())) {
Symbol const *symbol1 = src1->symbolOf();
Symbol const *symbol2 = src2->symbolOf();
expr->val = sym_GetValue(symbol1) - sym_GetValue(symbol2);
expr->val = symbol1->getValue() - symbol2->getValue();
expr->isKnown = true;
} else if (op == RPN_AND && (constMaskVal = tryConstMask(src1, src2)) != -1) {
expr->val = constMaskVal;
@@ -522,7 +518,7 @@ void rpn_BinaryOp(enum RPNCommand op, Expression *expr, const Expression *src1,
// If it's not known, start computing the RPN expression
// Convert the left-hand expression if it's constant
if (rpn_isKnown(src1)) {
if (src1->isKnown) {
uint32_t lval = src1->val;
uint8_t bytes[] = {RPN_CONST, (uint8_t)lval, (uint8_t)(lval >> 8),
(uint8_t)(lval >> 16), (uint8_t)(lval >> 24)};
@@ -550,7 +546,7 @@ void rpn_BinaryOp(enum RPNCommand op, Expression *expr, const Expression *src1,
uint32_t rval = src2->val;
uint8_t bytes[] = {RPN_CONST, (uint8_t)rval, (uint8_t)(rval >> 8),
(uint8_t)(rval >> 16), (uint8_t)(rval >> 24)};
if (rpn_isKnown(src2)) {
if (src2->isKnown) {
ptr = bytes;
len = sizeof(bytes);
patchSize = sizeof(bytes);
@@ -577,7 +573,7 @@ void rpn_HIGH(Expression *expr, const Expression *src)
*expr = *src;
expr->isSymbol = false;
if (rpn_isKnown(expr)) {
if (expr->isKnown) {
expr->val = (uint32_t)expr->val >> 8 & 0xFF;
} else {
uint8_t bytes[] = {RPN_CONST, 8, 0, 0, 0, RPN_SHR,
@@ -592,7 +588,7 @@ void rpn_LOW(Expression *expr, const Expression *src)
*expr = *src;
expr->isSymbol = false;
if (rpn_isKnown(expr)) {
if (expr->isKnown) {
expr->val = expr->val & 0xFF;
} else {
uint8_t bytes[] = {RPN_CONST, 0xFF, 0, 0, 0, RPN_AND};
@@ -604,8 +600,8 @@ void rpn_LOW(Expression *expr, const Expression *src)
void rpn_ISCONST(Expression *expr, const Expression *src)
{
rpn_Init(expr);
expr->val = rpn_isKnown(src);
initExpression(expr);
expr->val = src->isKnown;
expr->isKnown = true;
expr->isSymbol = false;
}
@@ -615,7 +611,7 @@ void rpn_NEG(Expression *expr, const Expression *src)
*expr = *src;
expr->isSymbol = false;
if (rpn_isKnown(expr)) {
if (expr->isKnown) {
expr->val = -(uint32_t)expr->val;
} else {
expr->rpnPatchSize++;
@@ -628,7 +624,7 @@ void rpn_NOT(Expression *expr, const Expression *src)
*expr = *src;
expr->isSymbol = false;
if (rpn_isKnown(expr)) {
if (expr->isKnown) {
expr->val = ~expr->val;
} else {
expr->rpnPatchSize++;