From e08efe036bee8f905962b289288b680aa6ea64cb Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 19 Jan 2011 08:41:24 +0900 Subject: [PATCH] Move the constant expression values into their own struct. --- tools/qfcc/include/expr.h | 67 ++- tools/qfcc/source/class.c | 4 +- tools/qfcc/source/constfold.c | 386 ++++++++-------- tools/qfcc/source/expr.c | 846 ++++++++++++++++------------------ tools/qfcc/source/function.c | 9 +- tools/qfcc/source/immediate.c | 61 ++- tools/qfcc/source/method.c | 4 +- tools/qfcc/source/qc-lex.l | 2 +- tools/qfcc/source/qc-parse.y | 5 +- tools/qfcc/source/qfcc.c | 6 +- tools/qfcc/source/qp-parse.y | 2 +- tools/qfcc/source/struct.c | 6 +- tools/qfcc/source/switch.c | 70 +-- 13 files changed, 704 insertions(+), 764 deletions(-) diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index a734be0fd..64cc57163 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -54,17 +54,7 @@ typedef enum { ex_temp, ///< temporary variable (::ex_temp_t) ex_nil, ///< umm, nil, null. nuff said (0 of any type) - ex_string, ///< string constant (expr_t::e::string_val) - ex_float, ///< float constant (expr_t::e::float_val) - ex_vector, ///< vector constant (expr_t::e::vector_val) - ex_entity, ///< entity constant (expr_t::e::entity_val) - ex_field, ///< field constant - ex_func, ///< function constant (expr_t::e::func_val) - ex_pointer, ///< pointer constant (expr_t::e::pointer) - ex_quaternion, ///< quaternion constant (expr_t::e::quaternion_val) - ex_integer, ///< integer constant (expr_t::e::integer_val) - ex_uinteger, ///< unsigned integer constant (expr_t::e::uinteger_val) - ex_short, ///< short constant (expr_t::e::short_val) + ex_value, ///< constant value (::ex_value_t) } expr_type; /** Binary and unary expressions. @@ -163,6 +153,22 @@ typedef struct { struct expr_s *step; ///< time step until the next state } ex_state_t; +typedef struct ex_value_s { + etype_t type; + union { + const char *string_val; ///< string constant + float float_val; ///< float constant + float vector_val[3]; ///< vector constant + int entity_val; ///< entity constant + int func_val; ///< function constant + ex_pointer_t pointer; ///< pointer constant + float quaternion_val[4]; ///< quaternion constant + int integer_val; ///< integer constant + unsigned uinteger_val; ///< unsigned integer constant + short short_val; ///< short constant + } v; +} ex_value_t; + #define POINTER_VAL(p) (((p).def ? (p).def->ofs : 0) + (p).val) typedef struct expr_s { @@ -181,23 +187,11 @@ typedef struct expr_s { struct def_s *def; ///< def reference expression struct symbol_s *symbol; ///< symbol reference expression ex_temp_t temp; ///< temporary variable expression - - const char *string_val; ///< string constant - float float_val; ///< float constant - float vector_val[3]; ///< vector constant - int entity_val; ///< entity constant - int func_val; ///< function constant - ex_pointer_t pointer; ///< pointer constant - float quaternion_val[4]; ///< quaternion constant - int integer_val; ///< integer constant - unsigned uinteger_val; ///< unsigned integer constant - short short_val; ///< short constant + ex_value_t value; ///< constant value } e; } expr_t; -extern etype_t qc_types[]; extern struct type_s *ev_types[]; -extern expr_type expr_types[]; /** Report a type mismatch error. @@ -368,6 +362,7 @@ expr_t *new_name_expr (const char *name); (expr_t::e::string_val). */ expr_t *new_string_expr (const char *string_val); +const char *expr_string (expr_t *e); /** Create a new float constant expression node. @@ -376,6 +371,7 @@ expr_t *new_string_expr (const char *string_val); (expr_t::e::float_val). */ expr_t *new_float_expr (float float_val); +float expr_float (expr_t *e); /** Create a new vector constant expression node. @@ -384,6 +380,7 @@ expr_t *new_float_expr (float float_val); (expr_t::e::vector_val). */ expr_t *new_vector_expr (const float *vector_val); +const float *expr_vector (expr_t *e); /** Create a new entity constant expression node. @@ -428,6 +425,7 @@ expr_t *new_pointer_expr (int val, struct type_s *type, struct def_s *def); (expr_t::e::quaternion_val). */ expr_t *new_quaternion_expr (const float *quaternion_val); +const float *expr_quaternion (expr_t *e); /** Create a new integer constant expression node. @@ -436,14 +434,7 @@ expr_t *new_quaternion_expr (const float *quaternion_val); (expr_t::e::integer_val). */ expr_t *new_integer_expr (int integer_val); - -/** Create a new unsigned integer constant expression node. - - \param uinteger_val The unsigned integer constant being represented. - \return The new unsigned integer constant expression node - (expr_t::e::uinteger_val). -*/ -expr_t *new_uinteger_expr (unsigned int uinteger_val); +int expr_integer (expr_t *e); /** Create a new short constant expression node. @@ -452,6 +443,7 @@ expr_t *new_uinteger_expr (unsigned int uinteger_val); (expr_t::e::short_val). */ expr_t *new_short_expr (short short_val); +short expr_short (expr_t *e); /** Check of the expression refers to a constant value. @@ -481,6 +473,13 @@ int is_math (int op); */ int is_logic (int op); +int is_string_val (expr_t *e); +int is_float_val (expr_t *e); +int is_vector_val (expr_t *e); +int is_quaternion_val (expr_t *e); +int is_integer_val (expr_t *e); +int is_short_val (expr_t *e); + /** Convert a constant def to a constant expression. \param var The def to convert. @@ -572,12 +571,8 @@ expr_t *append_expr (expr_t *block, expr_t *e); void print_expr (expr_t *e); void convert_int (expr_t *e); -void convert_uint (expr_t *e); void convert_short (expr_t *e); -void convert_uint_int (expr_t *e); -void convert_int_uint (expr_t *e); void convert_short_int (expr_t *e); -void convert_short_uint (expr_t *e); void convert_nil (expr_t *e, struct type_s *t); expr_t *test_expr (expr_t *e, int test); diff --git a/tools/qfcc/source/class.c b/tools/qfcc/source/class.c index 6fb706ed0..787208f72 100644 --- a/tools/qfcc/source/class.c +++ b/tools/qfcc/source/class.c @@ -552,8 +552,8 @@ class_message_response (class_t *class, int class_msg, expr_t *sel) class_t *c = class; category_t *cat; - if (sel->type != ex_pointer - && sel->e.pointer.type != type_SEL.t.fldptr.type) { + if (sel->type != ex_value && sel->e.value.type != ev_pointer + && sel->e.value.v.pointer.type != type_SEL.t.fldptr.type) { error (sel, "not a selector"); return 0; } diff --git a/tools/qfcc/source/constfold.c b/tools/qfcc/source/constfold.c index 447a34bc3..c00e7e86e 100644 --- a/tools/qfcc/source/constfold.c +++ b/tools/qfcc/source/constfold.c @@ -94,8 +94,12 @@ do_op_string (int op, expr_t *e, expr_t *e1, expr_t *e2) if (op == '=' || op == 'b' || !is_constant (e1) || !is_constant (e2)) return e; - s1 = e1->e.string_val ? e1->e.string_val : ""; - s2 = e2->e.string_val ? e2->e.string_val : ""; + s1 = expr_string (e1); + s2 = expr_string (e2); + if (!s1) + s1 = ""; + if (!s2) + s2 = ""; switch (op) { case '+': @@ -104,36 +108,32 @@ do_op_string (int op, expr_t *e, expr_t *e1, expr_t *e2) dstring_clearstr (temp_str); dstring_appendstr (temp_str, s1); dstring_appendstr (temp_str, s2); - e1->e.string_val = save_string (temp_str->str); + e = new_string_expr (save_string (temp_str->str)); break; case LT: - e1->type = ex_integer; - e1->e.integer_val = strcmp (s1, s2) < 0; + e = new_integer_expr (strcmp (s1, s2) < 0); break; case GT: - e1->type = ex_integer; - e1->e.integer_val = strcmp (s1, s2) > 0; + e = new_integer_expr (strcmp (s1, s2) > 0); break; case LE: - e1->type = ex_integer; - e1->e.integer_val = strcmp (s1, s2) <= 0; + e = new_integer_expr (strcmp (s1, s2) <= 0); break; case GE: - e1->type = ex_integer; - e1->e.integer_val = strcmp (s1, s2) >= 0; + e = new_integer_expr (strcmp (s1, s2) >= 0); break; case EQ: - e1->type = ex_integer; - e1->e.integer_val = strcmp (s1, s2) == 0; + e = new_integer_expr (strcmp (s1, s2) == 0); break; case NE: - e1->type = ex_integer; - e1->e.integer_val = strcmp (s1, s2) != 0; + e = new_integer_expr (strcmp (s1, s2)); break; default: internal_error (e1, 0); } - return e1; + e->file = e1->file; + e->line = e1->line; + return e; } static expr_t * @@ -143,15 +143,18 @@ convert_to_float (expr_t *e) return e; switch (e->type) { - case ex_integer: - convert_int (e); - return e; - case ex_uinteger: - convert_uint (e); - return e; - case ex_short: - convert_short (e); - return e; + case ex_value: + switch (e->e.value.type) { + case ev_integer: + convert_int (e); + return e; + case ev_short: + convert_short (e); + return e; + default: + internal_error (e, 0); + } + break; case ex_def: case ex_expr: case ex_uexpr: @@ -209,108 +212,103 @@ do_op_float (int op, expr_t *e, expr_t *e1, expr_t *e2) } e->e.expr.type = type; - if (op == '*' && is_constant (e1) && e1->e.float_val == 1) + if (op == '*' && is_constant (e1) && expr_float (e1) == 1) return e2; - if (op == '*' && is_constant (e2) && e2->e.float_val == 1) + if (op == '*' && is_constant (e2) && expr_float (e2) == 1) return e1; - if (op == '*' && is_constant (e1) && e1->e.float_val == 0) + if (op == '*' && is_constant (e1) && expr_float (e1) == 0) return e1; - if (op == '*' && is_constant (e2) && e2->e.float_val == 0) + if (op == '*' && is_constant (e2) && expr_float (e2) == 0) return e2; - if (op == '/' && is_constant (e2) && e2->e.float_val == 1) + if (op == '/' && is_constant (e2) && expr_float (e2) == 1) return e1; - if (op == '/' && is_constant (e2) && e2->e.float_val == 0) + if (op == '/' && is_constant (e2) && expr_float (e2) == 0) return error (e, "division by zero"); - if (op == '/' && is_constant (e1) && e1->e.float_val == 0) + if (op == '/' && is_constant (e1) && expr_float (e1) == 0) return e1; - if (op == '+' && is_constant (e1) && e1->e.float_val == 0) + if (op == '+' && is_constant (e1) && expr_float (e1) == 0) return e2; - if (op == '+' && is_constant (e2) && e2->e.float_val == 0) + if (op == '+' && is_constant (e2) && expr_float (e2) == 0) return e1; - if (op == '-' && is_constant (e2) && e2->e.float_val == 0) + if (op == '-' && is_constant (e2) && expr_float (e2) == 0) return e1; if (op == '=' || op == 'b' || !is_constant (e1) || !is_constant (e2)) return e; - f1 = e1->e.float_val; - f2 = e2->e.float_val; + f1 = expr_float (e1); + f2 = expr_float (e2); switch (op) { case '+': - e1->e.float_val += f2; + e = new_float_expr (f1 + f2); break; case '-': - e1->e.float_val -= f2; + e = new_float_expr (f1 - f2); break; case '*': - e1->e.float_val *= f2; + e = new_float_expr (f1 * f2); break; case '/': if (!f2) return error (e1, "divide by zero"); - e1->e.float_val /= f2; + e = new_float_expr (f1 / f2); break; case '&': - e1->e.float_val = (int) f1 & (int) f2; + e = new_float_expr ((int)f1 & (int)f2); break; case '|': - e1->e.float_val = (int) f1 | (int) f2; + e = new_float_expr ((int)f1 | (int)f2); break; case '^': - e1->e.float_val = (int) f1 ^ (int) f2; + e = new_float_expr ((int)f1 ^ (int)f2); break; case '%': - e1->e.float_val = (int) f1 % (int) f2; + e = new_float_expr ((int)f1 % (int)f2); break; case SHL: - e1->e.float_val = (int) f1 << (int) f2; + e = new_float_expr ((int)f1 << (int)f2); break; case SHR: - e1->e.float_val = (int) f1 >> (int) f2; + e = new_float_expr ((int)f1 >> (int)f2); break; case AND: - e1->type = ex_integer; - e1->e.integer_val = f1 && f2; + e = new_integer_expr (f1 && f2); break; case OR: - e1->type = ex_integer; - e1->e.integer_val = f1 || f2; + e = new_integer_expr (f1 || f2); break; case LT: - e1->type = ex_integer; - e1->e.integer_val = f1 < f2; + e = new_integer_expr (f1 < f2); break; case GT: - e1->type = ex_integer; - e1->e.integer_val = f1 > f2; + e = new_integer_expr (f1 > f2); break; case LE: - e1->type = ex_integer; - e1->e.integer_val = f1 <= f2; + e = new_integer_expr (f1 <= f2); break; case GE: - e1->type = ex_integer; - e1->e.integer_val = f1 >= f2; + e = new_integer_expr (f1 >= f2); break; case EQ: - e1->type = ex_integer; - e1->e.integer_val = f1 == f2; + e = new_integer_expr (f1 == f2); break; case NE: - e1->type = ex_integer; - e1->e.integer_val = f1 != f2; + e = new_integer_expr (f1 != f2); break; default: internal_error (e1, 0); } - return e1; + e->file = e1->file; + e->line = e1->line; + return e; } static expr_t * do_op_vector (int op, expr_t *e, expr_t *e1, expr_t *e2) { - float *v1, *v2; + const float *v1, *v2; + vec3_t v; static int valid[] = {'=', 'b', '+', '-', '*', EQ, NE, 0}; expr_t *t; @@ -342,69 +340,69 @@ do_op_vector (int op, expr_t *e, expr_t *e1, expr_t *e2) e->e.expr.type = &type_vector; } - if (op == '*' && is_constant (e1) && e1->type == ex_float - && e1->e.float_val == 1) - return e2; - if (op == '*' && is_constant (e2) && e2->type == ex_float - && e2->e.float_val == 1) + if (op == '*' && is_float_val (e2) && expr_float (e2) == 1) return e1; - if (op == '*' && is_constant (e1) && e1->type == ex_float - && e1->e.float_val == 0) + if (op == '*' && is_float_val (e2) && expr_float (e2) == 0) return new_vector_expr (vec3_origin); - if (op == '*' && is_constant (e2) && e2->type == ex_float - && e2->e.float_val == 0) - return new_vector_expr (vec3_origin); - if (op == '/' && is_constant (e2) && e2->type == ex_float - && e2->e.float_val == 1) + if (op == '/' && is_float_val (e2) && expr_float (e2) == 1) return e1; - if (op == '/' && is_constant (e2) && e2->type == ex_float - && e2->e.float_val == 0) + if (op == '/' && is_float_val (e2) && expr_float (e2) == 0) return error (e, "division by zero"); - if (op == '+' && is_constant (e1) && VectorIsZero (e1->e.vector_val)) + if (op == '+' && is_constant (e1) && VectorIsZero (expr_vector (e1))) return e2; - if (op == '+' && is_constant (e2) && VectorIsZero (e2->e.vector_val)) + if (op == '+' && is_constant (e2) && VectorIsZero (expr_vector (e2))) return e1; - if (op == '-' && is_constant (e2) && VectorIsZero (e2->e.vector_val)) + if (op == '-' && is_constant (e1) && VectorIsZero (expr_vector (e1))) { + vec3_t v; + VectorNegate (expr_vector (e2), v); + e = new_vector_expr (v); + e->file = e2->file; + e->line = e2->line; + return e; + } + if (op == '-' && is_constant (e2) && VectorIsZero (expr_vector (e2))) return e1; if (op == '=' || op == 'b' || !is_constant (e1) || !is_constant (e2)) return e; - v1 = e1->e.vector_val; - v2 = e2->e.vector_val; + v1 = expr_vector (e1); + v2 = expr_vector (e2); switch (op) { case '+': - VectorAdd (v1, v2, v1); + VectorAdd (v1, v2, v); + e = new_vector_expr (v); break; case '-': - VectorSubtract (v1, v2, v1); + VectorSubtract (v1, v2, v); + e = new_vector_expr (v); break; case '/': if (!v2[0]) return error (e1, "divide by zero"); - VectorScale (v1, 1 / v2[0], v1); + VectorScale (v1, 1 / v2[0], v); break; case '*': if (get_type (e2) == &type_vector) { - e1->type = ex_float; - e1->e.float_val = DotProduct (v1, v2); + e = new_float_expr (DotProduct (v1, v2)); } else { - VectorScale (v1, v2[0], v1); + VectorScale (v1, v2[0], v); + e = new_vector_expr (v); } break; case EQ: - e1->type = ex_integer; - e1->e.integer_val = VectorCompare (v1, v2); + e = new_integer_expr (VectorCompare (v1, v2)); break; case NE: - e1->type = ex_integer; - e1->e.integer_val = !VectorCompare (v1, v2); + e = new_integer_expr (!VectorCompare (v1, v2)); break; default: internal_error (e1, 0); } - return e1; + e->file = e1->file; + e->line = e1->line; + return e; } static expr_t * @@ -498,18 +496,21 @@ do_op_pointer (int op, expr_t *e, expr_t *e1, expr_t *e2) static expr_t * do_op_quaternion (int op, expr_t *e, expr_t *e1, expr_t *e2) { - float *q1, *q2; + const float *q1, *q2; + quat_t q; static int valid[] = {'=', 'b', '+', '-', '*', EQ, NE, 0}; expr_t *t; if (get_type (e1) != &type_quaternion) { - if (op != '*') + if (op != '*' || op != '/') return error (e1, "invalid operand for quaternion"); - t = e1; - e->e.expr.e1 = e1 = e2; - e2 = t; + if (op == '*') { + t = e1; + e->e.expr.e1 = e1 = e2; + e2 = t; + } } if (get_type (e2) != &type_quaternion) { e->e.expr.e2 = e2 = convert_to_float (e2); @@ -528,70 +529,65 @@ do_op_quaternion (int op, expr_t *e, expr_t *e1, expr_t *e2) e->e.expr.type = &type_quaternion; } - if (op == '*' && is_constant (e1) && e1->type == ex_float - && e1->e.float_val == 1) - return e2; - if (op == '*' && is_constant (e2) && e2->type == ex_float - && e2->e.float_val == 1) + if (op == '*' && is_float_val (e2) && expr_float (e2) == 1) return e1; - if (op == '*' && is_constant (e1) && e1->type == ex_float - && e1->e.float_val == 0) + if (op == '*' && is_float_val (e2) && expr_float (e2) == 0) return new_quaternion_expr (quat_origin); - if (op == '*' && is_constant (e2) && e2->type == ex_float - && e2->e.float_val == 0) - return new_quaternion_expr (quat_origin); - if (op == '/' && is_constant (e2) && e2->type == ex_float - && e2->e.float_val == 1) + if (op == '/' && is_float_val (e2) && expr_float (e2) == 1) return e1; - if (op == '/' && is_constant (e2) && e2->type == ex_float - && e2->e.float_val == 0) + if (op == '/' && is_float_val (e2) && expr_float (e2) == 0) return error (e, "division by zero"); - if (op == '+' && is_constant (e1) && QuatIsZero (e1->e.quaternion_val)) + if (op == '+' && is_constant (e1) && QuatIsZero (expr_quaternion (e1))) return e2; - if (op == '+' && is_constant (e2) && QuatIsZero (e2->e.quaternion_val)) + if (op == '+' && is_constant (e2) && QuatIsZero (expr_quaternion (e2))) return e1; - if (op == '-' && is_constant (e2) && QuatIsZero (e2->e.quaternion_val)) + if (op == '-' && is_constant (e2) && QuatIsZero (expr_quaternion (e2))) return e1; if (op == '=' || op == 'b' || !is_constant (e1) || !is_constant (e2)) return e; - q1 = e1->e.quaternion_val; - q2 = e2->e.quaternion_val; + q1 = expr_quaternion (e1); + q2 = expr_quaternion (e2); switch (op) { case '+': - QuatAdd (q1, q2, q1); + QuatAdd (q1, q2, q); + e = new_quaternion_expr (q); break; case '-': - QuatSubtract (q1, q2, q1); + QuatSubtract (q1, q2, q); + e = new_quaternion_expr (q); break; case '/': - if (!q2[0]) - return error (e1, "divide by zero"); - QuatScale (q1, 1 / q2[0], q1); - q1[3] /= q2[0]; + if (is_float_val (e2)) { + QuatScale (q1, 1 / expr_float (e2), q); + } else { + QuatInverse (q2, q); + QuatScale (q2, expr_float (e1), q); + } + e = new_quaternion_expr (q); break; case '*': if (get_type (e2) == &type_quaternion) { - QuatMult (q1, q2, q1); + QuatMult (q1, q2, q); } else { - QuatScale (q1, q2[0], q1); - q1[3] *= q2[0]; + QuatScale (q1, q2[0], q); } + e = new_quaternion_expr (q); break; case EQ: - e1->type = ex_integer; - e1->e.integer_val = QuatCompare (q1, q2); + e = new_integer_expr (QuatCompare (q1, q2)); break; case NE: - e1->type = ex_integer; - e1->e.integer_val = !QuatCompare (q1, q2); + e = new_integer_expr (!QuatCompare (q1, q2)); break; default: internal_error (e1, 0); } - return e1; + e->file = e1->file; + e->line = e1->line; + return e; } static expr_t * @@ -606,10 +602,10 @@ do_op_integer (int op, expr_t *e, expr_t *e1, expr_t *e2) if (!valid_op (op, valid)) return error (e1, "invalid operand for integer"); - if (e1->type == ex_short) + if (is_short_val (e1)) convert_short_int (e1); - if (e2->type == ex_short) + if (is_short_val (e2)) convert_short_int (e2); if (is_compare (op) || is_logic (op)) { @@ -621,100 +617,96 @@ do_op_integer (int op, expr_t *e, expr_t *e1, expr_t *e2) e->e.expr.type = &type_integer; } - if (op == '*' && is_constant (e1) && e1->e.integer_val == 1) + if (op == '*' && is_constant (e1) && expr_integer (e1) == 1) return e2; - if (op == '*' && is_constant (e2) && e2->e.integer_val == 1) + if (op == '*' && is_constant (e2) && expr_integer (e2) == 1) return e1; - if (op == '*' && is_constant (e1) && e1->e.integer_val == 0) + if (op == '*' && is_constant (e1) && expr_integer (e1) == 0) return e1; - if (op == '*' && is_constant (e2) && e2->e.integer_val == 0) + if (op == '*' && is_constant (e2) && expr_integer (e2) == 0) return e2; - if (op == '/' && is_constant (e2) && e2->e.integer_val == 1) + if (op == '/' && is_constant (e2) && expr_integer (e2) == 1) return e1; - if (op == '/' && is_constant (e2) && e2->e.integer_val == 0) + if (op == '/' && is_constant (e2) && expr_integer (e2) == 0) return error (e, "division by zero"); - if (op == '/' && is_constant (e1) && e1->e.integer_val == 0) + if (op == '/' && is_constant (e1) && expr_integer (e1) == 0) return e1; - if (op == '+' && is_constant (e1) && e1->e.integer_val == 0) + if (op == '+' && is_constant (e1) && expr_integer (e1) == 0) return e2; - if (op == '+' && is_constant (e2) && e2->e.integer_val == 0) + if (op == '+' && is_constant (e2) && expr_integer (e2) == 0) return e1; - if (op == '-' && is_constant (e2) && e2->e.integer_val == 0) + if (op == '-' && is_constant (e2) && expr_integer (e2) == 0) return e1; if (op == '=' || op == 'b' || !is_constant (e1) || !is_constant (e2)) return e; - i1 = e1->e.integer_val; - i2 = e2->e.integer_val; + i1 = expr_integer (e1); + i2 = expr_integer (e2); switch (op) { case '+': - e1->e.integer_val += i2; + e = new_integer_expr (i1 + i2); break; case '-': - e1->e.integer_val -= i2; + e = new_integer_expr (i1 - i2); break; case '*': - e1->e.integer_val *= i2; + e = new_integer_expr (i1 * i2); break; case '/': if (options.warnings.integer_divide) warning (e2, "%d / %d == %d", i1, i2, i1 / i2); - e1->e.integer_val /= i2; + e = new_integer_expr (i1 / i2); break; case '&': - e1->e.integer_val = i1 & i2; + e = new_integer_expr (i1 & i2); break; case '|': - e1->e.integer_val = i1 | i2; + e = new_integer_expr (i1 | i2); break; case '^': - e1->e.integer_val = i1 ^ i2; + e = new_integer_expr (i1 ^ i2); break; case '%': - e1->e.integer_val = i1 % i2; + e = new_integer_expr (i1 % i2); break; case SHL: - e1->e.integer_val = i1 << i2; + e = new_integer_expr (i1 << i2); break; case SHR: - e1->e.integer_val = i1 >> i2; + e = new_integer_expr (i1 >> i2); break; case AND: - e1->e.integer_val = i1 && i2; + e = new_integer_expr (i1 && i2); break; case OR: - e1->e.integer_val = i1 || i2; + e = new_integer_expr (i1 || i2); break; case LT: - e1->type = ex_integer; - e1->e.integer_val = i1 < i2; + e = new_integer_expr (i1 < i2); break; case GT: - e1->type = ex_integer; - e1->e.integer_val = i1 > i2; + e = new_integer_expr (i1 > i2); break; case LE: - e1->type = ex_integer; - e1->e.integer_val = i1 <= i2; + e = new_integer_expr (i1 <= i2); break; case GE: - e1->type = ex_integer; - e1->e.integer_val = i1 >= i2; + e = new_integer_expr (i1 >= i2); break; case EQ: - e1->type = ex_integer; - e1->e.integer_val = i1 == i2; + e = new_integer_expr (i1 == i2); break; case NE: - e1->type = ex_integer; - e1->e.integer_val = i1 != i2; + e = new_integer_expr (i1 != i2); break; default: internal_error (e1, 0); } - return e1; + e->file = e1->file; + e->line = e1->line; + return e; } static expr_t * @@ -741,76 +733,72 @@ do_op_short (int op, expr_t *e, expr_t *e1, expr_t *e2) if (op == '=' || op == 'b' || !is_constant (e1) || !is_constant (e2)) return e; - i1 = e1->e.short_val; - i2 = e2->e.short_val; + i1 = expr_short (e1); + i2 = expr_short (e2); switch (op) { case '+': - e1->e.short_val += i2; + e = new_short_expr (i1 + i2); break; case '-': - e1->e.short_val -= i2; + e = new_short_expr (i1 - i2); break; case '*': - e1->e.short_val *= i2; + e = new_short_expr (i1 * i2); break; case '/': if (options.warnings.integer_divide) warning (e2, "%d / %d == %d", i1, i2, i1 / i2); - e1->e.short_val /= i2; + e = new_short_expr (i1 / i2); break; case '&': - e1->e.short_val = i1 & i2; + e = new_short_expr (i1 & i2); break; case '|': - e1->e.short_val = i1 | i2; + e = new_short_expr (i1 | i2); break; case '^': - e1->e.short_val = i1 ^ i2; + e = new_short_expr (i1 ^ i2); break; case '%': - e1->e.short_val = i1 % i2; + e = new_short_expr (i1 % i2); break; case SHL: - e1->e.short_val = i1 << i2; + e = new_short_expr (i1 << i2); break; case SHR: - e1->e.short_val = i1 >> i2; + e = new_short_expr (i1 >> i2); break; case AND: - e1->e.short_val = i1 && i2; + e = new_short_expr (i1 && i2); break; case OR: - e1->e.short_val = i1 || i2; + e = new_short_expr (i1 || i2); break; case LT: - e1->type = ex_integer; - e1->e.integer_val = i1 < i2; + e = new_integer_expr (i1 < i2); break; case GT: - e1->type = ex_integer; - e1->e.integer_val = i1 > i2; + e = new_integer_expr (i1 > i2); break; case LE: - e1->type = ex_integer; - e1->e.integer_val = i1 <= i2; + e = new_integer_expr (i1 <= i2); break; case GE: - e1->type = ex_integer; - e1->e.integer_val = i1 >= i2; + e = new_integer_expr (i1 >= i2); break; case EQ: - e1->type = ex_integer; - e1->e.integer_val = i1 == i2; + e = new_integer_expr (i1 == i2); break; case NE: - e1->type = ex_integer; - e1->e.integer_val = i1 != i2; + e = new_integer_expr (i1 != i2); break; default: internal_error (e1, 0); } - return e1; + e->file = e1->file; + e->line = e1->line; + return e; } static expr_t * diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index e590b322b..c15db77c8 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -68,32 +68,6 @@ static __attribute__ ((used)) const char rcsid[] = static expr_t *free_exprs; int lineno_base; -etype_t qc_types[] = { - ev_void, // ex_error - ev_void, // ex_state - ev_void, // ex_bool - ev_void, // ex_label - ev_void, // ex_block - ev_void, // ex_expr - ev_void, // ex_uexpr - ev_void, // ex_def - ev_void, // ex_symbol - ev_void, // ex_temp - - ev_void, // ex_nil - ev_string, // ex_string - ev_float, // ex_float - ev_vector, // ex_vector - ev_entity, // ex_entity - ev_field, // ex_field - ev_func, // ex_func - ev_pointer, // ex_pointer - ev_quat, // ex_quaternion - ev_integer, // ex_integer - ev_integer, // ex_uinteger - ev_short, // ex_short -}; - type_t *ev_types[ev_type_count] = { &type_void, &type_string, @@ -109,26 +83,6 @@ type_t *ev_types[ev_type_count] = { &type_void, // FIXME what type? }; -expr_type expr_types[] = { - ex_nil, // ev_void - ex_string, // ev_string - ex_float, // ev_float - ex_vector, // ev_vector - ex_entity, // ev_entity - ex_field, // ev_field - ex_func, // ev_func - ex_pointer, // ev_pointer - ex_quaternion, // ev_quat - ex_integer, // ev_integer - ex_uinteger, // ev_uinteger - ex_short, // ev_short - ex_nil, // ev_struct - ex_nil, // ev_object - ex_nil, // ev_class - ex_nil, // ev_sel - ex_nil, // ev_array -}; - type_t * get_type (expr_t *e) { @@ -156,24 +110,15 @@ get_type (expr_t *e) return e->e.symbol->type; case ex_temp: return e->e.temp.type; - case ex_pointer: - return pointer_type (e->e.pointer.type); - case ex_integer: - if (options.code.progsversion == PROG_ID_VERSION) { - e->type = ex_float; - e->e.float_val = e->e.integer_val; + case ex_value: + if (e->e.value.type == ev_pointer) + return pointer_type (e->e.value.v.pointer.type); + if (e->e.value.type == ev_integer + && options.code.progsversion == PROG_ID_VERSION) { + e->e.value.type = ev_float; + e->e.value.v.float_val = e->e.value.v.integer_val; } - // fall through - case ex_string: - case ex_float: - case ex_vector: - case ex_entity: - case ex_field: - case ex_func: - case ex_quaternion: - case ex_uinteger: - case ex_short: - return ev_types[qc_types[e->type]]; + return ev_types[e->e.value.type]; } return 0; } @@ -370,17 +315,7 @@ copy_expr (expr_t *e) case ex_def: case ex_symbol: case ex_nil: - case ex_string: - case ex_float: - case ex_vector: - case ex_entity: - case ex_field: - case ex_func: - case ex_pointer: - case ex_quaternion: - case ex_integer: - case ex_uinteger: - case ex_short: + case ex_value: // nothing to do here n = new_expr (); *n = *e; @@ -613,8 +548,9 @@ expr_t * new_string_expr (const char *string_val) { expr_t *e = new_expr (); - e->type = ex_string; - e->e.string_val = string_val; + e->type = ex_value; + e->e.value.type = ev_string; + e->e.value.v.string_val = string_val; return e; } @@ -622,8 +558,9 @@ expr_t * new_float_expr (float float_val) { expr_t *e = new_expr (); - e->type = ex_float; - e->e.float_val = float_val; + e->type = ex_value; + e->e.value.type = ev_float; + e->e.value.v.float_val = float_val; return e; } @@ -631,8 +568,9 @@ expr_t * new_vector_expr (const float *vector_val) { expr_t *e = new_expr (); - e->type = ex_vector; - memcpy (e->e.vector_val, vector_val, sizeof (e->e.vector_val)); + e->type = ex_value; + e->e.value.type = ev_vector; + VectorCopy (vector_val, e->e.value.v.vector_val); return e; } @@ -640,8 +578,9 @@ expr_t * new_entity_expr (int entity_val) { expr_t *e = new_expr (); - e->type = ex_entity; - e->e.entity_val = entity_val; + e->type = ex_value; + e->e.value.type = ev_entity; + e->e.value.v.entity_val = entity_val; return e; } @@ -649,10 +588,11 @@ expr_t * new_field_expr (int field_val, type_t *type, def_t *def) { expr_t *e = new_expr (); - e->type = ex_field; - e->e.pointer.val = field_val; - e->e.pointer.type = type; - e->e.pointer.def = def; + e->type = ex_value; + e->e.value.type = ev_field; + e->e.value.v.pointer.val = field_val; + e->e.value.v.pointer.type = type; + e->e.value.v.pointer.def = def; return e; } @@ -660,8 +600,9 @@ expr_t * new_func_expr (int func_val) { expr_t *e = new_expr (); - e->type = ex_func; - e->e.func_val = func_val; + e->type = ex_value; + e->e.value.type = ev_func; + e->e.value.v.func_val = func_val; return e; } @@ -669,10 +610,11 @@ expr_t * new_pointer_expr (int val, type_t *type, def_t *def) { expr_t *e = new_expr (); - e->type = ex_pointer; - e->e.pointer.val = val; - e->e.pointer.type = type; - e->e.pointer.def = def; + e->type = ex_value; + e->e.value.type = ev_pointer; + e->e.value.v.pointer.val = val; + e->e.value.v.pointer.type = type; + e->e.value.v.pointer.def = def; return e; } @@ -680,8 +622,9 @@ expr_t * new_quaternion_expr (const float *quaternion_val) { expr_t *e = new_expr (); - e->type = ex_quaternion; - memcpy (e->e.quaternion_val, quaternion_val, sizeof (e->e.quaternion_val)); + e->type = ex_value; + e->e.value.type = ev_quat; + QuatCopy (quaternion_val, e->e.value.v.quaternion_val); return e; } @@ -689,17 +632,9 @@ expr_t * new_integer_expr (int integer_val) { expr_t *e = new_expr (); - e->type = ex_integer; - e->e.integer_val = integer_val; - return e; -} - -expr_t * -new_uinteger_expr (unsigned int uinteger_val) -{ - expr_t *e = new_expr (); - e->type = ex_uinteger; - e->e.uinteger_val = uinteger_val; + e->type = ex_value; + e->e.value.type = ev_integer; + e->e.value.v.integer_val = integer_val; return e; } @@ -707,20 +642,177 @@ expr_t * new_short_expr (short short_val) { expr_t *e = new_expr (); - e->type = ex_short; - e->e.short_val = short_val; + e->type = ex_value; + e->e.value.type = ev_short; + e->e.value.v.short_val = short_val; return e; } int is_constant (expr_t *e) { - if (e->type >= ex_nil - || (e->type == ex_def && e->e.def->constant)) + if (e->type == ex_nil || e->type == ex_value + || (e->type == ex_symbol && e->e.symbol->sy_type == sy_const)) return 1; return 0; } +int +is_string_val (expr_t *e) +{ + if (e->type == ex_nil) + return 1; + if (e->type == ex_value && e->e.value.type == ev_string) + return 1; + if (e->type == ex_symbol && e->e.symbol->sy_type == sy_const + && e->e.symbol->type->type == ev_string) + return 1; + return 0; +} + +const char * +expr_string (expr_t *e) +{ + if (e->type == ex_nil) + return 0; + if (e->type == ex_value && e->e.value.type == ev_string) + return e->e.value.v.string_val; + //if (e->type == ex_symbol && e->e.symbol->sy_type == sy_const + // && e->e.symbol->type->type == ev_string) + // return e->e.symbol->s.value; + internal_error (e, "not a string constant"); +} + +int +is_float_val (expr_t *e) +{ + if (e->type == ex_nil) + return 1; + if (e->type == ex_value && e->e.value.type == ev_float) + return 1; + if (e->type == ex_symbol && e->e.symbol->sy_type == sy_const + && e->e.symbol->type->type == ev_float) + return 1; + return 0; +} + +float +expr_float (expr_t *e) +{ + if (e->type == ex_nil) + return 0; + if (e->type == ex_value && e->e.value.type == ev_float) + return e->e.value.v.float_val; + if (e->type == ex_symbol && e->e.symbol->sy_type == sy_const + && e->e.symbol->type->type == ev_float) + return e->e.symbol->s.value; + internal_error (e, "not a float constant"); +} + +int +is_vector_val (expr_t *e) +{ + if (e->type == ex_nil) + return 1; + if (e->type == ex_value && e->e.value.type == ev_vector) + return 1; + if (e->type == ex_symbol && e->e.symbol->sy_type == sy_const + && e->e.symbol->type->type == ev_vector) + return 1; + return 0; +} + +const float * +expr_vector (expr_t *e) +{ + if (e->type == ex_nil) + return vec3_origin; + if (e->type == ex_value && e->e.value.type == ev_vector) + return e->e.value.v.vector_val; + //if (e->type == ex_symbol && e->e.symbol->sy_type == sy_const + // && e->e.symbol->type->type == ev_vector) + // return e->e.symbol->s.value; + internal_error (e, "not a vector constant"); +} + +int +is_quaternion_val (expr_t *e) +{ + if (e->type == ex_nil) + return 1; + if (e->type == ex_value && e->e.value.type == ev_quat) + return 1; + if (e->type == ex_symbol && e->e.symbol->sy_type == sy_const + && e->e.symbol->type->type == ev_quat) + return 1; + return 0; +} + +const float * +expr_quaternion (expr_t *e) +{ + if (e->type == ex_nil) + return quat_origin; + if (e->type == ex_value && e->e.value.type == ev_quat) + return e->e.value.v.quaternion_val; + //if (e->type == ex_symbol && e->e.symbol->sy_type == sy_const + // && e->e.symbol->type->type == ev_quat) + // return e->e.symbol->s.value; + internal_error (e, "not a quaternion constant"); +} + +int +is_integer_val (expr_t *e) +{ + if (e->type == ex_nil) + return 1; + if (e->type == ex_value && e->e.value.type == ev_integer) + return 1; + if (e->type == ex_symbol && e->e.symbol->sy_type == sy_const + && e->e.symbol->type->type == ev_integer) + return 1; + return 0; +} + +int +expr_integer (expr_t *e) +{ + if (e->type == ex_nil) + return 0; + if (e->type == ex_value && e->e.value.type == ev_integer) + return e->e.value.v.integer_val; + if (e->type == ex_symbol && e->e.symbol->sy_type == sy_const + && e->e.symbol->type->type == ev_integer) + return e->e.symbol->s.value; + internal_error (e, "not an integer constant"); +} + +int +is_short_val (expr_t *e) +{ + if (e->type == ex_nil) + return 1; + if (e->type == ex_value && e->e.value.type == ev_short) + return 1; + if (e->type == ex_symbol && e->e.symbol->sy_type == sy_const + && e->e.symbol->type->type == ev_short) + return 1; + return 0; +} + +short +expr_short (expr_t *e) +{ + if (e->type == ex_nil) + return 0; + if (e->type == ex_value && e->e.value.type == ev_short) + return e->e.value.v.short_val; + if (e->type == ex_symbol && e->e.symbol->sy_type == sy_const + && e->e.symbol->type->type == ev_short) + return e->e.symbol->s.value; + internal_error (e, "not a short constant"); +} + expr_t * constant_expr (expr_t *var) { @@ -755,8 +847,7 @@ new_bind_expr (expr_t *e1, expr_t *e2) expr_t *e; if (!e2 || e2->type != ex_temp) { - error (e1, "internal error"); - abort (); + internal_error (e1, 0); } e = new_expr (); e->type = ex_expr; @@ -934,41 +1025,46 @@ print_expr (expr_t *e) case ex_nil: printf ("NIL"); break; - case ex_string: - printf ("\"%s\"", e->e.string_val); - break; - case ex_float: - printf ("%g", e->e.float_val); - break; - case ex_vector: - printf ("'%g", e->e.vector_val[0]); - printf (" %g", e->e.vector_val[1]); - printf (" %g'", e->e.vector_val[2]); - break; - case ex_quaternion: - printf ("'%g", e->e.quaternion_val[0]); - printf (" %g", e->e.quaternion_val[1]); - printf (" %g", e->e.quaternion_val[2]); - printf (" %g'", e->e.quaternion_val[3]); - break; - case ex_pointer: - printf ("(%s)[%d]", pr_type_name[e->e.pointer.type->type], - e->e.pointer.val); - break; - case ex_field: - printf ("%d", e->e.pointer.val); - break; - case ex_entity: - case ex_func: - case ex_integer: - printf ("%d", e->e.integer_val); - break; - case ex_uinteger: - printf ("%u", e->e.uinteger_val); - break; - case ex_short: - printf ("%d", e->e.short_val); - break; + case ex_value: + switch (e->e.value.type) { + case ev_string: + printf ("\"%s\"", e->e.value.v.string_val); + break; + case ev_float: + printf ("%g", e->e.value.v.float_val); + break; + case ev_vector: + printf ("'%g", e->e.value.v.vector_val[0]); + printf (" %g", e->e.value.v.vector_val[1]); + printf (" %g'", e->e.value.v.vector_val[2]); + break; + case ev_quat: + printf ("'%g", e->e.value.v.quaternion_val[0]); + printf (" %g", e->e.value.v.quaternion_val[1]); + printf (" %g", e->e.value.v.quaternion_val[2]); + printf (" %g'", e->e.value.v.quaternion_val[3]); + break; + case ev_pointer: + printf ("(%s)[%d]", + pr_type_name[e->e.value.v.pointer.type->type], + e->e.value.v.pointer.val); + break; + case ev_field: + printf ("%d", e->e.value.v.pointer.val); + break; + case ev_entity: + case ev_func: + case ev_integer: + printf ("%d", e->e.value.v.integer_val); + break; + case ev_short: + printf ("%d", e->e.value.v.short_val); + break; + case ev_void: + case ev_invalid: + case ev_type_count: + internal_error (e, "weird expression type"); + } } } @@ -997,8 +1093,7 @@ test_expr (expr_t *e, int test) return e; switch (type) { case ev_type_count: - error (e, "internal error"); - abort (); + internal_error (e, 0); case ev_void: if (options.traditional) { if (options.warnings.traditional) @@ -1065,8 +1160,7 @@ backpatch (ex_list_t *list, expr_t *label) || e->e.expr.op == 'n')) e->e.expr.e2 = label; else { - error (e, "internal compiler error"); - abort (); + internal_error (e, 0); } } } @@ -1077,8 +1171,7 @@ merge (ex_list_t *l1, ex_list_t *l2) ex_list_t *m; if (!l1 && !l2) { - error (0, "internal error"); - abort (); + internal_error (0, 0); } if (!l2) return l1; @@ -1124,9 +1217,9 @@ convert_bool (expr_t *e, int block) e = test_expr (e, 1); if (e->type == ex_error) return e; - if (e->type == ex_integer) { + if (is_integer_val (e)) { b = new_unary_expr ('g', 0); - if (e->e.integer_val) + if (expr_integer (e)) e = new_bool_expr (make_list (b), 0, b); else e = new_bool_expr (0, make_list (b), b); @@ -1210,65 +1303,38 @@ bool_expr (int op, expr_t *label, expr_t *e1, expr_t *e2) e2->e.bool.false_list), block); break; } - error (e1, "internal error"); - abort (); + internal_error (e1, 0); } void convert_int (expr_t *e) { - e->type = ex_float; - e->e.float_val = e->e.integer_val; -} - -void -convert_uint (expr_t *e) -{ - e->type = ex_float; - e->e.float_val = e->e.uinteger_val; + e->e.value.v.float_val = expr_integer (e); + e->e.value.type = ev_float; + e->type = ex_value; } void convert_short (expr_t *e) { - e->type = ex_float; - e->e.float_val = e->e.short_val; -} - -void -convert_uint_int (expr_t *e) -{ - e->type = ex_integer; - e->e.integer_val = e->e.uinteger_val; -} - -void -convert_int_uint (expr_t *e) -{ - e->type = ex_uinteger; - e->e.uinteger_val = e->e.integer_val; + e->e.value.v.float_val = expr_short (e); + e->e.value.type = ev_float; + e->type = ex_value; } void convert_short_int (expr_t *e) { - e->type = ex_integer; - e->e.integer_val = e->e.short_val; -} - -void -convert_short_uint (expr_t *e) -{ - e->type = ex_uinteger; - e->e.uinteger_val = e->e.short_val; + e->e.value.v.integer_val = expr_short (e); + e->e.value.type = ev_integer; + e->type = ex_value; } void convert_nil (expr_t *e, type_t *t) { - e->type = expr_types[t->type]; - if (e->type == ex_pointer) - e->e.pointer.type = &type_void; + memset (&e->e.value, 0, sizeof (e->e.value)); + e->e.value.type = t->type; } int @@ -1444,8 +1510,7 @@ binary_expr (int op, expr_t *e1, expr_t *e2) t1 = get_type (e1); t2 = get_type (e2); if (!t1 || !t2) { - error (e1, "internal error"); - abort (); + internal_error (e1, 0); } if (op == EQ || op == NE) { if (e1->type == ex_nil) { @@ -1463,117 +1528,11 @@ binary_expr (int op, expr_t *e1, expr_t *e2) if (e2->type == ex_bool) e2 = convert_from_bool (e2, t1); - if (e1->type == ex_short) { - if (t2 == &type_integer) { - convert_short_int (e1); - t1 = &type_integer; -// } else if (t2 == &type_uinteger) { -// convert_short_uint (e1); -// t1 = &type_uinteger; - } - } - - if (e2->type == ex_short) { - if (t1 == &type_integer) { - convert_short_int (e2); - t2 = &type_integer; -// } else if (t1 == &type_uinteger) { -// convert_short_uint (e2); -// t2 = &type_uinteger; - } - } - - if (e1->type == ex_integer) { - if (t2 == &type_float - || t2 == &type_vector - || t2 == &type_quaternion) { - convert_int (e1); - t1 = &type_float; -// } else if (t2 == &type_uinteger) { -// convert_int_uint (e1); -// t1 = &type_uinteger; - } - } else if (e1->type == ex_uinteger) { - if (t2 == &type_float - || t2 == &type_vector - || t2 == &type_quaternion) { - convert_uint (e1); - t1 = &type_float; - } else if (t2 == &type_integer) { - convert_uint_int (e1); - t1 = &type_integer; - } - } else if (e2->type == ex_integer) { - if (t1 == &type_float - || t1 == &type_vector - || t1 == &type_quaternion) { - convert_int (e2); - t2 = &type_float; -// } else if (t1 == &type_uinteger) { -// convert_int_uint (e2); -// t2 = &type_uinteger; - } - } else if (e2->type == ex_uinteger) { - if (t1 == &type_float - || t1 == &type_vector - || t1 == &type_quaternion) { - convert_uint (e2); - t2 = &type_float; - } else if (t1 == &type_integer) { - convert_uint_int (e2); - t2 = &type_integer; - } - } - if ((e = check_precedence (op, e1, e2))) return e; - if (t1 != t2) { - switch (t1->type) { - case ev_float: - if (t2 == &type_vector || t2 == &type_quaternion) { - type = &type_vector; - } else { - type = &type_float; - } - break; - case ev_vector: - if (t2 == &type_quaternion) { - type = &type_quaternion; - } else { - type = &type_vector; - } - break; - case ev_field: - if (t1->t.fldptr.type == t2) { - type = t1->t.fldptr.type; - } else { - goto type_mismatch; - } - break; - case ev_func: - if (e1->type == ex_func && !e1->e.func_val) { - type = t2; - } else if (e2->type == ex_func && !e2->e.func_val) { - type = t1; - } else { - goto type_mismatch; - } - break; - case ev_pointer: - if (!type_assignable (t1, t2) && !type_assignable (t2, t1)) - goto type_mismatch; - type = t1; - break; - default: - type_mismatch: - type = t1; - break; - //return type_mismatch (e1, e2, op); - } - } else { - type = t1; - } + type = t1; + if (is_compare (op) || is_logic (op)) { if (options.code.progsversion > PROG_ID_VERSION) type = &type_integer; @@ -1583,7 +1542,7 @@ binary_expr (int op, expr_t *e1, expr_t *e2) type = &type_float; } if (!type) - error (e1, "internal error"); + internal_error (e1, 0); if (options.code.progsversion == PROG_ID_VERSION) { switch (op) { @@ -1643,17 +1602,48 @@ asx_expr (int op, expr_t *e1, expr_t *e2) expr_t * unary_expr (int op, expr_t *e) { + vec3_t v; + quat_t q; + const char *s; + check_initialized (e); if (e->type == ex_error) return e; switch (op) { case '-': + if (is_constant (e)) { + switch (extract_type (e)) { + case ev_string: + case ev_entity: + case ev_field: + case ev_func: + case ev_pointer: + return error (e, "invalid type for unary -"); + case ev_float: + return new_float_expr (-expr_float (e)); + case ev_vector: + VectorNegate (expr_vector (e), v); + return new_vector_expr (v); + case ev_quat: + QuatNegate (expr_vector (e), q); + return new_vector_expr (q); + case ev_integer: + return new_integer_expr (-expr_integer (e)); + case ev_short: + return new_short_expr (-expr_short (e)); + case ev_invalid: + case ev_type_count: + case ev_void: + break; + } + internal_error (e, "weird expression type"); + } switch (e->type) { + case ex_value: // should be handled above case ex_error: case ex_label: case ex_state: - error (e, "internal error"); - abort (); + internal_error (e, 0); case ex_uexpr: if (e->e.expr.op == '-') return e->e.expr.e1; @@ -1678,43 +1668,44 @@ unary_expr (int op, expr_t *e) n->e.expr.type = e->e.symbol->type; return n; } - case ex_short: - e->e.short_val *= -1; - return e; - case ex_integer: - case ex_uinteger: - e->e.integer_val *= -1; - return e; - case ex_float: - e->e.float_val *= -1; - return e; case ex_nil: - case ex_string: - case ex_entity: - case ex_field: - case ex_func: - case ex_pointer: return error (e, "invalid type for unary -"); - case ex_vector: - e->e.vector_val[0] *= -1; - e->e.vector_val[1] *= -1; - e->e.vector_val[2] *= -1; - return e; - case ex_quaternion: - e->e.quaternion_val[0] *= -1; - e->e.quaternion_val[1] *= -1; - e->e.quaternion_val[2] *= -1; - e->e.quaternion_val[3] *= -1; - return e; } break; case '!': + if (is_constant (e)) { + switch (extract_type (e)) { + case ev_entity: + case ev_field: + case ev_func: + case ev_pointer: + internal_error (e, 0); + case ev_string: + s = expr_string (e); + return new_integer_expr (!s || !s[0]); + case ev_float: + return new_integer_expr (!expr_float (e)); + case ev_vector: + return new_integer_expr (!VectorIsZero (expr_vector (e))); + case ev_quat: + return new_integer_expr (!QuatIsZero (expr_quaternion (e))); + case ev_integer: + return new_integer_expr (!expr_integer (e)); + case ev_short: + return new_short_expr (!expr_short (e)); + case ev_invalid: + case ev_type_count: + case ev_void: + break; + } + internal_error (e, "weird expression type"); + } switch (e->type) { + case ex_value: // should be handled above case ex_error: case ex_label: case ex_state: - error (e, "internal error"); - abort (); + internal_error (e, 0); case ex_bool: return new_bool_expr (e->e.bool.false_list, e->e.bool.true_list, e); @@ -1737,49 +1728,40 @@ unary_expr (int op, expr_t *e) } case ex_nil: return error (e, "invalid type for unary !"); - case ex_short: - e->e.short_val = !e->e.short_val; - return e; - case ex_integer: - case ex_uinteger: - e->e.integer_val = !e->e.integer_val; - return e; - case ex_float: - e->e.integer_val = !e->e.float_val; - e->type = ex_integer; - return e; - case ex_string: - e->e.integer_val = !e->e.string_val || !e->e.string_val[0]; - e->type = ex_integer; - return e; - case ex_vector: - e->e.integer_val = !e->e.vector_val[0] - && !e->e.vector_val[1] - && !e->e.vector_val[2]; - e->type = ex_integer; - return e; - case ex_quaternion: - e->e.integer_val = !e->e.quaternion_val[0] - && !e->e.quaternion_val[1] - && !e->e.quaternion_val[2] - && !e->e.quaternion_val[3]; - e->type = ex_integer; - return e; - case ex_entity: - case ex_field: - case ex_func: - case ex_pointer: - error (e, "internal error"); - abort (); } break; case '~': + if (is_constant (e)) { + switch (extract_type (e)) { + case ev_string: + case ev_entity: + case ev_field: + case ev_func: + case ev_pointer: + case ev_vector: + return error (e, "invalid type for unary -"); + case ev_float: + return new_float_expr (~(int) expr_float (e)); + case ev_quat: + QuatConj (expr_vector (e), q); + return new_vector_expr (q); + case ev_integer: + return new_integer_expr (~expr_integer (e)); + case ev_short: + return new_short_expr (~expr_short (e)); + case ev_invalid: + case ev_type_count: + case ev_void: + break; + } + internal_error (e, "weird expression type"); + } switch (e->type) { + case ex_value: // should be handled above case ex_error: case ex_label: case ex_state: - error (e, "internal error"); - abort (); + internal_error (e, 0); case ex_uexpr: if (e->e.expr.op == '~') return e->e.expr.e1; @@ -1807,26 +1789,7 @@ bitnot_expr: n->e.expr.type = t; return n; } - case ex_short: - e->e.short_val = ~e->e.short_val; - return e; - case ex_integer: - case ex_uinteger: - e->e.integer_val = ~e->e.integer_val; - return e; - case ex_float: - e->e.float_val = ~(int) e->e.float_val; - return e; - case ex_quaternion: - QuatConj (e->e.quaternion_val, e->e.quaternion_val); - return e; case ex_nil: - case ex_string: - case ex_vector: - case ex_entity: - case ex_field: - case ex_func: - case ex_pointer: return error (e, "invalid type for unary ~"); } break; @@ -1839,8 +1802,7 @@ bitnot_expr: case '+': return e; // FIXME typechecking } - error (e, "internal error"); - abort (); + internal_error (e, 0); } expr_t * @@ -1894,7 +1856,8 @@ build_function_call (expr_t *fexpr, type_t *ftype, expr_t *params) err = error (e, "formal parameter %d is too large to be passed by" " value", i + 1); check_initialized (e); - if (ftype->t.func.param_types[i] == &type_float && e->type == ex_integer) { + if (ftype->t.func.param_types[i] == &type_float + && is_integer_val (e)) { convert_int (e); t = &type_float; } @@ -1912,13 +1875,13 @@ build_function_call (expr_t *fexpr, type_t *ftype, expr_t *params) t = ftype->t.func.param_types[i]; } else { if (e->type == ex_nil) - convert_nil (e, t = &type_vector); //XXX largest param size + convert_nil (e, t = &type_vector); //FIXME largest param size if (e->type == ex_bool) convert_from_bool (e, get_type (e)); - if (e->type == ex_integer + if (is_integer_val (e) && options.code.progsversion == PROG_ID_VERSION) convert_int (e); - if (e->type == ex_integer && options.warnings.vararg_integer) + if (is_integer_val (e) && options.warnings.vararg_integer) warning (e, "passing integer constant into ... function"); } arg_types[arg_count - 1 - i] = t; @@ -1937,7 +1900,7 @@ build_function_call (expr_t *fexpr, type_t *ftype, expr_t *params) } else { *a = cast_expr (arg_types[i], e); } - // new_binary_expr calls inc_users for both args, but in_users doesn't + // new_binary_expr calls inc_users for both args, but inc_users doesn't // walk expression chains so only the first arg expression in the chain // (the last arg in the call) gets its user count incremented, thus // ensure all other arg expressions get their user counts incremented. @@ -1984,7 +1947,7 @@ function_expr (expr_t *fexpr, expr_t *params) return error (fexpr, "Called object is not a function"); } - if (fexpr->type == ex_def && params && params->type == ex_string) { + if (fexpr->type == ex_def && params && is_string_val (params)) { // FIXME eww, I hate this, but it's needed :( // FIXME make a qc hook? :) def_t *func = fexpr->e.def; @@ -2033,16 +1996,15 @@ return_expr (function_t *f, expr_t *e) } if (e->type == ex_bool) e = convert_from_bool (e, f->sym->type->t.func.type); - if (f->sym->type->t.func.type == &type_float && e->type == ex_integer) { - e->type = ex_float; - e->e.float_val = e->e.integer_val; + if (f->sym->type->t.func.type == &type_float && is_integer_val (e)) { + convert_int (e); t = &type_float; } check_initialized (e); if (t == &type_void) { if (e->type == ex_nil) { t = f->sym->type->t.func.type; - e->type = expr_types[t->type]; + convert_nil (e, t); if (e->type == ex_nil) return error (e, "invalid return type for NIL"); } else { @@ -2145,7 +2107,7 @@ array_expr (expr_t *array, expr_t *index) type_t *index_type = get_type (index); expr_t *scale; expr_t *e; - int size; + int ind = 0; if (array->type == ex_error) return array; @@ -2156,32 +2118,32 @@ array_expr (expr_t *array, expr_t *index) return error (array, "not an array"); if (index_type != &type_integer) return error (index, "invalid array index type"); + if (is_short_val (index)) + ind = expr_short (index); + if (is_integer_val (index)) + ind = expr_integer (index); if (array_type->t.func.num_params - && index->type >= ex_integer - && (index->e.integer_val < array_type->t.array.base - || index->e.integer_val - array_type->t.array.base - >= array_type->t.array.size)) + && is_constant (index) + && (ind < array_type->t.array.base + || ind - array_type->t.array.base >= array_type->t.array.size)) return error (index, "array index out of bounds"); - size = type_size (array_type->t.array.type); - scale = new_expr (); - scale->type = expr_types[index_type->type]; - scale->e.integer_val = size; + scale = new_integer_expr (type_size (array_type->t.array.type)); index = binary_expr ('*', index, scale); index = binary_expr ('-', index, binary_expr ('*', new_integer_expr (array_type->t.array.base), scale)); index = fold_constants (index); - if ((index->type == ex_integer - && index->e.integer_val < 32768 && index->e.integer_val >= -32768) - || (index->type == ex_uinteger - && index->e.uinteger_val < 32768)) { - index->type = ex_short; - } + if (is_short_val (index)) + ind = expr_short (index); + if (is_integer_val (index)) + ind = expr_integer (index); + if ((is_constant (index) && ind < 32768 && ind >= -32768)) + index = new_short_expr (ind); if (is_array (array_type)) { e = address_expr (array, index, array_type->t.array.type); } else { - if (index->type != ex_short || index->e.integer_val) { + if (!is_short_val (index) || expr_short (index)) { e = new_binary_expr ('&', array, index); //e->e.expr.type = array_type->aux_type; e->e.expr.type = array_type; @@ -2229,10 +2191,9 @@ address_expr (expr_t *e1, expr_t *e2, type_t *t) e->file = e1->file; } else if (is_array (type)) { e = e1; - e->type = ex_pointer; - e->e.pointer.val = 0; - e->e.pointer.type = t; - e->e.pointer.def = def; + e = new_pointer_expr (0, t, def); + e->file = e1->file; + e->line = e1->line; } else { e = new_unary_expr ('&', e1); e->e.expr.type = pointer_type (t); @@ -2267,11 +2228,12 @@ address_expr (expr_t *e1, expr_t *e2, type_t *t) if (e2) { if (e2->type == ex_error) return e2; - if (e->type == ex_pointer && e2->type == ex_short) { - e->e.pointer.val += e2->e.short_val; - e->e.pointer.type = t; + if (e->type == ex_value && e->e.value.type == ev_pointer + && is_short_val (e2)) { + e->e.value.v.pointer.val += expr_short (e2); + e->e.value.v.pointer.type = t; } else { - if (e2->type != ex_short || e2->e.short_val) { + if (!is_short_val (e2) || expr_short (e2)) { if (e->type == ex_expr && e->e.expr.op == '&') { e = new_binary_expr ('&', e->e.expr.e1, binary_expr ('+', e->e.expr.e2, e2)); @@ -2450,19 +2412,15 @@ build_for_statement (expr_t *init, expr_t *test, expr_t *next, expr_t * build_state_expr (expr_t *frame, expr_t *think, expr_t *step) { - if (frame->type == ex_integer) + if (is_integer_val (frame)) convert_int (frame); - else if (frame->type == ex_uinteger) - convert_uint (frame); if (!type_assignable (&type_float, get_type (frame))) return error (frame, "invalid type for frame number"); if (extract_type (think) != ev_func) return error (think, "invalid type for think"); if (step) { - if (step->type == ex_integer) + if (is_integer_val (step)) convert_int (step); - else if (step->type == ex_uinteger) - convert_uint (step); if (!type_assignable (&type_float, get_type (step))) return error (step, "invalid type for frame number"); } @@ -2477,9 +2435,9 @@ is_indirect (expr_t *e) if (!(e->type == ex_uexpr && e->e.expr.op == '.')) return 0; e = e->e.expr.e1; - if (e->type != ex_pointer - || !(POINTER_VAL (e->e.pointer) >= 0 - && POINTER_VAL (e->e.pointer) < 65536)) { + if ((e->type != ex_value && e->e.value.type != ev_pointer) + || !(POINTER_VAL (e->e.value.v.pointer) >= 0 + && POINTER_VAL (e->e.value.v.pointer) < 65536)) { return 1; } return 0; @@ -2533,8 +2491,7 @@ assign_expr (expr_t *e1, expr_t *e2) t1 = get_type (e1); t2 = get_type (e2); if (!t1 || !t2) { - error (e1, "internal error"); - abort (); + internal_error (e1, 0); } //XXX func = func ??? if (t1->type != ev_pointer || !is_array (t2)) @@ -2599,9 +2556,9 @@ assign_expr (expr_t *e1, expr_t *e2) op = PAS; } else { e = e1->e.expr.e1; - if (e->type != ex_pointer - || !(POINTER_VAL (e->e.pointer) > 0 - && POINTER_VAL (e->e.pointer) < 65536)) { + if ((e->type != ex_value || e->e.value.type != ev_pointer) + || !(POINTER_VAL (e->e.value.v.pointer) > 0 + && POINTER_VAL (e->e.value.v.pointer) < 65536)) { e1 = e; op = PAS; } @@ -2614,9 +2571,9 @@ assign_expr (expr_t *e1, expr_t *e2) } if (e2->type == ex_uexpr) { e = e2->e.expr.e1; - if (e->type != ex_pointer - || !(POINTER_VAL (e->e.pointer) > 0 - && POINTER_VAL (e->e.pointer) < 65536)) { + if ((e->type != ex_value || e->e.value.type != ev_pointer) + || !(POINTER_VAL (e->e.value.v.pointer) > 0 + && POINTER_VAL (e->e.value.v.pointer) < 65536)) { if (e->type == ex_expr && e->e.expr.op == '&' && e->e.expr.type->type == ev_pointer && e->e.expr.e1->type < ex_nil) { @@ -2632,7 +2589,7 @@ assign_expr (expr_t *e1, expr_t *e2) return new_move_expr (e1, e2, get_type (e2)); } if (!type) - error (e1, "internal error"); + internal_error (e1, 0); e = new_binary_expr (op, e1, e2); e->e.expr.type = type; @@ -2841,8 +2798,7 @@ expr_t * sizeof_expr (expr_t *expr, struct type_s *type) { if (!((!expr) ^ (!type))) { - error (0, "internal error"); - abort (); + internal_error (0, 0); } if (!type) type = get_type (expr); diff --git a/tools/qfcc/source/function.c b/tools/qfcc/source/function.c index 06a7f9bfd..29c0da05e 100644 --- a/tools/qfcc/source/function.c +++ b/tools/qfcc/source/function.c @@ -543,7 +543,7 @@ build_builtin_function (symbol_t *sym, expr_t *bi_val) error (bi_val, "%s redefined", sym->name); return 0; } - if (bi_val->type != ex_integer && bi_val->type != ex_float) { + if (!is_integer_val (bi_val) && !is_float_val (bi_val)) { error (bi_val, "invalid constant for = #"); return 0; } @@ -554,9 +554,10 @@ build_builtin_function (symbol_t *sym, expr_t *bi_val) sym->s.func->sym = sym; add_function (sym->s.func); - bi = bi_val->e.integer_val; - if (bi_val->type == ex_integer) - bi = (int)bi_val->e.float_val; + if (is_integer_val (bi_val)) + bi = expr_integer (bi_val); + else + bi = expr_float (bi_val); sym->s.func->builtin = bi; //reloc_def_func (sym->s.func, def->ofs); build_function (sym->s.func); diff --git a/tools/qfcc/source/immediate.c b/tools/qfcc/source/immediate.c index 228bf2341..333898369 100644 --- a/tools/qfcc/source/immediate.c +++ b/tools/qfcc/source/immediate.c @@ -170,53 +170,48 @@ ReuseConstant (expr_t *expr, def_t *def) cn = 0; if (e.type == ex_nil) convert_nil (&e, def->type); - switch (e.type) { - case ex_entity: + if (!is_constant (&e)) + abort (); + switch (extract_type (&e)) { + case ev_entity: tab = entity_imm_defs; type = &type_entity; break; - case ex_field: + case ev_field: tab = field_imm_defs; type = &type_field; break; - case ex_func: + case ev_func: tab = func_imm_defs; type = &type_function; break; - case ex_pointer: + case ev_pointer: tab = pointer_imm_defs; type = &type_pointer; break; - case ex_integer: - case ex_uinteger: + case ev_integer: if (!def || def->type != &type_float) { tab = integer_imm_defs; - //FIXME - //if (e.type == ex_uinteger) - // type = &type_uinteger; - //else - type = &type_integer; + type = &type_integer; break; } - if (e.type == ex_uinteger) - e.e.float_val = e.e.uinteger_val; - else - e.e.float_val = e.e.integer_val; - e.type = ex_float; - case ex_float: + e.e.value.v.float_val = expr_integer (&e); + e.e.value.type = ev_float; + e.type = ex_value; + case ev_float: tab = float_imm_defs; type = &type_float; break; - case ex_string: - e.e.integer_val = ReuseString (e.e.string_val); + case ev_string: + e.e.value.v.integer_val = ReuseString (expr_string (&e)); tab = string_imm_defs; type = &type_string; break; - case ex_vector: + case ev_vector: tab = vector_imm_defs; type = &type_vector; break; - case ex_quaternion: + case ev_quat: tab = quaternion_imm_defs; type = &type_quaternion; break; @@ -269,22 +264,22 @@ ReuseConstant (expr_t *expr, def_t *def) cn->initialized = cn->constant = 1; cn->nosave = 1; // copy the immediate to the global area - switch (e.type) { - case ex_string: + switch (e.e.value.type) { + case ev_string: reloc = new_reloc (cn->ofs, rel_def_string); break; - case ex_func: - if (e.e.func_val) + case ev_func: + if (e.e.value.v.func_val) reloc = new_reloc (cn->ofs, rel_def_func); break; - case ex_field: - if (e.e.pointer.def) - reloc_def_field_ofs (e.e.pointer.def, cn->ofs); + case ev_field: + if (e.e.value.v.pointer.def) + reloc_def_field_ofs (e.e.value.v.pointer.def, cn->ofs); break; - case ex_pointer: - if (e.e.pointer.def) { - EMIT_DEF_OFS (G_INT (cn->ofs), e.e.pointer.def); - e.e.pointer.def->users--; + case ev_pointer: + if (e.e.value.v.pointer.def) { + EMIT_DEF_OFS (G_INT (cn->ofs), e.e.value.v.pointer.def); + e.e.value.v.pointer.def->users--; } break; default: diff --git a/tools/qfcc/source/method.c b/tools/qfcc/source/method.c index 1a6f8568b..07539c3bd 100644 --- a/tools/qfcc/source/method.c +++ b/tools/qfcc/source/method.c @@ -350,7 +350,7 @@ selector_index (const char *sel_id) selector_t * get_selector (expr_t *sel) { - selector_t _sel = {0, 0, sel->e.pointer.val}; + selector_t _sel = {0, 0, sel->e.value.v.pointer.val}; _sel.index /= type_size (type_SEL.t.fldptr.type); return (selector_t *) Hash_FindElement (sel_index_hash, &_sel); } @@ -534,7 +534,7 @@ method_check_params (method_t *method, expr_t *args) mtype->t.func.param_types[i], t); } } else { - if (e->type == ex_integer && options.warnings.vararg_integer) + if (is_integer_val (e) && options.warnings.vararg_integer) warning (e, "passing integer consant into ... function"); } } diff --git a/tools/qfcc/source/qc-lex.l b/tools/qfcc/source/qc-lex.l index f92f08431..c9655eabe 100644 --- a/tools/qfcc/source/qc-lex.l +++ b/tools/qfcc/source/qc-lex.l @@ -124,7 +124,7 @@ STRING \"(\\.|[^"\\])*\" const char *c = yytext + yyleng - 1; int i = strtol (yytext, 0, 0); if (*c == 'u' || *c == 'U') - yylval.expr = new_uinteger_expr (i); + yylval.expr = new_integer_expr (i);//FIXME else yylval.expr = new_integer_expr (i); return CONST; diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index 590237fdf..cb61d1509 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -365,7 +365,7 @@ non_field_type | non_field_type array_decl { if ($2) - $$ = array_type ($1, $2->e.integer_val); + $$ = array_type ($1, $2->e.value.v.integer_val); else $$ = pointer_type ($1); } @@ -465,7 +465,8 @@ array_decl : '[' fexpr ']' { $2 = constant_expr ($2); - if ($2->type != ex_integer || $2->e.integer_val < 1) { + if (($2->type != ex_value && $2->e.value.type != ev_integer) + || $2->e.value.v.integer_val < 1) { error (0, "invalid array size"); $$ = 0; } else { diff --git a/tools/qfcc/source/qfcc.c b/tools/qfcc/source/qfcc.c index ad2c5cc01..695826e99 100644 --- a/tools/qfcc/source/qfcc.c +++ b/tools/qfcc/source/qfcc.c @@ -610,15 +610,13 @@ finish_compilation (void) return !errors; if (options.code.progsversion != PROG_ID_VERSION) { - e.type = ex_integer; - e.e.integer_val = type_size (&type_param); + e = *new_integer_expr (type_size (&type_param)); ReuseConstant (&e, get_def (&type_integer, ".param_size", pr.scope, st_global)); } if (options.code.debug) { - e.type = ex_string; - e.e.string_val = debugfile; + e = *new_string_expr (debugfile); ReuseConstant (&e, get_def (&type_string, ".debug_file", pr.scope, st_global)); } diff --git a/tools/qfcc/source/qp-parse.y b/tools/qfcc/source/qp-parse.y index 6cd154963..392883e40 100644 --- a/tools/qfcc/source/qp-parse.y +++ b/tools/qfcc/source/qp-parse.y @@ -220,7 +220,7 @@ type : standard_type | ARRAY '[' CONST RANGE CONST ']' OF standard_type { - $$ = based_array_type ($8, $3->e.integer_val, $5->e.integer_val); + $$ = based_array_type ($8, expr_integer ($3), expr_integer ($5)); } ; diff --git a/tools/qfcc/source/struct.c b/tools/qfcc/source/struct.c index 271975143..a8d3d85d6 100644 --- a/tools/qfcc/source/struct.c +++ b/tools/qfcc/source/struct.c @@ -163,12 +163,12 @@ add_enum (symbol_t *enm, symbol_t *name, expr_t *val) value = ((symbol_t *)(*enum_tab->symtail))->s.value + 1; if (val) { val = constant_expr (val); - if (val->type < ex_nil) + if (!is_constant (val)) error (val, "non-constant initializer"); - else if (val->type != ex_integer) + else if (!is_integer_val (val)) error (val, "invalid initializer type"); else - value = val->e.integer_val; + value = expr_integer (val); } name->s.value = value; symtab_addsymbol (enum_tab, name); diff --git a/tools/qfcc/source/switch.c b/tools/qfcc/source/switch.c index b169433e3..95ea1bd92 100644 --- a/tools/qfcc/source/switch.c +++ b/tools/qfcc/source/switch.c @@ -52,6 +52,7 @@ static __attribute__ ((used)) const char rcsid[] = #include "qfcc.h" #include "reloc.h" #include "switch.h" +#include "symtab.h" #include "type.h" #include "qc-parse.h" @@ -64,6 +65,14 @@ typedef struct case_node_s { struct case_node_s *left, *right; } case_node_t; +static uintptr_t +get_value (expr_t *e) +{ + if (e->type == ex_symbol) + return e->e.symbol->s.value; + return e->e.value.v.integer_val; +} + static uintptr_t get_hash (void *_cl, void *unused) { @@ -71,9 +80,7 @@ get_hash (void *_cl, void *unused) if (!cl->value) return 0; - if (cl->value->type == ex_string) - return (uintptr_t) cl->value->e.string_val; - return cl->value->e.integer_val; + return get_value (cl->value); } static int @@ -83,16 +90,17 @@ compare (void *_cla, void *_clb, void *unused) case_label_t *clb = (case_label_t *) _clb; expr_t *v1 = cla->value; expr_t *v2 = clb->value; + uintptr_t val1, val2; if (v1 == v2) return 1; if ((v1 && !v2) || (!v1 && v2)) return 0; - if (v1->type != v2->type) + if (extract_type (v1) != extract_type (v2)) return 0; - if (v1->type == ex_string) - return v1->e.string_val == v2->e.string_val; - return v1->e.integer_val == v2->e.integer_val; + val1 = get_value (v1); + val2 = get_value (v1); + return val1 == val2; } struct expr_s * @@ -145,22 +153,20 @@ label_compare (const void *_a, const void *_b) const case_label_t **b = (const case_label_t **) _b; const char *s1, *s2; - switch ((*a)->value->type) { - case ex_string: - s1 = (*a)->value->e.string_val ? (*a)->value->e.string_val : ""; - s2 = (*b)->value->e.string_val ? (*b)->value->e.string_val : ""; - return strcmp (s1, s2); - break; - case ex_float: - return (*a)->value->e.float_val - (*b)->value->e.float_val; - break; - case ex_integer: - return (*a)->value->e.integer_val - (*b)->value->e.integer_val; - break; - default: - error (0, "internal compiler error in switch"); - abort (); + if (is_string_val ((*a)->value)) { + s1 = expr_string ((*a)->value); + if (!s1) + s1 = ""; + s2 = expr_string ((*b)->value); + if (!s2) + s2 = ""; + return strcmp (s1, s2); + } else if (is_float_val ((*a)->value)) { + return expr_float ((*a)->value) - expr_float ((*b)->value); + } else if (is_integer_val ((*a)->value)) { + return expr_integer ((*a)->value) - expr_integer ((*b)->value); } + internal_error (0, "in switch"); } static case_node_t * @@ -178,11 +184,11 @@ new_case_node (expr_t *low, expr_t *high) } else { int size; - if (low->type != ex_integer) { + if (!is_integer_val (low)) { error (low, "switch: internal error"); abort (); } - size = high->e.integer_val - low->e.integer_val + 1; + size = expr_integer (high) - expr_integer (low) + 1; node->labels = calloc (size, sizeof (case_node_t *)); } node->left = node->right = 0; @@ -223,18 +229,18 @@ build_case_tree (case_label_t **labels, int count, int range) if (!nodes) Sys_Error ("out of memory"); - if (range && labels[0]->value->type == ex_integer) { + if (range && is_integer_val (labels[0]->value)) { for (i = 0; i < count - 1; i = j, num_nodes++) { for (j = i + 1; j < count; j++) { - if (labels[j]->value->e.integer_val - - labels[j - 1]->value->e.integer_val > 1) + if (expr_integer (labels[j]->value) + - expr_integer (labels[j - 1]->value) > 1) break; } nodes[num_nodes] = new_case_node (labels[i]->value, labels[j - 1]->value); for (k = i; k < j; k++) - nodes[num_nodes]->labels[labels[k]->value->e.integer_val - - labels[i]->value->e.integer_val] + nodes[num_nodes]->labels[expr_integer (labels[k]->value) + - expr_integer (labels[i]->value)] = labels[k]->label; } if (i < count) { @@ -297,15 +303,15 @@ build_switch (expr_t *sw, case_node_t *tree, int op, expr_t *sw_val, build_switch (sw, tree->right, op, sw_val, temp, default_label); } } else { - int low = tree->low->e.integer_val; - int high = tree->high->e.integer_val; + int low = expr_integer (tree->low); + int high = expr_integer (tree->high); def_t *def; expr_t *table; const char *name = new_label_name (); int i; expr_t *range = binary_expr ('-', tree->high, tree->low); - range->type = ex_uinteger; + range = fold_constants (range); //FIXME unsigned int better? def = get_def (array_type (&type_integer, high - low + 1), name,