From fcebdbcaea10a21e84d3cf4b8ae7e4b9ed5d6797 Mon Sep 17 00:00:00 2001 From: Kray-G Date: Tue, 29 Oct 2019 21:09:51 +0900 Subject: [PATCH] fixed #14: some bug fixes. --- src/backend/compile.c | 31 +++++++++++++++++++----------- src/parser/eval.c | 4 ++-- src/parser/initializer.c | 16 ++++++++++++++- src/parser/typetree.h | 1 + test/test-lacc/initialize-array.c | 9 +++++++++ test/test-lacc/pointer-immediate.c | 24 +++++++++++++++++++++++ test/test-lacc/push-immediate.c | 9 +++++++++ test/test-lacc/test.cmd | 6 ++++-- 8 files changed, 84 insertions(+), 16 deletions(-) create mode 100644 test/test-lacc/pointer-immediate.c create mode 100644 test/test-lacc/push-immediate.c diff --git a/src/backend/compile.c b/src/backend/compile.c index 03edbe7..c1d862e 100644 --- a/src/backend/compile.c +++ b/src/backend/compile.c @@ -340,6 +340,19 @@ static struct immediate constant(int64_t n, int w) return imm; } +/* + * Check if operand can be represented as a 32 bit constant, which is + * the largest width allowed for many instructions. + */ +static int is_int_constant(struct var v) +{ + return v.kind == IMMEDIATE + && (is_integer(v.type) || is_pointer(v.type)) + && !v.symbol + && (size_of(v.type) < 4 + || (v.imm.i <= INT_MAX && v.imm.i >= INT_MIN)); +} + /* * Return smallest type big enough to cover the i'th eightbyte slice of * aggregate type. Scalar types are returned as is. @@ -710,8 +723,13 @@ static void push(struct var v) emit(INSTR_PUSH, OPT_MEM, location(address(0, SI, 0, 0), 8)); } } else if (is_scalar(v.type)) { - if (v.kind == IMMEDIATE && size_of(v.type) < 8 && !is_real(v.type)) { - emit(INSTR_PUSH, OPT_IMM, value_of(v, 8)); + if (v.kind == IMMEDIATE && is_int_constant(v)) { + if (size_of(v.type) == 8) { + load_int(v, AX, 8); + emit(INSTR_PUSH, OPT_REG, reg(AX, 8)); + } else { + emit(INSTR_PUSH, OPT_IMM, value_of(v, 8)); + } } else { /* * Not possible to push SSE registers, so load as if normal @@ -2183,15 +2201,6 @@ static int operand_equal(struct var a, struct var b) && a.offset == b.offset; } -static int is_int_constant(struct var v) -{ - return v.kind == IMMEDIATE - && (is_integer(v.type) || is_pointer(v.type)) - && !v.symbol - && (size_of(v.type) < 8 - || (v.imm.i <= INT_MAX && v.imm.i >= INT_MIN)); -} - static enum reg compile_add( struct var target, Type type, diff --git a/src/parser/eval.c b/src/parser/eval.c index e4a0f60..91e6e4c 100644 --- a/src/parser/eval.c +++ b/src/parser/eval.c @@ -606,7 +606,7 @@ static struct expression add( l.offset += r.imm.i * size; expr = as_expr(l); } else if (is_constant(l) && r.kind == IMMEDIATE) { - l.imm.i += r.imm.i; + l.imm.i += r.imm.i * size; expr = as_expr(l); } else if (r.kind != IMMEDIATE || r.imm.i) { type = l.type; @@ -678,7 +678,7 @@ static struct expression sub( l.offset -= r.imm.i * size; expr = as_expr(l); } else if (is_constant(l) && r.kind == IMMEDIATE) { - l.imm.i -= r.imm.i; + l.imm.i -= r.imm.i * size; expr = as_expr(l); } else if (is_immediate_false(as_expr(r))) { expr = as_expr(l); diff --git a/src/parser/initializer.c b/src/parser/initializer.c index c4a203c..74e6c71 100644 --- a/src/parser/initializer.c +++ b/src/parser/initializer.c @@ -416,12 +416,13 @@ static struct block *initialize_array( { int is_designator; Type type, elem; - size_t initial, width, i, c; + size_t initial, width, count, i, c; assert(is_array(target.type)); assert(target.kind == DIRECT); i = c = 0; + count = is_complete(target.type) ? type_array_len(target.type) : 0; type = target.type; elem = type_next(type); width = size_of(elem); @@ -461,10 +462,23 @@ static struct block *initialize_array( i += 1; c = i > c ? i : c; if (has_next_array_element(state, &is_designator)) { + if (!is_designator && count && c >= count) + break; consume(','); } else break; } } + if (state == CURRENT) { + if (peek().token == ',') { + next(); + if (peek().token != '}') { + warning("Length of array initializer elements exceeds target array size."); + } + } + while (peek().token != '}' && peek().token != END) { + next(); + } + } if (!is_complete(type) || !size_of(type)) { assert(is_array(target.symbol->type)); diff --git a/src/parser/typetree.h b/src/parser/typetree.h index 7c95197..cddc64a 100644 --- a/src/parser/typetree.h +++ b/src/parser/typetree.h @@ -26,6 +26,7 @@ INTERNAL Type type_create_function(Type next); INTERNAL Type type_create_array(Type next, size_t count); INTERNAL Type type_create_incomplete(Type next); INTERNAL Type type_create_vla(Type next, const struct symbol *count); +INTERNAL Type type_copy_incomplete(Type type); /* Add const, volatile, and restrict qualifiers to type. */ INTERNAL Type type_set_const(Type type); diff --git a/test/test-lacc/initialize-array.c b/test/test-lacc/initialize-array.c index 69185b7..c28c27b 100644 --- a/test/test-lacc/initialize-array.c +++ b/test/test-lacc/initialize-array.c @@ -17,6 +17,11 @@ struct { int k; } obj = {1, 2, 3,}; +struct { + long a[4]; + long b; +} s6[] = { 1, 2, 3, -1L, 5, 6, }; + void verify(void) { int i, j; for (i = 0; i < 2; ++i) @@ -31,6 +36,10 @@ void verify(void) { printf("pc = {{%d, %d, %d, %d}}\n", pc.e[0], pc.e[1], pc.e[2], pc.e[3]); printf("obj = {{%d, %d, %d, %d}, %d}, size = %lu\n", obj.v[0], obj.v[1], obj.v[2], obj.v[3], obj.k, sizeof(obj)); + for (i = 0; i < 2; ++i) { + printf("s6[%d]: {{%ld, %ld, %ld, %ld}, %ld}\n", i, + s6[i].a[0], s6[i].a[0], s6[i].a[0], s6[i].a[0], s6[i].b); + } } int arr[] = {1, 2, 3, 4, 5}; diff --git a/test/test-lacc/pointer-immediate.c b/test/test-lacc/pointer-immediate.c new file mode 100644 index 0000000..06afa89 --- /dev/null +++ b/test/test-lacc/pointer-immediate.c @@ -0,0 +1,24 @@ +#include +#include + +typedef float vec_t[3]; + +typedef struct { + vec_t loc; +} point_t; + +static int offsets[] = { + (unsigned long)&((point_t*)0)->loc[0], + (unsigned long)&((point_t*)0)->loc[2], + (unsigned long)&((vec_t*)0)[1] +}; + +int main(void) { + int *a = (((int*) 0x10) - 2); + int *b = (((int*) 0x10) + 2); + + assert(a == (int *) 0x08); + assert(b == (int *) 0x18); + + return printf("%d, %d, %d\n", offsets[0], offsets[1], offsets[2]); +} diff --git a/test/test-lacc/push-immediate.c b/test/test-lacc/push-immediate.c new file mode 100644 index 0000000..dd448c0 --- /dev/null +++ b/test/test-lacc/push-immediate.c @@ -0,0 +1,9 @@ +int printf(const char *, ...); + +int foo(int a, int b, int c, int d, int e, int f, unsigned int g) { + return printf("%d, %d, %d, %d, %d, %d, %u\n", a, b, c, d, e, f, g); +} + +int main(void) { + return foo(1, 2, 3, 4, 5, 6, 0xFF000000u); +} diff --git a/test/test-lacc/test.cmd b/test/test-lacc/test.cmd index 22d8449..8f5f7fb 100644 --- a/test/test-lacc/test.cmd +++ b/test/test-lacc/test.cmd @@ -7,8 +7,8 @@ if NOT "%1" == "" SET GEN=..\..\kcc.exe -x :CLEANUP pushd %~dp0 -del *.expect > NUL 2>&1 -del *.result > NUL 2>&1 +del /S /Q *.expect > NUL 2>&1 +del /S /Q *.result > NUL 2>&1 :DO_TEST REM c11 @@ -202,6 +202,7 @@ call :TEST params-mixed.c call :TEST params-system-v.c call :TEST partial-initialization.c call :TEST pointer-diff.c +call :TEST pointer-immediate.c call :TEST pointer.c call :TEST preprocess-expression.c call :TEST preprocess.c @@ -210,6 +211,7 @@ REM call :TEST printstr.c call :TEST promote-unsigned.c call :TEST prototype-scope-enum.c call :TEST ptrdiff.c +call :TEST push-immediate.c call :TEST qualifier-repeat.c call :TEST register-param.c REM call :TEST return-bitfield.c