From 14f428a81d03b8b847ff83b423364118cab03868 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 13 Nov 2024 14:05:46 +0900 Subject: [PATCH] [qfcc] Don't dereference pointer for field access As I suspected, the dereference was premature, although it can act as an optimization when multiple fields of an object are accessed, though it won't work for writes to lvalues (which means my fixes for spir-v code-gen currently don't work for lvalue writes). Still, progress. Need to get field member ids set. --- tools/qfcc/source/expr_process.c | 2 -- tools/qfcc/source/target_spirv.c | 22 +++++++++++++++++----- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/tools/qfcc/source/expr_process.c b/tools/qfcc/source/expr_process.c index dd1e731b8..99e42e486 100644 --- a/tools/qfcc/source/expr_process.c +++ b/tools/qfcc/source/expr_process.c @@ -102,7 +102,6 @@ proc_field (const expr_t *expr) if (is_reference (obj_type)) { obj_type = dereference_type (obj_type); - object = pointer_deref (object); } if (is_class (obj_type)) { @@ -116,7 +115,6 @@ proc_field (const expr_t *expr) || is_class (ref_type))) { return type_mismatch (object, member, '.'); } - object = pointer_deref (object); obj_type = ref_type; } if (is_algebra (obj_type)) { diff --git a/tools/qfcc/source/target_spirv.c b/tools/qfcc/source/target_spirv.c index 7c165ea5e..838461929 100644 --- a/tools/qfcc/source/target_spirv.c +++ b/tools/qfcc/source/target_spirv.c @@ -998,18 +998,19 @@ spirv_field (const expr_t *e, spirvctx_t *ctx) auto base_type = get_type (e); unsigned base_id = spirv_emit_expr (e, ctx); int op = SpvOpCompositeExtract; - bool literal_ind = true; - if (is_pointer (base_type)) { - res_type = pointer_type (res_type); + auto acc_type = res_type; + bool literal_ind = true; + if (is_pointer (base_type) || is_reference (base_type)) { + acc_type = pointer_type (res_type); op = SpvOpAccessChain; literal_ind = false; } - int tid = type_id (res_type, ctx); + int acc_type_id = type_id (acc_type, ctx); int id = spirv_id (ctx); auto insn = spirv_new_insn (op, 4 + num_fields, ctx->code_space); - INSN (insn, 1) = tid; + INSN (insn, 1) = acc_type_id; INSN (insn, 2) = id; INSN (insn, 3) = base_id; auto field_ind = &INSN (insn, 4); @@ -1025,6 +1026,17 @@ spirv_field (const expr_t *e, spirvctx_t *ctx) *field_ind++ = spirv_emit_expr (ind, ctx); } } + if (acc_type != res_type) { + // base is a pointer or reference so load the value + unsigned ptr_id = id; + int res_type_id = type_id (res_type, ctx); + + id = spirv_id (ctx); + insn = spirv_new_insn (SpvOpLoad, 4, ctx->code_space); + INSN (insn, 1) = res_type_id; + INSN (insn, 2) = id; + INSN (insn, 3) = ptr_id; + } return id; }