There's no real need to warn when the same register is declared twice. Currently the libva driver does do that and this warning makes other errors really hide in a sea of warnings. Redefining a register with different parameters is a real error though, so we should not allow that and error out in that case. Signed-off-by: Damien Lespiau <damien.lespiau at intel.com> --- assembler/gram.y | 74 +++++++++++++++++++++++++++++++++++++++++++----------- 1 files changed, 59 insertions(+), 15 deletions(-) diff --git a/assembler/gram.y b/assembler/gram.y index be8ff01..8b56bd9 100644 --- a/assembler/gram.y +++ b/assembler/gram.y @@ -96,6 +96,46 @@ void set_direct_dst_operand(struct brw_reg *dst, struct brw_reg *reg, void set_direct_src_operand(struct src_operand *src, struct brw_reg *reg, int type); +/* like strcmp, but handles NULL pointers */ +static bool strcmp0(const char *s1, const char* s2) +{ + if (!s1) + return -(s1 != s2); + if (!s2) + return s1 != s2; + return strcmp (s1, s2); +} + +static bool region_equal(struct region *r1, struct region *r2) +{ + return memcmp(r1, r2, sizeof(struct region)) == 0; +} + +static bool reg_equal(struct brw_reg *r1, struct brw_reg *r2) +{ + return memcmp(r1, r2, sizeof(struct brw_reg)) == 0; +} + +static bool declared_register_equal(struct declared_register *r1, + struct declared_register *r2) +{ + if (strcmp0(r1->name, r2->name) != 0) + return false; + + if (!reg_equal(&r1->reg, &r2->reg)) + return false; + + if (!region_equal(&r1->src_region, &r2->src_region)) + return false; + + if (r1->element_size != r2->element_size || + r1->dst_region != r2->dst_region || + r1->type != r2->type) + return false; + + return true; +} + static void brw_program_init(struct brw_program *p) { memset(p, 0, sizeof(struct brw_program)); @@ -431,23 +471,27 @@ declare_type: TYPE EQ regtype ; declare_pragma: DECLARE_PRAGMA STRING declare_base declare_elementsize declare_srcregion declare_dstregion declare_type { - struct declared_register *reg; - int defined; - defined = (reg = find_register($2)) != NULL; - if (defined) { - fprintf(stderr, "WARNING: %s already defined\n", $2); + struct declared_register reg, *found, *new_reg; + + reg.name = $2; + reg.reg = $3; + reg.element_size = $4; + reg.src_region = $5; + reg.dst_region = $6; + reg.type = $7; + + found = find_register($2); + if (found) { + if (!declared_register_equal(®, found)) { + fprintf(stderr, "Error: %s already defined and " + "definitions don't agree\n", $2); + YYERROR; + } free($2); // $2 has been malloc'ed by strdup } else { - reg = calloc(sizeof(struct declared_register), 1); - reg->name = $2; - } - reg->reg = $3; - reg->element_size = $4; - reg->src_region = $5; - reg->dst_region = $6; - reg->type = $7; - if (!defined) { - insert_register(reg); + new_reg = malloc(sizeof(struct declared_register)); + *new_reg = reg; + insert_register(new_reg); } } ; -- 1.7.7.5