summaryrefslogtreecommitdiff
path: root/05
diff options
context:
space:
mode:
Diffstat (limited to '05')
-rw-r--r--05/constants.b2
-rw-r--r--05/main.c2
-rw-r--r--05/parse.b44
-rw-r--r--05/util.b75
4 files changed, 116 insertions, 7 deletions
diff --git a/05/constants.b b/05/constants.b
index 85aff7a..fa2d0f4 100644
--- a/05/constants.b
+++ b/05/constants.b
@@ -126,7 +126,7 @@
; uchar kind (one of the constants below)
; uchar info
; ushort (padding)
-; uint type (0 if expression hasn't been typed yet)
+; uint type
; immediately following the header in memory are the arguments of the expression
; - for constant ints, the 64-bit integral value
; - for constant floats, the 64-bit double value (even if expression has type float)
diff --git a/05/main.c b/05/main.c
index 357feff..ed86f51 100644
--- a/05/main.c
+++ b/05/main.c
@@ -3,4 +3,4 @@
long double d;
} (*x)(void);
*/
-typedef long int unsigned Foo[3 * 3];
+typedef long int unsigned Foo[19 + (-3) % 187 - 28 + 5 * 6];
diff --git a/05/parse.b b/05/parse.b
index bff260b..1764f82 100644
--- a/05/parse.b
+++ b/05/parse.b
@@ -943,6 +943,7 @@ function evaluate_constant_expression
argument p_value
local a
local b
+ local p
if *1expr == EXPRESSION_CONSTANT_INT goto eval_constant_int
if *1expr == EXPRESSION_IDENTIFIER goto eval_constant_identifier
@@ -951,8 +952,11 @@ function evaluate_constant_expression
if *1expr == EXPRESSION_BITWISE_NOT goto eval_bitwise_not
if *1expr == EXPRESSION_LOGICAL_NOT goto eval_logical_not
if *1expr == EXPRESSION_CAST goto eval_todo ; @TODO
- if *1expr == EXPRESSION_LOGICAL_NOT goto eval_logical_not
+ if *1expr == EXPRESSION_ADD goto eval_add
+ if *1expr == EXPRESSION_SUB goto eval_sub
if *1expr == EXPRESSION_MUL goto eval_mul
+ if *1expr == EXPRESSION_DIV goto eval_div
+ if *1expr == EXPRESSION_REMAINDER goto eval_remainder
byte 0xcc
:eval_todo
@@ -998,13 +1002,49 @@ function evaluate_constant_expression
:eval_logical_not0
*8p_value = 1
return expr
+ :eval_add
+ expr += 8
+ expr = evaluate_constant_expression(expr, &a)
+ expr = evaluate_constant_expression(expr, &b)
+ *8p_value = a + b
+ return expr
+ :eval_sub
+ expr += 8
+ expr = evaluate_constant_expression(expr, &a)
+ expr = evaluate_constant_expression(expr, &b)
+ *8p_value = a - b
+ return expr
:eval_mul
expr += 8
expr = evaluate_constant_expression(expr, &a)
expr = evaluate_constant_expression(expr, &b)
*8p_value = a * b
return expr
-
+ :eval_div
+ p = expr + 4 ; pointer to type
+ expr += 8
+ expr = evaluate_constant_expression(expr, &a)
+ expr = evaluate_constant_expression(expr, &b)
+ if *1p == TYPE_UNSIGNED_LONG goto eval_div_unsigned
+ ; division is signed or uses a small type, so we can use 64-bit signed division
+ *8p_value = a / b
+ return expr
+ :eval_div_unsigned
+ ; must use unsigned division
+ divmod_unsigned(a, b, p_value, &a)
+ return expr
+ :eval_remainder
+ p = expr + 4 ; pointer to type
+ expr += 8
+ expr = evaluate_constant_expression(expr, &a)
+ expr = evaluate_constant_expression(expr, &b)
+ if *1p == TYPE_UNSIGNED_LONG goto eval_rem_unsigned
+ *8p_value = a % b
+ return expr
+ :eval_rem_unsigned
+ divmod_unsigned(a, b, &a, p_value)
+ return expr
+
; the "usual conversions" for binary operators, as the C standard calls it
function expr_binary_type_usual_conversions
argument token ; for errors
diff --git a/05/util.b b/05/util.b
index c8c3e97..4a32af2 100644
--- a/05/util.b
+++ b/05/util.b
@@ -25,6 +25,75 @@ function full_multiply_signed
*8p_upper = upper
return
+
+function divmod_unsigned
+ argument a
+ argument b
+ argument p_quotient
+ argument p_remainder
+ local q
+ local r
+
+ ; mov rax, [rbp-16]
+ byte 0x48
+ byte 0x8b
+ byte 0x85
+ byte 0xf0
+ byte 0xff
+ byte 0xff
+ byte 0xff
+
+ ; mov rbx, rax
+ byte 0x48
+ byte 0x89
+ byte 0xc3
+
+ ; mov rax, [rbp-8]
+ byte 0x48
+ byte 0x8b
+ byte 0x85
+ byte 0xf8
+ byte 0xff
+ byte 0xff
+ byte 0xff
+
+ ; xor edx, edx
+ byte 0x31
+ byte 0xd2
+
+ ; div rbx
+ byte 0x48
+ byte 0xf7
+ byte 0xf3
+
+ ; mov [rbp-40], rax
+ byte 0x48
+ byte 0x89
+ byte 0x85
+ byte 0xd8
+ byte 0xff
+ byte 0xff
+ byte 0xff
+
+ ; mov rax, rdx
+ byte 0x48
+ byte 0x89
+ byte 0xd0
+
+ ; mov [rbp-48], rax
+ byte 0x48
+ byte 0x89
+ byte 0x85
+ byte 0xd0
+ byte 0xff
+ byte 0xff
+ byte 0xff
+
+ *8p_quotient = q
+ *8p_remainder = r
+
+ return
+
; allows for negative shifts
function right_shift
argument x
@@ -93,7 +162,8 @@ function free
syscall(11, psize, size)
return
-; returns a pointer to a null-terminated string containing the number given
+; returns a pointer to a null-terminated string containing the
+; (unsigned) number given
function itos
global 32 itos_string
argument x
@@ -102,10 +172,9 @@ function itos
p = &itos_string
p += 30
:itos_loop
- c = x % 10
+ divmod_unsigned(x, 10, &x, &c)
c += '0
*1p = c
- x /= 10
if x == 0 goto itos_loop_end
p -= 1
goto itos_loop