From ddc6f6bcb04c2a37c68cf25f8630acc44cfc310b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 30 Jun 2021 20:05:27 +0900 Subject: [PATCH] [qfcc] Un-dereference src expression early for movep The VM has no pointer to direct reference move instruction. Fixes #9 --- tools/qfcc/source/statements.c | 18 +++++++++++------- tools/qfcc/test/Makemodule.am | 11 +++++++++++ tools/qfcc/test/ptrstructcast.r | 22 ++++++++++++++++++++++ 3 files changed, 44 insertions(+), 7 deletions(-) create mode 100644 tools/qfcc/test/ptrstructcast.r diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index d2ae28e65..959f0f3c6 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -787,9 +787,13 @@ expr_assign_copy (sblock_t *sblock, expr_t *e, operand_t **op, operand_t *src) } type = st_memset; if (is_indirect (dst_expr)) { - goto dereference_dst; + need_ptr = 1; } } else { + if (is_indirect (src_expr)) { + src_expr = expr_file_line (address_expr (src_expr, 0, 0), e); + need_ptr = 1; + } if (!src) { // This is the very right-hand node of a non-nil assignment chain // (there may be more chains somwhere within src_expr, but they @@ -802,15 +806,15 @@ expr_assign_copy (sblock_t *sblock, expr_t *e, operand_t **op, operand_t *src) if (op) { *op = src; } - if (is_indirect (dst_expr) || is_indirect (src_expr)) { + if (is_indirect (dst_expr)) { src = operand_address (src, src_expr); - goto dereference_dst; + need_ptr = 1; } } - if (0) { -dereference_dst: - // dst_expr is a dereferenced pointer, so need to un-dereference it - // to get the pointer and switch to storep instructions. + if (need_ptr) { + // dst_expr and/or src_expr are dereferenced pointers, so need to + // un-dereference dst_expr to get the pointer and switch to movep + // or memsetp instructions. dst_expr = expr_file_line (address_expr (dst_expr, 0, 0), e); need_ptr = 1; } diff --git a/tools/qfcc/test/Makemodule.am b/tools/qfcc/test/Makemodule.am index 54bb87dcf..15f9b9309 100644 --- a/tools/qfcc/test/Makemodule.am +++ b/tools/qfcc/test/Makemodule.am @@ -34,6 +34,7 @@ test_progs_dat=\ tools/qfcc/test/paramret.dat \ tools/qfcc/test/postop.dat \ tools/qfcc/test/ptraliasenc.dat \ + tools/qfcc/test/ptrstructcast.dat \ tools/qfcc/test/quaternion.dat \ tools/qfcc/test/return-ivar.dat \ tools/qfcc/test/sendv.dat \ @@ -394,6 +395,16 @@ tools/qfcc/test/ptraliasenc.run: $(qfcc_test_run_deps) include $(ptraliasenc_dep) # am--include-marker r_depfiles_remade += $(ptraliasenc_dep) +tools_qfcc_test_ptrstructcast_dat_SOURCES=tools/qfcc/test/ptrstructcast.r +ptrstructcast_obj=$(tools_qfcc_test_ptrstructcast_dat_SOURCES:.r=.o) +ptrstructcast_dep=$(call qcautodep,$(tools_qfcc_test_ptrstructcast_dat_SOURCES)) +tools/qfcc/test/ptrstructcast.dat$(EXEEXT): $(ptrstructcast_obj) $(QFCC_DEP) + $(V_QFCCLD)$(QLINK) -o $@ $(ptrstructcast_obj) +tools/qfcc/test/ptrstructcast.run: $(qfcc_test_run_deps) + @$(top_srcdir)/tools/qfcc/test/build-run $@ +include $(ptrstructcast_dep) # am--include-marker +r_depfiles_remade += $(ptrstructcast_dep) + tools_qfcc_test_quaternion_dat_SOURCES=tools/qfcc/test/quaternion.r quaternion_obj=$(tools_qfcc_test_quaternion_dat_SOURCES:.r=.o) quaternion_dep=$(call qcautodep,$(tools_qfcc_test_quaternion_dat_SOURCES)) diff --git a/tools/qfcc/test/ptrstructcast.r b/tools/qfcc/test/ptrstructcast.r new file mode 100644 index 000000000..36e560d08 --- /dev/null +++ b/tools/qfcc/test/ptrstructcast.r @@ -0,0 +1,22 @@ +typedef struct Point_s { + int x; + int y; +} Point; + +typedef struct Extent_s { + int width; + int height; +} Extent; + +int +foo (Point p) +{ + Extent e = *(Extent *)&p; + return e.width * e.height; +} + +int +main (void) +{ + return foo ({ 6, 7 }) != 42; +}