Use std::vector for RPN data

This commit is contained in:
Rangi42
2024-02-22 22:30:44 -05:00
committed by Sylvie
parent a5ea25cde5
commit 17861a970f
3 changed files with 29 additions and 49 deletions

View File

@@ -7,16 +7,12 @@
#include "linkdefs.hpp" #include "linkdefs.hpp"
#define MAXRPNLEN 1048576
struct Expression { struct Expression {
int32_t val; // If the expression's value is known, it's here int32_t val; // If the expression's value is known, it's here
char *reason; // Why the expression is not known, if it isn't char *reason; // Why the expression is not known, if it isn't
bool isKnown; // Whether the expression's value is known bool isKnown; // Whether the expression's value is known
bool isSymbol; // Whether the expression represents a symbol bool isSymbol; // Whether the expression represents a symbol
uint8_t *rpn; // Array of bytes serializing the RPN expression std::vector<uint8_t> *rpn; // Bytes serializing the RPN expression
uint32_t rpnCapacity; // Size of the `rpn` buffer
uint32_t rpnLength; // Used size of the `rpn` buffer
uint32_t rpnPatchSize; // Size the expression will take in the object file uint32_t rpnPatchSize; // Size the expression will take in the object file
}; };

View File

@@ -176,12 +176,12 @@ static uint32_t getSymbolID(struct Symbol *sym)
return sym->ID; return sym->ID;
} }
static void writerpn(std::vector<uint8_t> &rpnexpr, const uint8_t *rpn, uint32_t rpnlen) static void writerpn(std::vector<uint8_t> &rpnexpr, const std::vector<uint8_t> &rpn)
{ {
char symName[512]; char symName[512];
size_t rpnptr = 0; size_t rpnptr = 0;
for (size_t offset = 0; offset < rpnlen; ) { for (size_t offset = 0; offset < rpn.size(); ) {
#define popbyte() rpn[offset++] #define popbyte() rpn[offset++]
#define writebyte(byte) rpnexpr[rpnptr++] = byte #define writebyte(byte) rpnexpr[rpnptr++] = byte
uint8_t rpndata = popbyte(); uint8_t rpndata = popbyte();
@@ -296,7 +296,7 @@ static void initpatch(struct Patch &patch, uint32_t type, struct Expression cons
patch.rpn[3] = (uint32_t)(expr->val) >> 16; patch.rpn[3] = (uint32_t)(expr->val) >> 16;
patch.rpn[4] = (uint32_t)(expr->val) >> 24; patch.rpn[4] = (uint32_t)(expr->val) >> 24;
} else { } else {
writerpn(patch.rpn, expr->rpn, expr->rpnLength); writerpn(patch.rpn, *expr->rpn);
} }
} }

View File

@@ -10,6 +10,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <vector>
#include "asm/main.hpp" #include "asm/main.hpp"
#include "asm/output.hpp" #include "asm/output.hpp"
@@ -39,32 +40,16 @@
static uint8_t *reserveSpace(struct Expression *expr, uint32_t size) static uint8_t *reserveSpace(struct Expression *expr, uint32_t size)
{ {
// This assumes the RPN length is always less than the capacity if (!expr->rpn) {
if (expr->rpnCapacity - expr->rpnLength < size) { expr->rpn = new(std::nothrow) std::vector<uint8_t>();
// If there isn't enough room to reserve the space, realloc
if (!expr->rpn) if (!expr->rpn)
expr->rpnCapacity = 256; // Initial size fatalerror("Failed to allocate RPN expression: %s\n", strerror(errno));
while (expr->rpnCapacity - expr->rpnLength < size) {
if (expr->rpnCapacity >= MAXRPNLEN)
// To avoid generating humongous object files, cap the
// size of RPN expressions
fatalerror("RPN expression cannot grow larger than "
EXPAND_AND_STR(MAXRPNLEN) " bytes\n");
else if (expr->rpnCapacity > MAXRPNLEN / 2)
expr->rpnCapacity = MAXRPNLEN;
else
expr->rpnCapacity *= 2;
}
expr->rpn = (uint8_t *)realloc(expr->rpn, expr->rpnCapacity);
if (!expr->rpn)
fatalerror("Failed to grow RPN expression: %s\n", strerror(errno));
} }
uint8_t *ptr = expr->rpn + expr->rpnLength; size_t curSize = expr->rpn->size();
expr->rpnLength += size; expr->rpn->resize(curSize + size);
return ptr; return &(*expr->rpn)[curSize];
} }
// Init a RPN expression // Init a RPN expression
@@ -74,15 +59,13 @@ static void rpn_Init(struct Expression *expr)
expr->isKnown = true; expr->isKnown = true;
expr->isSymbol = false; expr->isSymbol = false;
expr->rpn = NULL; expr->rpn = NULL;
expr->rpnCapacity = 0;
expr->rpnLength = 0;
expr->rpnPatchSize = 0; expr->rpnPatchSize = 0;
} }
// Free the RPN expression // Free the RPN expression
void rpn_Free(struct Expression *expr) void rpn_Free(struct Expression *expr)
{ {
free(expr->rpn); delete expr->rpn;
free(expr->reason); free(expr->reason);
rpn_Init(expr); rpn_Init(expr);
} }
@@ -325,7 +308,7 @@ struct Symbol const *rpn_SymbolOf(struct Expression const *expr)
{ {
if (!rpn_isSymbol(expr)) if (!rpn_isSymbol(expr))
return NULL; return NULL;
return sym_FindScopedSymbol((char const *)expr->rpn + 1); return sym_FindScopedSymbol((char const *)&(*expr->rpn)[1]);
} }
bool rpn_IsDiffConstant(struct Expression const *src, struct Symbol const *sym) bool rpn_IsDiffConstant(struct Expression const *src, struct Symbol const *sym)
@@ -551,10 +534,7 @@ void rpn_BinaryOp(enum RPNCommand op, struct Expression *expr,
(uint8_t)(lval >> 16), (uint8_t)(lval >> 24)}; (uint8_t)(lval >> 16), (uint8_t)(lval >> 24)};
expr->rpnPatchSize = sizeof(bytes); expr->rpnPatchSize = sizeof(bytes);
expr->rpn = NULL; expr->rpn = NULL;
expr->rpnCapacity = 0; memcpy(reserveSpace(expr, sizeof(bytes)), bytes, sizeof(bytes));
expr->rpnLength = 0;
memcpy(reserveSpace(expr, sizeof(bytes)), bytes,
sizeof(bytes));
// Use the other expression's un-const reason // Use the other expression's un-const reason
expr->reason = src2->reason; expr->reason = src2->reason;
@@ -563,16 +543,14 @@ void rpn_BinaryOp(enum RPNCommand op, struct Expression *expr,
// Otherwise just reuse its RPN buffer // Otherwise just reuse its RPN buffer
expr->rpnPatchSize = src1->rpnPatchSize; expr->rpnPatchSize = src1->rpnPatchSize;
expr->rpn = src1->rpn; expr->rpn = src1->rpn;
expr->rpnCapacity = src1->rpnCapacity;
expr->rpnLength = src1->rpnLength;
expr->reason = src1->reason; expr->reason = src1->reason;
free(src2->reason); free(src2->reason);
} }
// Now, merge the right expression into the left one // Now, merge the right expression into the left one
uint8_t *ptr = src2->rpn; // Pointer to the right RPN uint8_t const *ptr = NULL;
uint32_t len = src2->rpnLength; // Size of the right RPN uint32_t len = 0;
uint32_t patchSize = src2->rpnPatchSize; uint32_t patchSize = 0;
// If the right expression is constant, merge a shim instead // If the right expression is constant, merge a shim instead
uint32_t rval = src2->val; uint32_t rval = src2->val;
@@ -582,14 +560,20 @@ void rpn_BinaryOp(enum RPNCommand op, struct Expression *expr,
ptr = bytes; ptr = bytes;
len = sizeof(bytes); len = sizeof(bytes);
patchSize = sizeof(bytes); patchSize = sizeof(bytes);
} else {
ptr = &(*src2->rpn)[0]; // Pointer to the right RPN
len = src2->rpn->size(); // Size of the right RPN
patchSize = src2->rpnPatchSize;
} }
// Copy the right RPN and append the operator // Copy the right RPN and append the operator
uint8_t *buf = reserveSpace(expr, len + 1); uint8_t *buf = reserveSpace(expr, len + 1);
if (ptr)
// If there was none, `memcpy(buf, NULL, 0)` would be UB
memcpy(buf, ptr, len); memcpy(buf, ptr, len);
buf[len] = op; buf[len] = op;
free(src2->rpn); // If there was none, this is `free(NULL)` delete src2->rpn; // If there was none, this is `delete NULL`
expr->rpnPatchSize += patchSize + 1; expr->rpnPatchSize += patchSize + 1;
} }
} }