diff --git a/tools/qfcc/include/def.h b/tools/qfcc/include/def.h index a00758bdf..a23f241d9 100644 --- a/tools/qfcc/include/def.h +++ b/tools/qfcc/include/def.h @@ -165,6 +165,9 @@ def_t *new_def (const char *name, struct type_s *type, \todo Make aliasing to the same type a no-op? */ def_t *alias_def (def_t *def, struct type_s *type, int offset); +//FIXME this probably shouldn't exist (it's for swizzles, so doing proper +//multi-width swizzles will remove the need for it) +def_t *cover_alias_def (def_t *def, struct type_s *type, int offset); /** Free a def. diff --git a/tools/qfcc/source/def.c b/tools/qfcc/source/def.c index e48ccc948..69ee75198 100644 --- a/tools/qfcc/source/def.c +++ b/tools/qfcc/source/def.c @@ -179,20 +179,12 @@ new_def (const char *name, type_t *type, defspace_t *space, } def_t * -alias_def (def_t *def, type_t *type, int offset) +cover_alias_def (def_t *def, type_t *type, int offset) { def_t *alias; - if (def->alias) { - expr_t e; - e.file = def->file; - e.line = def->line; - internal_error (&e, "aliasing an alias def"); - } - if (type_size (type) > type_size (def->type)) - internal_error (0, "aliasing a def to a larger type"); - if (offset < 0 || offset + type_size (type) > type_size (def->type)) - internal_error (0, "invalid alias offset"); + if (offset + type_size (type) <= 0 || offset >= type_size (def->type)) + internal_error (0, "invalid cover offset"); for (alias = def->alias_defs; alias; alias = alias->next) { if (alias->type == type && alias->offset == offset) return alias; @@ -212,6 +204,22 @@ alias_def (def_t *def, type_t *type, int offset) return alias; } +def_t * +alias_def (def_t *def, type_t *type, int offset) +{ + if (def->alias) { + expr_t e; + e.file = def->file; + e.line = def->line; + internal_error (&e, "aliasing an alias def"); + } + if (type_size (type) > type_size (def->type)) + internal_error (0, "aliasing a def to a larger type"); + if (offset < 0 || offset + type_size (type) > type_size (def->type)) + internal_error (0, "invalid alias offset"); + return cover_alias_def (def, type, offset); +} + def_t * temp_def (type_t *type) { diff --git a/tools/qfcc/source/emit.c b/tools/qfcc/source/emit.c index d5615a794..8e0045155 100644 --- a/tools/qfcc/source/emit.c +++ b/tools/qfcc/source/emit.c @@ -191,11 +191,11 @@ cover_def_32 (def_t *def, int *adj) *adj = offset & 3; if (offset & 3) { if (def->alias) { - cover = alias_def (def->alias, def->type, def->offset); + cover = cover_alias_def (def->alias, def->type, + def->offset - (offset & 3)); } else { - cover = alias_def (def, def->type, 0); + cover = cover_alias_def (def, def->type, -(offset & 3)); } - cover->offset -= offset & 3; } return cover; } @@ -215,11 +215,11 @@ cover_def_64 (def_t *def, int *adj) *adj = (offset & 6) >> 1; if (offset & 6) { if (def->alias) { - cover = alias_def (def->alias, def->type, def->offset); + cover = cover_alias_def (def->alias, def->type, + def->offset - (offset & 6)); } else { - cover = alias_def (def, def->type, 0); + cover = cover_alias_def (def, def->type, -(offset & 6)); } - cover->offset -= offset & 6; } return cover; }