Dynamically allocate RPN expression buffer

This commit is contained in:
dbrotz
2019-05-02 19:31:26 -07:00
parent a37a09c09c
commit b256e4c2e3
4 changed files with 74 additions and 18 deletions

View File

@@ -13,7 +13,8 @@
struct Expression { struct Expression {
int32_t nVal; int32_t nVal;
uint8_t tRPN[256]; uint8_t *tRPN;
uint32_t nRPNCapacity;
uint32_t nRPNLength; uint32_t nRPNLength;
uint32_t nRPNOut; uint32_t nRPNOut;
uint32_t isReloc; uint32_t isReloc;
@@ -69,7 +70,8 @@ uint16_t rpn_PopByte(struct Expression *expr);
void rpn_BankSymbol(struct Expression *expr, char *tzSym); void rpn_BankSymbol(struct Expression *expr, char *tzSym);
void rpn_BankSection(struct Expression *expr, char *tzSectionName); void rpn_BankSection(struct Expression *expr, char *tzSectionName);
void rpn_BankSelf(struct Expression *expr); 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); void rpn_CheckHRAM(struct Expression *expr, const struct Expression *src);
#endif /* RGBDS_ASM_RPN_H */ #endif /* RGBDS_ASM_RPN_H */

View File

@@ -1772,6 +1772,7 @@ z80_ld_mem : T_Z80_LD op_mem_ind comma T_MODE_SP
(!rpn_isReloc(&$2)) && ($2.nVal >= 0xFF00)) { (!rpn_isReloc(&$2)) && ($2.nVal >= 0xFF00)) {
out_AbsByte(0xE0); out_AbsByte(0xE0);
out_AbsByte($2.nVal & 0xFF); out_AbsByte($2.nVal & 0xFF);
rpn_Free(&$2);
} else { } else {
out_AbsByte(0xEA); out_AbsByte(0xEA);
out_RelWord(&$2); out_RelWord(&$2);
@@ -1826,12 +1827,14 @@ z80_ld_a : T_Z80_LD reg_r comma T_MODE_C_IND
(!rpn_isReloc(&$4)) && ($4.nVal >= 0xFF00)) { (!rpn_isReloc(&$4)) && ($4.nVal >= 0xFF00)) {
out_AbsByte(0xF0); out_AbsByte(0xF0);
out_AbsByte($4.nVal & 0xFF); out_AbsByte($4.nVal & 0xFF);
rpn_Free(&$4);
} else { } else {
out_AbsByte(0xFA); out_AbsByte(0xFA);
out_RelWord(&$4); out_RelWord(&$4);
} }
} else { } else {
yyerror("Destination operand must be A"); yyerror("Destination operand must be A");
rpn_Free(&$4);
} }
} }
; ;
@@ -1964,6 +1967,7 @@ z80_rst : T_Z80_RST const_8bit
yyerror("Invalid address $%x for RST", $2.nVal); yyerror("Invalid address $%x for RST", $2.nVal);
else else
out_AbsByte(0xC7 | $2.nVal); out_AbsByte(0xC7 | $2.nVal);
rpn_Free(&$2);
} }
; ;

View File

@@ -782,7 +782,7 @@ void out_RelByte(struct Expression *expr)
} else { } else {
out_AbsByte(expr->nVal); out_AbsByte(expr->nVal);
} }
rpn_Reset(expr); rpn_Free(expr);
} }
/* /*
@@ -825,7 +825,7 @@ void out_RelWord(struct Expression *expr)
} else { } else {
out_AbsWord(expr->nVal); out_AbsWord(expr->nVal);
} }
rpn_Reset(expr); rpn_Free(expr);
} }
/* /*
@@ -871,7 +871,7 @@ void out_RelLong(struct Expression *expr)
} else { } else {
out_AbsLong(expr->nVal); out_AbsLong(expr->nVal);
} }
rpn_Reset(expr); rpn_Free(expr);
} }
/* /*
@@ -892,7 +892,7 @@ void out_PCRelByte(struct Expression *expr)
nPC += 1; nPC += 1;
pPCSymbol->nValue += 1; pPCSymbol->nValue += 1;
rpn_Reset(expr); rpn_Free(expr);
} }
/* /*

View File

@@ -10,6 +10,7 @@
* Controls RPN expressions for objectfiles * Controls RPN expressions for objectfiles
*/ */
#include <assert.h>
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
@@ -24,12 +25,37 @@
void mergetwoexpressions(struct Expression *expr, const struct Expression *src1, void mergetwoexpressions(struct Expression *expr, const struct Expression *src1,
const struct Expression *src2) const struct Expression *src2)
{ {
*expr = *src1; assert(src1->tRPN != NULL && src2->tRPN != NULL);
memcpy(&(expr->tRPN[expr->nRPNLength]), src2->tRPN, src2->nRPNLength);
expr->nRPNLength += src2->nRPNLength; if (src1->nRPNLength > UINT32_MAX - src2->nRPNLength)
expr->isReloc |= src2->isReloc; fatalerror("RPN expression is too large");
expr->isPCRel |= src2->isPCRel;
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) #define joinexpr() mergetwoexpressions(expr, src1, src2)
@@ -39,20 +65,44 @@ void mergetwoexpressions(struct Expression *expr, const struct Expression *src1,
*/ */
void pushbyte(struct Expression *expr, int b) 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; 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->nRPNLength = 0;
expr->nRPNOut = 0; expr->nRPNOut = 0;
expr->isReloc = 0; expr->isReloc = 0;
expr->isPCRel = 0; expr->isPCRel = 0;
} }
/*
* Free the RPN expression
*/
void rpn_Free(struct Expression *expr)
{
free(expr->tRPN);
rpn_Init(expr);
}
/* /*
* Returns the next rpn byte in expression * Returns the next rpn byte in expression
*/ */
@@ -85,7 +135,7 @@ uint32_t rpn_isPCRelative(const struct Expression *expr)
*/ */
void rpn_Number(struct Expression *expr, uint32_t i) void rpn_Number(struct Expression *expr, uint32_t i)
{ {
rpn_Reset(expr); rpn_Init(expr);
pushbyte(expr, RPN_CONST); pushbyte(expr, RPN_CONST);
pushbyte(expr, i); pushbyte(expr, i);
pushbyte(expr, i >> 8); pushbyte(expr, i >> 8);
@@ -99,7 +149,7 @@ void rpn_Symbol(struct Expression *expr, char *tzSym)
if (!sym_isConstant(tzSym)) { if (!sym_isConstant(tzSym)) {
const struct sSymbol *psym; const struct sSymbol *psym;
rpn_Reset(expr); rpn_Init(expr);
psym = sym_FindSymbol(tzSym); psym = sym_FindSymbol(tzSym);
@@ -118,7 +168,7 @@ void rpn_Symbol(struct Expression *expr, char *tzSym)
void rpn_BankSelf(struct Expression *expr) void rpn_BankSelf(struct Expression *expr)
{ {
rpn_Reset(expr); rpn_Init(expr);
/* /*
* This symbol is not really relocatable, but this makes the assembler * This symbol is not really relocatable, but this makes the assembler
@@ -138,7 +188,7 @@ void rpn_BankSymbol(struct Expression *expr, char *tzSym)
} }
if (!sym_isConstant(tzSym)) { if (!sym_isConstant(tzSym)) {
rpn_Reset(expr); rpn_Init(expr);
/* /*
* Check that the symbol exists by evaluating and discarding the * Check that the symbol exists by evaluating and discarding the
@@ -158,7 +208,7 @@ void rpn_BankSymbol(struct Expression *expr, char *tzSym)
void rpn_BankSection(struct Expression *expr, char *tzSectionName) 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 * This symbol is not really relocatable, but this makes the assembler