[qfcc] Fix adjusted swizzles for the same def

The singleton alias resulted in the adjusted swizzles being corrupted
when for the same def. Other than adding properly sized swizzles
(planned), the simplest solution is to (separately) allow alias that
stick out from from the def.
This commit is contained in:
Bill Currie 2023-08-26 23:08:55 +09:00
parent 29a57b7128
commit a5304461dd
3 changed files with 28 additions and 17 deletions

View file

@ -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.

View file

@ -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)
{

View file

@ -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;
}