diff --git a/tools/qfcc/source/dot_expr.c b/tools/qfcc/source/dot_expr.c index 5b61c4d32..6025be7b3 100644 --- a/tools/qfcc/source/dot_expr.c +++ b/tools/qfcc/source/dot_expr.c @@ -383,6 +383,22 @@ print_field (dstring_t *dstr, const expr_t *e, int level, int id, ".", e->loc.line); } +static void +print_array (dstring_t *dstr, const expr_t *e, int level, int id, + const expr_t *next) +{ + int indent = level * 2 + 2; + + _print_expr (dstr, e->array.base, level, id, next); + _print_expr (dstr, e->array.index, level, id, next); + dasprintf (dstr, "%*se_%p -> \"e_%p\" [label=\"b\"];\n", indent, "", e, + e->array.base); + dasprintf (dstr, "%*se_%p -> \"e_%p\" [label=\"i\"];\n", indent, "", e, + e->array.index); + dasprintf (dstr, "%*se_%p [label=\"%s\\n%d\"];\n", indent, "", e, + "[]", e->loc.line); +} + static void print_subexpr (dstring_t *dstr, const expr_t *e, int level, int id, const expr_t *next) { @@ -715,9 +731,10 @@ print_swizzle (dstring_t *dstr, const expr_t *e, int level, int id, const expr_t static char swizzle_components[] = "xyzw"; int indent = level * 2 + 2; ex_swizzle_t swiz = e->swizzle; + int count = type_width (swiz.type); const char *swizzle = ""; - for (int i = 0; i < 4; i++) { + for (int i = 0; i < count; i++) { if (swiz.zero & (1 << i)) { swizzle = va (0, "%s0", swizzle); } else { @@ -835,7 +852,7 @@ _print_expr (dstring_t *dstr, const expr_t *e, int level, int id, [ex_incop] = nullptr, [ex_cond] = print_cond, [ex_field] = print_field, - [ex_array] = nullptr, + [ex_array] = print_array, [ex_decl] = nullptr, }; int indent = level * 2 + 2; diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 6b8e1b03a..fe7cbc4e8 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -666,10 +666,14 @@ const expr_t * new_swizzle_expr (const expr_t *src, const char *swizzle) { src = convert_name (src); - if (src->type == ex_error) { + if (is_error (src)) { return (expr_t *) src; } auto src_type = get_type (src); + if (is_reference (src_type)) { + src_type = dereference_type (src_type); + src = pointer_deref (src); + } int src_width = type_width (src_type); ex_swizzle_t swiz = {}; @@ -720,7 +724,6 @@ new_swizzle_expr (const expr_t *src, const char *swizzle) swiz.source[comp_count++] = ind; } } - swiz.zero |= (0xf << comp_count) & 0xf; swiz.src = src; swiz.type = vector_type (base_type (src_type), comp_count); diff --git a/tools/qfcc/source/expr_construct.c b/tools/qfcc/source/expr_construct.c index 66ed450a4..c2101115e 100644 --- a/tools/qfcc/source/expr_construct.c +++ b/tools/qfcc/source/expr_construct.c @@ -51,7 +51,9 @@ get_value (const expr_t *e, int i, int j) } if (type_rows (t) > 1) { auto ind = new_int_expr (j, false); - e = array_expr (e, ind); + auto a = new_array_expr (e, ind); + a->array.type = base_type (t); + e = a; } return e; } diff --git a/tools/qfcc/source/expr_process.c b/tools/qfcc/source/expr_process.c index efc8c75f0..53ed4cc05 100644 --- a/tools/qfcc/source/expr_process.c +++ b/tools/qfcc/source/expr_process.c @@ -341,6 +341,10 @@ proc_decl (const expr_t *expr) if (decl->assign.dst->type != ex_symbol) { internal_error (decl->assign.dst, "not a symbol"); } + init = expr_process (init); + if (is_error (init)) { + return init; + } pr.loc = decl->assign.dst->loc; sym = decl->assign.dst->symbol; } else if (decl->type == ex_symbol) { diff --git a/tools/qfcc/source/glsl-declaration.c b/tools/qfcc/source/glsl-declaration.c index 28384101e..28caa9246 100644 --- a/tools/qfcc/source/glsl-declaration.c +++ b/tools/qfcc/source/glsl-declaration.c @@ -48,12 +48,6 @@ glsl_parse_declaration (specifier_t spec, symbol_t *sym, const expr_t *init, if (sym->type) { internal_error (0, "unexected typed symbol"); } - if (init) { - init = expr_process (init); - if (is_error (init)) { - return; - } - } auto attributes = glsl_optimize_attributes (spec.attributes); if (sym && sym->sy_type == sy_expr) { auto id_list = sym->expr; diff --git a/tools/qfcc/source/target_spirv.c b/tools/qfcc/source/target_spirv.c index dd9138a21..8b66f063f 100644 --- a/tools/qfcc/source/target_spirv.c +++ b/tools/qfcc/source/target_spirv.c @@ -1259,6 +1259,24 @@ spirv_return (const expr_t *e, spirvctx_t *ctx) return 0; } +static unsigned +spirv_swizzle (const expr_t *e, spirvctx_t *ctx) +{ + int count = type_width (e->swizzle.type); + unsigned src_id = spirv_emit_expr (e->swizzle.src, ctx); + unsigned tid = type_id (e->swizzle.type, ctx); + unsigned id = spirv_id (ctx); + auto insn = spirv_new_insn (SpvOpVectorShuffle, 4 + count, ctx->code_space); + INSN (insn, 1) = tid; + INSN (insn, 2) = id; + INSN (insn, 3) = src_id; + INSN (insn, 4) = src_id; + for (int i = 0; i < count; i++) { + INSN (insn, 5 + i) = e->swizzle.source[i]; + } + return id; +} + static unsigned spirv_extend (const expr_t *e, spirvctx_t *ctx) { @@ -1341,16 +1359,21 @@ spirv_cond (const expr_t *e, spirvctx_t *ctx) } static unsigned -spirv_field (const expr_t *e, spirvctx_t *ctx) +spirv_field_array (const expr_t *e, spirvctx_t *ctx) { auto res_type = get_type (e); ex_list_t list = {}; - // convert the left-branching field expression chain to a list - for (; e->type == ex_field; e = e->field.object) { - list_prepend (&list, e); + // convert the left-branching field/array expression chain to a list + while (e->type == ex_field || e->type == ex_array) { + for (; e->type == ex_field; e = e->field.object) { + list_prepend (&list, e); + } + for (; e->type == ex_array; e = e->array.base) { + list_prepend (&list, e); + } } - int num_fields = list_count (&list); - // e is now the base object of the field expression chain + int num_obj = list_count (&list); + // e is now the base object of the field/array expression chain auto base_type = get_type (e); unsigned base_id = spirv_emit_expr (e, ctx); int op = SpvOpCompositeExtract; @@ -1366,20 +1389,29 @@ spirv_field (const expr_t *e, spirvctx_t *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); + auto insn = spirv_new_insn (op, 4 + num_obj, ctx->code_space); INSN (insn, 1) = acc_type_id; INSN (insn, 2) = id; INSN (insn, 3) = base_id; auto field_ind = &INSN (insn, 4); for (auto l = list.head; l; l = l->next) { - if (l->expr->field.member->type != ex_symbol) { - internal_error (l->expr->field.member, "not a symbol"); - } - auto sym = l->expr->field.member->symbol; - if (literal_ind) { - *field_ind++ = sym->id; + auto obj = l->expr; + unsigned index; + if (obj->type == ex_field) { + if (obj->field.member->type != ex_symbol) { + internal_error (obj->field.member, "not a symbol"); + } + auto sym = obj->field.member->symbol; + index = sym->id; + } else if (obj->type == ex_array) { + index = expr_integral (obj->array.index); } else { - auto ind = new_uint_expr (sym->id); + internal_error (obj, "what the what?!?"); + } + if (literal_ind) { + *field_ind++ = index; + } else { + auto ind = new_uint_expr (index); *field_ind++ = spirv_emit_expr (ind, ctx); } } @@ -1471,9 +1503,11 @@ spirv_emit_expr (const expr_t *e, spirvctx_t *ctx) [ex_assign] = spirv_assign, [ex_branch] = spirv_branch, [ex_return] = spirv_return, + [ex_swizzle] = spirv_swizzle, [ex_extend] = spirv_extend, [ex_cond] = spirv_cond, - [ex_field] = spirv_field, + [ex_field] = spirv_field_array, + [ex_array] = spirv_field_array, [ex_loop] = spirv_loop, [ex_select] = spirv_select, };