From 8fcdcb173184115c39bc175045aa94c942959c4d Mon Sep 17 00:00:00 2001 From: ISSOtm Date: Sun, 8 Mar 2020 16:52:54 +0100 Subject: [PATCH] Implement `ISCONST`, reporting compile-time constness --- include/asm/rpn.h | 1 + src/asm/asmy.y | 2 ++ src/asm/globlex.c | 1 + src/asm/rgbasm.5 | 5 ++++- src/asm/rpn.c | 8 ++++++++ test/asm/isconst.asm | 29 +++++++++++++++++++++++++++++ test/asm/isconst.err | 13 +++++++++++++ test/asm/isconst.out | 6 ++++++ 8 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 test/asm/isconst.asm create mode 100644 test/asm/isconst.err create mode 100644 test/asm/isconst.out diff --git a/include/asm/rpn.h b/include/asm/rpn.h index f0cd7773..61557bd8 100644 --- a/include/asm/rpn.h +++ b/include/asm/rpn.h @@ -54,6 +54,7 @@ void rpn_BinaryOp(enum RPNCommand op, struct Expression *expr, const struct Expression *src2); void rpn_HIGH(struct Expression *expr, const struct Expression *src); void rpn_LOW(struct Expression *expr, const struct Expression *src); +void rpn_ISCONST(struct Expression *expr, const struct Expression *src); void rpn_UNNEG(struct Expression *expr, const struct Expression *src); void rpn_UNNOT(struct Expression *expr, const struct Expression *src); void rpn_BankSymbol(struct Expression *expr, char const *tzSym); diff --git a/src/asm/asmy.y b/src/asm/asmy.y index f068a745..8688f576 100644 --- a/src/asm/asmy.y +++ b/src/asm/asmy.y @@ -539,6 +539,7 @@ static void strsubUTF8(char *dest, const char *src, uint32_t pos, uint32_t len) %left T_OP_FLOOR %token T_OP_HIGH T_OP_LOW +%token T_OP_ISCONST %left T_OP_STRCMP %left T_OP_STRIN @@ -1194,6 +1195,7 @@ relocexpr_no_str : scoped_id { rpn_Symbol(&$$, $1); } | T_OP_NOT relocexpr %prec NEG { rpn_UNNOT(&$$, &$2); } | T_OP_HIGH '(' relocexpr ')' { rpn_HIGH(&$$, &$3); } | T_OP_LOW '(' relocexpr ')' { rpn_LOW(&$$, &$3); } + | T_OP_ISCONST '(' relocexpr ')'{ rpn_ISCONST(&$$, &$3); } | T_OP_BANK '(' scoped_id ')' { /* '@' is also a T_ID, it is handled here. */ rpn_BankSymbol(&$$, $3); diff --git a/src/asm/globlex.c b/src/asm/globlex.c index b951bba7..83f7b2aa 100644 --- a/src/asm/globlex.c +++ b/src/asm/globlex.c @@ -460,6 +460,7 @@ const struct sLexInitString lexer_strings[] = { {"high", T_OP_HIGH}, {"low", T_OP_LOW}, + {"isconst", T_OP_ISCONST}, {"strcmp", T_OP_STRCMP}, {"strin", T_OP_STRIN}, diff --git a/src/asm/rgbasm.5 b/src/asm/rgbasm.5 index 9140b350..638454e8 100644 --- a/src/asm/rgbasm.5 +++ b/src/asm/rgbasm.5 @@ -553,7 +553,7 @@ which references the same macro, which has the same problem. .Pp One of the best features of an assembler is the ability to write macros for it. Macros also provide a method of passing arguments to them and they can then react to the input using -.Sy IF +.Ic IF constructs. .Pp .Bd -literal -offset indent @@ -1261,6 +1261,9 @@ For labels, as the linker has to resolve this, it can't be used when the express has been defined. .It Fn HIGH arg Ta Returns the top 8 bits of the operand if Ar arg No is a label or constant, or the top 8-bit register if it is a 16-bit register. .It Fn LOW arg Ta Returns the bottom 8 bits of the operand if Ar arg No is a label or constant, or the bottom 8-bit register if it is a 16-bit register Pq Cm AF No isn't a valid register for this function . +.It Fn ISCONST arg Ta Returns 1 if Ar arg Ns No 's value is known by RGBASM (e.g. if it can be an argument to +.Ic IF ) , +or 0 if only RGBLINK can compute its value. .El .Sh MISCELLANEOUS .Ss Changing options while assembling diff --git a/src/asm/rpn.c b/src/asm/rpn.c index ff62c78e..5099779e 100644 --- a/src/asm/rpn.c +++ b/src/asm/rpn.c @@ -499,6 +499,14 @@ void rpn_LOW(struct Expression *expr, const struct Expression *src) } } +void rpn_ISCONST(struct Expression *expr, const struct Expression *src) +{ + rpn_Init(expr); + expr->nVal = rpn_isKnown(src); + expr->isKnown = true; + expr->isSymbol = false; +} + void rpn_UNNEG(struct Expression *expr, const struct Expression *src) { *expr = *src; diff --git a/test/asm/isconst.asm b/test/asm/isconst.asm new file mode 100644 index 00000000..250a2462 --- /dev/null +++ b/test/asm/isconst.asm @@ -0,0 +1,29 @@ + +TEST_NUM = 0 + +test_expr: MACRO +TEST_NUM = TEST_NUM + 1 + +IS_CONST = ISCONST(\1) + PRINTT "Test #{d:TEST_NUM}: ISCONST reports {IS_CONST}\n" + IF (\1) || 1 ; Only test if the expression can be evaluated + WARN "Test #{d:TEST_NUM}: Compile-time constant" + ENDC +ENDM + + test_expr 1 + test_expr UnknownLabel + +SECTION "fixed", WRAM0[$CAFE] + +FixedLabel: + ds 42 + test_expr FixedLabel + test_expr @ - FixedLabel + +SECTION "floating", WRAMX + +FloatingLabel: + ds 69 + test_expr FloatingLabel + test_expr @ - FloatingLabel diff --git a/test/asm/isconst.err b/test/asm/isconst.err new file mode 100644 index 00000000..f18704d1 --- /dev/null +++ b/test/asm/isconst.err @@ -0,0 +1,13 @@ +warning: isconst.asm(14) -> isconst.asm::test_expr(10): [-Wuser] + Test #1: Compile-time constant +ERROR: isconst.asm(15) -> isconst.asm::test_expr(9): + Expected constant expression: 'UnknownLabel' is not constant at assembly time +warning: isconst.asm(21) -> isconst.asm::test_expr(10): [-Wuser] + Test #3: Compile-time constant +warning: isconst.asm(22) -> isconst.asm::test_expr(10): [-Wuser] + Test #4: Compile-time constant +ERROR: isconst.asm(28) -> isconst.asm::test_expr(9): + Expected constant expression: 'FloatingLabel' is not constant at assembly time +warning: isconst.asm(29) -> isconst.asm::test_expr(10): [-Wuser] + Test #6: Compile-time constant +error: Assembly aborted (2 errors)! diff --git a/test/asm/isconst.out b/test/asm/isconst.out new file mode 100644 index 00000000..219bf753 --- /dev/null +++ b/test/asm/isconst.out @@ -0,0 +1,6 @@ +Test #1: ISCONST reports $1 +Test #2: ISCONST reports $0 +Test #3: ISCONST reports $1 +Test #4: ISCONST reports $1 +Test #5: ISCONST reports $0 +Test #6: ISCONST reports $1