diff --git a/include/asm/rpn.hpp b/include/asm/rpn.hpp index 63561adf..17f3d2df 100644 --- a/include/asm/rpn.hpp +++ b/include/asm/rpn.hpp @@ -7,16 +7,12 @@ #include "linkdefs.hpp" -#define MAXRPNLEN 1048576 - struct Expression { - 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 - bool isKnown; // Whether the expression's value is known - bool isSymbol; // Whether the expression represents a symbol - uint8_t *rpn; // Array of bytes serializing the RPN expression - uint32_t rpnCapacity; // Size of the `rpn` buffer - uint32_t rpnLength; // Used size of the `rpn` buffer + 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 + bool isKnown; // Whether the expression's value is known + bool isSymbol; // Whether the expression represents a symbol + std::vector *rpn; // Bytes serializing the RPN expression uint32_t rpnPatchSize; // Size the expression will take in the object file }; diff --git a/src/asm/output.cpp b/src/asm/output.cpp index 03ef93ae..65695ec5 100644 --- a/src/asm/output.cpp +++ b/src/asm/output.cpp @@ -176,12 +176,12 @@ static uint32_t getSymbolID(struct Symbol *sym) return sym->ID; } -static void writerpn(std::vector &rpnexpr, const uint8_t *rpn, uint32_t rpnlen) +static void writerpn(std::vector &rpnexpr, const std::vector &rpn) { char symName[512]; size_t rpnptr = 0; - for (size_t offset = 0; offset < rpnlen; ) { + for (size_t offset = 0; offset < rpn.size(); ) { #define popbyte() rpn[offset++] #define writebyte(byte) rpnexpr[rpnptr++] = byte 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[4] = (uint32_t)(expr->val) >> 24; } else { - writerpn(patch.rpn, expr->rpn, expr->rpnLength); + writerpn(patch.rpn, *expr->rpn); } } diff --git a/src/asm/rpn.cpp b/src/asm/rpn.cpp index f07f4dba..1d8337ce 100644 --- a/src/asm/rpn.cpp +++ b/src/asm/rpn.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include "asm/main.hpp" #include "asm/output.hpp" @@ -39,32 +40,16 @@ static uint8_t *reserveSpace(struct Expression *expr, uint32_t size) { - // This assumes the RPN length is always less than the capacity - if (expr->rpnCapacity - expr->rpnLength < size) { - // If there isn't enough room to reserve the space, realloc + if (!expr->rpn) { + expr->rpn = new(std::nothrow) std::vector(); if (!expr->rpn) - expr->rpnCapacity = 256; // Initial size - 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)); + fatalerror("Failed to allocate RPN expression: %s\n", strerror(errno)); } - uint8_t *ptr = expr->rpn + expr->rpnLength; + size_t curSize = expr->rpn->size(); - expr->rpnLength += size; - return ptr; + expr->rpn->resize(curSize + size); + return &(*expr->rpn)[curSize]; } // Init a RPN expression @@ -74,15 +59,13 @@ static void rpn_Init(struct Expression *expr) expr->isKnown = true; expr->isSymbol = false; expr->rpn = NULL; - expr->rpnCapacity = 0; - expr->rpnLength = 0; expr->rpnPatchSize = 0; } // Free the RPN expression void rpn_Free(struct Expression *expr) { - free(expr->rpn); + delete expr->rpn; free(expr->reason); rpn_Init(expr); } @@ -325,7 +308,7 @@ struct Symbol const *rpn_SymbolOf(struct Expression const *expr) { if (!rpn_isSymbol(expr)) 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) @@ -551,10 +534,7 @@ void rpn_BinaryOp(enum RPNCommand op, struct Expression *expr, (uint8_t)(lval >> 16), (uint8_t)(lval >> 24)}; expr->rpnPatchSize = sizeof(bytes); expr->rpn = NULL; - expr->rpnCapacity = 0; - expr->rpnLength = 0; - memcpy(reserveSpace(expr, sizeof(bytes)), bytes, - sizeof(bytes)); + memcpy(reserveSpace(expr, sizeof(bytes)), bytes, sizeof(bytes)); // Use the other expression's un-const reason expr->reason = src2->reason; @@ -563,16 +543,14 @@ void rpn_BinaryOp(enum RPNCommand op, struct Expression *expr, // Otherwise just reuse its RPN buffer expr->rpnPatchSize = src1->rpnPatchSize; expr->rpn = src1->rpn; - expr->rpnCapacity = src1->rpnCapacity; - expr->rpnLength = src1->rpnLength; expr->reason = src1->reason; free(src2->reason); } // Now, merge the right expression into the left one - uint8_t *ptr = src2->rpn; // Pointer to the right RPN - uint32_t len = src2->rpnLength; // Size of the right RPN - uint32_t patchSize = src2->rpnPatchSize; + uint8_t const *ptr = NULL; + uint32_t len = 0; + uint32_t patchSize = 0; // If the right expression is constant, merge a shim instead uint32_t rval = src2->val; @@ -582,14 +560,20 @@ void rpn_BinaryOp(enum RPNCommand op, struct Expression *expr, ptr = bytes; len = 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 uint8_t *buf = reserveSpace(expr, len + 1); - memcpy(buf, ptr, len); + if (ptr) + // If there was none, `memcpy(buf, NULL, 0)` would be UB + memcpy(buf, ptr, len); 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; } }