From 1d78cd0f03e503d6acce6f83e8609d484ca2978f Mon Sep 17 00:00:00 2001 From: ISSOtm Date: Mon, 20 Jan 2020 23:12:41 +0100 Subject: [PATCH] Axe the `constexpr` expression evaluator This avoids redundancy between them (and also having to port fixes and features) The error messages have been preserved through a string reporting mechanism --- Makefile | 1 - include/asm/constexpr.h | 35 ----- include/asm/rpn.h | 1 + src/asm/asmy.y | 145 +++++-------------- src/asm/constexpr.c | 298 ---------------------------------------- src/asm/globlex.c | 1 - src/asm/lexer.c | 1 - src/asm/rpn.c | 91 +++++++----- test/asm/bank.err | 8 +- test/asm/overflow.err | 2 - test/asm/pc-bank.err | 2 +- test/asm/shift.err | 16 +-- 12 files changed, 101 insertions(+), 500 deletions(-) delete mode 100644 include/asm/constexpr.h delete mode 100644 src/asm/constexpr.c diff --git a/Makefile b/Makefile index d9ee6eeb..96b08cd8 100644 --- a/Makefile +++ b/Makefile @@ -54,7 +54,6 @@ all: rgbasm rgblink rgbfix rgbgfx rgbasm_obj := \ src/asm/asmy.o \ src/asm/charmap.o \ - src/asm/constexpr.o \ src/asm/fstack.o \ src/asm/globlex.o \ src/asm/lexer.o \ diff --git a/include/asm/constexpr.h b/include/asm/constexpr.h deleted file mode 100644 index 1e566e53..00000000 --- a/include/asm/constexpr.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * This file is part of RGBDS. - * - * Copyright (c) 1997-2018, Carsten Sorensen and RGBDS contributors. - * - * SPDX-License-Identifier: MIT - */ - -#ifndef RGBDS_ASM_CONSTEXPR_H -#define RGBDS_ASM_CONSTEXPR_H - -#include - -struct ConstExpression { - union { - int32_t nVal; - struct sSymbol *pSym; - } u; - uint32_t isSym; -}; - -void constexpr_Symbol(struct ConstExpression *expr, char *tzSym); -void constexpr_BankSymbol(struct ConstExpression *expr, char *tzSym); -void constexpr_BankSection(struct ConstExpression *expr, char *tzSym); -void constexpr_Number(struct ConstExpression *expr, int32_t i); -void constexpr_UnaryOp(struct ConstExpression *expr, - int32_t op, - const struct ConstExpression *src); -void constexpr_BinaryOp(struct ConstExpression *expr, - int32_t op, - const struct ConstExpression *src1, - const struct ConstExpression *src2); -int32_t constexpr_GetConstantValue(struct ConstExpression *expr); - -#endif /* RGBDS_ASM_CONSTEXPR_H */ diff --git a/include/asm/rpn.h b/include/asm/rpn.h index 6bd8163e..f8bcdc63 100644 --- a/include/asm/rpn.h +++ b/include/asm/rpn.h @@ -19,6 +19,7 @@ struct Expression { bool isKnown; // Whether the expression's value is known int32_t nVal; // If the expression's value is known, it's here + char *reason; // Why the expression is not known, if it isn't uint8_t *tRPN; // Array of bytes serializing the RPN expression uint32_t nRPNCapacity; // Size of the `tRPN` buffer uint32_t nRPNLength; // Used size of the `tRPN` buffer diff --git a/src/asm/asmy.y b/src/asm/asmy.y index 8d24e441..4406ead6 100644 --- a/src/asm/asmy.y +++ b/src/asm/asmy.y @@ -18,7 +18,6 @@ #include "asm/asm.h" #include "asm/charmap.h" -#include "asm/constexpr.h" #include "asm/fstack.h" #include "asm/lexer.h" #include "asm/main.h" @@ -510,11 +509,10 @@ static void strsubUTF8(char *dest, const char *src, uint32_t pos, uint32_t len) char tzString[MAXSTRLEN + 1]; struct Expression sVal; int32_t nConstValue; - struct ConstExpression sConstExpr; } %type relocconst -%type const +%type const %type uconst %type const_3bit %type const_8bit @@ -966,17 +964,17 @@ global_list_entry : T_ID equ : T_LABEL T_POP_EQU const { - sym_AddEqu($1, constexpr_GetConstantValue(&$3)); + sym_AddEqu($1, $3); } ; set : T_LABEL T_POP_SET const { - sym_AddSet($1, constexpr_GetConstantValue(&$3)); + sym_AddSet($1, $3); } | T_LABEL T_POP_EQUAL const { - sym_AddSet($1, constexpr_GetConstantValue(&$3)); + sym_AddSet($1, $3); } ; @@ -1004,12 +1002,10 @@ incbin : T_POP_INCBIN string charmap : T_POP_CHARMAP string comma const { - int32_t value = constexpr_GetConstantValue(&$4); - - if ((value & 0xFF) != value) + if (($4 & 0xFF) != $4) warning(WARNING_TRUNCATION, "Expression must be 8-bit"); - if (charmap_Add($2, value & 0xFF) == -1) + if (charmap_Add($2, $4 & 0xFF) == -1) yyerror("Error parsing charmap. Either you've added too many (%i), or the input character length is too long (%i)' : %s\n", MAXCHARMAPS, CHARMAPLENGTH, strerror(errno)); } ; @@ -1044,26 +1040,26 @@ printt : T_POP_PRINTT string printv : T_POP_PRINTV const { - printf("$%X", constexpr_GetConstantValue(&$2)); + printf("$%X", $2); } ; printi : T_POP_PRINTI const { - printf("%d", constexpr_GetConstantValue(&$2)); + printf("%d", $2); } ; printf : T_POP_PRINTF const { - math_Print(constexpr_GetConstantValue(&$2)); + math_Print($2); } ; if : T_POP_IF const { nIFDepth++; - if (!constexpr_GetConstantValue(&$2)) { + if (!$2) { /* * Continue parsing after ELSE, or at ELIF or * ENDC keyword. @@ -1095,7 +1091,7 @@ elif : T_POP_ELIF const */ skipElif = true; - if (!constexpr_GetConstantValue(&$2)) { + if (!$2) { /* * Continue parsing after ELSE, or at * ELIF or ENDC keyword. @@ -1127,7 +1123,7 @@ endc : T_POP_ENDC const_3bit : const { - int32_t value = constexpr_GetConstantValue(&$1); + int32_t value = $1; if ((value < 0) || (value > 7)) yyerror("Immediate value must be 3-bit"); else @@ -1268,57 +1264,57 @@ relocconst : T_ID } | T_OP_ROUND '(' const ')' { - rpn_Number(&$$, math_Round(constexpr_GetConstantValue(&$3))); + rpn_Number(&$$, math_Round($3)); } | T_OP_CEIL '(' const ')' { - rpn_Number(&$$, math_Ceil(constexpr_GetConstantValue(&$3))); + rpn_Number(&$$, math_Ceil($3)); } | T_OP_FLOOR '(' const ')' { - rpn_Number(&$$, math_Floor(constexpr_GetConstantValue(&$3))); + rpn_Number(&$$, math_Floor($3)); } | T_OP_FDIV '(' const comma const ')' { rpn_Number(&$$, - math_Div(constexpr_GetConstantValue(&$3), - constexpr_GetConstantValue(&$5))); + math_Div($3, + $5)); } | T_OP_FMUL '(' const comma const ')' { rpn_Number(&$$, - math_Mul(constexpr_GetConstantValue(&$3), - constexpr_GetConstantValue(&$5))); + math_Mul($3, + $5)); } | T_OP_SIN '(' const ')' { - rpn_Number(&$$, math_Sin(constexpr_GetConstantValue(&$3))); + rpn_Number(&$$, math_Sin($3)); } | T_OP_COS '(' const ')' { - rpn_Number(&$$, math_Cos(constexpr_GetConstantValue(&$3))); + rpn_Number(&$$, math_Cos($3)); } | T_OP_TAN '(' const ')' { - rpn_Number(&$$, math_Tan(constexpr_GetConstantValue(&$3))); + rpn_Number(&$$, math_Tan($3)); } | T_OP_ASIN '(' const ')' { - rpn_Number(&$$, math_ASin(constexpr_GetConstantValue(&$3))); + rpn_Number(&$$, math_ASin($3)); } | T_OP_ACOS '(' const ')' { - rpn_Number(&$$, math_ACos(constexpr_GetConstantValue(&$3))); + rpn_Number(&$$, math_ACos($3)); } | T_OP_ATAN '(' const ')' { - rpn_Number(&$$, math_ATan(constexpr_GetConstantValue(&$3))); + rpn_Number(&$$, math_ATan($3)); } | T_OP_ATAN2 '(' const comma const ')' { rpn_Number(&$$, - math_ATan2(constexpr_GetConstantValue(&$3), - constexpr_GetConstantValue(&$5))); + math_ATan2($3, + $5)); } | T_OP_STRCMP '(' string comma string ')' { @@ -1339,92 +1335,23 @@ relocconst : T_ID uconst : const { - int32_t value = constexpr_GetConstantValue(&$1); + int32_t value = $1; if (value < 0) fatalerror("Constant mustn't be negative: %d", value); $$ = value; } ; -const : T_ID { constexpr_Symbol(&$$, $1); } - | T_NUMBER { constexpr_Number(&$$, $1); } - | T_OP_HIGH '(' const ')' { constexpr_UnaryOp(&$$, $1, &$3); } - | T_OP_LOW '(' const ')' { constexpr_UnaryOp(&$$, $1, &$3); } - | T_OP_BANK '(' T_ID ')' +const : relocconst { - constexpr_BankSymbol(&$$, $3); + if (!rpn_isKnown(&$1)) { + yyerror("Expected constant expression: %s", + $1.reason); + $$ = 0; + } else { + $$ = $1.nVal; + } } - | T_OP_BANK '(' string ')' - { - constexpr_BankSection(&$$, $3); - } - | string - { - char *s = $1; - int32_t length = charmap_Convert(&s); - constexpr_Number(&$$, str2int2(s, length)); - free(s); - } - | T_OP_LOGICNOT const %prec NEG { constexpr_UnaryOp(&$$, $1, &$2); } - | const T_OP_LOGICOR const { constexpr_BinaryOp(&$$, $2, &$1, &$3); } - | const T_OP_LOGICAND const { constexpr_BinaryOp(&$$, $2, &$1, &$3); } - | const T_OP_LOGICEQU const { constexpr_BinaryOp(&$$, $2, &$1, &$3); } - | const T_OP_LOGICGT const { constexpr_BinaryOp(&$$, $2, &$1, &$3); } - | const T_OP_LOGICLT const { constexpr_BinaryOp(&$$, $2, &$1, &$3); } - | const T_OP_LOGICGE const { constexpr_BinaryOp(&$$, $2, &$1, &$3); } - | const T_OP_LOGICLE const { constexpr_BinaryOp(&$$, $2, &$1, &$3); } - | const T_OP_LOGICNE const { constexpr_BinaryOp(&$$, $2, &$1, &$3); } - | const T_OP_ADD const { constexpr_BinaryOp(&$$, $2, &$1, &$3); } - | const T_OP_SUB const { constexpr_BinaryOp(&$$, $2, &$1, &$3); } - | const T_OP_XOR const { constexpr_BinaryOp(&$$, $2, &$1, &$3); } - | const T_OP_OR const { constexpr_BinaryOp(&$$, $2, &$1, &$3); } - | const T_OP_AND const { constexpr_BinaryOp(&$$, $2, &$1, &$3); } - | const T_OP_SHL const { constexpr_BinaryOp(&$$, $2, &$1, &$3); } - | const T_OP_SHR const { constexpr_BinaryOp(&$$, $2, &$1, &$3); } - | const T_OP_MUL const { constexpr_BinaryOp(&$$, $2, &$1, &$3); } - | const T_OP_DIV const { constexpr_BinaryOp(&$$, $2, &$1, &$3); } - | const T_OP_MOD const { constexpr_BinaryOp(&$$, $2, &$1, &$3); } - | T_OP_ADD const %prec NEG { constexpr_UnaryOp(&$$, $1, &$2); } - | T_OP_SUB const %prec NEG { constexpr_UnaryOp(&$$, $1, &$2); } - | T_OP_NOT const %prec NEG { constexpr_UnaryOp(&$$, $1, &$2); } - | T_OP_ROUND '(' const ')' { constexpr_UnaryOp(&$$, $1, &$3); } - | T_OP_CEIL '(' const ')' { constexpr_UnaryOp(&$$, $1, &$3); } - | T_OP_FLOOR '(' const ')' { constexpr_UnaryOp(&$$, $1, &$3); } - | T_OP_FDIV '(' const comma const ')' { constexpr_BinaryOp(&$$, $1, &$3, &$5); } - | T_OP_FMUL '(' const comma const ')' { constexpr_BinaryOp(&$$, $1, &$3, &$5); } - | T_OP_SIN '(' const ')' { constexpr_UnaryOp(&$$, $1, &$3); } - | T_OP_COS '(' const ')' { constexpr_UnaryOp(&$$, $1, &$3); } - | T_OP_TAN '(' const ')' { constexpr_UnaryOp(&$$, $1, &$3); } - | T_OP_ASIN '(' const ')' { constexpr_UnaryOp(&$$, $1, &$3); } - | T_OP_ACOS '(' const ')' { constexpr_UnaryOp(&$$, $1, &$3); } - | T_OP_ATAN '(' const ')' { constexpr_UnaryOp(&$$, $1, &$3); } - | T_OP_ATAN2 '(' const comma const ')' { constexpr_BinaryOp(&$$, $1, &$3, &$5); } - | T_OP_DEF { - oDontExpandStrings = true; - } '(' T_ID ')' - { - struct sSymbol const *sym = sym_FindSymbol($4); - if (sym && !(sym_IsDefined(sym) && sym->type != SYM_LABEL)) - yyerror("Label \"%s\" is not a valid argument to DEF", - $4); - constexpr_Number(&$$, !!sym); - oDontExpandStrings = false; - } - | T_OP_STRCMP '(' string comma string ')' - { - constexpr_Number(&$$, strcmp($3, $5)); - } - | T_OP_STRIN '(' string comma string ')' - { - char *p = strstr($3, $5); - - if (p != NULL) - constexpr_Number(&$$, p - $3 + 1); - else - constexpr_Number(&$$, 0); - } - | T_OP_STRLEN '(' string ')' { constexpr_Number(&$$, strlenUTF8($3)); } - | '(' const ')' { $$ = $2; } ; string : T_STRING diff --git a/src/asm/constexpr.c b/src/asm/constexpr.c deleted file mode 100644 index d4b323cc..00000000 --- a/src/asm/constexpr.c +++ /dev/null @@ -1,298 +0,0 @@ -/* - * This file is part of RGBDS. - * - * Copyright (c) 1997-2018, Carsten Sorensen and RGBDS contributors. - * - * SPDX-License-Identifier: MIT - */ - -#include -#include -#include - -#include "asm/asm.h" -#include "asm/constexpr.h" -#include "asm/lexer.h" -#include "asm/main.h" -#include "asm/mymath.h" -#include "asm/output.h" -#include "asm/rpn.h" -#include "asm/symbol.h" -#include "asm/warning.h" - -#include "asmy.h" - -void constexpr_Symbol(struct ConstExpression *expr, char *tzSym) -{ - struct sSymbol *sym = sym_FindSymbol(tzSym); - - if (!sym) { - fatalerror("'%s' not defined", tzSym); - } else if (!sym_IsConstant(sym)) { - expr->u.pSym = sym; - expr->isSym = 1; - } else { - constexpr_Number(expr, sym_GetConstantValue(tzSym)); - } -} - -void constexpr_BankSymbol(struct ConstExpression *expr, char *tzSym) -{ - constexpr_Number(expr, 0); - struct sSymbol *sym = sym_FindSymbol(tzSym); - - if (!sym) { - yyerror("BANK argument doesn't exist"); - } else if (sym == pPCSymbol) { - if (pCurrentSection->nBank == -1) - yyerror("Current bank is not known yet"); - else - constexpr_Number(expr, pCurrentSection->nBank); - } else if (sym->type != SYM_LABEL) { - yyerror("BANK argument must be a label"); - } else if (sym->pSection->nBank == -1) { - yyerror("BANK argument's bank is not known yet'"); - } else { - constexpr_Number(expr, sym->pSection->nBank); - } -} - -void constexpr_BankSection(struct ConstExpression *expr, char *tzSectionName) -{ - constexpr_Number(expr, 0); - struct Section *pSection = out_FindSectionByName(tzSectionName); - - if (!pSection) - yyerror("Section \"%s\" doesn't exist", tzSectionName); - else if (pSection->nBank == -1) - yyerror("Section \"%s\"'s bank is not known yet", - tzSectionName); - else - constexpr_Number(expr, pSection->nBank); -} - -void constexpr_Number(struct ConstExpression *expr, int32_t i) -{ - expr->u.nVal = i; - expr->isSym = 0; -} - -void constexpr_UnaryOp(struct ConstExpression *expr, - int32_t op, - const struct ConstExpression *src) -{ - if (src->isSym) - fatalerror("Non-constant operand in constant expression"); - - int32_t value = src->u.nVal; - int32_t result = 0; - - switch (op) { - case T_OP_HIGH: - result = (value >> 8) & 0xFF; - break; - case T_OP_LOW: - result = value & 0xFF; - break; - case T_OP_LOGICNOT: - result = !value; - break; - case T_OP_ADD: - result = value; - break; - case T_OP_SUB: - result = -(uint32_t)value; - break; - case T_OP_NOT: - result = ~value; - break; - case T_OP_ROUND: - result = math_Round(value); - break; - case T_OP_CEIL: - result = math_Ceil(value); - break; - case T_OP_FLOOR: - result = math_Floor(value); - break; - case T_OP_SIN: - result = math_Sin(value); - break; - case T_OP_COS: - result = math_Cos(value); - break; - case T_OP_TAN: - result = math_Tan(value); - break; - case T_OP_ASIN: - result = math_ASin(value); - break; - case T_OP_ACOS: - result = math_ACos(value); - break; - case T_OP_ATAN: - result = math_ATan(value); - break; - default: - fatalerror("Unknown unary op"); - } - - constexpr_Number(expr, result); -} - -void constexpr_BinaryOp(struct ConstExpression *expr, - int32_t op, - const struct ConstExpression *src1, - const struct ConstExpression *src2) -{ - int32_t value1; - int32_t value2; - int32_t result = 0; - - if (op == T_OP_SUB && src1->isSym && src2->isSym) { - char *symName1 = src1->u.pSym->tzName; - char *symName2 = src2->u.pSym->tzName; - - if (!sym_IsRelocDiffDefined(symName1, symName2)) - fatalerror("'%s - %s' not defined", symName1, symName2); - value1 = sym_GetDefinedValue(symName1); - value2 = sym_GetDefinedValue(symName2); - result = value1 - value2; - } else if (src1->isSym || src2->isSym) { - fatalerror("Non-constant operand in constant expression"); - } else { - value1 = src1->u.nVal; - value2 = src2->u.nVal; - - switch (op) { - case T_OP_LOGICOR: - result = value1 || value2; - break; - case T_OP_LOGICAND: - result = value1 && value2; - break; - case T_OP_LOGICEQU: - result = value1 == value2; - break; - case T_OP_LOGICGT: - result = value1 > value2; - break; - case T_OP_LOGICLT: - result = value1 < value2; - break; - case T_OP_LOGICGE: - result = value1 >= value2; - break; - case T_OP_LOGICLE: - result = value1 <= value2; - break; - case T_OP_LOGICNE: - result = value1 != value2; - break; - case T_OP_ADD: - result = (uint32_t)value1 + (uint32_t)value2; - break; - case T_OP_SUB: - result = (uint32_t)value1 - (uint32_t)value2; - break; - case T_OP_XOR: - result = value1 ^ value2; - break; - case T_OP_OR: - result = value1 | value2; - break; - case T_OP_AND: - result = value1 & value2; - break; - case T_OP_SHL: - case T_OP_SHR: - if (value2 < 0) - warning(WARNING_SHIFT_AMOUNT, "Shifting %s by negative amount %d", - op == T_OP_SHL ? "left" : "right", - value2); - if (op == T_OP_SHR) { - value2 = -value2; /* Right shift == neg left */ - - if (value1 < 0) - warning(WARNING_SHIFT, "Shifting negative value %d", - value1); - } - - if (value2 >= 0) { - // Shift left - if (value2 >= 32) { - warning(WARNING_SHIFT_AMOUNT, "Shifting left by large amount %d", - value2); - result = 0; - } else { - /* - * Use unsigned to force a bitwise shift - * Casting back is OK because the types - * implement two's complement behavior - */ - result = (uint32_t)value1 << value2; - } - } else { - // Shift right - value2 = -value2; - if (value2 >= 32) { - warning(WARNING_SHIFT_AMOUNT, "Shifting right by large amount %d", - value2); - result = value1 < 0 ? -1 : 0; - } else if (value1 >= 0) { - result = value1 >> value2; - } else { - /* - * The C standard leaves shifting right - * negative values undefined, so use a - * left shift manually sign-extended - */ - result = (uint32_t)value1 >> value2 | - -((uint32_t)1 << (32 - value2)); - } - } - break; - case T_OP_MUL: - result = (uint32_t)value1 * (uint32_t)value2; - break; - case T_OP_DIV: - if (value2 == 0) - fatalerror("Division by zero"); - if (value1 == INT32_MIN && value2 == -1) { - warning(WARNING_DIV, "Division of min value by -1"); - result = INT32_MIN; - } else { - result = value1 / value2; - } - break; - case T_OP_MOD: - if (value2 == 0) - fatalerror("Division by zero"); - if (value1 == INT32_MIN && value2 == -1) - result = 0; - else - result = value1 % value2; - break; - case T_OP_FDIV: - result = math_Div(value1, value2); - break; - case T_OP_FMUL: - result = math_Mul(value1, value2); - break; - case T_OP_ATAN2: - result = math_ATan2(value1, value2); - break; - default: - fatalerror("Unknown binary op"); - } - } - - constexpr_Number(expr, result); -} - -int32_t constexpr_GetConstantValue(struct ConstExpression *expr) -{ - if (expr->isSym) - fatalerror("Non-constant expression"); - return expr->u.nVal; -} diff --git a/src/asm/globlex.c b/src/asm/globlex.c index e591cd1a..44881a96 100644 --- a/src/asm/globlex.c +++ b/src/asm/globlex.c @@ -14,7 +14,6 @@ #include #include "asm/asm.h" -#include "asm/constexpr.h" #include "asm/lexer.h" #include "asm/main.h" #include "asm/rpn.h" diff --git a/src/asm/lexer.c b/src/asm/lexer.c index 6d457901..23e00e0c 100644 --- a/src/asm/lexer.c +++ b/src/asm/lexer.c @@ -15,7 +15,6 @@ #include #include "asm/asm.h" -#include "asm/constexpr.h" #include "asm/fstack.h" #include "asm/lexer.h" #include "asm/main.h" diff --git a/src/asm/rpn.c b/src/asm/rpn.c index 50fb42e3..652b1660 100644 --- a/src/asm/rpn.c +++ b/src/asm/rpn.c @@ -23,6 +23,21 @@ #include "asm/output.h" #include "asm/warning.h" +/* Makes an expression "not known", also setting its error message */ +#define makeUnknown(expr_, ...) do { \ + struct Expression *_expr = expr_; \ + _expr->isKnown = false; \ + /* If we had `asprintf` this would be great, but alas. */ \ + _expr->reason = malloc(128); /* Use an initial reasonable size */ \ + if (!_expr->reason) \ + fatalerror("Can't allocate err string: %s", strerror(errno)); \ + int size = snprintf(_expr->reason, 128, __VA_ARGS__); \ + if (size >= 128) { /* If this wasn't enough, try again */ \ + _expr->reason = realloc(_expr->reason, size + 1); \ + sprintf(_expr->reason, __VA_ARGS__); \ + } \ +} while (0) + static uint8_t *reserveSpace(struct Expression *expr, uint32_t size) { /* This assumes the RPN length is always less than the capacity */ @@ -65,6 +80,7 @@ void rpn_Init(struct Expression *expr) expr->nRPNPatchSize = 0; expr->nRPNOut = 0; expr->isKnown = true; + expr->reason = NULL; } /* @@ -73,6 +89,7 @@ void rpn_Init(struct Expression *expr) void rpn_Free(struct Expression *expr) { free(expr->tRPN); + free(expr->reason); rpn_Init(expr); } @@ -111,7 +128,7 @@ void rpn_Symbol(struct Expression *expr, char *tzSym) if (!sym || !sym_IsConstant(sym)) { rpn_Init(expr); sym_Ref(tzSym); - expr->isKnown = false; + makeUnknown(expr, "'%s' is not defined", tzSym); expr->nRPNPatchSize += 5; /* 1-byte opcode + 4-byte symbol ID */ size_t nameLen = strlen(tzSym) + 1; /* Don't forget NUL! */ @@ -136,7 +153,7 @@ void rpn_BankSelf(struct Expression *expr) rpn_Init(expr); if (pCurrentSection->nBank == -1) - expr->isKnown = false; + makeUnknown(expr, "Current section's bank is not known"); else expr->nVal = pCurrentSection->nBank; @@ -173,7 +190,7 @@ void rpn_BankSymbol(struct Expression *expr, char *tzSym) /* Symbol's section is known and bank is fixed */ expr->nVal = pSymbol->pSection->nBank; else - expr->isKnown = false; + makeUnknown(expr, "\"%s\"'s bank is not known", tzSym); } } @@ -186,7 +203,8 @@ void rpn_BankSection(struct Expression *expr, char *tzSectionName) if (pSection && pSection->nBank != -1) expr->nVal = pSection->nBank; else - expr->isKnown = false; + makeUnknown(expr, "Section \"%s\"'s bank is not known", + tzSectionName); size_t nameLen = strlen(tzSectionName) + 1; /* Don't forget NUL! */ uint8_t *ptr = reserveSpace(expr, nameLen + 1); @@ -234,9 +252,6 @@ void rpn_LOGNOT(struct Expression *expr, const struct Expression *src) static int32_t shift(int32_t shiftee, int32_t amount) { - if (shiftee < 0) - warning(WARNING_SHIFT, "Shifting negative value %d", shiftee); - if (amount >= 0) { // Left shift if (amount >= 32) { @@ -346,50 +361,46 @@ void rpn_BinaryOp(enum RPNCommand op, struct Expression *expr, expr->nVal = src1->nVal & src2->nVal; break; case RPN_SHL: - if (expr->isKnown) { - if (src2->nVal < 0) - warning(WARNING_SHIFT_AMOUNT, "Shifting left by negative value: %d", - src2->nVal); + if (src2->nVal < 0) + warning(WARNING_SHIFT_AMOUNT, "Shifting left by negative amount %d", + src2->nVal); - expr->nVal = shift(src1->nVal, src2->nVal); - } + expr->nVal = shift(src1->nVal, src2->nVal); break; case RPN_SHR: - if (expr->isKnown) { - if (src2->nVal < 0) - warning(WARNING_SHIFT_AMOUNT, "Shifting right by negative value: %d", - src2->nVal); + if (src1->nVal < 0) + warning(WARNING_SHIFT, "Shifting negative value %d", + src1->nVal); - expr->nVal = shift(src1->nVal, -src2->nVal); - } + if (src2->nVal < 0) + warning(WARNING_SHIFT_AMOUNT, "Shifting right by negative amount %d", + src2->nVal); + + expr->nVal = shift(src1->nVal, -src2->nVal); break; case RPN_MUL: expr->nVal = uleft * uright; break; case RPN_DIV: - if (expr->isKnown) { - if (src2->nVal == 0) - fatalerror("Division by zero"); + if (src2->nVal == 0) + fatalerror("Division by zero"); - if (src1->nVal == INT32_MIN - && src2->nVal == -1) { - warning(WARNING_DIV, "Division of min value by -1"); - expr->nVal = INT32_MIN; - } else { - expr->nVal = src1->nVal / src2->nVal; - } + if (src1->nVal == INT32_MIN + && src2->nVal == -1) { + warning(WARNING_DIV, "Division of min value by -1"); + expr->nVal = INT32_MIN; + } else { + expr->nVal = src1->nVal / src2->nVal; } break; case RPN_MOD: - if (expr->isKnown) { - if (src2->nVal == 0) - fatalerror("Division by zero"); + if (src2->nVal == 0) + fatalerror("Division by zero"); - if (src1->nVal == INT32_MIN && src2->nVal == -1) - expr->nVal = 0; - else - expr->nVal = src1->nVal % src2->nVal; - } + if (src1->nVal == INT32_MIN && src2->nVal == -1) + expr->nVal = 0; + else + expr->nVal = src1->nVal % src2->nVal; break; case RPN_UNSUB: @@ -425,12 +436,18 @@ void rpn_BinaryOp(enum RPNCommand op, struct Expression *expr, expr->nRPNLength = 0; memcpy(reserveSpace(expr, sizeof(bytes)), bytes, sizeof(bytes)); + + /* Use the other expression's un-const reason */ + expr->reason = src2->reason; + free(src1->reason); } else { /* Otherwise just reuse its RPN buffer */ expr->nRPNPatchSize = src1->nRPNPatchSize; expr->tRPN = src1->tRPN; expr->nRPNCapacity = src1->nRPNCapacity; expr->nRPNLength = src1->nRPNLength; + expr->reason = src1->reason; + free(src2->reason); } /* Now, merge the right expression into the left one */ diff --git a/test/asm/bank.err b/test/asm/bank.err index 6623e217..9654dbce 100644 --- a/test/asm/bank.err +++ b/test/asm/bank.err @@ -1,9 +1,9 @@ ERROR: bank.asm(14) -> bank.asm::def_sect(8): - Section "ROMX_bad"'s bank is not known yet + Expected constant expression: Section "ROMX_bad"'s bank is not known ERROR: bank.asm(16) -> bank.asm::def_sect(8): - Section "VRAM_bad"'s bank is not known yet + Expected constant expression: Section "VRAM_bad"'s bank is not known ERROR: bank.asm(18) -> bank.asm::def_sect(8): - Section "SRAM_bad"'s bank is not known yet + Expected constant expression: Section "SRAM_bad"'s bank is not known ERROR: bank.asm(21) -> bank.asm::def_sect(8): - Section "WRAMX_bad"'s bank is not known yet + Expected constant expression: Section "WRAMX_bad"'s bank is not known error: Assembly aborted (4 errors)! diff --git a/test/asm/overflow.err b/test/asm/overflow.err index 03071f3f..8ed2aa85 100644 --- a/test/asm/overflow.err +++ b/test/asm/overflow.err @@ -2,8 +2,6 @@ warning: overflow.asm(24): [-Wdiv] Division of min value by -1 warning: overflow.asm(25): [-Wdiv] Division of min value by -1 -warning: overflow.asm(35): [-Wshift] - Shifting negative value -1 warning: overflow.asm(39): [-Wlarge-constant] Integer constant '4294967296' is too large warning: overflow.asm(42): [-Wlarge-constant] diff --git a/test/asm/pc-bank.err b/test/asm/pc-bank.err index e81e10cf..3c165fb9 100644 --- a/test/asm/pc-bank.err +++ b/test/asm/pc-bank.err @@ -1,5 +1,5 @@ ERROR: pc-bank.asm(2): Source address $2a00 not in $FF00 to $FFFF ERROR: pc-bank.asm(11): - Current bank is not known yet + Expected constant expression: Current section's bank is not known error: Assembly aborted (2 errors)! diff --git a/test/asm/shift.err b/test/asm/shift.err index aea9476e..ba1c7543 100644 --- a/test/asm/shift.err +++ b/test/asm/shift.err @@ -6,18 +6,12 @@ warning: shift.asm(14) -> shift.asm::test(3): [-Wshift-amount] Shifting left by large amount 9001 warning: shift.asm(14) -> shift.asm::test(6): [-Wshift-amount] Shifting left by large amount 9001 -warning: shift.asm(15) -> shift.asm::test(3): [-Wshift] - Shifting negative value -1 -warning: shift.asm(16) -> shift.asm::test(3): [-Wshift] - Shifting negative value -1 warning: shift.asm(16) -> shift.asm::test(3): [-Wshift-amount] Shifting left by large amount 32 warning: shift.asm(16) -> shift.asm::test(6): [-Wshift-amount] Shifting left by large amount 32 warning: shift.asm(17) -> shift.asm::test(3): [-Wshift-amount] - Shifting left by negative value: -9001 -warning: shift.asm(17) -> shift.asm::test(3): [-Wshift] - Shifting negative value -1 + Shifting left by negative amount -9001 warning: shift.asm(17) -> shift.asm::test(3): [-Wshift-amount] Shifting right by large amount 9001 warning: shift.asm(17) -> shift.asm::test(6): [-Wshift-amount] @@ -52,15 +46,15 @@ warning: shift.asm(23) -> shift.asm::test(3): [-Wshift] Shifting negative value -4 warning: shift.asm(23) -> shift.asm::test(6): [-Wshift] Shifting negative value -4 -warning: shift.asm(24) -> shift.asm::test(3): [-Wshift-amount] - Shifting right by negative value: -9001 warning: shift.asm(24) -> shift.asm::test(3): [-Wshift] Shifting negative value -1 warning: shift.asm(24) -> shift.asm::test(3): [-Wshift-amount] - Shifting left by large amount 9001 -warning: shift.asm(24) -> shift.asm::test(6): [-Wshift-amount] Shifting right by negative amount -9001 +warning: shift.asm(24) -> shift.asm::test(3): [-Wshift-amount] + Shifting left by large amount 9001 warning: shift.asm(24) -> shift.asm::test(6): [-Wshift] Shifting negative value -1 +warning: shift.asm(24) -> shift.asm::test(6): [-Wshift-amount] + Shifting right by negative amount -9001 warning: shift.asm(24) -> shift.asm::test(6): [-Wshift-amount] Shifting left by large amount 9001