mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-10 23:32:09 +00:00
[qfcc] Promote types before expanding scalars
This fixes the internal error generated by the likes of `(sv_gravity * '0 0 1')` where sv_gravity is a float and `'0 0 1'` is an ivec3: the vector is promoted to vec3 first so that expanding sv_gravity is expanded to vec3 instead of ivec3 (which is not permitted for a float: expansion requires the destination base type to be the same as the source).
This commit is contained in:
parent
47ac7b924f
commit
942ea22266
1 changed files with 46 additions and 24 deletions
|
@ -853,13 +853,16 @@ entity_compare (int op, expr_t *e1, expr_t *e2)
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define invalid_binary_expr(_op, _e1, _e2) \
|
||||||
|
_invalid_binary_expr(_op, _e1, _e2, __FILE__, __LINE__)
|
||||||
static expr_t *
|
static expr_t *
|
||||||
invalid_binary_expr (int op, expr_t *e1, expr_t *e2)
|
_invalid_binary_expr (int op, expr_t *e1, expr_t *e2,
|
||||||
|
const char *file, int line)
|
||||||
{
|
{
|
||||||
type_t *t1, *t2;
|
type_t *t1, *t2;
|
||||||
t1 = get_type (e1);
|
t1 = get_type (e1);
|
||||||
t2 = get_type (e2);
|
t2 = get_type (e2);
|
||||||
return error (e1, "invalid binary expression: %s %s %s",
|
return _error (e1, file, line, "invalid binary expression: %s %s %s",
|
||||||
get_type_string (t1), get_op_string (op),
|
get_type_string (t1), get_op_string (op),
|
||||||
get_type_string (t2));
|
get_type_string (t2));
|
||||||
}
|
}
|
||||||
|
@ -977,6 +980,15 @@ static int is_call (expr_t *e)
|
||||||
return e->type == ex_block && e->e.block.is_call;
|
return e->type == ex_block && e->e.block.is_call;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static type_t *
|
||||||
|
promote_type (type_t *dst, type_t *src)
|
||||||
|
{
|
||||||
|
if (is_vector (dst) || is_quaternion (dst)) {
|
||||||
|
return dst;
|
||||||
|
}
|
||||||
|
return vector_type (base_type (dst), type_width (src));
|
||||||
|
}
|
||||||
|
|
||||||
expr_t *
|
expr_t *
|
||||||
binary_expr (int op, expr_t *e1, expr_t *e2)
|
binary_expr (int op, expr_t *e1, expr_t *e2)
|
||||||
{
|
{
|
||||||
|
@ -1056,6 +1068,38 @@ binary_expr (int op, expr_t *e1, expr_t *e2)
|
||||||
// vector/quaternion and scalar won't get here as vector and quaternion
|
// vector/quaternion and scalar won't get here as vector and quaternion
|
||||||
// are distict types with type.width == 1, but vector and vec3 WILL get
|
// are distict types with type.width == 1, but vector and vec3 WILL get
|
||||||
// here because of vec3 being float{3}
|
// here because of vec3 being float{3}
|
||||||
|
if (t1 != t2) {
|
||||||
|
type_t *pt1 = t1;
|
||||||
|
type_t *pt2 = t2;
|
||||||
|
if (is_float (base_type (t1)) && is_double (base_type (t2))
|
||||||
|
&& e2->implicit) {
|
||||||
|
pt2 = promote_type (t1, t2);
|
||||||
|
} else if (is_double (base_type (t1)) && is_float (base_type (t2))
|
||||||
|
&& e1->implicit) {
|
||||||
|
pt1 = promote_type (t2, t1);
|
||||||
|
} else if (type_promotes (base_type (t1), base_type (t2))) {
|
||||||
|
pt2 = promote_type (t1, t2);
|
||||||
|
} else if (type_promotes (base_type (t2), base_type (t1))) {
|
||||||
|
pt1 = promote_type (t2, t1);
|
||||||
|
} else if (base_type (t1) == base_type (t2)) {
|
||||||
|
if (is_vector (t1) || is_quaternion (t1)) {
|
||||||
|
pt2 = t1;
|
||||||
|
} else if (is_vector (t2) || is_quaternion (t2)) {
|
||||||
|
pt1 = t2;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
debug (e1, "%d %d\n", e1->implicit, e2->implicit);
|
||||||
|
return invalid_binary_expr (op, e1, e2);
|
||||||
|
}
|
||||||
|
if (pt1 != t1) {
|
||||||
|
e1 = cast_expr (pt1, e1);
|
||||||
|
t1 = pt1;
|
||||||
|
}
|
||||||
|
if (pt2 != t2) {
|
||||||
|
e2 = cast_expr (pt2, e2);
|
||||||
|
t2 = pt2;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (type_width (t1) == 1) {
|
if (type_width (t1) == 1) {
|
||||||
// scalar op vec
|
// scalar op vec
|
||||||
if (!(e = convert_scalar (e1, op, e2))) {
|
if (!(e = convert_scalar (e1, op, e2))) {
|
||||||
|
@ -1076,28 +1120,6 @@ binary_expr (int op, expr_t *e1, expr_t *e2)
|
||||||
// vec op vec of different widths
|
// vec op vec of different widths
|
||||||
return invalid_binary_expr (op, e1, e2);
|
return invalid_binary_expr (op, e1, e2);
|
||||||
}
|
}
|
||||||
if (t1 != t2) {
|
|
||||||
if (is_float (base_type (t1)) && is_double (base_type (t2))
|
|
||||||
&& e2->implicit) {
|
|
||||||
e2 = cast_expr (t1, e2);
|
|
||||||
} else if (is_double (base_type (t1)) && is_float (base_type (t2))
|
|
||||||
&& e1->implicit) {
|
|
||||||
e1 = cast_expr (t2, e1);
|
|
||||||
} else if (type_promotes (base_type (t1), base_type (t2))) {
|
|
||||||
e2 = cast_expr (t1, e2);
|
|
||||||
} else if (type_promotes (base_type (t2), base_type (t1))) {
|
|
||||||
e1 = cast_expr (t2, e1);
|
|
||||||
} else if (base_type (t1) == base_type (t2)) {
|
|
||||||
if (is_vector (t1) || is_quaternion (t1)) {
|
|
||||||
e2 = cast_expr (t1, e2);
|
|
||||||
} else if (is_vector (t2) || is_quaternion (t2)) {
|
|
||||||
e1 = cast_expr (t2, e1);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
debug (e1, "%d %d\n", e1->implicit, e2->implicit);
|
|
||||||
return invalid_binary_expr (op, e1, e2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
t1 = get_type (e1);
|
t1 = get_type (e1);
|
||||||
t2 = get_type (e2);
|
t2 = get_type (e2);
|
||||||
et1 = low_level_type (t1);
|
et1 = low_level_type (t1);
|
||||||
|
|
Loading…
Reference in a new issue