ref: 6ff9435e0a3a132a52816d37c9c545799c8b2eb0
parent: 40006c6152935c420b2ad2ecf1ccdfde355fa215
parent: b256e4c2e38ffe82bdfb83a7742e8bf179f32411
author: Antonio Niño Díaz <antonio_nd@outlook.com>
date: Sun May 5 19:33:36 EDT 2019
Merge pull request #335 from dbrotz/fix-334 Dynamically allocate RPN expression buffer
--- a/include/asm/rpn.h
+++ b/include/asm/rpn.h
@@ -13,7 +13,8 @@
struct Expression {
int32_t nVal;
- uint8_t tRPN[256];
+ uint8_t *tRPN;
+ uint32_t nRPNCapacity;
uint32_t nRPNLength;
uint32_t nRPNOut;
uint32_t isReloc;
@@ -69,7 +70,8 @@
void rpn_BankSymbol(struct Expression *expr, char *tzSym);
void rpn_BankSection(struct Expression *expr, char *tzSectionName);
void rpn_BankSelf(struct Expression *expr);
-void rpn_Reset(struct Expression *expr);
+void rpn_Init(struct Expression *expr);
+void rpn_Free(struct Expression *expr);
void rpn_CheckHRAM(struct Expression *expr, const struct Expression *src);
#endif /* RGBDS_ASM_RPN_H */
--- a/src/asm/asmy.y
+++ b/src/asm/asmy.y
@@ -1772,6 +1772,7 @@
(!rpn_isReloc(&$2)) && ($2.nVal >= 0xFF00)) {
out_AbsByte(0xE0);
out_AbsByte($2.nVal & 0xFF);
+ rpn_Free(&$2);
} else {
out_AbsByte(0xEA);
out_RelWord(&$2);
@@ -1826,6 +1827,7 @@
(!rpn_isReloc(&$4)) && ($4.nVal >= 0xFF00)) {
out_AbsByte(0xF0);
out_AbsByte($4.nVal & 0xFF);
+ rpn_Free(&$4);
} else {
out_AbsByte(0xFA);
out_RelWord(&$4);
@@ -1832,6 +1834,7 @@
}
} else {
yyerror("Destination operand must be A");
+ rpn_Free(&$4);
}
}
;
@@ -1964,6 +1967,7 @@
yyerror("Invalid address $%x for RST", $2.nVal);
else
out_AbsByte(0xC7 | $2.nVal);
+ rpn_Free(&$2);
}
;
--- a/src/asm/output.c
+++ b/src/asm/output.c
@@ -782,7 +782,7 @@
} else {
out_AbsByte(expr->nVal);
}
- rpn_Reset(expr);
+ rpn_Free(expr);
}
/*
@@ -825,7 +825,7 @@
} else {
out_AbsWord(expr->nVal);
}
- rpn_Reset(expr);
+ rpn_Free(expr);
}
/*
@@ -871,7 +871,7 @@
} else {
out_AbsLong(expr->nVal);
}
- rpn_Reset(expr);
+ rpn_Free(expr);
}
/*
@@ -892,7 +892,7 @@
nPC += 1;
pPCSymbol->nValue += 1;
- rpn_Reset(expr);
+ rpn_Free(expr);
}
/*
--- a/src/asm/rpn.c
+++ b/src/asm/rpn.c
@@ -10,6 +10,7 @@
* Controls RPN expressions for objectfiles
*/
+#include <assert.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
@@ -24,12 +25,37 @@
void mergetwoexpressions(struct Expression *expr, const struct Expression *src1,
const struct Expression *src2)
{
- *expr = *src1;
- memcpy(&(expr->tRPN[expr->nRPNLength]), src2->tRPN, src2->nRPNLength);
+ assert(src1->tRPN != NULL && src2->tRPN != NULL);
- expr->nRPNLength += src2->nRPNLength;
- expr->isReloc |= src2->isReloc;
- expr->isPCRel |= src2->isPCRel;
+ if (src1->nRPNLength > UINT32_MAX - src2->nRPNLength)
+ fatalerror("RPN expression is too large");
+
+ uint32_t len = src1->nRPNLength + src2->nRPNLength;
+
+ expr->tRPN = src1->tRPN;
+
+ if (src1->nRPNCapacity >= len) {
+ expr->nRPNCapacity = src1->nRPNCapacity;
+ } else {
+ uint32_t cap1 = src1->nRPNCapacity;
+ uint32_t cap2 = src2->nRPNCapacity;
+ uint32_t cap = (cap1 > cap2) ? cap1 : cap2;
+
+ if (len > cap)
+ cap = (cap <= UINT32_MAX / 2) ? cap * 2 : len;
+
+ expr->nRPNCapacity = cap;
+ expr->tRPN = realloc(expr->tRPN, expr->nRPNCapacity);
+ if (expr->tRPN == NULL)
+ fatalerror("No memory for RPN expression");
+ }
+
+ memcpy(expr->tRPN + src1->nRPNLength, src2->tRPN, src2->nRPNLength);
+ free(src2->tRPN);
+
+ expr->nRPNLength = len;
+ expr->isReloc = src1->isReloc || src2->isReloc;
+ expr->isPCRel = src1->isPCRel || src2->isPCRel;
}
#define joinexpr() mergetwoexpressions(expr, src1, src2)
@@ -39,14 +65,29 @@
*/
void pushbyte(struct Expression *expr, int b)
{
+ if (expr->nRPNLength == expr->nRPNCapacity) {
+ if (expr->nRPNCapacity == 0)
+ expr->nRPNCapacity = 256;
+ else if (expr->nRPNCapacity > UINT32_MAX / 2)
+ fatalerror("RPN expression is too large");
+ else
+ expr->nRPNCapacity *= 2;
+ expr->tRPN = realloc(expr->tRPN, expr->nRPNCapacity);
+
+ if (expr->tRPN == NULL)
+ fatalerror("No memory for RPN expression");
+ }
+
expr->tRPN[expr->nRPNLength++] = b & 0xFF;
}
/*
- * Reset the RPN module
+ * Init the RPN expression
*/
-void rpn_Reset(struct Expression *expr)
+void rpn_Init(struct Expression *expr)
{
+ expr->tRPN = NULL;
+ expr->nRPNCapacity = 0;
expr->nRPNLength = 0;
expr->nRPNOut = 0;
expr->isReloc = 0;
@@ -54,6 +95,15 @@
}
/*
+ * Free the RPN expression
+ */
+void rpn_Free(struct Expression *expr)
+{
+ free(expr->tRPN);
+ rpn_Init(expr);
+}
+
+/*
* Returns the next rpn byte in expression
*/
uint16_t rpn_PopByte(struct Expression *expr)
@@ -85,7 +135,7 @@
*/
void rpn_Number(struct Expression *expr, uint32_t i)
{
- rpn_Reset(expr);
+ rpn_Init(expr);
pushbyte(expr, RPN_CONST);
pushbyte(expr, i);
pushbyte(expr, i >> 8);
@@ -99,7 +149,7 @@
if (!sym_isConstant(tzSym)) {
const struct sSymbol *psym;
- rpn_Reset(expr);
+ rpn_Init(expr);
psym = sym_FindSymbol(tzSym);
@@ -118,7 +168,7 @@
void rpn_BankSelf(struct Expression *expr)
{
- rpn_Reset(expr);
+ rpn_Init(expr);
/*
* This symbol is not really relocatable, but this makes the assembler
@@ -138,7 +188,7 @@
}
if (!sym_isConstant(tzSym)) {
- rpn_Reset(expr);
+ rpn_Init(expr);
/*
* Check that the symbol exists by evaluating and discarding the
@@ -158,7 +208,7 @@
void rpn_BankSection(struct Expression *expr, char *tzSectionName)
{
- rpn_Reset(expr);
+ rpn_Init(expr);
/*
* This symbol is not really relocatable, but this makes the assembler