mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-22 20:41:20 +00:00
[qfcc] Support offset aliases of values
But explicitly not for pointers (even an offset of 0 breaks the pointer relocation).
This commit is contained in:
parent
b456f936c6
commit
73d1044bec
3 changed files with 31 additions and 3 deletions
|
@ -67,6 +67,8 @@ void value_store (pr_type_t *dst, const struct type_s *dstType,
|
||||||
const struct expr_s *src);
|
const struct expr_s *src);
|
||||||
const char *get_value_string (const struct ex_value_s *value);
|
const char *get_value_string (const struct ex_value_s *value);
|
||||||
|
|
||||||
|
struct ex_value_s *offset_alias_value (struct ex_value_s *value,
|
||||||
|
struct type_s *type, int offset);
|
||||||
struct ex_value_s *alias_value (struct ex_value_s *value, struct type_s *type);
|
struct ex_value_s *alias_value (struct ex_value_s *value, struct type_s *type);
|
||||||
struct def_s *emit_value (struct ex_value_s *value, struct def_s *def);
|
struct def_s *emit_value (struct ex_value_s *value, struct def_s *def);
|
||||||
struct def_s *emit_value_core (struct ex_value_s *value, struct def_s *def,
|
struct def_s *emit_value_core (struct ex_value_s *value, struct def_s *def,
|
||||||
|
|
|
@ -154,7 +154,7 @@ _print_operand (operand_t *op)
|
||||||
printf ("%s", op->def->name);
|
printf ("%s", op->def->name);
|
||||||
break;
|
break;
|
||||||
case op_value:
|
case op_value:
|
||||||
printf ("(%s) %s", pr_type_name[op->type->type],
|
printf ("(%s) %s", get_type_string (op->type),
|
||||||
get_value_string (op->value));
|
get_value_string (op->value));
|
||||||
break;
|
break;
|
||||||
case op_label:
|
case op_label:
|
||||||
|
@ -514,8 +514,18 @@ offset_alias_operand (type_t *type, int offset, operand_t *aop, expr_t *expr)
|
||||||
def = def->alias;
|
def = def->alias;
|
||||||
return def_operand (alias_def (def, type, offset), 0, expr);
|
return def_operand (alias_def (def, type, offset), 0, expr);
|
||||||
} else if (aop->op_type == op_value) {
|
} else if (aop->op_type == op_value) {
|
||||||
|
if (!is_ptr (aop->value->type)) {
|
||||||
|
auto value = offset_alias_value (aop->value, type, offset);
|
||||||
|
top = value_operand (value, expr);
|
||||||
|
} else {
|
||||||
|
// even an offset of 0 will break a pointer value because of
|
||||||
|
// relocations
|
||||||
|
if (offset) {
|
||||||
|
internal_error (expr, "offset alias of pointer value operand");
|
||||||
|
}
|
||||||
top = value_operand (aop->value, expr);
|
top = value_operand (aop->value, expr);
|
||||||
top->type = type;
|
top->type = type;
|
||||||
|
}
|
||||||
return top;
|
return top;
|
||||||
} else {
|
} else {
|
||||||
internal_error (expr, "invalid alias target: %s: %s",
|
internal_error (expr, "invalid alias target: %s: %s",
|
||||||
|
|
|
@ -531,6 +531,22 @@ ReuseString (const char *str)
|
||||||
return strpool_addstr (pr.strings, str);
|
return strpool_addstr (pr.strings, str);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ex_value_t *
|
||||||
|
offset_alias_value (ex_value_t *value, type_t *type, int offset)
|
||||||
|
{
|
||||||
|
if (type_size (type) > type_size (value->type)) {
|
||||||
|
error (0, "unable to alias to a larger sized value");
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
if (offset < 0 || offset + type_size (type) > type_size (value->type)) {
|
||||||
|
error (0, "invalid offset");
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
pr_type_t data[type_size (value->type)];
|
||||||
|
memcpy (data, &value->v, sizeof (pr_type_t) * type_size (value->type));
|
||||||
|
return new_type_value (type, data + offset);
|
||||||
|
}
|
||||||
|
|
||||||
ex_value_t *
|
ex_value_t *
|
||||||
alias_value (ex_value_t *value, type_t *type)
|
alias_value (ex_value_t *value, type_t *type)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue