diff --git a/include/QF/progs.h b/include/QF/progs.h index b90c96e99..2e18fa3c5 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -403,16 +403,6 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ */ ///@{ -/** \internal - \param p pointer to ::progs_t VM struct - \param o offset into global data space - \param t typename prefix (see pr_type_u) - \return lvalue of the appropriate type - - \hideinitializer -*/ -#define G_var(p,o,t) ((p)->pr_globals[o].t##_var) - /** Access a global as an arbitray type. More direct than G_STRUCT @@ -428,6 +418,16 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ */ #define G_PACKED(p,t,o) (*(t *) &(p)->pr_globals[o]) +/** \internal + \param p pointer to ::progs_t VM struct + \param o offset into global data space + \param t typename prefix (see pr_type_u) + \return lvalue of the appropriate type + + \hideinitializer +*/ +#define G_var(p,o,t) G_PACKED(p, pr_##t##_t, o) + /** Access a float global. Can be assigned to. \par QC type: @@ -450,7 +450,7 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ \hideinitializer */ -#define G_DOUBLE(p,o) (*(double *) ((p)->pr_globals + o)) +#define G_DOUBLE(p,o) G_var (p, o, double) /** Access an int global. Can be assigned to. @@ -476,6 +476,30 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ */ #define G_UINT(p,o) G_var (p, o, uint) +/** Access a long global. Can be assigned to. + + \par QC type: + \c long + \param p pointer to ::progs_t VM struct + \param o offset into global data space + \return long lvalue + + \hideinitializer +*/ +#define G_LONG(p,o) G_var (p, o, long) + +/** Access an unsigned long global. Can be assigned to. + + \par QC type: + \c ulong + \param p pointer to ::progs_t VM struct + \param o offset into global data space + \return unsigned long lvalue + + \hideinitializer +*/ +#define G_ULONG(p,o) G_var (p, o, ulong) + /** Access a vector global. Can be assigned to. \par QC type: @@ -486,7 +510,7 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ \hideinitializer */ -#define G_VECTOR(p,o) (&G_var (p, o, vector)) +#define G_VECTOR(p,o) (&G_var (p, o, float)) /** Access a quaternion global. Can be assigned to. @@ -498,7 +522,7 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ \hideinitializer */ -#define G_QUAT(p,o) (&G_var (p, o, quat)) +#define G_QUAT(p,o) (&G_var (p, o, float)) /** Access a string index global. Can be assigned to. @@ -534,8 +558,31 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ \hideinitializer */ -#define G_POINTER(p,o) G_var (p, o, pointer) +#define G_POINTER(p,o) G_var (p, o, ptr) +/** Access a field global. + + \par QC type: + \c field + \param p pointer to ::progs_t VM struct + \param o offset into global data space + \return field offset + + \hideinitializer +*/ +#define G_FIELD(p,o) G_var (p, o, field) + +/** Access an entity global. + + \par QC type: + \c entity + \param p pointer to ::progs_t VM struct + \param o offset into global data space + \return entity "pointer" + + \hideinitializer +*/ +#define G_ENTITY(p,o) G_var (p, o, entity) /** Access an entity global. @@ -620,16 +667,6 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ */ ///@{ -/** \internal - \param p pointer to ::progs_t VM struct - \param n parameter number (0-7) - \param t typename prefix (see pr_type_u) - \return lvalue of the appropriate type - - \hideinitializer -*/ -#define P_var(p,n,t) ((p)->pr_params[n]->t##_var) - /** Access a parameter as an arbitray type. \par QC type: @@ -644,6 +681,16 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ */ #define P_PACKED(p,t,n) (*(t *) (p)->pr_params[n]) +/** \internal + \param p pointer to ::progs_t VM struct + \param n parameter number (0-7) + \param t typename prefix (see pr_type_u) + \return lvalue of the appropriate type + + \hideinitializer +*/ +#define P_var(p,n,t) P_PACKED(p, pr_##t##_t, n) + /** Access a float parameter. Can be assigned to. \par QC type: @@ -666,7 +713,7 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ \hideinitializer */ -#define P_DOUBLE(p,n) P_PACKED(p, double, n) +#define P_DOUBLE(p,n) P_var (p, n, double) /** Access an int parameter. Can be assigned to. @@ -692,6 +739,30 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ */ #define P_UINT(p,n) P_var (p, n, uint) +/** Access a long parameter. Can be assigned to. + + \par QC type: + \c long + \param p pointer to ::progs_t VM struct + \param n parameter number (0-7) + \return long lvalue + + \hideinitializer +*/ +#define P_LONG(p,n) P_var (p, n, long) + +/** Access an unsigned long parameter. Can be assigned to. + + \par QC type: + \c ulong + \param p pointer to ::progs_t VM struct + \param n parameter number (0-7) + \return unsigned long lvalue + + \hideinitializer +*/ +#define P_ULONG(p,n) P_var (p, n, ulong) + /** Access a vector parameter. Can be used any way a vec3_t variable can. \par QC type: @@ -702,7 +773,7 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ \hideinitializer */ -#define P_VECTOR(p,n) (&P_var (p, n, vector)) +#define P_VECTOR(p,n) (&P_var (p, n, float)) /** Access a quaterion parameter. Can be used any way a quat_t variable can. @@ -714,7 +785,7 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ \hideinitializer */ -#define P_QUAT(p,n) (&P_var (p, n, quat)) +#define P_QUAT(p,n) (&P_var (p, n, float)) /** Access a string index parameter. Can be assigned to. @@ -750,7 +821,7 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ \hideinitializer */ -#define P_POINTER(p,n) P_var (p, n, pointer) +#define P_POINTER(p,n) P_var (p, n, ptr) /** Access an entity parameter. @@ -839,16 +910,7 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ */ ///@{ -/** \internal - \param p pointer to ::progs_t VM struct - \param t typename prefix (see pr_type_u) - \return lvalue of the appropriate type - - \hideinitializer -*/ -#define R_var(p,t) ((p)->pr_return->t##_var) - -/** Access the VM function return value parameter as an arbitray type. +/** Access the VM function return value as an arbitray type. \par QC type: \c struct etc small enough to fit in the return slot @@ -861,6 +923,15 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ */ #define R_PACKED(p,t) (*(t *) (p)->pr_return) +/** \internal + \param p pointer to ::progs_t VM struct + \param t typename prefix (see pr_type_u) + \return lvalue of the appropriate type + + \hideinitializer +*/ +#define R_var(p,t) R_PACKED(p, pr_##t##_t) + /** Access the VM function return value as a \c float \par QC type: @@ -881,7 +952,7 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ \hideinitializer */ -#define R_DOUBLE(p) R_PACKED (p, double) +#define R_DOUBLE(p) R_var (p, double) /** Access the VM function return value as a \c ::pr_int_t (AKA int32_t) @@ -905,6 +976,28 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ */ #define R_UINT(p) R_var (p, uint) +/** Access the VM function return value as a \c ::pr_long_t (AKA int32_t) + + \par QC type: + \c long + \param p pointer to ::progs_t VM struct + \return ::pr_long_t lvalue + + \hideinitializer +*/ +#define R_LONG(p) R_var (p, long) + +/** Access the VM function return value as a \c ::pr_ulong_t (AKA uint32_t) + + \par QC type: + \c ulong + \param p pointer to ::progs_t VM struct + \return ::pr_long_t lvalue + + \hideinitializer +*/ +#define R_ULONG(p) R_var (p, ulong) + /** Access the VM function return value as a \c ::vec3_t vector. \par QC type: @@ -914,7 +1007,7 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ \hideinitializer */ -#define R_VECTOR(p) (&R_var (p, vector)) +#define R_VECTOR(p) (&R_var (p, float)) /** Access the VM function return value as a \c ::quat_t quaternion. @@ -925,7 +1018,7 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ \hideinitializer */ -#define R_QUAT(p) (&R_var (p, quat)) +#define R_QUAT(p) (&R_var (p, float)) /** Access the VM function return value as a ::pr_string_t (a VM string reference). @@ -958,7 +1051,7 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ \hideinitializer */ -#define R_POINTER(p) R_var (p, pointer) +#define R_POINTER(p) R_var (p, ptr) /** Set the return value to the given C string. The returned string will @@ -1036,6 +1129,19 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ */ #define E_fld(e,o) ((e)->pr->pr_edict_area[(e)->edict + (o)]) +/** Access an entity field as an arbitray type. + + \par QC type: + \c struct etc small enough to fit in a single parameter + \param e pointer to the entity + \param t C type of the structure + \param o field offset into entity data space + \return structure lvalue. use & to make a pointer of the + appropriate type. + + \hideinitializer +*/ +#define E_PACKED(e,t,o) (*(t *) &E_fld (e, o)) /** \internal \param e pointer to the entity @@ -1045,7 +1151,7 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ \hideinitializer */ -#define E_var(e,o,t) (E_fld (e,o).t##_var) +#define E_var(e,o,t) E_PACKED (e, pr_##t##_t,o) /** Access a float entity field. Can be assigned to. @@ -1070,7 +1176,7 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ \hideinitializer */ -#define E_DOUBLE(e,o) (*(double *) ((e)->v + o)) +#define E_DOUBLE(e,o) E_var (e, o, double) /** Access an int entity field. Can be assigned to. @@ -1096,6 +1202,30 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ */ #define E_UINT(e,o) E_var (e, o, uint) +/** Access a long entity field. Can be assigned to. + + \par QC type: + \c long + \param e pointer to the entity + \param o field offset into entity data space + \return long lvalue + + \hideinitializer +*/ +#define E_LONG(e,o) E_var (e, o, long) + +/** Access an unsigned long entity field. Can be assigned to. + + \par QC type: + \c ulong + \param e pointer to the entity + \param o field offset into entity data space + \return unsigned long lvalue + + \hideinitializer +*/ +#define E_ULONG(e,o) E_var (e, o, ulong) + /** Access a vector entity field. Can be used any way a vec3_t variable can. \par QC type: @@ -1106,7 +1236,7 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ \hideinitializer */ -#define E_VECTOR(e,o) (&E_var (e, o, vector)) +#define E_VECTOR(e,o) (&E_var (e, o, float)) /** Access a quaternion entity field. Can be used any way a quat_t variable can. @@ -1119,7 +1249,7 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ \hideinitializer */ -#define E_QUAT(e,o) E_var (e, o, quat) +#define E_QUAT(e,o) E_var (e, o, float) /** Access a string index entity field. Can be assigned to. @@ -1155,7 +1285,7 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ \hideinitializer */ -#define E_POINTER(e,o) E_var (e, o, pointer) +#define E_POINTER(e,o) E_var (e, o, ptr) /** Access a string entity field, converting it to a C string. Kills the diff --git a/include/QF/progs/pr_comp.h b/include/QF/progs/pr_comp.h index a1051c079..696de6218 100644 --- a/include/QF/progs/pr_comp.h +++ b/include/QF/progs/pr_comp.h @@ -39,6 +39,8 @@ typedef int64_t pr_long_t __attribute__((aligned(8))); typedef uint64_t pr_ulong_t __attribute__((aligned(8))); typedef uint16_t pr_ushort_t __attribute__((aligned(2)));; +#define PR_PTR(t, p) (*(pr_##t##_t *) (p)) + #define PR_VEC_TYPE(t,n,s) \ typedef t n __attribute__ ((vector_size (s*sizeof (t)))) @@ -540,16 +542,12 @@ typedef struct dfunction_s { dparmsize_t param_size[PR_MAX_PARAMS]; } dfunction_t; -typedef union pr_type_u { - float float_var; - pr_string_t string_var; - pr_func_t func_var; - pr_uint_t entity_var; - float vector_var; // really [3], but this structure must be 32 bits - float quat_var; // really [4], but this structure must be 32 bits - pr_int_t int_var; - pr_ptr_t pointer_var; - pr_uint_t uint_var; +typedef struct pr_type_s { + union { + pr_int_t value; + pr_uint_t uint_value; + pr_float_t float_value; + }; } pr_type_t; typedef pr_type_t pr_void_t; // so size of void is 1 diff --git a/include/QF/simd/types.h b/include/QF/simd/types.h index 43d564745..26aceccd0 100644 --- a/include/QF/simd/types.h +++ b/include/QF/simd/types.h @@ -31,7 +31,7 @@ #include #include -#define VEC_TYPE(t,n,s) \ +#define QF_VEC_TYPE(t,n,s) \ typedef t n __attribute__ ((vector_size (s*sizeof (t)))) /** Three element vector type for interfacing with compact data. @@ -41,8 +41,8 @@ */ typedef double vec3d_t[3]; -VEC_TYPE (double, vec2d_t, 2); -VEC_TYPE (int64_t, vec2l_t, 2); +QF_VEC_TYPE (double, vec2d_t, 2); +QF_VEC_TYPE (int64_t, vec2l_t, 2); /** Four element vector type for horizontal (AOS) vector data. * @@ -53,11 +53,11 @@ VEC_TYPE (int64_t, vec2l_t, 2); * a single component from four vectors, or a single row/column (depending on * context) of an Nx4 or 4xN matrix. */ -VEC_TYPE (double, vec4d_t, 4); +QF_VEC_TYPE (double, vec4d_t, 4); /** Used mostly for __builtin_shuffle. */ -VEC_TYPE (int64_t, vec4l_t, 4); +QF_VEC_TYPE (int64_t, vec4l_t, 4); /** Three element vector type for interfacing with compact data. * @@ -66,8 +66,8 @@ VEC_TYPE (int64_t, vec4l_t, 4); */ typedef float vec3f_t[3]; -VEC_TYPE (float, vec2f_t, 2); -VEC_TYPE (int, vec2i_t, 2); +QF_VEC_TYPE (float, vec2f_t, 2); +QF_VEC_TYPE (int, vec2i_t, 2); /** Four element vector type for horizontal (AOS) vector data. * @@ -78,11 +78,11 @@ VEC_TYPE (int, vec2i_t, 2); * a single component from four vectors, or a single row/column (depending on * context) of an Nx4 or 4xN matrix. */ -VEC_TYPE (float, vec4f_t, 4); +QF_VEC_TYPE (float, vec4f_t, 4); /** Used mostly for __builtin_shuffle. */ -VEC_TYPE (int, vec4i_t, 4); +QF_VEC_TYPE (int, vec4i_t, 4); #define VEC2D_FMT "[%.17g, %.17g]" #define VEC2L_FMT "[%"PRIi64", %"PRIi64"]" diff --git a/libs/gamecode/pr_debug.c b/libs/gamecode/pr_debug.c index d27255e11..09fec6c90 100644 --- a/libs/gamecode/pr_debug.c +++ b/libs/gamecode/pr_debug.c @@ -31,8 +31,6 @@ # include "config.h" #endif -#define _GNU_SOURCE // for qsort_r - #ifdef HAVE_STRING_H # include #endif @@ -48,6 +46,7 @@ #include "QF/cvar.h" #include "QF/dstring.h" #include "QF/hash.h" +#include "QF/heapsort.h" #include "QF/mathlib.h" #include "QF/progs.h" #include "QF/qendian.h" @@ -337,11 +336,11 @@ parse_expression (progs_t *pr, const char *expr, int conditional) goto error; if (!Script_GetToken (es, 1)) goto error; - pr->wp_val.int_var = strtol (es->token->str, &e, 0); + PR_PTR (int, &pr->wp_val) = strtol (es->token->str, &e, 0); if (e == es->token->str) goto error; if (*e == '.' || *e == 'e' || *e == 'E') - pr->wp_val.float_var = strtod (es->token->str, &e); + PR_PTR (float, &pr->wp_val) = strtod (es->token->str, &e); pr->wp_conditional = 1; } } @@ -385,7 +384,7 @@ pr_debug_clear (progs_t *pr, void *data) pr->watch = 0; pr->wp_conditional = 0; - pr->wp_val.int_var = 0; + PR_PTR (int, &pr->wp_val) = 0; for (int i = 0; i < ev_type_count; i++ ) { res->type_encodings[i] = &res->void_type; @@ -478,6 +477,14 @@ process_compunit (prdeb_resources_t *res, pr_def_t *def) } } +static int +def_compare_sort (const void *_da, const void *_db, void *_res) +{ + pr_def_t da = *(const pr_def_t *)_da; + pr_def_t db = *(const pr_def_t *)_db; + return da.ofs - db.ofs; +} + static int func_compare_sort (const void *_fa, const void *_fb, void *_res) { @@ -552,9 +559,12 @@ PR_DebugSetSym (progs_t *pr, pr_debug_header_t *debug) } res->auxfunction_map[res->auxfunctions[i].function] = &res->auxfunctions[i]; + heapsort_r (res->local_defs + res->auxfunctions[i].local_defs, + res->auxfunctions[i].num_locals, sizeof (pr_def_t), + def_compare_sort, res); } - qsort_r (res->sorted_functions, pr->progs->functions.count, - sizeof (pr_func_t), func_compare_sort, res); + heapsort_r (res->sorted_functions, pr->progs->functions.count, + sizeof (pr_func_t), func_compare_sort, res); for (pr_uint_t i = 0; i < debug->num_locals; i++) { if (type_encodings) { @@ -612,7 +622,7 @@ PR_LoadDebug (progs_t *pr) if (!str) return 1; - res->debugfile = PR_GetString (pr, str->string_var); + res->debugfile = PR_GetString (pr, PR_PTR (string, str)); sym_file = QFS_SkipPath (res->debugfile); path_end = QFS_SkipPath (pr->progs_name); sym_path = malloc (strlen (sym_file) + (path_end - pr->progs_name) + 1); @@ -1152,7 +1162,7 @@ pr_debug_string_view (qfot_type_t *type, pr_type_t *value, void *_data) { __auto_type data = (pr_debug_data_t *) _data; dstring_t *dstr = data->dstr; - pr_string_t string = value->string_var; + pr_string_t string = PR_PTR (string, value); if (PR_StringValid (data->pr, string)) { const char *str = PR_GetString (data->pr, string); @@ -1196,11 +1206,11 @@ pr_debug_float_view (qfot_type_t *type, pr_type_t *value, void *_data) dstring_t *dstr = data->dstr; if (data->pr->progs->version == PROG_ID_VERSION - && ISDENORM (value->int_var) - && value->uint_var != 0x80000000) { - dasprintf (dstr, "<%08x>", value->int_var); + && ISDENORM (PR_PTR (int, value)) + && PR_PTR (uint, value) != 0x80000000) { + dasprintf (dstr, "<%08x>", PR_PTR (int, value)); } else { - dasprintf (dstr, "%.9g", value->float_var); + dasprintf (dstr, "%.9g", PR_PTR (float, value)); } } @@ -1210,7 +1220,7 @@ pr_debug_vector_view (qfot_type_t *type, pr_type_t *value, void *_data) __auto_type data = (pr_debug_data_t *) _data; dstring_t *dstr = data->dstr; - dasprintf (dstr, "'%.9g %.9g %.9g'", VectorExpand (&value->vector_var)); + dasprintf (dstr, "'%.9g %.9g %.9g'", VectorExpand (&PR_PTR (float, value))); } static void @@ -1221,15 +1231,15 @@ pr_debug_entity_view (qfot_type_t *type, pr_type_t *value, void *_data) dstring_t *dstr = data->dstr; if (pr->pr_edicts - && value->entity_var < pr->max_edicts - && !(value->entity_var % pr->pr_edict_size)) { - edict_t *edict = PROG_TO_EDICT (pr, value->entity_var); + && PR_PTR (entity, value) < pr->max_edicts + && !(PR_PTR (entity, value) % pr->pr_edict_size)) { + edict_t *edict = PROG_TO_EDICT (pr, PR_PTR (entity, value)); if (edict) { dasprintf (dstr, "entity %d", NUM_FOR_BAD_EDICT (pr, edict)); return; } } - dasprintf (dstr, "entity [%x]", value->entity_var); + dasprintf (dstr, "entity [%x]", PR_PTR (entity, value)); } static void @@ -1238,12 +1248,12 @@ pr_debug_field_view (qfot_type_t *type, pr_type_t *value, void *_data) __auto_type data = (pr_debug_data_t *) _data; progs_t *pr = data->pr; dstring_t *dstr = data->dstr; - pr_def_t *def = PR_FieldAtOfs (pr, value->int_var); + pr_def_t *def = PR_FieldAtOfs (pr, PR_PTR (int, value)); if (def) { dasprintf (dstr, ".%s", PR_GetString (pr, def->name)); } else { - dasprintf (dstr, ".<$%04x>", value->int_var); + dasprintf (dstr, ".<$%04x>", PR_PTR (int, value)); } } @@ -1254,12 +1264,12 @@ pr_debug_func_view (qfot_type_t *type, pr_type_t *value, void *_data) progs_t *pr = data->pr; dstring_t *dstr = data->dstr; - if (value->func_var >= pr->progs->functions.count) { - dasprintf (dstr, "INVALID:%d", value->func_var); - } else if (!value->func_var) { + if (PR_PTR (func, value) >= pr->progs->functions.count) { + dasprintf (dstr, "INVALID:%d", PR_PTR (func, value)); + } else if (!PR_PTR (func, value)) { dstring_appendstr (dstr, "NULL"); } else { - dfunction_t *f = pr->pr_functions + value->func_var; + dfunction_t *f = pr->pr_functions + PR_PTR (func, value); dasprintf (dstr, "%s()", PR_GetString (pr, f->name)); } } @@ -1270,7 +1280,7 @@ pr_debug_ptr_view (qfot_type_t *type, pr_type_t *value, void *_data) __auto_type data = (pr_debug_data_t *) _data; progs_t *pr = data->pr; dstring_t *dstr = data->dstr; - pr_ptr_t offset = value->int_var; + pr_ptr_t offset = PR_PTR (int, value); pr_ptr_t offs = offset; pr_def_t *def = 0; @@ -1292,7 +1302,7 @@ pr_debug_quaternion_view (qfot_type_t *type, pr_type_t *value, void *_data) __auto_type data = (pr_debug_data_t *) _data; dstring_t *dstr = data->dstr; - dasprintf (dstr, "'%.9g %.9g %.9g %.9g'", QuatExpand (&value->quat_var)); + dasprintf (dstr, "'%.9g %.9g %.9g %.9g'", QuatExpand (&PR_PTR (float, value))); } static void @@ -1301,7 +1311,7 @@ pr_debug_int_view (qfot_type_t *type, pr_type_t *value, void *_data) __auto_type data = (pr_debug_data_t *) _data; dstring_t *dstr = data->dstr; - dasprintf (dstr, "%d", value->int_var); + dasprintf (dstr, "%d", PR_PTR (int, value)); } static void @@ -1310,7 +1320,7 @@ pr_debug_uint_view (qfot_type_t *type, pr_type_t *value, void *_data) __auto_type data = (pr_debug_data_t *) _data; dstring_t *dstr = data->dstr; - dasprintf (dstr, "$%08x", value->uint_var); + dasprintf (dstr, "$%08x", PR_PTR (uint, value)); } static void @@ -1319,7 +1329,7 @@ pr_debug_short_view (qfot_type_t *type, pr_type_t *value, void *_data) __auto_type data = (pr_debug_data_t *) _data; dstring_t *dstr = data->dstr; - dasprintf (dstr, "%04x", (short)value->int_var); + dasprintf (dstr, "%04x", (short)PR_PTR (int, value)); } static void @@ -1355,7 +1365,7 @@ pr_debug_ushort_view (qfot_type_t *type, pr_type_t *value, void *_data) __auto_type data = (pr_debug_data_t *) _data; dstring_t *dstr = data->dstr; - dasprintf (dstr, "%04x", (pr_ushort_t)value->int_var); + dasprintf (dstr, "%04x", (pr_ushort_t)PR_PTR (int, value)); } static void @@ -1431,7 +1441,7 @@ PR_Debug_Watch (progs_t *pr, const char *expr) (int) (intptr_t) (pr->watch - pr->pr_globals)); if (pr->wp_conditional) Sys_Printf (" if new val == %d\n", - pr->wp_val.int_var); + PR_PTR (int, &pr->wp_val)); } else { Sys_Printf (" none active\n"); } return; @@ -1444,7 +1454,7 @@ PR_Debug_Watch (progs_t *pr, const char *expr) if (pr->watch) { Sys_Printf ("watchpoint set to [%d]\n", PR_SetPointer (pr, pr->watch)); if (pr->wp_conditional) - Sys_Printf (" if new val == %d\n", pr->wp_val.int_var); + Sys_Printf (" if new val == %d\n", PR_PTR (int, &pr->wp_val)); } else { Sys_Printf ("watchpoint cleared\n"); } @@ -1490,6 +1500,7 @@ PR_PrintStatement (progs_t *pr, dstatement_t *s, int contents) int dump_code = contents & 2; const char *fmt; const char *mnemonic; + const char *width = ""; dfunction_t *call_func = 0; pr_def_t *param_def = 0; pr_auxfunction_t *aux_func = 0; @@ -1558,13 +1569,15 @@ PR_PrintStatement (progs_t *pr, dstatement_t *s, int contents) print_raw_op (pr, s->a, PR_BASE_IND (s->op, A), op_type[0], op_width[0]), print_raw_op (pr, s->b, PR_BASE_IND (s->op, B), - op_type[0], op_width[0]), + op_type[1], op_width[1]), print_raw_op (pr, s->c, PR_BASE_IND (s->op, C), - op_type[0], op_width[0])); + op_type[2], op_width[2])); } + } else if (op_width[0] > 1 || op_width[1] > 1 || op_width[2] > 1) { + width = va (res->va, "{%d,%d,%d}", VectorExpand (op_width)); } - dasprintf (res->line, "%s ", mnemonic); + dasprintf (res->line, "%s%s ", mnemonic, width); while (*fmt) { if (*fmt == '%') { @@ -1683,8 +1696,8 @@ PR_PrintStatement (progs_t *pr, dstatement_t *s, int contents) case 'E': { edict_t *ed = 0; - opval = pr->pr_globals[s->a].entity_var; - param_ind = pr->pr_globals[s->b].uint_var; + opval = G_ENTITY (pr, s->a); + param_ind = G_FIELD (pr, s->b); if (param_ind < pr->progs->entityfields && opval > 0 && opval < pr->pr_edict_area_size) { diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index a7d4fbac7..e8c4f2551 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -287,7 +287,7 @@ PR_EnterFunction (progs_t *pr, bfunction_t *f) if (pr_deadbeef_locals) { for (pr_uint_t i = f->params_start; i < f->params_start + f->locals; i++) { - pr->pr_globals[i].int_var = 0xdeadbeef; + pr->pr_globals[i].value = 0xdeadbeef; } } @@ -304,8 +304,8 @@ PR_EnterFunction (progs_t *pr, bfunction_t *f) copy_param (dstParams[i], pr->pr_params[i], f->param_size[i].size); } copy_args = pr->pr_argc - i; - argc->int_var = copy_args; - argv->int_var = dstParams[i] - pr->pr_globals; + PR_PTR (int, argc) = copy_args; + PR_PTR (ptr, argv) = PR_SetPointer (pr, dstParams[i]); if (i < PR_MAX_PARAMS) { memcpy (dstParams[i], pr->pr_params[i], (copy_args * pr->pr_param_size) * sizeof (pr_type_t)); @@ -517,7 +517,7 @@ static inline void pr_memset (pr_type_t *dst, int val, pr_uint_t count) { while (count-- > 0) { - (*dst++).int_var = val; + (*dst++).value = val; } } @@ -839,7 +839,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) PR_BoundsCheck (pr, pointer, ev_int); } ptr = pr->pr_globals + pointer; - ptr->int_var = OPA(int); + ptr->value = OPA(int); break; case OP_STOREP_V_v6p: pointer = OPB(ptr); @@ -847,7 +847,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) PR_BoundsCheck (pr, pointer, ev_vector); } ptr = pr->pr_globals + pointer; - VectorCopy (&OPA(float), &ptr->vector_var); + VectorCopy (&OPA(float), &PR_PTR (float, ptr)); break; case OP_STOREP_Q_v6p: pointer = OPB(ptr); @@ -855,7 +855,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) PR_BoundsCheck (pr, pointer, ev_quaternion); } ptr = pr->pr_globals + pointer; - QuatCopy (&OPA(float), &ptr->quat_var); + QuatCopy (&OPA(float), &PR_PTR (float, ptr)); break; case OP_STOREP_D_v6p: pointer = OPB(ptr); @@ -910,7 +910,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) "field in an edict"); } fldofs = OPA(entity) + OPB(field); - OPC(int) = pr->pr_edict_area[fldofs].int_var; + OPC(int) = PR_PTR (int, &pr->pr_edict_area[fldofs]); break; case OP_LOAD_V_v6p: if (pr_boundscheck) { @@ -961,23 +961,21 @@ pr_exec_quakec (progs_t *pr, int exitdepth) PR_BoundsCheck (pr, pointer, ev_int); } ptr = pr->pr_globals + pointer; - OPC(int) = ptr->int_var; + OPC(int) = ptr->value; break; case OP_LOADB_V_v6p: pointer = OPA(entity) + OPB(field); if (pr_boundscheck) { PR_BoundsCheck (pr, pointer, ev_vector); } - ptr = pr->pr_globals + pointer; - VectorCopy (&ptr->vector_var, &OPC(float)); + VectorCopy (G_VECTOR (pr, pointer), &OPC(float)); break; case OP_LOADB_Q_v6p: pointer = OPA(entity) + OPB(field); if (pr_boundscheck) { PR_BoundsCheck (pr, pointer, ev_quaternion); } - ptr = pr->pr_globals + pointer; - QuatCopy (&ptr->quat_var, &OPC(float)); + QuatCopy (G_QUAT (pr, pointer), &OPC(float)); break; case OP_LOADB_D_v6p: pointer = OPA(entity) + OPB(field); @@ -1000,7 +998,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) PR_BoundsCheck (pr, pointer, ev_int); } ptr = pr->pr_globals + pointer; - OPC(int) = ptr->int_var; + OPC(int) = ptr->value; break; case OP_LOADBI_V_v6p: pointer = OPA(ptr) + (short) st->b; @@ -1008,7 +1006,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) PR_BoundsCheck (pr, pointer, ev_vector); } ptr = pr->pr_globals + pointer; - VectorCopy (&ptr->vector_var, &OPC(float)); + VectorCopy (G_VECTOR (pr, pointer), &OPC(float)); break; case OP_LOADBI_Q_v6p: pointer = OPA(ptr) + (short) st->b; @@ -1016,7 +1014,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) PR_BoundsCheck (pr, pointer, ev_quaternion); } ptr = pr->pr_globals + pointer; - QuatCopy (&ptr->quat_var, &OPC(float)); + QuatCopy (G_QUAT (pr, pointer), &OPC(float)); break; case OP_LOADBI_D_v6p: pointer = OPA(ptr) + (short) st->b; @@ -1049,7 +1047,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) PR_BoundsCheck (pr, pointer, ev_int); } ptr = pr->pr_globals + pointer; - ptr->int_var = OPA(int); + ptr->value = OPA(int); break; case OP_STOREB_V_v6p: pointer = OPB(ptr) + OPC(int); @@ -1057,7 +1055,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) PR_BoundsCheck (pr, pointer, ev_vector); } ptr = pr->pr_globals + pointer; - VectorCopy (&OPA(float), &ptr->vector_var); + VectorCopy (&OPA(float), G_VECTOR (pr, pointer)); break; case OP_STOREB_Q_v6p: pointer = OPB(ptr) + OPC(int); @@ -1065,7 +1063,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) PR_BoundsCheck (pr, pointer, ev_quaternion); } ptr = pr->pr_globals + pointer; - QuatCopy (&OPA(float), &ptr->quat_var); + QuatCopy (&OPA(float), G_QUAT (pr, pointer)); break; case OP_STOREB_D_v6p: pointer = OPB(ptr) + OPC(int); @@ -1088,7 +1086,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) PR_BoundsCheck (pr, pointer, ev_int); } ptr = pr->pr_globals + pointer; - ptr->int_var = OPA(int); + ptr->value = OPA(int); break; case OP_STOREBI_V_v6p: pointer = OPB(ptr) + (short) st->c; @@ -1096,7 +1094,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) PR_BoundsCheck (pr, pointer, ev_vector); } ptr = pr->pr_globals + pointer; - VectorCopy (&OPA(float), &ptr->vector_var); + VectorCopy (&OPA(float), G_VECTOR (pr, pointer)); break; case OP_STOREBI_Q_v6p: pointer = OPB(ptr) + (short) st->c; @@ -1104,7 +1102,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) PR_BoundsCheck (pr, pointer, ev_quaternion); } ptr = pr->pr_globals + pointer; - QuatCopy (&OPA(float), &ptr->quat_var); + QuatCopy (&OPA(float), G_QUAT (pr, pointer)); break; case OP_STOREBI_D_v6p: pointer = OPB(ptr) + (short) st->c; @@ -1128,7 +1126,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) if (pr_boundscheck) { check_stack_pointer (pr, stack, 1); } - stk->int_var = OPA(int); + stk->value = OPA(int); *pr->globals.stack = stack; } break; @@ -1174,14 +1172,13 @@ pr_exec_quakec (progs_t *pr, int exitdepth) PR_BoundsCheck (pr, pointer, ev_int); } - stk->int_var = ptr->int_var; + stk->value = ptr->value; *pr->globals.stack = stack; } break; case OP_PUSHB_V_v6p: { pr_ptr_t stack = *pr->globals.stack - 3; - pr_type_t *stk = pr->pr_globals + stack; pointer = OPA(ptr) + OPB(int); ptr = pr->pr_globals + pointer; @@ -1191,14 +1188,13 @@ pr_exec_quakec (progs_t *pr, int exitdepth) PR_BoundsCheck (pr, pointer, ev_int); } - VectorCopy (&ptr->vector_var, &stk->vector_var); + VectorCopy (G_VECTOR (pr, pointer), G_VECTOR (pr, stack)); *pr->globals.stack = stack; } break; case OP_PUSHB_Q_v6p: { pr_ptr_t stack = *pr->globals.stack - 4; - pr_type_t *stk = pr->pr_globals + stack; pointer = OPA(ptr) + OPB(int); ptr = pr->pr_globals + pointer; @@ -1208,7 +1204,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) PR_BoundsCheck (pr, pointer, ev_quaternion); } - QuatCopy (&ptr->quat_var, &stk->quat_var); + QuatCopy (G_QUAT (pr, pointer), G_QUAT (pr, stack)); *pr->globals.stack = stack; } break; @@ -1232,14 +1228,13 @@ pr_exec_quakec (progs_t *pr, int exitdepth) PR_BoundsCheck (pr, pointer, ev_int); } - stk->int_var = ptr->int_var; + stk->value = ptr->value; *pr->globals.stack = stack; } break; case OP_PUSHBI_V_v6p: { pr_ptr_t stack = *pr->globals.stack - 3; - pr_type_t *stk = pr->pr_globals + stack; pointer = OPA(ptr) + st->b; ptr = pr->pr_globals + pointer; @@ -1249,14 +1244,13 @@ pr_exec_quakec (progs_t *pr, int exitdepth) PR_BoundsCheck (pr, pointer, ev_int); } - VectorCopy (&ptr->vector_var, &stk->vector_var); + VectorCopy (G_VECTOR (pr, pointer), G_VECTOR (pr, stack)); *pr->globals.stack = stack; } break; case OP_PUSHBI_Q_v6p: { pr_ptr_t stack = *pr->globals.stack - 4; - pr_type_t *stk = pr->pr_globals + stack; pointer = OPA(ptr) + st->b; ptr = pr->pr_globals + pointer; @@ -1266,7 +1260,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) PR_BoundsCheck (pr, pointer, ev_quaternion); } - QuatCopy (&ptr->quat_var, &stk->quat_var); + QuatCopy (G_QUAT (pr, pointer), G_QUAT (pr, stack)); *pr->globals.stack = stack; } break; @@ -1284,7 +1278,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) if (pr_boundscheck) { check_stack_pointer (pr, stack, 1); } - OPA(int) = stk->int_var; + OPA(int) = stk->value; *pr->globals.stack = stack + 1; } break; @@ -1330,14 +1324,13 @@ pr_exec_quakec (progs_t *pr, int exitdepth) PR_BoundsCheck (pr, pointer, ev_int); } - ptr->int_var = stk->int_var; + ptr->value = stk->value; *pr->globals.stack = stack + 1; } break; case OP_POPB_V_v6p: { pr_ptr_t stack = *pr->globals.stack; - pr_type_t *stk = pr->pr_globals + stack; pointer = OPA(ptr) + OPB(int); ptr = pr->pr_globals + pointer; @@ -1347,14 +1340,13 @@ pr_exec_quakec (progs_t *pr, int exitdepth) PR_BoundsCheck (pr, pointer, ev_int); } - VectorCopy (&stk->vector_var, &ptr->vector_var); + VectorCopy (G_VECTOR (pr, stack), G_VECTOR (pr, pointer)); *pr->globals.stack = stack + 3; } break; case OP_POPB_Q_v6p: { pr_ptr_t stack = *pr->globals.stack; - pr_type_t *stk = pr->pr_globals + stack; pointer = OPA(ptr) + OPB(int); ptr = pr->pr_globals + pointer; @@ -1364,7 +1356,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) PR_BoundsCheck (pr, pointer, ev_quaternion); } - QuatCopy (&stk->quat_var, &ptr->quat_var); + QuatCopy (G_QUAT (pr, stack), G_QUAT (pr, pointer)); *pr->globals.stack = stack + 4; } break; @@ -1388,14 +1380,13 @@ pr_exec_quakec (progs_t *pr, int exitdepth) PR_BoundsCheck (pr, pointer, ev_int); } - ptr->int_var = stk->int_var; + ptr->value = stk->value; *pr->globals.stack = stack + 1; } break; case OP_POPBI_V_v6p: { pr_ptr_t stack = *pr->globals.stack; - pr_type_t *stk = pr->pr_globals + stack; pointer = OPA(ptr) + st->b; ptr = pr->pr_globals + pointer; @@ -1405,14 +1396,13 @@ pr_exec_quakec (progs_t *pr, int exitdepth) PR_BoundsCheck (pr, pointer, ev_int); } - VectorCopy (&stk->vector_var, &ptr->vector_var); + VectorCopy (G_VECTOR (pr, stack), G_VECTOR (pr, pointer)); *pr->globals.stack = stack + 3; } break; case OP_POPBI_Q_v6p: { pr_ptr_t stack = *pr->globals.stack; - pr_type_t *stk = pr->pr_globals + stack; pointer = OPA(ptr) + st->b; ptr = pr->pr_globals + pointer; @@ -1422,7 +1412,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) PR_BoundsCheck (pr, pointer, ev_quaternion); } - QuatCopy (&stk->quat_var, &ptr->quat_var); + QuatCopy (G_QUAT (pr, stack), G_QUAT (pr, pointer)); *pr->globals.stack = stack + 4; } break; @@ -1481,8 +1471,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) if (pr_boundscheck) { PR_BoundsCheck (pr, pointer, ev_int); } - ptr = pr->pr_globals + pointer; - pointer = ptr->int_var; + pointer = G_POINTER (pr, pointer); if (pr_boundscheck && (pointer >= pr->progs->statements.count)) { PR_RunError (pr, "Invalid jump destination"); @@ -1551,9 +1540,9 @@ op_call: int frame = pr->fields.frame + self; int think = pr->fields.think + self; float time = *pr->globals.ftime + 0.1; - pr->pr_edict_area[nextthink].float_var = time; - pr->pr_edict_area[frame].float_var = OPA(float); - pr->pr_edict_area[think].func_var = OPB(func); + PR_PTR (float, &pr->pr_edict_area[nextthink]) = time; + PR_PTR (float, &pr->pr_edict_area[frame]) = OPA(float); + PR_PTR (func, &pr->pr_edict_area[think]) = OPB(func); } break; case OP_STATE_F_v6p: @@ -1563,9 +1552,9 @@ op_call: int frame = pr->fields.frame + self; int think = pr->fields.think + self; float time = *pr->globals.ftime + OPC(float); - pr->pr_edict_area[nextthink].float_var = time; - pr->pr_edict_area[frame].float_var = OPA(float); - pr->pr_edict_area[think].func_var = OPB(func); + PR_PTR (float, &pr->pr_edict_area[nextthink]) = time; + PR_PTR (float, &pr->pr_edict_area[frame]) = OPA(float); + PR_PTR (func, &pr->pr_edict_area[think]) = OPB(func); } break; case OP_ADD_I_v6p: @@ -1748,8 +1737,7 @@ op_call: OPC(float) = OPA(double) < OPB(double); break; case OP_NOT_D_v6p: - OPC(int) = (op_a[0].int_var - || (op_a[1].int_var & ~0x80000000u)); + OPC(int) = (op_a[0].value || (op_a[1].value & ~0x80000000u)); break; case OP_EQ_D_v6p: OPC(int) = OPA(double) == OPB(double); @@ -1783,17 +1771,17 @@ op_call: default: PR_RunError (pr, "Bad opcode %i", st->op & ~OP_BREAK); } - if (pr->watch && pr->watch->int_var != old_val.int_var) { + if (pr->watch && pr->watch->value != old_val.value) { if (!pr->wp_conditional - || pr->watch->int_var == pr->wp_val.int_var) { + || pr->watch->value == pr->wp_val.value) { if (pr->debug_handler) { pr->debug_handler (prd_watchpoint, 0, pr->debug_data); } else { PR_RunError (pr, "watchpoint hit: %d -> %d", - old_val.int_var, pr->watch->int_var); + old_val.value, pr->watch->value); } } - old_val.int_var = pr->watch->int_var; + old_val.value = pr->watch->value; } } exit_program: @@ -1877,7 +1865,7 @@ pr_jump_mode (progs_t *pr, const dstatement_t *st, int jump_ind) break; case 1: // variable indexed array: a + *b (only +ve) - jump_offs = (op_a + OPB(uint))->uint_var; + jump_offs = PR_PTR (uint, op_a + OPB(uint)); break; case 2: // constant indexed pointer: *a + b (supports -ve offset) @@ -1963,7 +1951,7 @@ pr_with (progs_t *pr, const dstatement_t *st) case 4: // hard-0 base - pr->pr_bases[st->c & 3] = pr->pr_globals[st->b].pointer_var; + pr->pr_bases[st->c & 3] = G_POINTER (pr, st->b);; return; case 5: pr->pr_bases[st->c & 3] = OPB(ptr); @@ -2571,7 +2559,7 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) case OP_CALL_C: case OP_CALL_D: mm = pr_call_mode (pr, st, st_op - OP_CALL_B + 1); - function = mm->func_var; + function = PR_PTR (func, mm); pr->pr_argc = 0; // op_c specifies the location for the return value if any pr->pr_xfunction->profile += profile - startprofile; @@ -2714,9 +2702,9 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) int frame = pr->fields.frame + self; int think = pr->fields.think + self; float time = *pr->globals.ftime + 0.1; - pr->pr_edict_area[nextthink].float_var = time; - pr->pr_edict_area[frame].float_var = OPA(float); - pr->pr_edict_area[think].func_var = op_b->func_var; + PR_PTR (float, &pr->pr_edict_area[nextthink]) = time; + PR_PTR (float, &pr->pr_edict_area[frame]) = OPA(float); + PR_PTR (func, &pr->pr_edict_area[think]) = OPB(func); } break; OP_cmp_T (GE, U, long, lvec2, lvec4, >=, ulong, ulvec2, ulvec4); @@ -2736,9 +2724,9 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) int frame = pr->fields.frame + self; int think = pr->fields.think + self; float time = *pr->globals.ftime + OPC(float); - pr->pr_edict_area[nextthink].float_var = time; - pr->pr_edict_area[frame].float_var = OPA(float); - pr->pr_edict_area[think].func_var = op_b->func_var; + PR_PTR (float, &pr->pr_edict_area[nextthink]) = time; + PR_PTR (float, &pr->pr_edict_area[frame]) = OPA(float); + PR_PTR (func, &pr->pr_edict_area[think]) = OPB(func); } break; // 1 1110 @@ -2768,9 +2756,9 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) int frame = pr->fields.frame + self; int think = pr->fields.think + self; double time = *pr->globals.dtime + 0.1; - *(double *) (&pr->pr_edict_area[nextthink]) = time; - pr->pr_edict_area[frame].int_var = OPA(int); - pr->pr_edict_area[think].func_var = op_b->func_var; + PR_PTR (double, &pr->pr_edict_area[nextthink]) = time; + PR_PTR (int, &pr->pr_edict_area[frame]) = OPA(int); + PR_PTR (func, &pr->pr_edict_area[think]) = OPB(func); } break; OP_cmp_T (LE, U, long, lvec2, lvec4, <=, ulong, ulvec2, ulvec4); @@ -2799,9 +2787,9 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) int frame = pr->fields.frame + self; int think = pr->fields.think + self; double time = *pr->globals.dtime + OPC(double); - *(double *) (&pr->pr_edict_area[nextthink]) = time; - pr->pr_edict_area[frame].int_var = OPA(int); - pr->pr_edict_area[think].func_var = op_b->func_var; + PR_PTR (double, &pr->pr_edict_area[nextthink]) = time; + PR_PTR (int, &pr->pr_edict_area[frame]) = OPA(int); + PR_PTR (func, &pr->pr_edict_area[think]) = OPB(func); } break; // 1 1111 @@ -2810,7 +2798,7 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) case OP_LEA_C: case OP_LEA_D: mm = pr_address_mode (pr, st, (st_op - OP_LEA_A)); - op_c->pointer_var = mm - pr->pr_globals; + OPC(ptr) = mm - pr->pr_globals; break; case OP_QV4MUL_F: OPC(vec4) = qvmulf (OPA(vec4), OPB(vec4)); @@ -2862,17 +2850,17 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) default: PR_RunError (pr, "Bad opcode o%03o", st->op & OP_MASK); } - if (pr->watch && pr->watch->int_var != old_val.int_var) { + if (pr->watch && pr->watch->value != old_val.value) { if (!pr->wp_conditional - || pr->watch->int_var == pr->wp_val.int_var) { + || pr->watch->value == pr->wp_val.value) { if (pr->debug_handler) { pr->debug_handler (prd_watchpoint, 0, pr->debug_data); } else { PR_RunError (pr, "watchpoint hit: %d -> %d", - old_val.int_var, pr->watch->int_var); + old_val.value, pr->watch->value); } } - old_val.int_var = pr->watch->int_var; + old_val.value = pr->watch->value; } } exit_program: diff --git a/libs/gamecode/pr_parse.c b/libs/gamecode/pr_parse.c index a1c198192..e43aef934 100644 --- a/libs/gamecode/pr_parse.c +++ b/libs/gamecode/pr_parse.c @@ -68,34 +68,34 @@ PR_UglyValueString (progs_t *pr, etype_t type, pr_type_t *val, dstring_t *line) switch (type) { case ev_string: - dsprintf (line, "%s", PR_GetString (pr, val->string_var)); + dsprintf (line, "%s", PR_GetString (pr, PR_PTR (string, val))); break; case ev_entity: dsprintf (line, "%d", - NUM_FOR_BAD_EDICT (pr, PROG_TO_EDICT (pr, val->entity_var))); + NUM_FOR_BAD_EDICT (pr, PROG_TO_EDICT (pr, PR_PTR (entity, val)))); break; case ev_func: - f = pr->pr_functions + val->func_var; + f = pr->pr_functions + PR_PTR (func, val); dsprintf (line, "%s", PR_GetString (pr, f->name)); break; case ev_field: - def = PR_FieldAtOfs (pr, val->int_var); + def = PR_FieldAtOfs (pr, PR_PTR (int, val)); dsprintf (line, "%s", PR_GetString (pr, def->name)); break; case ev_void: dstring_copystr (line, "void"); break; case ev_float: - dsprintf (line, "%.9g", val->float_var); + dsprintf (line, "%.9g", PR_PTR (float, val)); break; case ev_int: - dsprintf (line, "%d", val->int_var); + dsprintf (line, "%d", PR_PTR (int, val)); break; case ev_vector: - dsprintf (line, "%.9g %.9g %.9g", VectorExpand (&val->vector_var)); + dsprintf (line, "%.9g %.9g %.9g", VectorExpand (&PR_PTR (float, val))); break; case ev_quaternion: - dsprintf (line, "%.9g %.9g %.9g %.9g", QuatExpand (&val->quat_var)); + dsprintf (line, "%.9g %.9g %.9g %.9g", QuatExpand (&PR_PTR (float, val))); break; default: dsprintf (line, "bad type %i", type); @@ -132,7 +132,7 @@ ED_EntityDict (progs_t *pr, edict_t *ed) // if the value is still all 0, skip the field type = d->type & ~DEF_SAVEGLOBAL; for (j = 0; j < pr_type_size[type]; j++) - if (v[j].int_var) + if (v[j].value) break; if (j == pr_type_size[type]) continue; @@ -226,11 +226,11 @@ ED_ParseEpair (progs_t *pr, pr_type_t *base, pr_def_t *key, const char *s) switch (key->type & ~DEF_SAVEGLOBAL) { case ev_string: - d->string_var = ED_NewString (pr, s); + PR_PTR (string, d) = ED_NewString (pr, s); break; case ev_float: - d->float_var = atof (s); + PR_PTR (float, d) = atof (s); break; case ev_vector: @@ -241,14 +241,14 @@ ED_ParseEpair (progs_t *pr, pr_type_t *base, pr_def_t *key, const char *s) while (*v && *v != ' ') v++; *v = 0; - (&d->vector_var)[i] = atof (w); + (&PR_PTR (float, d))[i] = atof (w); w = v = v + 1; } free (string); break; case ev_entity: - d->entity_var = EDICT_TO_PROG (pr, EDICT_NUM (pr, atoi (s))); + PR_PTR (entity, d) = EDICT_TO_PROG (pr, EDICT_NUM (pr, atoi (s))); break; case ev_field: @@ -257,7 +257,7 @@ ED_ParseEpair (progs_t *pr, pr_type_t *base, pr_def_t *key, const char *s) Sys_Printf ("Can't find field %s\n", s); return false; } - d->int_var = G_INT (pr, def->ofs); + PR_PTR (int, d) = G_INT (pr, def->ofs); break; case ev_func: @@ -266,7 +266,7 @@ ED_ParseEpair (progs_t *pr, pr_type_t *base, pr_def_t *key, const char *s) Sys_Printf ("Can't find function %s\n", s); return false; } - d->func_var = func - pr->pr_functions; + PR_PTR (func, d) = func - pr->pr_functions; break; default: diff --git a/libs/gamecode/pr_strings.c b/libs/gamecode/pr_strings.c index eb0fcc6ab..92129f7ad 100644 --- a/libs/gamecode/pr_strings.c +++ b/libs/gamecode/pr_strings.c @@ -38,6 +38,7 @@ #include #include #include +#include #include "QF/dstring.h" #include "QF/hash.h" @@ -60,10 +61,12 @@ typedef struct fmt_item_s { int precision; union { const char *string_var; - int integer_var; - unsigned uinteger_var; + pr_int_t int_var; + pr_uint_t uint_var; float float_var; double double_var; + pr_long_t long_var; + pr_ulong_t ulong_var; } data; struct fmt_item_s *next; } fmt_item_t; @@ -769,23 +772,35 @@ I_DoPrint (dstring_t *tmp, dstring_t *result, fmt_item_t *formatting) break; case 'c': dstring_appendstr (tmp, "c"); - PRINT (integer); + PRINT (int); break; case 'i': case 'd': - dstring_appendstr (tmp, "d"); - PRINT (integer); + if (current->flags & FMT_LONG) { + dstring_appendstr (tmp, PRId64); + PRINT (ulong); + } else { + dstring_appendstr (tmp, PRId32); + PRINT (uint); + } break; case 'x': - dstring_appendstr (tmp, "x"); - PRINT (integer); + if (current->flags & FMT_LONG) { + dstring_appendstr (tmp, PRIx64); + PRINT (ulong); + } else { + dstring_appendstr (tmp, PRIx32); + PRINT (uint); + } break; case 'u': - if (current->flags & FMT_HEX) - dstring_appendstr (tmp, "x"); - else - dstring_appendstr (tmp, "u"); - PRINT (uinteger); + if (current->flags & FMT_LONG) { + dstring_appendstr (tmp, PRIu64); + PRINT (ulong); + } else { + dstring_appendstr (tmp, PRIu32); + PRINT (uint); + } break; case 'f': dstring_appendstr (tmp, "f"); @@ -860,9 +875,7 @@ fmt_append_item (fmt_state_t *state) } #undef P_var -#define P_var(p,n,t) (state->args[n]->t##_var) -#undef P_DOUBLE -#define P_DOUBLE(p,n) (*(double *) (state->args[n])) +#define P_var(p,n,t) PR_PTR (t, state->args[n]) /** State machine for PR_Sprintf * @@ -1021,6 +1034,12 @@ static void fmt_state_modifiers (fmt_state_t *state) { // no modifiers supported + if (state->c[0] == 'l' + && (state->c[1] == 'i' || state->c[1] == 'd' || state->c[1] == 'x' + || state->c[1] == 'u')) { + (*state->fi)->flags |= FMT_LONG; + state->c++; + } state->state = fmt_state_conversion; } @@ -1038,8 +1057,7 @@ fmt_state_conversion (fmt_state_t *state) case 'e': // entity (*state->fi)->type = 'i'; - (*state->fi)->data.integer_var = - P_EDICTNUM (pr, state->fmt_count); + (*state->fi)->data.int_var = P_EDICTNUM (pr, state->fmt_count); state->fmt_count++; fmt_append_item (state); @@ -1047,9 +1065,13 @@ fmt_state_conversion (fmt_state_t *state) case 'i': case 'd': case 'c': - // integer + // int (*state->fi)->type = conv; - (*state->fi)->data.integer_var = P_INT (pr, state->fmt_count); + if ((*state->fi)->flags & FMT_LONG) { + (*state->fi)->data.long_var = P_LONG (pr, state->fmt_count); + } else { + (*state->fi)->data.int_var = P_INT (pr, state->fmt_count); + } state->fmt_count++; fmt_append_item (state); @@ -1076,7 +1098,7 @@ fmt_state_conversion (fmt_state_t *state) // pointer (*state->fi)->flags |= FMT_ALTFORM; (*state->fi)->type = 'x'; - (*state->fi)->data.uinteger_var = P_UINT (pr, state->fmt_count); + (*state->fi)->data.uint_var = P_UINT (pr, state->fmt_count); state->fmt_count++; fmt_append_item (state); @@ -1134,9 +1156,13 @@ fmt_state_conversion (fmt_state_t *state) break; case 'u': case 'x': - // integer, unsigned or hex notation + // int, unsigned or hex notation (*state->fi)->type = conv; - (*state->fi)->data.uinteger_var = P_UINT (pr, state->fmt_count); + if ((*state->fi)->flags & FMT_LONG) { + (*state->fi)->data.ulong_var = P_ULONG (pr, state->fmt_count); + } else { + (*state->fi)->data.uint_var = P_UINT (pr, state->fmt_count); + } state->fmt_count++; fmt_append_item (state); diff --git a/libs/gib/bi_gib.c b/libs/gib/bi_gib.c index c0a59178c..29d95930a 100644 --- a/libs/gib/bi_gib.c +++ b/libs/gib/bi_gib.c @@ -86,7 +86,8 @@ bi_gib_builtin_f (void) pr_list = PR_Zone_Malloc (builtin->pr, GIB_Argc() * sizeof (pr_type_t)); for (i = 0; i < GIB_Argc(); i++) - pr_list[i].int_var = PR_SetTempString (builtin->pr, GIB_Argv(i)); + PR_PTR (string, &pr_list[i]) = PR_SetTempString (builtin->pr, + GIB_Argv(i)); PR_RESET_PARAMS (builtin->pr); P_INT (builtin->pr, 0) = GIB_Argc(); diff --git a/libs/ruamoko/pr_cmds.c b/libs/ruamoko/pr_cmds.c index bf8d9c19c..63fc6c1e3 100644 --- a/libs/ruamoko/pr_cmds.c +++ b/libs/ruamoko/pr_cmds.c @@ -62,10 +62,10 @@ PF_VarString (progs_t *pr, int first, int argc) pr_type_t **argv = pr->pr_params; for (len = 0, i = first; i < argc; i++) - len += strlen (PR_GetString (pr, argv[i]->string_var)); + len += strlen (PR_GetString (pr, *(pr_string_t *) argv[i])); dst = out = Hunk_TempAlloc (0, len + 1); for (i = first; i < argc; i++) { - src = PR_GetString (pr, argv[i]->string_var); + src = PR_GetString (pr, PR_PTR (string, argv[i])); while (*src) *dst++ = *src++; } diff --git a/libs/ruamoko/rua_hash.c b/libs/ruamoko/rua_hash.c index 6f8b74547..63020060e 100644 --- a/libs/ruamoko/rua_hash.c +++ b/libs/ruamoko/rua_hash.c @@ -276,7 +276,7 @@ bi_Hash_FindList (progs_t *pr, void *_res) pr_list = PR_Zone_Malloc (pr, count * sizeof (pr_type_t)); // the hash tables stores progs pointers... for (count = 0, l = list; *l; l++) - pr_list[count++].int_var = (intptr_t) *l; + PR_PTR (ptr, &pr_list[count++]) = (intptr_t) *l; free (list); RETURN_POINTER (pr, pr_list); } @@ -296,7 +296,7 @@ bi_Hash_FindElementList (progs_t *pr, void *_res) pr_list = PR_Zone_Malloc (pr, count * sizeof (pr_type_t)); // the hash tables stores progs pointers... for (count = 0, l = list; *l; l++) - pr_list[count++].int_var = (intptr_t) *l; + PR_PTR (ptr, &pr_list[count++]) = (intptr_t) *l; free (list); RETURN_POINTER (pr, pr_list); } @@ -356,7 +356,7 @@ bi_Hash_GetList (progs_t *pr, void *_res) pr_list = PR_Zone_Malloc (pr, count * sizeof (pr_type_t)); // the hash tables stores progs pointers... for (count = 0, l = list; *l; l++) - pr_list[count++].int_var = (intptr_t) *l; + PR_PTR(ptr, &pr_list[count++]) = (intptr_t) *l; free (list); RETURN_POINTER (pr, pr_list); } diff --git a/libs/ruamoko/rua_obj.c b/libs/ruamoko/rua_obj.c index 510dff248..c7942c8e0 100644 --- a/libs/ruamoko/rua_obj.c +++ b/libs/ruamoko/rua_obj.c @@ -1507,25 +1507,27 @@ rua_obj_msg_sendv (progs_t *pr, void *data) RUA_CALL_END (pr, imp) } +#define RETAIN_COUNT(obj) PR_PTR (int, &(obj)[-1]) + static void rua_obj_increment_retaincount (progs_t *pr, void *data) { pr_type_t *obj = &P_STRUCT (pr, pr_type_t, 0); - R_INT (pr) = ++(*--obj).int_var; + R_INT (pr) = ++RETAIN_COUNT (obj); } static void rua_obj_decrement_retaincount (progs_t *pr, void *data) { pr_type_t *obj = &P_STRUCT (pr, pr_type_t, 0); - R_INT (pr) = --(*--obj).int_var; + R_INT (pr) = --RETAIN_COUNT (obj); } static void rua_obj_get_retaincount (progs_t *pr, void *data) { pr_type_t *obj = &P_STRUCT (pr, pr_type_t, 0); - R_INT (pr) = (*--obj).int_var; + R_INT (pr) = RETAIN_COUNT (obj); } static void diff --git a/libs/ruamoko/rua_scene.c b/libs/ruamoko/rua_scene.c index 11aee7eb7..d43a4da7b 100644 --- a/libs/ruamoko/rua_scene.c +++ b/libs/ruamoko/rua_scene.c @@ -76,9 +76,13 @@ rua_scene_free (rua_scene_resources_t *res, rua_scene_t *scene) } static rua_scene_t * __attribute__((pure)) -rua__scene_get (rua_scene_resources_t *res, int id, const char *name) +rua__scene_get (rua_scene_resources_t *res, pr_ulong_t id, const char *name) { - rua_scene_t *scene = PR_RESGET (res->scene_map, id); + rua_scene_t *scene = 0; + + if (id <= 0xffffffffu) { + scene = PR_RESGET (res->scene_map, (pr_int_t) id); + } // scene->prev will be null if the handle is unallocated if (!scene || !scene->prev) { @@ -89,29 +93,42 @@ rua__scene_get (rua_scene_resources_t *res, int id, const char *name) #define rua_scene_get(res, id) rua__scene_get(res, id, __FUNCTION__) static entity_t * __attribute__((pure)) -rua__entity_get (progs_t *pr, rua_scene_t *scene, int id, const char *name) +rua__entity_get (rua_scene_resources_t *res, pr_ulong_t id, const char *name) { - entity_t *ent = Scene_GetEntity (scene->scene, id); + pr_ulong_t scene_id = id & 0xffffffff; + entity_t *ent = 0; + + rua_scene_t *scene = rua__scene_get (res, scene_id, name); + if (scene) { + pr_int_t entity_id = id >> 32; + ent = Scene_GetEntity (scene->scene, entity_id); + } if (!ent) { - PR_RunError (pr, "invalid entity passed to %s", name + 3); + PR_RunError (res->pr, "invalid entity passed to %s", name + 3); } return ent; } -#define rua_entity_get(pr, scene, id) rua__entity_get(pr, scene, id, __FUNCTION__) +#define rua_entity_get(res, id) rua__entity_get(res, id, __FUNCTION__) static transform_t * __attribute__((pure)) -rua__transform_get (progs_t *pr, rua_scene_t *scene, int id, const char *name) +rua__transform_get (rua_scene_resources_t *res, pr_ulong_t id, const char *name) { - transform_t *transform = Scene_GetTransform (scene->scene, id); + pr_ulong_t scene_id = id & 0xffffffff; + transform_t *transform = 0; + + rua_scene_t *scene = rua_scene_get (res, scene_id); + if (scene) { + pr_int_t transform_id = id >> 32; + transform = Scene_GetTransform (scene->scene, transform_id); + } if (!transform) { - PR_RunError (pr, "invalid transform passed to %s", name + 3); + PR_RunError (res->pr, "invalid transform passed to %s", name + 3); } return transform; } -#define rua_transform_get(pr, scene, id) \ - rua__transform_get(pr, scene, id, __FUNCTION__) +#define rua_transform_get(res, id) rua__transform_get(res, id, __FUNCTION__) static int __attribute__((pure)) rua_scene_index (rua_scene_resources_t *res, rua_scene_t *scene) @@ -119,6 +136,9 @@ rua_scene_index (rua_scene_resources_t *res, rua_scene_t *scene) return PR_RESINDEX (res->scene_map, scene); } +#define MAKE_ID(id, sc_id) ((((pr_ulong_t) (id)) << 32) \ + | ((sc_id) & 0xffffffff)) + static void bi_Scene_NewScene (progs_t *pr, void *_res) { @@ -135,7 +155,9 @@ bi_Scene_NewScene (progs_t *pr, void *_res) scene->prev = &res->scenes; res->scenes = scene; - R_INT (pr) = rua_scene_index (res, scene); + // scene id in lower 32-bits for all handles + // zero upper 32-bits zero means scene, otherwise transform or entity + R_ULONG (pr) = MAKE_ID (0, rua_scene_index (res, scene)); } static void @@ -149,7 +171,7 @@ static void bi_Scene_DeleteScene (progs_t *pr, void *_res) { rua_scene_resources_t *res = _res; - rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); + rua_scene_t *scene = rua_scene_get (res, P_ULONG (pr, 0)); rua_delete_scene (res, scene); } @@ -158,17 +180,21 @@ static void bi_Scene_CreateEntity (progs_t *pr, void *_res) { rua_scene_resources_t *res = _res; - rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); + pr_ulong_t scene_id = P_ULONG (pr, 0); + rua_scene_t *scene = rua_scene_get (res, scene_id); entity_t *ent = Scene_CreateEntity (scene->scene); - R_INT (pr) = ent->id; + R_ULONG (pr) = MAKE_ID (ent->id, scene_id); } static void bi_Scene_DestroyEntity (progs_t *pr, void *_res) { rua_scene_resources_t *res = _res; - rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); - entity_t *ent = rua_entity_get (pr, scene, P_INT (pr, 1)); + pr_ulong_t id = P_ULONG (pr, 0); + entity_t *ent = rua_entity_get (res, id); + pr_ulong_t scene_id = id & 0xffffffff; + // bad scene caught above + rua_scene_t *scene = rua_scene_get (res, scene_id); Scene_DestroyEntity (scene->scene, ent); } @@ -176,18 +202,18 @@ static void bi_Entity_GetTransform (progs_t *pr, void *_res) { rua_scene_resources_t *res = _res; - rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); - entity_t *ent = rua_entity_get (pr, scene, P_INT (pr, 1)); + pr_ulong_t ent_id = P_ULONG (pr, 0); + entity_t *ent = rua_entity_get (res, ent_id); - R_INT (pr) = ent->transform->id; + // ent_id contains scene id + R_ULONG (pr) = MAKE_ID (ent->transform->id, ent_id); } static void bi_Transform_ChildCount (progs_t *pr, void *_res) { rua_scene_resources_t *res = _res; - rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); - transform_t *transform = rua_transform_get (pr, scene, P_INT (pr, 1)); + transform_t *transform = rua_transform_get (res, P_ULONG (pr, 0)); R_UINT (pr) = Transform_ChildCount (transform); } @@ -196,8 +222,7 @@ static void bi_Transform_GetChild (progs_t *pr, void *_res) { rua_scene_resources_t *res = _res; - rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); - transform_t *transform = rua_transform_get (pr, scene, P_INT (pr, 1)); + transform_t *transform = rua_transform_get (res, P_ULONG (pr, 0)); transform_t *child = Transform_GetChild (transform, P_UINT (pr, 2)); R_UINT (pr) = child ? child->id : 0; @@ -207,9 +232,8 @@ static void bi_Transform_SetParent (progs_t *pr, void *_res) { rua_scene_resources_t *res = _res; - rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); - transform_t *transform = rua_transform_get (pr, scene, P_INT (pr, 1)); - transform_t *parent = rua_transform_get (pr, scene, P_INT (pr, 2)); + transform_t *transform = rua_transform_get (res, P_ULONG (pr, 0)); + transform_t *parent = rua_transform_get (res, P_ULONG (pr, 1)); Transform_SetParent (transform, parent); } @@ -218,19 +242,19 @@ static void bi_Transform_GetParent (progs_t *pr, void *_res) { rua_scene_resources_t *res = _res; - rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); - transform_t *transform = rua_transform_get (pr, scene, P_INT (pr, 1)); + pr_ulong_t transform_id = P_ULONG (pr, 0); + transform_t *transform = rua_transform_get (res, transform_id); transform_t *parent = Transform_GetParent (transform); - R_INT (pr) = parent ? parent->id : 0; + // transform_id contains scene id + R_ULONG (pr) = parent ? MAKE_ID (parent->id, transform_id) : 0; } static void bi_Transform_SetTag (progs_t *pr, void *_res) { rua_scene_resources_t *res = _res; - rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); - transform_t *transform = rua_transform_get (pr, scene, P_INT (pr, 1)); + transform_t *transform = rua_transform_get (res, P_ULONG (pr, 0)); pr_uint_t tag = P_UINT (pr, 2); Transform_SetTag (transform, tag); } @@ -239,8 +263,7 @@ static void bi_Transform_GetTag (progs_t *pr, void *_res) { rua_scene_resources_t *res = _res; - rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); - transform_t *transform = rua_transform_get (pr, scene, P_INT (pr, 1)); + transform_t *transform = rua_transform_get (res, P_ULONG (pr, 0)); R_UINT (pr) = Transform_GetTag (transform); } @@ -249,8 +272,7 @@ static void bi_Transform_GetLocalMatrix (progs_t *pr, void *_res) { rua_scene_resources_t *res = _res; - rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); - transform_t *transform = rua_transform_get (pr, scene, P_INT (pr, 1)); + transform_t *transform = rua_transform_get (res, P_ULONG (pr, 0)); Transform_GetLocalMatrix (transform, &R_PACKED (pr, pr_vec4_t)); } @@ -258,8 +280,7 @@ static void bi_Transform_GetLocalInverse (progs_t *pr, void *_res) { rua_scene_resources_t *res = _res; - rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); - transform_t *transform = rua_transform_get (pr, scene, P_INT (pr, 1)); + transform_t *transform = rua_transform_get (res, P_ULONG (pr, 0)); Transform_GetLocalInverse (transform, &R_PACKED (pr, pr_vec4_t)); } @@ -267,8 +288,7 @@ static void bi_Transform_GetWorldMatrix (progs_t *pr, void *_res) { rua_scene_resources_t *res = _res; - rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); - transform_t *transform = rua_transform_get (pr, scene, P_INT (pr, 1)); + transform_t *transform = rua_transform_get (res, P_ULONG (pr, 0)); Transform_GetWorldMatrix (transform, &R_PACKED (pr, pr_vec4_t)); } @@ -276,8 +296,7 @@ static void bi_Transform_GetWorldInverse (progs_t *pr, void *_res) { rua_scene_resources_t *res = _res; - rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); - transform_t *transform = rua_transform_get (pr, scene, P_INT (pr, 1)); + transform_t *transform = rua_transform_get (res, P_ULONG (pr, 0)); Transform_GetWorldInverse (transform, &R_PACKED (pr, pr_vec4_t)); } @@ -285,17 +304,15 @@ static void bi_Transform_SetLocalPosition (progs_t *pr, void *_res) { rua_scene_resources_t *res = _res; - rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); - transform_t *transform = rua_transform_get (pr, scene, P_INT (pr, 1)); - Transform_SetLocalPosition (transform, P_PACKED (pr, pr_vec4_t, 2)); + transform_t *transform = rua_transform_get (res, P_ULONG (pr, 0)); + Transform_SetLocalPosition (transform, P_PACKED (pr, pr_vec4_t, 1)); } static void bi_Transform_GetLocalPosition (progs_t *pr, void *_res) { rua_scene_resources_t *res = _res; - rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); - transform_t *transform = rua_transform_get (pr, scene, P_INT (pr, 1)); + transform_t *transform = rua_transform_get (res, P_ULONG (pr, 0)); R_PACKED (pr, pr_vec4_t) = Transform_GetLocalPosition (transform); } @@ -303,17 +320,15 @@ static void bi_Transform_SetLocalRotation (progs_t *pr, void *_res) { rua_scene_resources_t *res = _res; - rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); - transform_t *transform = rua_transform_get (pr, scene, P_INT (pr, 1)); - Transform_SetLocalRotation (transform, P_PACKED (pr, pr_vec4_t, 2)); + transform_t *transform = rua_transform_get (res, P_ULONG (pr, 0)); + Transform_SetLocalRotation (transform, P_PACKED (pr, pr_vec4_t, 1)); } static void bi_Transform_GetLocalRotation (progs_t *pr, void *_res) { rua_scene_resources_t *res = _res; - rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); - transform_t *transform = rua_transform_get (pr, scene, P_INT (pr, 1)); + transform_t *transform = rua_transform_get (res, P_ULONG (pr, 0)); R_PACKED (pr, pr_vec4_t) = Transform_GetLocalRotation (transform); } @@ -321,17 +336,15 @@ static void bi_Transform_SetLocalScale (progs_t *pr, void *_res) { rua_scene_resources_t *res = _res; - rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); - transform_t *transform = rua_transform_get (pr, scene, P_INT (pr, 1)); - Transform_SetLocalScale (transform, P_PACKED (pr, pr_vec4_t, 2)); + transform_t *transform = rua_transform_get (res, P_ULONG (pr, 0)); + Transform_SetLocalScale (transform, P_PACKED (pr, pr_vec4_t, 1)); } static void bi_Transform_GetLocalScale (progs_t *pr, void *_res) { rua_scene_resources_t *res = _res; - rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); - transform_t *transform = rua_transform_get (pr, scene, P_INT (pr, 1)); + transform_t *transform = rua_transform_get (res, P_ULONG (pr, 0)); R_PACKED (pr, pr_vec4_t) = Transform_GetLocalScale (transform); } @@ -339,17 +352,15 @@ static void bi_Transform_SetWorldPosition (progs_t *pr, void *_res) { rua_scene_resources_t *res = _res; - rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); - transform_t *transform = rua_transform_get (pr, scene, P_INT (pr, 1)); - Transform_SetWorldPosition (transform, P_PACKED (pr, pr_vec4_t, 2)); + transform_t *transform = rua_transform_get (res, P_ULONG (pr, 0)); + Transform_SetWorldPosition (transform, P_PACKED (pr, pr_vec4_t, 1)); } static void bi_Transform_GetWorldPosition (progs_t *pr, void *_res) { rua_scene_resources_t *res = _res; - rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); - transform_t *transform = rua_transform_get (pr, scene, P_INT (pr, 1)); + transform_t *transform = rua_transform_get (res, P_ULONG (pr, 0)); R_PACKED (pr, pr_vec4_t) = Transform_GetWorldPosition (transform); } @@ -357,17 +368,15 @@ static void bi_Transform_SetWorldRotation (progs_t *pr, void *_res) { rua_scene_resources_t *res = _res; - rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); - transform_t *transform = rua_transform_get (pr, scene, P_INT (pr, 1)); - Transform_SetWorldRotation (transform, P_PACKED (pr, pr_vec4_t, 2)); + transform_t *transform = rua_transform_get (res, P_ULONG (pr, 0)); + Transform_SetWorldRotation (transform, P_PACKED (pr, pr_vec4_t, 1)); } static void bi_Transform_GetWorldRotation (progs_t *pr, void *_res) { rua_scene_resources_t *res = _res; - rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); - transform_t *transform = rua_transform_get (pr, scene, P_INT (pr, 1)); + transform_t *transform = rua_transform_get (res, P_ULONG (pr, 0)); R_PACKED (pr, pr_vec4_t) = Transform_GetWorldRotation (transform); } @@ -375,8 +384,7 @@ static void bi_Transform_GetWorldScale (progs_t *pr, void *_res) { rua_scene_resources_t *res = _res; - rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); - transform_t *transform = rua_transform_get (pr, scene, P_INT (pr, 1)); + transform_t *transform = rua_transform_get (res, P_ULONG (pr, 0)); R_PACKED (pr, pr_vec4_t) = Transform_GetWorldScale (transform); } @@ -384,18 +392,16 @@ static void bi_Transform_SetLocalTransform (progs_t *pr, void *_res) { rua_scene_resources_t *res = _res; - rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); - transform_t *transform = rua_transform_get (pr, scene, P_INT (pr, 1)); - Transform_SetLocalTransform (transform, P_PACKED (pr, pr_vec4_t, 2), - P_PACKED (pr, pr_vec4_t, 3), P_PACKED (pr, pr_vec4_t, 4)); + transform_t *transform = rua_transform_get (res, P_ULONG (pr, 0)); + Transform_SetLocalTransform (transform, P_PACKED (pr, pr_vec4_t, 1), + P_PACKED (pr, pr_vec4_t, 2), P_PACKED (pr, pr_vec4_t, 3)); } static void bi_Transform_Forward (progs_t *pr, void *_res) { rua_scene_resources_t *res = _res; - rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); - transform_t *transform = rua_transform_get (pr, scene, P_INT (pr, 1)); + transform_t *transform = rua_transform_get (res, P_ULONG (pr, 0)); R_PACKED (pr, pr_vec4_t) = Transform_Forward (transform); } @@ -403,8 +409,7 @@ static void bi_Transform_Right (progs_t *pr, void *_res) { rua_scene_resources_t *res = _res; - rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); - transform_t *transform = rua_transform_get (pr, scene, P_INT (pr, 1)); + transform_t *transform = rua_transform_get (res, P_ULONG (pr, 0)); R_PACKED (pr, pr_vec4_t) = Transform_Right (transform); } @@ -412,8 +417,7 @@ static void bi_Transform_Up (progs_t *pr, void *_res) { rua_scene_resources_t *res = _res; - rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); - transform_t *transform = rua_transform_get (pr, scene, P_INT (pr, 1)); + transform_t *transform = rua_transform_get (res, P_ULONG (pr, 0)); R_PACKED (pr, pr_vec4_t) = Transform_Up (transform); } @@ -421,44 +425,43 @@ bi_Transform_Up (progs_t *pr, void *_res) #define P(a, s) { .size = (s), .alignment = BITOP_LOG2 (a), } #define bi(x,np,params...) {#x, bi_##x, -1, np, {params}} static builtin_t builtins[] = { - bi(Scene_NewScene, 0), - bi(Scene_DeleteScene, 1, p(ptr)), - bi(Scene_CreateEntity, 1, p(ptr)), - bi(Scene_DestroyEntity, 2, p(ptr), p(ptr)), + bi(Scene_NewScene, 0), + bi(Scene_DeleteScene, 1, p(ulong)), + bi(Scene_CreateEntity, 1, p(ulong)), + bi(Scene_DestroyEntity, 1, p(ulong)), - bi(Entity_GetTransform, 2, p(ptr), p(ptr)), + bi(Entity_GetTransform, 1, p(ulong)), - bi(Transform_ChildCount, 2, p(ptr), p(ptr)), - bi(Transform_GetChild, 3, p(ptr), p(ptr), p(int)), - bi(Transform_SetParent, 3, p(ptr), p(ptr), p(ptr)), - bi(Transform_GetParent, 2, p(ptr), p(ptr)), + bi(Transform_ChildCount, 1, p(ulong)), + bi(Transform_GetChild, 2, p(ulong), p(int)), + bi(Transform_SetParent, 2, p(ulong), p(ulong)), + bi(Transform_GetParent, 1, p(ulong)), - bi(Transform_SetTag, 3, p(ptr), p(ptr), p(uint)), - bi(Transform_GetTag, 2, p(ptr), p(ptr)), + bi(Transform_SetTag, 2, p(ulong), p(uint)), + bi(Transform_GetTag, 1, p(ulong)), - bi(Transform_GetLocalMatrix, 2, p(ptr), p(ptr)), - bi(Transform_GetLocalInverse, 2, p(ptr), p(ptr)), - bi(Transform_GetWorldMatrix, 2, p(ptr), p(ptr)), - bi(Transform_GetWorldInverse, 2, p(ptr), p(ptr)), + bi(Transform_GetLocalMatrix, 1, p(ulong)), + bi(Transform_GetLocalInverse, 1, p(ulong)), + bi(Transform_GetWorldMatrix, 1, p(ulong)), + bi(Transform_GetWorldInverse, 1, p(ulong)), - bi(Transform_SetLocalPosition, 3, p(ptr), p(ptr), p(vec4)), - bi(Transform_GetLocalPosition, 2, p(ptr), p(ptr)), - bi(Transform_SetLocalRotation, 3, p(ptr), p(ptr), p(vec4)), - bi(Transform_GetLocalRotation, 2, p(ptr), p(ptr)), - bi(Transform_SetLocalScale, 3, p(ptr), p(ptr), p(vec4)), - bi(Transform_GetLocalScale, 2, p(ptr), p(ptr)), + bi(Transform_SetLocalPosition, 2, p(ulong), p(vec4)), + bi(Transform_GetLocalPosition, 1, p(ulong)), + bi(Transform_SetLocalRotation, 2, p(ulong), p(vec4)), + bi(Transform_GetLocalRotation, 1, p(ulong)), + bi(Transform_SetLocalScale, 2, p(ulong), p(vec4)), + bi(Transform_GetLocalScale, 1, p(ulong)), - bi(Transform_SetWorldPosition, 3, p(ptr), p(ptr), p(vec4)), - bi(Transform_GetWorldPosition, 2, p(ptr), p(ptr)), - bi(Transform_SetWorldRotation, 3, p(ptr), p(ptr), p(vec4)), - bi(Transform_GetWorldRotation, 2, p(ptr), p(ptr)), - bi(Transform_GetWorldScale, 2, p(ptr), p(ptr)), + bi(Transform_SetWorldPosition, 2, p(ulong), p(vec4)), + bi(Transform_GetWorldPosition, 1, p(ulong)), + bi(Transform_SetWorldRotation, 2, p(ulong), p(vec4)), + bi(Transform_GetWorldRotation, 1, p(ulong)), + bi(Transform_GetWorldScale, 1, p(ulong)), - bi(Transform_SetLocalTransform, 5, p(ptr), p(ptr), - p(vec4), p(vec4), p(vec4)), - bi(Transform_Forward, 2, p(ptr), p(ptr)), - bi(Transform_Right, 2, p(ptr), p(ptr)), - bi(Transform_Up, 2, p(ptr), p(ptr)), + bi(Transform_SetLocalTransform, 4, p(ulong), p(vec4), p(vec4), p(vec4)), + bi(Transform_Forward, 1, p(ulong)), + bi(Transform_Right, 1, p(ulong)), + bi(Transform_Up, 1, p(ulong)), {0} }; diff --git a/nq/include/sv_progs.h b/nq/include/sv_progs.h index 4a09f1c5a..3849adf07 100644 --- a/nq/include/sv_progs.h +++ b/nq/include/sv_progs.h @@ -186,13 +186,9 @@ extern progs_t sv_pr_state; #define SVstring(e,f) SVFIELD (e, f, string) #define SVfunc(e,f) SVFIELD (e, f, func) #define SVentity(e,f) SVFIELD (e, f, entity) -#define SVvector(e,f) (&SVFIELD (e, f, vector)) +#define SVvector(e,f) (&SVFIELD (e, f, float)) #define SVint(e,f) SVFIELD (e, f, int) -#if TYPECHECK_PROGS -#define SVdouble(e,f) E_DOUBLE (e, PR_AccessField (&sv_pr_state, #f, ev_##t, __FILE__, __LINE__)) -#else -#define SVdouble(e,f) E_DOUBLE (e, sv_fields.f) -#endif +#define SVdouble(e,f) SVFIELD (e, f, double) typedef struct edict_leaf_s { struct edict_leaf_s *next; diff --git a/nq/source/sv_pr_cmds.c b/nq/source/sv_pr_cmds.c index 9984d97ff..b133b0bf4 100644 --- a/nq/source/sv_pr_cmds.c +++ b/nq/source/sv_pr_cmds.c @@ -1139,7 +1139,7 @@ PF_WriteBytes (progs_t *pr, void *data) } } for (i = 0; i < argc; i++) { - p = argv[i]->float_var; + p = PR_PTR (float, &argv[i]); MSG_WriteByte (msg, p); } } diff --git a/qw/include/sv_progs.h b/qw/include/sv_progs.h index 701475b7e..47e6b1198 100644 --- a/qw/include/sv_progs.h +++ b/qw/include/sv_progs.h @@ -193,13 +193,9 @@ extern progs_t sv_pr_state; #define SVstring(e,f) SVFIELD (e, f, string) #define SVfunc(e,f) SVFIELD (e, f, func) #define SVentity(e,f) SVFIELD (e, f, entity) -#define SVvector(e,f) (&SVFIELD (e, f, vector)) +#define SVvector(e,f) (&SVFIELD (e, f, float)) #define SVint(e,f) SVFIELD (e, f, int) -#if TYPECHECK_PROGS -#define SVdouble(e,f) E_DOUBLE (e, PR_AccessField (&sv_pr_state, #f, ev_##t, __FILE__, __LINE__)) -#else -#define SVdouble(e,f) E_DOUBLE (e, sv_fields.f) -#endif +#define SVdouble(e,f) SVFIELD (e, f, double) typedef struct edict_leaf_s { struct edict_leaf_s *next; diff --git a/qw/source/sv_pr_cmds.c b/qw/source/sv_pr_cmds.c index 103b0a3a3..fe892ea7c 100644 --- a/qw/source/sv_pr_cmds.c +++ b/qw/source/sv_pr_cmds.c @@ -1130,7 +1130,7 @@ PF_WriteBytes (progs_t *pr, void *data) } } for (i = 0; i < argc; i++) { - p = argv[i]->float_var; + p = PR_PTR (float, argv[i]); buf[i] = p; } diff --git a/qw/source/sv_progs.c b/qw/source/sv_progs.c index 345efc945..23a9c4061 100644 --- a/qw/source/sv_progs.c +++ b/qw/source/sv_progs.c @@ -181,16 +181,16 @@ static void free_edict (progs_t *pr, edict_t *ent) { if (sv_old_entity_free) { - E_fld (ent, sv_fields.model).entity_var = 0; - E_fld (ent, sv_fields.takedamage).float_var = 0; - E_fld (ent, sv_fields.modelindex).float_var = 0; - E_fld (ent, sv_fields.colormap).float_var = 0; - E_fld (ent, sv_fields.skin).float_var = 0; - E_fld (ent, sv_fields.frame).float_var = 0; - E_fld (ent, sv_fields.nextthink).float_var = -1; - E_fld (ent, sv_fields.solid).float_var = 0; - memset (&E_fld (ent, sv_fields.origin).vector_var, 0, 3*sizeof (float)); - memset (&E_fld (ent, sv_fields.angles).vector_var, 0, 3*sizeof (float)); + E_STRING (ent, sv_fields.model) = 0; + E_FLOAT (ent, sv_fields.takedamage) = 0; + E_FLOAT (ent, sv_fields.modelindex) = 0; + E_FLOAT (ent, sv_fields.colormap) = 0; + E_FLOAT (ent, sv_fields.skin) = 0; + E_FLOAT (ent, sv_fields.frame) = 0; + E_FLOAT (ent, sv_fields.nextthink) = -1; + E_FLOAT (ent, sv_fields.solid) = 0; + VectorZero (E_VECTOR (ent, sv_fields.origin)); + VectorZero (E_VECTOR (ent, sv_fields.angles)); } else { ED_ClearEdict (pr, ent, 0); } diff --git a/ruamoko/qwaq/builtins/main.c b/ruamoko/qwaq/builtins/main.c index b4954a0bb..02e703822 100644 --- a/ruamoko/qwaq/builtins/main.c +++ b/ruamoko/qwaq/builtins/main.c @@ -149,6 +149,7 @@ init_qf (void) //Cvar_Set (developer, "1"); Memory_Init (Sys_Alloc (8 * 1024 * 1024), 8 * 1024 * 1024); + PR_Init_Cvars (); } static void @@ -208,7 +209,6 @@ create_progs (qwaq_thread_t *thread) pr->no_exec_limit = 1; pr->hashlink_freelist = &thread->hashlink_freelist; - PR_Init_Cvars (); pr_debug = 2; pr_boundscheck = 0; PR_Init (pr); diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index 2b3887ae1..b9534086e 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -205,6 +205,8 @@ typedef struct ex_value_s { unsigned uint_val; ///< unsigned int constant int16_t short_val; ///< short constant uint16_t ushort_val; ///< unsigned short constant +#define VEC_TYPE(type_name, base_type) pr_##type_name##_t type_name##_val; +#include "tools/qfcc/include/vec_types.h" } v; } ex_value_t; @@ -256,6 +258,17 @@ typedef struct { struct type_s *type; ///< result type } ex_horizontal_t; +//NOTE always operates on vec4 or dvec4, so needs a suitable destination and +//care must be taken when working with smaller source operands (check aligmnet +//and adjust swizzle operation as needed) +typedef struct { + struct expr_s *src; ///< source expression + unsigned source[4]; ///< src component indices + unsigned neg; ///< bitmask of dst components to negate + unsigned zero; ///< bitmask of dst components to 0 + struct type_s *type; ///< result type +} ex_swizzle_t; + #define POINTER_VAL(p) (((p).def ? (p).def->offset : 0) + (p).val) typedef struct expr_s { @@ -291,6 +304,7 @@ typedef struct expr_s { ex_with_t with; ///< with expr param struct type_s *nil; ///< type for nil if known ex_horizontal_t hop; ///< horizontal vector operation + ex_swizzle_t swizzle; ///< vector swizzle operation } e; } expr_t; @@ -309,7 +323,6 @@ expr_t *type_mismatch (expr_t *e1, expr_t *e2, int op); expr_t *param_mismatch (expr_t *e, int param, const char *fn, struct type_s *t1, struct type_s *t2); -expr_t *cast_error (expr_t *e, struct type_s *t1, struct type_s *t2); expr_t *test_error (expr_t *e, struct type_s *t); extern expr_t *local_expr; @@ -479,6 +492,8 @@ expr_t *new_unary_expr (int op, expr_t *e1); */ expr_t *new_horizontal_expr (int op, expr_t *vec, struct type_s *type); +expr_t *new_swizzle_expr (expr_t *src, const char *swizzle); + /** Create a new def reference (non-temporary variable) expression node. \return The new def reference expression node (::def_t). @@ -632,6 +647,9 @@ int expr_int (expr_t *e) __attribute__((pure)); expr_t *new_uint_expr (unsigned uint_val); unsigned expr_uint (expr_t *e) __attribute__((pure)); +expr_t *new_long_expr (pr_long_t long_val); +expr_t *new_ulong_expr (pr_ulong_t ulong_val); + /** Create a new short constant expression node. \param short_val The short constant being represented. @@ -640,6 +658,7 @@ unsigned expr_uint (expr_t *e) __attribute__((pure)); */ expr_t *new_short_expr (short short_val); short expr_short (expr_t *e) __attribute__((pure)); +unsigned short expr_ushort (expr_t *e) __attribute__((pure)); int expr_integral (expr_t *e) __attribute__((pure)); @@ -759,8 +778,6 @@ expr_t *new_param_expr (struct type_s *type, int num); */ void convert_name (expr_t *e); -expr_t *convert_vector (expr_t *e); - expr_t *append_expr (expr_t *block, expr_t *e); expr_t *prepend_expr (expr_t *block, expr_t *e); @@ -768,10 +785,6 @@ expr_t *reverse_expr_list (expr_t *e); void print_expr (expr_t *e); void dump_dot_expr (void *e, const char *filename); -void convert_int (expr_t *e); -void convert_short (expr_t *e); -void convert_short_int (expr_t *e); -void convert_double (expr_t *e); expr_t *convert_nil (expr_t *e, struct type_s *t); expr_t *test_expr (expr_t *e); diff --git a/tools/qfcc/include/expr_names.h b/tools/qfcc/include/expr_names.h index 05d1f197a..8c6db70b6 100644 --- a/tools/qfcc/include/expr_names.h +++ b/tools/qfcc/include/expr_names.h @@ -63,5 +63,6 @@ EX_EXPR(adjstk) ///< stack adjust expression (::ex_adjstk_t) EX_EXPR(with) ///< with expression (::ex_with_t) EX_EXPR(args) ///< @args marker in parameter list. no data EX_EXPR(horizontal) ///< horizontal vector operation (::ex_horzontal_t) +EX_EXPR(swizzle) ///< vector swizzle operation (::ex_swizzle_t) ///@} diff --git a/tools/qfcc/include/obj_file.h b/tools/qfcc/include/obj_file.h index e93c3013a..d1bc0a268 100644 --- a/tools/qfcc/include/obj_file.h +++ b/tools/qfcc/include/obj_file.h @@ -308,7 +308,7 @@ enum { \hideinitializer */ -#define QFO_var(q, s, t, o) ((q)->spaces[s].data[o].t##_var) +#define QFO_var(q, s, t, o) (*(pr_##t##_t *) &(q)->spaces[s].data[o]) /** Access a double variable in the object file. Can be assigned to. diff --git a/tools/qfcc/include/qfcc.h b/tools/qfcc/include/qfcc.h index b678cc5a4..a6384c91c 100644 --- a/tools/qfcc/include/qfcc.h +++ b/tools/qfcc/include/qfcc.h @@ -97,16 +97,17 @@ typedef struct pr_info_s { extern pr_info_t pr; #define GETSTR(s) (pr.strings->strings + (s)) -#define D_var(t, d) ((d)->space->data[(d)->offset].t##_var) -#define D_DOUBLE(d) (*(double *) ((d)->space->data + (d)->offset)) +#define D_PACKED(t,d) (*(t *) &(d)->space->data[(d)->offset]) +#define D_var(t, d) D_PACKED (pr_##t##_t, d) +#define D_DOUBLE(d) D_var (double, d) #define D_FLOAT(d) D_var (float, d) #define D_INT(d) D_var (int, d) -#define D_VECTOR(d) (&D_var (vector, d)) -#define D_QUAT(d) (&D_var (quat, d)) +#define D_VECTOR(d) (&D_var (float, d)) +#define D_QUAT(d) (&D_var (float, d)) #define D_STRING(d) D_var (string, d) #define D_GETSTR(d) GETSTR (D_STRING (d)) #define D_FUNCTION(d) D_var (func, d) -#define D_POINTER(t,d) ((t *)((d)->space->data + (d)->offset)) +#define D_POINTER(t,d) (&D_PACKED (t, d)) #define D_STRUCT(t,d) (*D_POINTER (t, d)) #define G_POINTER(s,t,o) ((t *)((s)->data + o)) diff --git a/tools/qfcc/include/type.h b/tools/qfcc/include/type.h index 63fb194e3..6dde9d55b 100644 --- a/tools/qfcc/include/type.h +++ b/tools/qfcc/include/type.h @@ -160,12 +160,45 @@ type_t *find_type (type_t *new); void new_typedef (const char *name, type_t *type); type_t *field_type (type_t *aux); type_t *pointer_type (type_t *aux); +type_t *vector_type (const type_t *ele_type, int width) __attribute__((pure)); +type_t *base_type (const type_t *vec_type) __attribute__((pure)); + +/** Return an integral type of same size as the provided type. + + Any 32-bit type will produce type_int (or one of ivec2, ivec3 or ivec4). + Any 64-bit type will produce type_long (lor one of lvec2, lvec3, or lvec4). + + Both type_width() and type_size() of the returned type will match the + provided type. + + \param base Type on which the return type will be based. + \return Matching integral type (int, long, or a vector form), or + null if no such match can be made. +*/ +type_t *int_type (const type_t *base) __attribute__((pure)); + +/** Return a floating point type of same size as the provided type. + + Any 32-bit type will produce type_float (or one of vec2, vec3 or vec4). + Any 64-bit type will produce type_double (lor one of dvec2, dvec3, or + dvec4). + + Both type_width() and type_size() of the returned type will match the + provided type. + + \param base Type on which the return type will be based. + \return Matching floating point type (float, double, or a vector + form), or null if no such match can be made. +*/ +type_t *float_type (const type_t *base) __attribute__((pure)); + type_t *array_type (type_t *aux, int size); type_t *based_array_type (type_t *aux, int base, int top); type_t *alias_type (type_t *type, type_t *alias_chain, const char *name); const type_t *unalias_type (const type_t *type) __attribute__((pure)); const type_t *dereference_type (const type_t *type) __attribute__((pure)); void print_type_str (struct dstring_s *str, const type_t *type); +const char *get_type_string (const type_t *type); void print_type (const type_t *type); void dump_dot_type (void *t, const char *filename); const char *encode_params (const type_t *type); @@ -186,6 +219,7 @@ int is_array (const type_t *type) __attribute__((pure)); int is_structural (const type_t *type) __attribute__((pure)); int type_compatible (const type_t *dst, const type_t *src) __attribute__((pure)); int type_assignable (const type_t *dst, const type_t *src); +int type_promotes (const type_t *dst, const type_t *src) __attribute__((pure)); int type_same (const type_t *dst, const type_t *src) __attribute__((pure)); int type_size (const type_t *type) __attribute__((pure)); int type_width (const type_t *type) __attribute__((pure)); @@ -196,5 +230,7 @@ void chain_initial_types (void); void clear_typedefs (void); extern type_t *ev_types[]; +extern int type_cast_map[]; +#define TYPE_CAST_CODE(from, to, width) (((width) << 6) | ((from) << 3) | (to)) #endif//__type_h diff --git a/tools/qfcc/include/value.h b/tools/qfcc/include/value.h index 21e10f43d..e8eb5a3a7 100644 --- a/tools/qfcc/include/value.h +++ b/tools/qfcc/include/value.h @@ -40,6 +40,7 @@ struct def_s; struct ex_value_s; struct tempop_s; struct type_s; +struct pr_type_s; struct ex_value_s *new_string_val (const char *string_val); struct ex_value_s *new_double_val (double double_val); @@ -55,8 +56,15 @@ struct ex_value_s *new_pointer_val (int val, struct type_s *type, struct ex_value_s *new_quaternion_val (const float *quaternion_val); struct ex_value_s *new_int_val (int int_val); struct ex_value_s *new_uint_val (int uint_val); +struct ex_value_s *new_long_val (pr_long_t long_val); +struct ex_value_s *new_ulong_val (pr_ulong_t ulong_val); struct ex_value_s *new_short_val (short short_val); struct ex_value_s *new_nil_val (struct type_s *type); +struct ex_value_s *new_type_value (const struct type_s *type, + const struct pr_type_s *data); +void value_store (pr_type_t *dst, const struct type_s *dstType, + const struct expr_s *src); +const char *get_value_string (const struct ex_value_s *value); struct ex_value_s *convert_value (struct ex_value_s *value, struct type_s *type); diff --git a/tools/qfcc/source/Makemodule.am b/tools/qfcc/source/Makemodule.am index d7d85e597..a070fad67 100644 --- a/tools/qfcc/source/Makemodule.am +++ b/tools/qfcc/source/Makemodule.am @@ -28,8 +28,10 @@ qfcc_SOURCES = \ tools/qfcc/source/expr_assign.c \ tools/qfcc/source/expr_binary.c \ tools/qfcc/source/expr_bool.c \ + tools/qfcc/source/expr_cast.c \ tools/qfcc/source/expr_compound.c \ tools/qfcc/source/expr_obj.c \ + tools/qfcc/source/expr_vector.c \ tools/qfcc/source/flow.c \ tools/qfcc/source/function.c \ tools/qfcc/source/grab.c \ diff --git a/tools/qfcc/source/constfold.c b/tools/qfcc/source/constfold.c index 6b01bc7f4..6f6287f43 100644 --- a/tools/qfcc/source/constfold.c +++ b/tools/qfcc/source/constfold.c @@ -55,13 +55,6 @@ typedef expr_t *(*operation_t) (int op, expr_t *e, expr_t *e1, expr_t *e2); typedef expr_t *(*unaryop_t) (int op, expr_t *e, expr_t *e1); -static expr_t * -cf_cast_expr (type_t *type, expr_t *e) -{ - e = cast_expr (type, e); - return e; -} - static __attribute__((pure)) int valid_op (int op, int *valid_ops) { @@ -162,33 +155,10 @@ convert_to_float (expr_t *e) if (is_float(get_type (e))) return e; - switch (e->type) { - case ex_value: - switch (e->e.value->lltype) { - case ev_int: - convert_int (e); - return e; - case ev_short: - convert_short (e); - return e; - case ev_double: - convert_double (e); - return e; - default: - internal_error (e, "bad conversion to float: %d", - e->e.value->lltype); - } - break; - case ex_symbol: - case ex_expr: - case ex_uexpr: - case ex_temp: - case ex_block: - e = cf_cast_expr (&type_float, e); - return e; - default: - internal_error (e, 0); - } + expr_t *n = cast_expr (&type_float, e); + n->file = e->file; + n->line = e->line; + return n; } static expr_t * @@ -197,32 +167,10 @@ convert_to_double (expr_t *e) if (is_double(get_type (e))) return e; - switch (e->type) { - case ex_value: - switch (e->e.value->lltype) { - case ev_int: - e->e.value = new_double_val (expr_int (e)); - return e; - case ev_short: - e->e.value = new_double_val (expr_short (e)); - return e; - case ev_float: - e->e.value = new_double_val (expr_float (e)); - return e; - default: - internal_error (e, 0); - } - break; - case ex_symbol: - case ex_expr: - case ex_uexpr: - case ex_temp: - case ex_block: - e = cf_cast_expr (&type_float, e); - return e; - default: - internal_error (e, 0); - } + expr_t *n = cast_expr (&type_double, e); + n->file = e->file; + n->line = e->line; + return n; } static expr_t * @@ -634,7 +582,7 @@ do_op_pointer (int op, expr_t *e, expr_t *e1, expr_t *e2) if (op != '.' && extract_type (e1) != extract_type (e2)) return type_mismatch (e1, e2, op); if (op == '.' && is_uint(get_type (e2))) - e->e.expr.e2 = cf_cast_expr (&type_int, e2); + e->e.expr.e2 = cast_expr (&type_int, e2); return e; } diff --git a/tools/qfcc/source/def.c b/tools/qfcc/source/def.c index 7a06a1730..bab482a9f 100644 --- a/tools/qfcc/source/def.c +++ b/tools/qfcc/source/def.c @@ -180,8 +180,6 @@ alias_def (def_t *def, type_t *type, int offset) 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 (type == def->type) - return def; for (alias = def->alias_defs; alias; alias = alias->next) { if (alias->type == type && alias->offset == offset) return alias; @@ -380,12 +378,20 @@ init_elements (struct def_s *def, expr_t *eles) reloc_def_op (c->e.labelref.label, &dummy); continue; } else if (c->type == ex_value) { - if (c->e.value->lltype == ev_int && is_float (element->type)) { - convert_int (c); - } - if (is_double (get_type (c)) && is_float (element->type) - && c->implicit) { - convert_double (c); + type_t *ctype = get_type (c); + if (ctype != element->type + && type_assignable (element->type, ctype)) { + if (!c->implicit + && !type_promotes (element->type, ctype)) { + warning (c, "initialization of %s with %s" + " (use a cast)\n)", + get_type_string (element->type), + get_type_string (ctype)); + } + expr_t *n = cast_expr (element->type, c); + n->line = c->line; + n->file = c->line; + c = n; } if (get_type (c) != element->type) { error (c, "type mismatch in initializer"); @@ -401,7 +407,7 @@ init_elements (struct def_s *def, expr_t *eles) internal_error (c, "bogus expression type in init_elements()"); } if (c->e.value->lltype == ev_string) { - EMIT_STRING (def->space, g->string_var, + EMIT_STRING (def->space, *(pr_string_t *) g, c->e.value->v.string_val); } else { memcpy (g, &c->e.value->v, type_size (get_type (c)) * 4); @@ -596,7 +602,8 @@ initialize_def (symbol_t *sym, expr_t *init, defspace_t *space, } init_type = get_type (init); if (!type_assignable (sym->type, init_type)) { - error (init, "type mismatch in initializer"); + error (init, "type mismatch in initializer: %s = %s", + get_type_string (sym->type), get_type_string (init_type)); return; } if (storage == sc_local && local_expr) { @@ -636,7 +643,7 @@ initialize_def (symbol_t *sym, expr_t *init, defspace_t *space, EMIT_STRING (sym->s.def->space, D_STRING (sym->s.def), v->v.string_val); } else { - memcpy (D_POINTER (void, sym->s.def), &v->v, + memcpy (D_POINTER (pr_type_t, sym->s.def), &v->v, type_size (sym->type) * sizeof (pr_type_t)); } } diff --git a/tools/qfcc/source/defspace.c b/tools/qfcc/source/defspace.c index a704b45a3..e1dc3b72a 100644 --- a/tools/qfcc/source/defspace.c +++ b/tools/qfcc/source/defspace.c @@ -173,7 +173,8 @@ defspace_alloc_aligned_loc (defspace_t *space, int size, int alignment) // exact fit, so just shrink the block or remove it if there is no // padding (any padding remains free) if (size + pad == loc->size) { - if (!pad) { + loc->size -= size; + if (!loc->size) { *l = loc->next; del_locref (loc); } diff --git a/tools/qfcc/source/dot_expr.c b/tools/qfcc/source/dot_expr.c index 29c5ac319..664796915 100644 --- a/tools/qfcc/source/dot_expr.c +++ b/tools/qfcc/source/dot_expr.c @@ -49,9 +49,10 @@ #include "tools/qfcc/include/expr.h" #include "tools/qfcc/include/method.h" +#include "tools/qfcc/include/strpool.h" #include "tools/qfcc/include/symtab.h" #include "tools/qfcc/include/type.h" -#include "tools/qfcc/include/strpool.h" +#include "tools/qfcc/include/value.h" #include "tools/qfcc/source/qc-parse.h" @@ -461,39 +462,9 @@ print_vector (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) { int indent = level * 2 + 2; - if (is_vector(e->e.vector.type)) { - expr_t *x = e->e.vector.list; - expr_t *y = x->next; - expr_t *z = y->next; - _print_expr (dstr, x, level, id, next); - _print_expr (dstr, y, level, id, next); - _print_expr (dstr, z, level, id, next); - dasprintf (dstr, "%*se_%p -> \"e_%p\";\n", indent, "", e, x); - dasprintf (dstr, "%*se_%p -> \"e_%p\";\n", indent, "", e, y); - dasprintf (dstr, "%*se_%p -> \"e_%p\";\n", indent, "", e, z); - } - if (is_quaternion(e->e.vector.type)) { - if (e->e.vector.list->next->next) { - expr_t *x = e->e.vector.list; - expr_t *y = x->next; - expr_t *z = y->next; - expr_t *w = z->next; - _print_expr (dstr, x, level, id, next); - _print_expr (dstr, y, level, id, next); - _print_expr (dstr, z, level, id, next); - _print_expr (dstr, w, level, id, next); - dasprintf (dstr, "%*se_%p -> \"e_%p\";\n", indent, "", e, x); - dasprintf (dstr, "%*se_%p -> \"e_%p\";\n", indent, "", e, y); - dasprintf (dstr, "%*se_%p -> \"e_%p\";\n", indent, "", e, z); - dasprintf (dstr, "%*se_%p -> \"e_%p\";\n", indent, "", e, w); - } else { - expr_t *v = e->e.vector.list; - expr_t *s = v->next; - _print_expr (dstr, v, level, id, next); - _print_expr (dstr, s, level, id, next); - dasprintf (dstr, "%*se_%p -> \"e_%p\";\n", indent, "", e, v); - dasprintf (dstr, "%*se_%p -> \"e_%p\";\n", indent, "", e, s); - } + for (expr_t *ele = e->e.vector.list; ele; ele = ele->next) { + _print_expr (dstr, ele, level, id, next); + dasprintf (dstr, "%*se_%p -> \"e_%p\";\n", indent, "", e, ele); } dasprintf (dstr, "%*se_%p [label=\"vector %d\"];\n", indent, "", e, e->line); @@ -521,96 +492,11 @@ static void print_value (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) { int indent = level * 2 + 2; - type_t *type; const char *label = "?!?"; - static dstring_t *type_str; - if (!type_str) { - type_str = dstring_newstr (); - } - - switch (e->e.value->lltype) { - case ev_string: - label = va (0, "\\\"%s\\\"", - quote_string (e->e.value->v.string_val)); - break; - case ev_double: - label = va (0, "f %g", e->e.value->v.double_val); - break; - case ev_float: - label = va (0, "f %g", e->e.value->v.float_val); - break; - case ev_vector: - label = va (0, "'%g %g %g'", - e->e.value->v.vector_val[0], - e->e.value->v.vector_val[1], - e->e.value->v.vector_val[2]); - break; - case ev_quaternion: - label = va (0, "'%g %g %g %g'", - e->e.value->v.quaternion_val[0], - e->e.value->v.quaternion_val[1], - e->e.value->v.quaternion_val[2], - e->e.value->v.quaternion_val[3]); - break; - case ev_ptr: - type = e->e.value->v.pointer.type; - dstring_clearstr(type_str); - if (type) { - print_type_str (type_str, type); - } - if (e->e.value->v.pointer.def) - label = va (0, "(*%s)[%d]<%s>", - type ? type_str->str : "???", - e->e.value->v.pointer.val, - e->e.value->v.pointer.def->name); - else - label = va (0, "(*%s)[%d]", - type ? type_str->str : "???", - e->e.value->v.pointer.val); - break; - case ev_field: - if (e->e.value->v.pointer.def) { - int offset = e->e.value->v.pointer.val; - offset += e->e.value->v.pointer.def->offset; - label = va (0, "field %d", offset); - } else { - label = va (0, "field %d", e->e.value->v.pointer.val); - } - break; - case ev_entity: - label = va (0, "ent %d", e->e.value->v.int_val); - break; - case ev_func: - label = va (0, "func %d", e->e.value->v.int_val); - break; - case ev_int: - label = va (0, "i %d", e->e.value->v.int_val); - break; - case ev_uint: - label = va (0, "u %u", e->e.value->v.uint_val); - break; - case ev_long: - label = va (0, "i %"PRIi64, e->e.value->v.long_val); - break; - case ev_ulong: - label = va (0, "u %"PRIu64, e->e.value->v.ulong_val); - break; - case ev_short: - label = va (0, "s %d", e->e.value->v.short_val); - break; - case ev_ushort: - label = va (0, "us %d", e->e.value->v.ushort_val); - break; - case ev_void: - label = ""; - break; - case ev_invalid: - label = ""; - break; - case ev_type_count: - label = ""; - break; + label = get_value_string (e->e.value); + if (is_string (e->e.value->type)) { + label = quote_string (html_string (label)); } dasprintf (dstr, "%*se_%p [label=\"%s\\n%d\"];\n", indent, "", e, label, e->line); @@ -669,6 +555,41 @@ print_args (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) e->line); } +static void +print_horizontal (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) +{ + int indent = level * 2 + 2; + + _print_expr (dstr, e->e.hop.vec, level, id, next); + dasprintf (dstr, "%*se_%p -> \"e_%p\";\n", indent, "", e, e->e.hop.vec); + dasprintf (dstr, "%*se_%p [label=\"hop %s\\n%d\"];\n", indent, "", e, + get_op_string (e->e.hop.op), e->line); +} + +static void +print_swizzle (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) +{ + static char swizzle_components[] = "xyzw"; + int indent = level * 2 + 2; + ex_swizzle_t swiz = e->e.swizzle; + const char *swizzle = ""; + + for (int i = 0; i < 4; i++) { + if (swiz.zero & (1 << i)) { + swizzle = va (0, "%s0", swizzle); + } else { + swizzle = va (0, "%s%s%c", swizzle, + swiz.neg & (1 << i) ? "-" : "", + swizzle_components[swiz.source[i]]); + } + } + + _print_expr (dstr, swiz.src, level, id, next); + dasprintf (dstr, "%*se_%p -> \"e_%p\";\n", indent, "", e, swiz.src); + dasprintf (dstr, "%*se_%p [label=\"swizzle %s\\n%d\"];\n", indent, "", e, + swizzle, e->line); +} + static void _print_expr (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) { @@ -698,6 +619,8 @@ _print_expr (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) [ex_adjstk] = print_adjstk, [ex_with] = print_with, [ex_args] = print_args, + [ex_horizontal] = print_horizontal, + [ex_swizzle] = print_swizzle, }; int indent = level * 2 + 2; diff --git a/tools/qfcc/source/dump_globals.c b/tools/qfcc/source/dump_globals.c index d95c772cc..77ae2a2bc 100644 --- a/tools/qfcc/source/dump_globals.c +++ b/tools/qfcc/source/dump_globals.c @@ -327,7 +327,7 @@ qfo_globals (qfo_t *qfo) QFO_TYPESTR (qfo, def->type)); if (!(def->flags & QFOD_EXTERNAL) && qfo->spaces[space].data) printf (" %d", - qfo->spaces[space].data[def->offset].int_var); + qfo->spaces[space].data[def->offset].value); puts (""); } } diff --git a/tools/qfcc/source/emit.c b/tools/qfcc/source/emit.c index 30b2d1b4b..d5615a794 100644 --- a/tools/qfcc/source/emit.c +++ b/tools/qfcc/source/emit.c @@ -179,6 +179,74 @@ use_tempop (operand_t *op, expr_t *expr) bug (expr, "temp users went negative: %s", operand_string (op)); } +static def_t * +cover_def_32 (def_t *def, int *adj) +{ + int offset = def->offset; + def_t *cover = def; + + if (def->alias) { + offset += def->alias->offset; + } + *adj = offset & 3; + if (offset & 3) { + if (def->alias) { + cover = alias_def (def->alias, def->type, def->offset); + } else { + cover = alias_def (def, def->type, 0); + } + cover->offset -= offset & 3; + } + return cover; +} + +static def_t * +cover_def_64 (def_t *def, int *adj) +{ + int offset = def->offset; + def_t *cover = def; + + if (def->alias) { + offset += def->alias->offset; + } + if (offset & 1) { + internal_error (0, "misaligned 64-bit swizzle source"); + } + *adj = (offset & 6) >> 1; + if (offset & 6) { + if (def->alias) { + cover = alias_def (def->alias, def->type, def->offset); + } else { + cover = alias_def (def, def->type, 0); + } + cover->offset -= offset & 6; + } + return cover; +} + +static def_t * +cover_def (def_t *def, int *adj) +{ + if (type_size (base_type (def->type)) == 1) { + return cover_def_32 (def, adj); + } else { + return cover_def_64 (def, adj); + } +} + +static void +adjust_swizzle (def_t *def, int adj) +{ + pr_ushort_t swiz = def->offset; + for (int i = 0; i < 8; i += 2) { + pr_ushort_t mask = 3 << i; + pr_ushort_t ind = swiz & mask; + swiz &= ~mask; + swiz |= (ind + (adj << i)) & mask; + } + def->offset = swiz; +} + static void emit_statement (statement_t *statement) { @@ -202,12 +270,28 @@ emit_statement (statement_t *statement) op_b = statement->opb; op_c = statement->opc; } + def_a = get_operand_def (statement->expr, op_a); use_tempop (op_a, statement->expr); def_b = get_operand_def (statement->expr, op_b); use_tempop (op_b, statement->expr); def_c = get_operand_def (statement->expr, op_c); use_tempop (op_c, statement->expr); + + if (strcmp (opcode, "swizzle") == 0) { + op_c->type = float_type (op_c->type); + op_a->type = float_type (op_a->type); + if (!op_c->type || !op_a->type) { + internal_error (statement->expr, "invalid types in swizzle"); + } + if (op_a->width < 4) { + int adj; + def_a = cover_def (def_a, &adj); + adjust_swizzle (def_b, adj); + op_a->width = 4; + } + } + inst = opcode_find (opcode, op_a, op_b, op_c); if (!inst) { diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 746a94f03..595eb1e87 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -42,7 +42,6 @@ #include "QF/alloc.h" #include "QF/dstring.h" #include "QF/mathlib.h" -#include "QF/sys.h" #include "QF/va.h" #include "tools/qfcc/include/qfcc.h" @@ -127,88 +126,6 @@ convert: e->e = new->e; } -expr_t * -convert_vector (expr_t *e) -{ - float val[4]; - - if (e->type != ex_vector) - return e; - if (is_vector(e->e.vector.type)) { - // guaranteed to have three elements - expr_t *x = e->e.vector.list; - expr_t *y = x->next; - expr_t *z = y->next; - x = fold_constants (cast_expr (&type_float, x)); - y = fold_constants (cast_expr (&type_float, y)); - z = fold_constants (cast_expr (&type_float, z)); - if (is_constant (x) && is_constant (y) && is_constant (z)) { - val[0] = expr_float(x); - val[1] = expr_float(y); - val[2] = expr_float(z); - return new_vector_expr (val); - } - // at least one of x, y, z is not constant, so rebuild the - // list incase any of them are new expressions - z->next = 0; - y->next = z; - x->next = y; - e->e.vector.list = x; - return e; - } - if (is_quaternion(e->e.vector.type)) { - // guaranteed to have two or four elements - if (e->e.vector.list->next->next) { - // four vals: x, y, z, w - expr_t *x = e->e.vector.list; - expr_t *y = x->next; - expr_t *z = y->next; - expr_t *w = z->next; - x = fold_constants (cast_expr (&type_float, x)); - y = fold_constants (cast_expr (&type_float, y)); - z = fold_constants (cast_expr (&type_float, z)); - w = fold_constants (cast_expr (&type_float, w)); - if (is_constant (x) && is_constant (y) && is_constant (z) - && is_constant (w)) { - val[0] = expr_float(x); - val[1] = expr_float(y); - val[2] = expr_float(z); - val[3] = expr_float(w); - return new_quaternion_expr (val); - } - // at least one of x, y, z, w is not constant, so rebuild the - // list incase any of them are new expressions - w->next = 0; - z->next = w; - y->next = z; - x->next = y; - e->e.vector.list = x; - return e; - } else { - // v, s - expr_t *v = e->e.vector.list; - expr_t *s = v->next; - - v = convert_vector (v); - s = fold_constants (cast_expr (&type_float, s)); - if (is_constant (v) && is_constant (s)) { - memcpy (val, expr_vector (v), 3 * sizeof (float)); - val[3] = expr_float (s); - return new_quaternion_expr (val); - } - // Either v or s is not constant, so can't convert to a quaternion - // constant. - // Rebuild the list in case v or s is a new expression - // the list will always be v, s - s->next = 0; - v->next = s; - e->e.vector.list = v; - return e; - } - } - internal_error (e, "bogus vector expression"); -} - type_t * get_type (expr_t *e) { @@ -278,6 +195,8 @@ get_type (expr_t *e) return &type_va_list; case ex_horizontal: return e->e.hop.type; + case ex_swizzle: + return e->e.swizzle.type; case ex_count: internal_error (e, "invalid expression"); } @@ -297,47 +216,17 @@ extract_type (expr_t *e) expr_t * type_mismatch (expr_t *e1, expr_t *e2, int op) { - dstring_t *t1 = dstring_newstr (); - dstring_t *t2 = dstring_newstr (); - - print_type_str (t1, get_type (e1)); - print_type_str (t2, get_type (e2)); - e1 = error (e1, "type mismatch: %s %s %s", - t1->str, get_op_string (op), t2->str); - dstring_delete (t1); - dstring_delete (t2); + get_type_string (get_type (e1)), get_op_string (op), + get_type_string (get_type (e2))); return e1; } expr_t * param_mismatch (expr_t *e, int param, const char *fn, type_t *t1, type_t *t2) { - dstring_t *s1 = dstring_newstr (); - dstring_t *s2 = dstring_newstr (); - - print_type_str (s1, t1); - print_type_str (s2, t2); - e = error (e, "type mismatch for parameter %d of %s: expected %s, got %s", - param, fn, s1->str, s2->str); - dstring_delete (s1); - dstring_delete (s2); - return e; -} - -expr_t * -cast_error (expr_t *e, type_t *t1, type_t *t2) -{ - dstring_t *s1 = dstring_newstr (); - dstring_t *s2 = dstring_newstr (); - - print_type_str (s1, t1); - print_type_str (s2, t2); - - e = error (e, "cannot cast from %s to %s", s1->str, s2->str); - dstring_delete (s1); - dstring_delete (s2); + param, fn, get_type_string (t1), get_type_string (t2)); return e; } @@ -435,7 +324,7 @@ copy_expr (expr_t *e) } if (e->e.block.result && !n->e.block.result) internal_error (e, "bogus block result?"); - break; + return n; case ex_expr: n = new_expr (); *n = *e; @@ -538,6 +427,11 @@ copy_expr (expr_t *e) *n = *e; e->e.hop.vec = copy_expr (e->e.hop.vec); return n; + case ex_swizzle: + n = new_expr (); + *n = *e; + e->e.swizzle.src = copy_expr (e->e.swizzle.src); + return n; case ex_count: break; } @@ -724,6 +618,74 @@ new_horizontal_expr (int op, expr_t *vec, type_t *type) return e; } +expr_t * +new_swizzle_expr (expr_t *src, const char *swizzle) +{ + type_t *src_type = get_type (src); + if (!src_type) { + return src; + } + int src_width = type_width (src_type); + // swizzle always generates a *vec4 + ex_swizzle_t swiz = {}; + +#define m(x) (1 << ((x) - 'a')) +#define v(x, mask) (((x) & 0x60) == 0x60 && (m(x) & (mask))) +#define vind(x) ((x) & 3) +#define cind(x) (-(((x) >> 3) ^ (x)) & 3) +#define tind(x) ((((~(x+1)>>2)&1) + x + 1) & 3) + const int color = m('r') | m('g') | m('b') | m('a'); + const int vector = m('x') | m('y') | m('z') | m('w'); + const int texture = m('s') | m('t') | m('p') | m('q'); + + int type_mask = 0; + int comp_count = 0; + + for (const char *s = swizzle; *s; s++) { + if (comp_count >= 4) { + return error (src, "too many components in swizzle"); + } + if (*s == '0') { + swiz.zero |= 1 << comp_count; + comp_count++; + } else if (*s == '-') { + swiz.neg |= 1 << comp_count; + } else { + int ind = 0; + int mask = 0; + if (v (*s, vector)) { + ind = vind (*s); + mask = 1; + } else if (v (*s, color)) { + ind = cind (*s); + mask = 2; + } else if (v (*s, texture)) { + ind = tind (*s); + mask = 4; + } + if (!mask) { + return error (src, "invalid component in swizzle"); + } + if (type_mask & ~mask) { + return error (src, "mixed components in swizzle"); + } + if (ind >= src_width) { + return error (src, "swizzle component out of bounds"); + } + type_mask |= mask; + swiz.source[comp_count++] = ind; + } + } + swiz.zero |= (0xf << comp_count) & 0xf; + swiz.src = new_alias_expr (vector_type (&type_float, src_width), src); + swiz.type = vector_type (base_type (src_type), 4); + + expr_t *expr = new_expr (); + expr->type = ex_swizzle; + expr->e.swizzle = swiz; + return expr; +} + expr_t * new_def_expr (def_t *def) { @@ -794,181 +756,85 @@ new_name_expr (const char *name) expr_t * new_string_expr (const char *string_val) { - expr_t *e = new_expr (); - e->type = ex_value; - e->e.value = new_string_val (string_val); - return e; + return new_value_expr (new_string_val (string_val)); } expr_t * new_double_expr (double double_val) { - expr_t *e = new_expr (); - e->type = ex_value; - e->e.value = new_double_val (double_val); - return e; + return new_value_expr (new_double_val (double_val)); } expr_t * new_float_expr (float float_val) { - expr_t *e = new_expr (); - e->type = ex_value; - e->e.value = new_float_val (float_val); - return e; + return new_value_expr (new_float_val (float_val)); } expr_t * new_vector_expr (const float *vector_val) { - expr_t *e = new_expr (); - e->type = ex_value; - e->e.value = new_vector_val (vector_val); - return e; -} - -expr_t * -new_vector_list (expr_t *e) -{ - expr_t *t; - int count; - type_t *type = &type_vector; - expr_t *vec; - - e = reverse_expr_list (e); // put the elements in the right order - for (t = e, count = 0; t; t = t->next) - count++; - switch (count) { - case 4: - type = &type_quaternion; - case 3: - // quaternion or vector. all expressions must be compatible with - // a float (ie, a scalar) - for (t = e; t; t = t->next) { - if (t->type == ex_error) { - return t; - } - if (!is_scalar (get_type (t))) { - return error (t, "invalid type for vector element"); - } - } - vec = new_expr (); - vec->type = ex_vector; - vec->e.vector.type = type; - vec->e.vector.list = e; - break; - case 2: - if (e->type == ex_error || e->next->type == ex_error) { - return e; - } - if (is_scalar (get_type (e)) && is_scalar (get_type (e->next))) { - // scalar, scalar - // expand [x, y] to [x, y, 0] - e->next->next = new_float_expr (0); - vec = new_expr (); - vec->type = ex_vector; - vec->e.vector.type = type; - vec->e.vector.list = e; - break; - } - // quaternion. either scalar, vector or vector, scalar - if (is_scalar (get_type (e)) - && is_vector (get_type (e->next))) { - // scalar, vector - // swap expressions - t = e; - e = e->next; - e->next = t; - t->next = 0; - } else if (is_vector (get_type (e)) - && is_scalar (get_type (e->next))) { - // vector, scalar - // do nothing - } else { - return error (t, "invalid types for vector elements"); - } - // v, s - vec = new_expr (); - vec->type = ex_vector; - vec->e.vector.type = &type_quaternion; - vec->e.vector.list = e; - break; - default: - return error (e, "invalid number of elements in vector exprssion"); - } - return vec; + return new_value_expr (new_vector_val (vector_val)); } expr_t * new_entity_expr (int entity_val) { - expr_t *e = new_expr (); - e->type = ex_value; - e->e.value = new_entity_val (entity_val); - return e; + return new_value_expr (new_entity_val (entity_val)); } expr_t * new_field_expr (int field_val, type_t *type, def_t *def) { - expr_t *e = new_expr (); - e->type = ex_value; - e->e.value = new_field_val (field_val, type, def); - return e; + return new_value_expr (new_field_val (field_val, type, def)); } expr_t * new_func_expr (int func_val, type_t *type) { - expr_t *e = new_expr (); - e->type = ex_value; - e->e.value = new_func_val (func_val, type); - return e; + return new_value_expr (new_func_val (func_val, type)); } expr_t * new_pointer_expr (int val, type_t *type, def_t *def) { - expr_t *e = new_expr (); - e->type = ex_value; - e->e.value = new_pointer_val (val, type, def, 0); - return e; + return new_value_expr (new_pointer_val (val, type, def, 0)); } expr_t * new_quaternion_expr (const float *quaternion_val) { - expr_t *e = new_expr (); - e->type = ex_value; - e->e.value = new_quaternion_val (quaternion_val); - return e; + return new_value_expr (new_quaternion_val (quaternion_val)); } expr_t * new_int_expr (int int_val) { - expr_t *e = new_expr (); - e->type = ex_value; - e->e.value = new_int_val (int_val); - return e; + return new_value_expr (new_int_val (int_val)); } expr_t * new_uint_expr (unsigned uint_val) { - expr_t *e = new_expr (); - e->type = ex_value; - e->e.value = new_uint_val (uint_val); - return e; + return new_value_expr (new_uint_val (uint_val)); +} + +expr_t * +new_long_expr (pr_long_t long_val) +{ + return new_value_expr (new_long_val (long_val)); +} + +expr_t * +new_ulong_expr (pr_ulong_t ulong_val) +{ + return new_value_expr (new_ulong_val (ulong_val)); } expr_t * new_short_expr (short short_val) { - expr_t *e = new_expr (); - e->type = ex_value; - e->e.value = new_short_val (short_val); - return e; + return new_value_expr (new_short_val (short_val)); } int @@ -1030,11 +896,9 @@ constant_expr (expr_t *e) } else { return e; } - new = new_expr (); - new->type = ex_value; + new = new_value_expr (value); new->line = e->line; new->file = e->file; - new->e.value = value; return new; } @@ -1300,6 +1164,22 @@ expr_short (expr_t *e) internal_error (e, "not a short constant"); } +unsigned short +expr_ushort (expr_t *e) +{ + if (e->type == ex_nil) { + return 0; + } + if (e->type == ex_value && e->e.value->lltype == ev_ushort) { + return e->e.value->v.ushort_val; + } + if (e->type == ex_symbol && e->e.symbol->sy_type == sy_const + && e->e.symbol->type->type == ev_ushort) { + return e->e.symbol->s.value->v.ushort_val; + } + internal_error (e, "not a ushort constant"); +} + int is_integral_val (expr_t *e) { @@ -1529,7 +1409,11 @@ get_struct_field (const type_t *t1, expr_t *e1, expr_t *e2) } field = symtab_lookup (strct, sym->name); if (!field && !is_entity(t1)) { - error (e2, "'%s' has no member named '%s'", t1->name + 4, sym->name); + const char *name = t1->name; + if (!strncmp (name, "tag ", 4)) { + name += 4; + } + error (e2, "'%s' has no member named '%s'", name, sym->name); e1->type = ex_error; } return field; @@ -1590,7 +1474,7 @@ field_expr (expr_t *e1, expr_t *e2) e1 = cast_expr (pointer_type (ivar->type), e1); return unary_expr ('.', e1); } - } else if (is_vector (t1) || is_quaternion (t1) || is_struct (t1)) { + } else if (is_nonscalar (t1) || is_struct (t1)) { symbol_t *field; field = get_struct_field (t1, e1, e2); @@ -1669,38 +1553,6 @@ convert_from_bool (expr_t *e, type_t *type) return e; } -void -convert_int (expr_t *e) -{ - float float_val = expr_int (e); - e->type = ex_value; - e->e.value = new_float_val (float_val); -} - -void -convert_short (expr_t *e) -{ - float float_val = expr_short (e); - e->type = ex_value; - e->e.value = new_float_val (float_val); -} - -void -convert_short_int (expr_t *e) -{ - float int_val = expr_short (e); - e->type = ex_value; - e->e.value = new_int_val (int_val); -} - -void -convert_double (expr_t *e) -{ - float float_val = expr_double (e); - e->type = ex_value; - e->e.value = new_float_val (float_val); -} - expr_t * convert_nil (expr_t *e, type_t *t) { @@ -1770,6 +1622,8 @@ has_function_call (expr_t *e) return has_function_call (e->e.retrn.ret_val); case ex_horizontal: return has_function_call (e->e.hop.vec); + case ex_swizzle: + return has_function_call (e->e.swizzle.src); case ex_error: case ex_state: case ex_label: @@ -1915,6 +1769,7 @@ unary_expr (int op, expr_t *e) case ex_alias: case ex_assign: case ex_horizontal: + case ex_swizzle: { expr_t *n = new_unary_expr (op, e); @@ -2008,6 +1863,7 @@ unary_expr (int op, expr_t *e) case ex_address: case ex_assign: case ex_horizontal: + case ex_swizzle: if (options.code.progsversion == PROG_VERSION) { return binary_expr (EQ, e, new_nil_expr ()); } else { @@ -2097,6 +1953,7 @@ unary_expr (int op, expr_t *e) case ex_alias: case ex_assign: case ex_horizontal: + case ex_swizzle: bitnot_expr: if (options.code.progsversion == PROG_ID_VERSION) { expr_t *n1 = new_int_expr (-1); @@ -2224,13 +2081,13 @@ build_function_call (expr_t *fexpr, const type_t *ftype, expr_t *params) convert_from_bool (e, get_type (e)); if (is_int_val (e) && options.code.progsversion == PROG_ID_VERSION) - convert_int (e); + e = cast_expr (&type_float, e); if (options.code.promote_float) { - if (is_float (get_type (e))) { + if (is_scalar (get_type (e)) && is_float (get_type (e))) { t = &type_double; } } else { - if (is_double (get_type (e))) { + if (is_scalar (get_type (e)) && is_double (get_type (e))) { if (!e->implicit) { warning (e, "passing double into ... function"); } @@ -2265,15 +2122,14 @@ build_function_call (expr_t *fexpr, const type_t *ftype, expr_t *params) // expression tree // That, or always use a temp, since it should get optimized out if (has_function_call (e)) { - expr_t *cast = cast_expr (arg_types[i], convert_vector (e)); + expr_t *cast = cast_expr (arg_types[i], e); expr_t *tmp = new_temp_def_expr (arg_types[i]); *a = expr_file_line (tmp, e); arg_exprs[arg_expr_count][0] = expr_file_line (cast, e); arg_exprs[arg_expr_count][1] = *a; arg_expr_count++; } else { - *a = expr_file_line (cast_expr (arg_types[i], convert_vector (e)), - e); + *a = expr_file_line (cast_expr (arg_types[i], e), e); } a = &(*a)->next; } @@ -2442,7 +2298,7 @@ return_expr (function_t *f, expr_t *e) e = convert_from_bool (e, (type_t *) ret_type); //FIXME cast } if (is_float(ret_type) && is_int_val (e)) { - convert_int (e); + e = cast_expr (&type_float, e); t = &type_float; } if (is_void(t)) { @@ -2459,8 +2315,9 @@ return_expr (function_t *f, expr_t *e) } if (!type_assignable (ret_type, t)) { if (!options.traditional) - return error (e, "type mismatch for return value of %s", - f->sym->name); + return error (e, "type mismatch for return value of %s: %s -> %s", + f->sym->name, get_type_string (t), + get_type_string (ret_type)); if (options.warnings.traditional) warning (e, "type mismatch for return value of %s", f->sym->name); @@ -2990,7 +2847,7 @@ build_state_expr (expr_t *e) if (think->type == ex_symbol) think = think_expr (think->e.symbol); if (is_int_val (frame)) - convert_int (frame); + frame = cast_expr (&type_float, frame); if (!type_assignable (&type_float, get_type (frame))) return error (frame, "invalid type for frame number"); if (extract_type (think) != ev_func) @@ -2999,7 +2856,7 @@ build_state_expr (expr_t *e) if (step->next) return error (step->next, "too many state arguments"); if (is_int_val (step)) - convert_int (step); + step = cast_expr (&type_float, step); if (!type_assignable (&type_float, get_type (step))) return error (step, "invalid type for step"); } @@ -3027,83 +2884,6 @@ think_expr (symbol_t *think_sym) return new_symbol_expr (think_sym); } -expr_t * -cast_expr (type_t *dstType, expr_t *e) -{ - expr_t *c; - type_t *srcType; - - convert_name (e); - - if (e->type == ex_error) - return e; - - dstType = (type_t *) unalias_type (dstType); //FIXME cast - srcType = get_type (e); - - if (dstType == srcType) - return e; - - if ((dstType == type_default && is_enum (srcType)) - || (is_enum (dstType) && srcType == type_default)) - return e; - if ((is_ptr (dstType) && is_string (srcType)) - || (is_string (dstType) && is_ptr (srcType))) { - c = new_alias_expr (dstType, e); - return c; - } - if (!(is_ptr (dstType) && (is_ptr (srcType) || is_integral (srcType) - || is_array (srcType))) - && !(is_integral (dstType) && is_ptr (srcType)) - && !(is_func (dstType) && is_func (srcType)) - && !(is_scalar (dstType) && is_scalar (srcType))) { - return cast_error (e, srcType, dstType); - } - if (is_array (srcType)) { - return address_expr (e, dstType->t.fldptr.type); - } - if (is_constant (e) && is_scalar (dstType) && is_scalar (srcType)) { - ex_value_t *val = 0; - if (e->type == ex_symbol && e->e.symbol->sy_type == sy_const) { - val = e->e.symbol->s.value; - } else if (e->type == ex_symbol - && e->e.symbol->sy_type == sy_var) { - // initialized global def treated as a constant - // from the tests above, the def is known to be constant - // and of one of the three storable scalar types - def_t *def = e->e.symbol->s.def; - if (is_float (def->type)) { - val = new_float_val (D_FLOAT (def)); - } else if (is_double (def->type)) { - val = new_double_val (D_DOUBLE (def)); - } else if (is_integral (def->type)) { - val = new_int_val (D_INT (def)); - } - } else if (e->type == ex_value) { - val = e->e.value; - } else if (e->type == ex_nil) { - convert_nil (e, dstType); - return e; - } - if (!val) - internal_error (e, "unexpected constant expression type"); - e->e.value = convert_value (val, dstType); - e->type = ex_value; - c = e; - } else if (is_integral (dstType) && is_integral (srcType)) { - c = new_alias_expr (dstType, e); - } else if (is_scalar (dstType) && is_scalar (srcType)) { - c = new_unary_expr ('C', e); - c->e.expr.type = dstType; - } else if (e->type == ex_uexpr && e->e.expr.op == '.') { - e->e.expr.type = dstType; - c = e; - } else { - c = new_alias_expr (dstType, e); - } - return c; -} - expr_t * encode_expr (type_t *type) { diff --git a/tools/qfcc/source/expr_assign.c b/tools/qfcc/source/expr_assign.c index e193de6aa..b04a98b36 100644 --- a/tools/qfcc/source/expr_assign.c +++ b/tools/qfcc/source/expr_assign.c @@ -142,6 +142,7 @@ is_lvalue (const expr_t *expr) case ex_with: case ex_args: case ex_horizontal: + case ex_swizzle: break; case ex_count: internal_error (expr, "invalid expression"); @@ -173,21 +174,20 @@ check_types_compatible (expr_t *dst, expr_t *src) } if (type_assignable (dst_type, src_type)) { - if (is_scalar (dst_type) && is_scalar (src_type)) { - if (!src->implicit) { - if (is_double (src_type)) { - warning (dst, "assignment of double to %s (use a cast)\n", - dst_type->name); - } - } - // the types are different but cast-compatible - expr_t *new = cast_expr (dst_type, src); - // the cast was a no-op, so the types are compatible at the - // low level (very true for default type <-> enum) - if (new != src) { - return assign_expr (dst, new); + debug (dst, "casting %s to %s", src_type->name, dst_type->name); + if (!src->implicit && !type_promotes (dst_type, src_type)) { + if (is_double (src_type)) { + warning (dst, "assignment of %s to %s (use a cast)\n", + src_type->name, dst_type->name); } } + // the types are different but cast-compatible + expr_t *new = cast_expr (dst_type, src); + // the cast was a no-op, so the types are compatible at the + // low level (very true for default type <-> enum) + if (new != src) { + return assign_expr (dst, new); + } return 0; } // traditional qcc is a little sloppy @@ -211,73 +211,31 @@ check_types_compatible (expr_t *dst, expr_t *src) return type_mismatch (dst, src, '='); } +static int +copy_elements (expr_t *block, expr_t *dst, expr_t *src, int base) +{ + int index = 0; + for (expr_t *e = src->e.vector.list; e; e = e->next) { + if (e->type == ex_vector) { + index += copy_elements (block, dst, e, index + base); + } else { + expr_t *dst_ele = array_expr (dst, new_int_expr (index + base)); + append_expr (block, assign_expr (dst_ele, e)); + index += type_width (get_type (e)); + } + } + return index; +} + static expr_t * assign_vector_expr (expr_t *dst, expr_t *src) { - expr_t *dx, *sx; - expr_t *dy, *sy; - expr_t *dz, *sz; - expr_t *dw, *sw; - expr_t *ds, *ss; - expr_t *dv, *sv; - expr_t *block; - - if (src->type == ex_vector) { - src = convert_vector (src); - if (src->type != ex_vector) { - // src was constant and thus converted - return assign_expr (dst, src); - } - } if (src->type == ex_vector && dst->type != ex_vector) { - if (is_vector(src->e.vector.type)) { - // guaranteed to have three elements - sx = src->e.vector.list; - sy = sx->next; - sz = sy->next; - dx = field_expr (dst, new_name_expr ("x")); - dy = field_expr (dst, new_name_expr ("y")); - dz = field_expr (dst, new_name_expr ("z")); - block = new_block_expr (); - append_expr (block, assign_expr (dx, sx)); - append_expr (block, assign_expr (dy, sy)); - append_expr (block, assign_expr (dz, sz)); - block->e.block.result = dst; - return block; - } - if (is_quaternion(src->e.vector.type)) { - // guaranteed to have two or four elements - if (src->e.vector.list->next->next) { - // four vals: x, y, z, w - sx = src->e.vector.list; - sy = sx->next; - sz = sy->next; - sw = sz->next; - dx = field_expr (dst, new_name_expr ("x")); - dy = field_expr (dst, new_name_expr ("y")); - dz = field_expr (dst, new_name_expr ("z")); - dw = field_expr (dst, new_name_expr ("w")); - block = new_block_expr (); - append_expr (block, assign_expr (dx, sx)); - append_expr (block, assign_expr (dy, sy)); - append_expr (block, assign_expr (dz, sz)); - append_expr (block, assign_expr (dw, sw)); - block->e.block.result = dst; - return block; - } else { - // v, s - sv = src->e.vector.list; - ss = sv->next; - dv = field_expr (dst, new_name_expr ("v")); - ds = field_expr (dst, new_name_expr ("s")); - block = new_block_expr (); - append_expr (block, assign_expr (dv, sv)); - append_expr (block, assign_expr (ds, ss)); - block->e.block.result = dst; - return block; - } - } - internal_error (src, "bogus vector expression"); + expr_t *block = new_block_expr (); + + copy_elements (block, dst, src, 0); + block->e.block.result = dst; + return block; } return 0; } diff --git a/tools/qfcc/source/expr_binary.c b/tools/qfcc/source/expr_binary.c index 6c792a1de..1c0429d09 100644 --- a/tools/qfcc/source/expr_binary.c +++ b/tools/qfcc/source/expr_binary.c @@ -642,6 +642,41 @@ static expr_type_t **binary_expr_types[ev_type_count] = { [ev_double] = double_x }; +// supported operators for scalar-vector expressions +static int scalar_vec_ops[] = { '*', '/', '%', MOD, 0 }; +static expr_t * +convert_scalar (expr_t *scalar, int op, expr_t *vec) +{ + int *s_op = scalar_vec_ops; + while (*s_op && *s_op != op) { + s_op++; + } + if (!*s_op) { + return 0; + } + + // expand the scalar to a vector of the same width as vec + type_t *vec_type = get_type (vec); + + if (is_constant (scalar)) { + for (int i = 1; i < type_width (get_type (vec)); i++) { + expr_t *s = copy_expr (scalar); + s->next = scalar; + scalar = s; + } + return new_vector_list (scalar); + } + + char swizzle[] = "xxxx"; + type_t *vec_base = base_type (vec_type); + expr_t *tmp = new_temp_def_expr (vector_type (vec_base, 4)); + expr_t *block = new_block_expr (); + swizzle[type_width (vec_type)] = 0; + append_expr (block, assign_expr (tmp, new_swizzle_expr (scalar, swizzle))); + block->e.block.result = new_alias_expr (vec_type, tmp); + return block; +} + static expr_t * pointer_arithmetic (int op, expr_t *e1, expr_t *e2) { @@ -787,11 +822,11 @@ double_compare (int op, expr_t *e1, expr_t *e2) if (is_constant (e1) && e1->implicit && is_double (t1) && is_float (t2)) { t1 = &type_float; - convert_double (e1); + e1 = cast_expr (t1, e1); } if (is_float (t1) && is_constant (e2) && e2->implicit && is_double (t2)) { t2 = &type_float; - convert_double (e2); + e2 = cast_expr (t2, e2); } if (is_double (t1)) { if (is_float (t2)) { @@ -828,11 +863,12 @@ entity_compare (int op, expr_t *e1, expr_t *e2) static expr_t * invalid_binary_expr (int op, expr_t *e1, expr_t *e2) { - etype_t t1, t2; - t1 = extract_type (e1); - t2 = extract_type (e2); + type_t *t1, *t2; + t1 = get_type (e1); + t2 = get_type (e2); return error (e1, "invalid binary expression: %s %s %s", - pr_type_name[t1], get_op_string (op), pr_type_name[t2]); + get_type_string (t1), get_op_string (op), + get_type_string (t2)); } static expr_t * @@ -957,7 +993,6 @@ binary_expr (int op, expr_t *e1, expr_t *e2) expr_type_t *expr_type; convert_name (e1); - e1 = convert_vector (e1); // FIXME this is target-specific info and should not be in the // expression tree if (e1->type == ex_alias && is_call (e1->e.alias.expr)) { @@ -981,7 +1016,6 @@ binary_expr (int op, expr_t *e1, expr_t *e2) return e1; convert_name (e2); - e2 = convert_vector (e2); if (e2->type == ex_error) return e2; @@ -1010,11 +1044,11 @@ binary_expr (int op, expr_t *e1, expr_t *e2) if (is_constant (e1) && is_double (t1) && e1->implicit && is_float (t2)) { t1 = &type_float; - convert_double (e1); + e1 = cast_expr (t1, e1); } if (is_constant (e2) && is_double (t2) && e2->implicit && is_float (t1)) { t2 = &type_float; - convert_double (e2); + e2 = cast_expr (t2, e2); } et1 = low_level_type (t1); @@ -1026,12 +1060,55 @@ binary_expr (int op, expr_t *e1, expr_t *e2) return invalid_binary_expr(op, e1, e2); if ((t1->width > 1 || t2->width > 1)) { - if (t1 != t2) { + // 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 + // here because of vec3 being float{3} + if (type_width (t1) == 1) { + // scalar op vec + if (!(e = convert_scalar (e1, op, e2))) { + return invalid_binary_expr (op, e1, e2); + } + e1 = e; + t1 = get_type (e1); + } + if (type_width (t2) == 1) { + // vec op scalar + if (!(e = convert_scalar (e2, op, e1))) { + return invalid_binary_expr (op, e1, e2); + } + e2 = e; + t2 = get_type (e2); + } + if (type_width (t1) != type_width (t2)) { + // vec op vec of different widths return invalid_binary_expr (op, e1, e2); } - e = new_binary_expr (op, e1, e2); - e->e.expr.type = t1; - return e; + 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 { + debug (e1, "%d %d\n", e1->implicit, e2->implicit); + return invalid_binary_expr (op, e1, e2); + } + } + t1 = get_type (e1); + t2 = get_type (e2); + et1 = low_level_type (t1); + et2 = low_level_type (t2); + // both widths are the same at this point + if (t1->width > 1) { + e = new_binary_expr (op, e1, e2); + e->e.expr.type = t1; + return e; + } } expr_type = binary_expr_types[et1][et2]; diff --git a/tools/qfcc/source/expr_cast.c b/tools/qfcc/source/expr_cast.c new file mode 100644 index 000000000..a02024c0c --- /dev/null +++ b/tools/qfcc/source/expr_cast.c @@ -0,0 +1,145 @@ +/* + expr_cast.c + + expression casting + + Copyright (C) 2022 Bill Currie + + Author: Bill Currie + Date: 2022/04/27 + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include + +#include "QF/mathlib.h" + +#include "tools/qfcc/include/qfcc.h" +#include "tools/qfcc/include/def.h" +#include "tools/qfcc/include/diagnostic.h" +#include "tools/qfcc/include/expr.h" +#include "tools/qfcc/include/type.h" +#include "tools/qfcc/include/value.h" + +static expr_t * +cast_error (expr_t *e, type_t *t1, type_t *t2) +{ + e = error (e, "cannot cast from %s to %s", get_type_string (t1), + get_type_string (t2)); + return e; +} + +static void +do_conversion (pr_type_t *dst_value, type_t *dstType, + pr_type_t *src_value, type_t *srcType, expr_t *expr) +{ + int from = type_cast_map[base_type (srcType)->type]; + int to = type_cast_map[base_type (dstType)->type]; + int width = type_width (srcType) - 1; + int conversion = TYPE_CAST_CODE (from, to, width); +#define OPA(type) (*((pr_##type##_t *) (src_value))) +#define OPC(type) (*((pr_##type##_t *) (dst_value))) + switch (conversion) { +#include "libs/gamecode/pr_convert.cinc" + default: + internal_error (expr, "invalid conversion code: %04o", conversion); + } +} + +static expr_t * +cast_math (type_t *dstType, type_t *srcType, expr_t *expr) +{ + pr_type_t src_value[type_size (srcType)]; + pr_type_t dst_value[type_size (dstType)]; + + value_store (src_value, srcType, expr); + + do_conversion (dst_value, dstType, src_value, srcType, expr); + + return new_value_expr (new_type_value (dstType, dst_value)); +} + +expr_t * +cast_expr (type_t *dstType, expr_t *e) +{ + expr_t *c; + type_t *srcType; + + convert_name (e); + + if (e->type == ex_error) + return e; + + dstType = (type_t *) unalias_type (dstType); //FIXME cast + srcType = get_type (e); + + if (dstType == srcType) + return e; + + if ((dstType == type_default && is_enum (srcType)) + || (is_enum (dstType) && srcType == type_default)) + return e; + if ((is_ptr (dstType) && is_string (srcType)) + || (is_string (dstType) && is_ptr (srcType))) { + c = new_alias_expr (dstType, e); + return c; + } + if (!(is_ptr (dstType) && (is_ptr (srcType) || is_integral (srcType) + || is_array (srcType))) + && !(is_integral (dstType) && is_ptr (srcType)) + && !(is_func (dstType) && is_func (srcType)) + && !(is_math (dstType) && is_math (srcType) + && type_width (dstType) == type_width (srcType)) + && !((is_int (dstType) || is_uint (dstType)) + && (is_short (srcType) || is_ushort (srcType)) + // [u]short is always width 0 + && type_width (dstType) == 1)) { + return cast_error (e, srcType, dstType); + } + if (is_array (srcType)) { + return address_expr (e, dstType->t.fldptr.type); + } + if (is_short (srcType)) { + e = new_int_expr (expr_short (e)); + srcType = &type_int; + } else if (is_ushort (srcType)) { + e = new_int_expr (expr_ushort (e)); + srcType = &type_int; + } + if (is_constant (e) && is_math (dstType) && is_math (srcType)) { + return cast_math (dstType, srcType, e); + } else if (is_integral (dstType) && is_integral (srcType)) { + c = new_alias_expr (dstType, e); + } else if (is_scalar (dstType) && is_scalar (srcType)) { + c = new_unary_expr ('C', e); + c->e.expr.type = dstType; + } else if (e->type == ex_uexpr && e->e.expr.op == '.') { + e->e.expr.type = dstType; + c = e; + } else { + c = new_alias_expr (dstType, e); + } + return c; +} diff --git a/tools/qfcc/source/expr_vector.c b/tools/qfcc/source/expr_vector.c new file mode 100644 index 000000000..0efc2b063 --- /dev/null +++ b/tools/qfcc/source/expr_vector.c @@ -0,0 +1,172 @@ +/* + expr_vector.c + + vector expressions + + Copyright (C) 2022 Bill Currie + + Author: Bill Currie + Date: 2022/04/27 + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include + +#include "QF/alloc.h" +#include "QF/dstring.h" +#include "QF/mathlib.h" +#include "QF/sys.h" +#include "QF/va.h" + +#include "tools/qfcc/include/qfcc.h" +#include "tools/qfcc/include/class.h" +#include "tools/qfcc/include/def.h" +#include "tools/qfcc/include/defspace.h" +#include "tools/qfcc/include/diagnostic.h" +#include "tools/qfcc/include/emit.h" +#include "tools/qfcc/include/expr.h" +#include "tools/qfcc/include/function.h" +#include "tools/qfcc/include/idstuff.h" +#include "tools/qfcc/include/method.h" +#include "tools/qfcc/include/options.h" +#include "tools/qfcc/include/reloc.h" +#include "tools/qfcc/include/shared.h" +#include "tools/qfcc/include/strpool.h" +#include "tools/qfcc/include/struct.h" +#include "tools/qfcc/include/symtab.h" +#include "tools/qfcc/include/type.h" +#include "tools/qfcc/include/value.h" + +#include "tools/qfcc/source/qc-parse.h" + +expr_t * +new_vector_list (expr_t *expr_list) +{ + type_t *ele_type = type_default; + + // lists are built in reverse order + expr_list = reverse_expr_list (expr_list); + + int width = 0; + int count = 0; + for (expr_t *e = expr_list; e; e = e->next) { + count++; + type_t *t = get_type (e); + if (!t) { + return e; + } + if (!is_math (t)) { + return error (e, "invalid type for vector element"); + } + width += type_width (t); + if (is_nonscalar (t)) { + t = base_type (t); + } + if (type_promotes (t, ele_type)) { + ele_type = t; + } + } + if (width < 2) { + return error (expr_list, "not a vector"); + } + if (width > 4) { + return error (expr_list, "resulting vector is too large: %d elements", + width); + } + + int all_constant = 1; + int all_implicit = 1; + expr_t *elements[count + 1]; + elements[count] = 0; + count = 0; + for (expr_t *e = expr_list; e; e = e->next) { + int cast_width = type_width (get_type (e)); + type_t *cast_type = vector_type (ele_type, cast_width); + all_implicit = all_implicit && e->implicit; + elements[count] = cast_expr (cast_type, fold_constants (e)); + all_constant = all_constant && is_constant (elements[count]); + count++; + } + + switch (count) { + case 4: + // all scalars (otherwise width would be too large) + break; + case 3: + // shuffle any vectors to the beginning of the list (there should + // be only one, but futhre...) + for (int i = 1; i < count; i++) { + if (is_nonscalar (get_type (elements[i]))) { + expr_t *t = elements[i]; + int j = i; + for (; j > 0 && is_scalar (get_type (elements[j])); j--) { + elements[j] = elements[j - 1]; + } + elements[j] = t; + } + } + break; + case 2: + if (is_scalar (get_type (elements[0])) + && is_nonscalar (get_type (elements[1]))) { + // swap s, v to be v, s (ie, vector always comes before scalar) + expr_t *t = elements[0]; + elements[0] = elements[1]; + elements[1] = t; + } + break; + case 1: + if (is_scalar (get_type (elements[0]))) { + internal_error (expr_list, "confused about vectors"); + } + // it's already a vector + return elements[0]; + } + + if (all_constant) { + type_t *vec_type = vector_type (ele_type, width); + pr_type_t value[type_size (vec_type)]; + + for (int i = 0, offs = 0; i < count; i++) { + type_t *src_type = get_type (elements[i]); + value_store (value + offs, src_type, elements[i]); + offs += type_size (src_type); + } + + expr_t *vec = new_value_expr (new_type_value (vec_type, value)); + vec->implicit = all_implicit; + return vec; + } + + for (int i = 0; i < count; i++) { + elements[i]->next = elements[i + 1]; + } + + expr_t *vec = new_expr (); + vec->type = ex_vector; + vec->e.vector.type = vector_type (ele_type, width); + vec->e.vector.list = elements[0]; + return vec; +} diff --git a/tools/qfcc/source/obj_file.c b/tools/qfcc/source/obj_file.c index d7144ae27..863d56d64 100644 --- a/tools/qfcc/source/obj_file.c +++ b/tools/qfcc/source/obj_file.c @@ -433,7 +433,7 @@ qfo_byteswap_space (void *space, int size, qfos_type_t type) case qfos_type: case qfos_debug: for (val = (pr_type_t *) space, c = 0; c < size; c++, val++) - val->int_var = LittleLong (val->int_var); + val->value = LittleLong (val->value); break; } } diff --git a/tools/qfcc/source/opcodes.c b/tools/qfcc/source/opcodes.c index 5c97f780c..23da7490b 100644 --- a/tools/qfcc/source/opcodes.c +++ b/tools/qfcc/source/opcodes.c @@ -41,6 +41,7 @@ #include +#include "tools/qfcc/include/diagnostic.h" #include "tools/qfcc/include/opcodes.h" #include "tools/qfcc/include/options.h" #include "tools/qfcc/include/qfcc.h" @@ -302,7 +303,26 @@ operand_width (const char *opname, operand_t *op) } return op->width; } - +#if 0 + if (!strcmp (name, "swizzle")) { + adjust_swizzle_op (&search_op, 0); + adjust_swizzle_op (&search_op, 2); + } +static void +adjust_swizzle_op (opcode_t *op, int opind) +{ + // swizzle instructions require both operands to be 4 components (4 or 8 + // words) in size with the same alignment. + op->widths[opind] = 4; + if (pr_type_size[op->types[opind]] == 1) { + op->types[opind] = ev_float; + } else if (pr_type_size[op->types[opind]] == 2) { + op->types[opind] = ev_double; + } else { + internal_error (0, "unexpected swizzle op size"); + } +} +#endif static opcode_t * rua_opcode_find (const char *name, operand_t *op_a, operand_t *op_b, operand_t *op_c) @@ -507,6 +527,9 @@ opcode_print_statement (pr_uint_t addr, dstatement_t *st) } else { mnemonic = pr_opcodes[st_op].mnemonic; } - printf ("%04x (%03x)%-8s %04x %04x %04x\n", - addr, st_op & 0x1ff, mnemonic, st->a, st->b, st->c); + printf ("%04x (%03x)%-8s %d:%04x %d:%04x %d:%04x\n", + addr, st_op & 0x1ff, mnemonic, + (st->op & OP_A_BASE) >> OP_A_SHIFT, st->a, + (st->op & OP_B_BASE) >> OP_B_SHIFT, st->b, + (st->op & OP_C_BASE) >> OP_C_SHIFT, st->c); } diff --git a/tools/qfcc/source/qc-lex.l b/tools/qfcc/source/qc-lex.l index c74dcea4a..495d69aa9 100644 --- a/tools/qfcc/source/qc-lex.l +++ b/tools/qfcc/source/qc-lex.l @@ -80,7 +80,9 @@ int yyget_debug (void) __attribute__((pure)); FILE *yyget_in (void) __attribute__((pure)); FILE *yyget_out (void) __attribute__((pure)); -static int keyword_or_id (char *token); +static int keyword_or_id (const char *token); +static expr_t *parse_float_vector (const char *token, int width); +static expr_t *parse_int_vector (const char *token, int width); extern QC_YYSTYPE qc_yylval; @@ -95,7 +97,12 @@ ID [a-zA-Z_][a-zA-Z_0-9]* FLOAT ({D}+|{D}*\.{D}+|{D}+\.{D}*)([eE]{m}?{D}+)? FLOATf {FLOAT}[fF] FLOATd {FLOAT}[dD] +FCOMP {m}?{FLOAT} +FD [fFdD] INT ({D}+|0[xX]{X}+|0[bB]{B}) +ICOMP {m}?{INT} +UL ([uU]?([lL][lL]?)?) +ULFD ({UL}|{FD}) RANGE \.\. ELLIPSIS \.\.\. FRAMEID {ID}(\.{ID})* @@ -122,18 +129,28 @@ STRING \"(\\.|[^"\\])*\" ^{s}*#{s}*pragma{s}+ { BEGIN (PRAGMA); } -{INT}+[uU]?([lL][lL]?)? { +{INT}+{UL}? { const char *c = yytext + yyleng - 1; - int i; + pr_long_t i; if (yytext[0] == '0' && tolower (yytext[1] == 'b')) i = strtol (yytext + 2, 0, 2); else i = strtol (yytext, 0, 0); - if (*c == 'u' || *c == 'U') - qc_yylval.expr = new_int_expr (i);//FIXME - else - qc_yylval.expr = new_int_expr (i); + if (tolower (*c) == 'u') { + if (tolower (c[1]) == 'l') { + qc_yylval.expr = new_ulong_expr (i); + } else { + qc_yylval.expr = new_uint_expr (i); + } + } else { + if (tolower (c[1]) == 'l') { + qc_yylval.expr = new_long_expr (i); + } else { + qc_yylval.expr = new_int_expr (i); + qc_yylval.expr->implicit = 1; + } + } return VALUE; } @@ -187,19 +204,33 @@ STRING \"(\\.|[^"\\])*\" } @ return '@'; -'{s}*{m}?{FLOAT}{s}+{m}?{FLOAT}{s}+{m}?{FLOAT}{s}*' { - vec3_t v; - sscanf (yytext, "' %f %f %f '", - &v[0], &v[1], &v[2]); - qc_yylval.expr = new_vector_expr (v); +'{s}*{ICOMP}{s}+{ICOMP}{s}*'{ULFD}? { + qc_yylval.expr = parse_int_vector (yytext, 2); return VALUE; } -'{s}*{m}?{FLOAT}{s}+{m}?{FLOAT}{s}+{m}?{FLOAT}{s}+{m}?{FLOAT}{s}*' { - quat_t q; - sscanf (yytext, "' %f %f %f %f'", - &q[0], &q[1], &q[2], &q[3]); - qc_yylval.expr = new_quaternion_expr (q); +'{s}*{ICOMP}{s}+{ICOMP}{s}+{ICOMP}{s}*'{ULFD}? { + qc_yylval.expr = parse_int_vector (yytext, 3); + return VALUE; + } + +'{s}*{ICOMP}{s}+{ICOMP}{s}+{ICOMP}{s}+{ICOMP}{s}*'{ULFD}? { + qc_yylval.expr = parse_int_vector (yytext, 4); + return VALUE; + } + +'{s}*{FCOMP}{s}+{FCOMP}{s}*'{FD}? { + qc_yylval.expr = parse_float_vector (yytext, 2); + return VALUE; + } + +'{s}*{FCOMP}{s}+{FCOMP}{s}+{FCOMP}{s}*'{FD}? { + qc_yylval.expr = parse_float_vector (yytext, 3); + return VALUE; + } + +'{s}*{FCOMP}{s}+{FCOMP}{s}+{FCOMP}{s}+{FCOMP}{s}*'{FD}? { + qc_yylval.expr = parse_float_vector (yytext, 4); return VALUE; } @@ -453,7 +484,7 @@ process_keyword (keyword_t *keyword, const char *token) } static int -keyword_or_id (char *token) +keyword_or_id (const char *token) { static hashtab_t *keyword_tab; static hashtab_t *qf_keyword_tab; @@ -525,6 +556,166 @@ keyword_or_id (char *token) return NAME; } +static expr_t * +parse_int_vector (const char *token, int width) +{ + char t1 = 0, t2 = 0; + type_t *type = 0; + + union { + pr_long_t l[4]; + pr_type_t t[PR_SIZEOF (dvec4)]; + } long_data = {}; + pr_type_t *data = __builtin_choose_expr ( + sizeof (pr_long_t) == sizeof (long), long_data.t, (void) 0); + + switch (width) { + case 4: + sscanf (token, "' %li %li %li %li '%c%c", + &long_data.l[0], &long_data.l[1], + &long_data.l[2], &long_data.l[3], &t1, &t2); + break; + case 3: + sscanf (token, "' %li %li %li '%c%c", + &long_data.l[0], &long_data.l[1], + &long_data.l[2], &t1, &t2); + break; + case 2: + sscanf (token, "' %li %li '%c%c", + &long_data.l[0], &long_data.l[1], &t1, &t2); + break; + } + t1 = tolower (t1); + t2 = tolower (t2); + switch (t1) { + case 'u': + if (t2 == 'l') { + type = &type_ulong; + } else { + type = &type_uint; + volatile union { + pr_uint_t u[4]; + pr_type_t t[PR_SIZEOF (ivec4)]; + } uint_data = { + .u = { + long_data.l[0], + long_data.l[1], + long_data.l[2], + long_data.l[3], + } + }; + data = (pr_type_t *) uint_data.t; + } + break; + case 'l': + type = &type_long; + break; + case 'f': + type = &type_float; + volatile union { + pr_float_t f[4]; + pr_type_t t[PR_SIZEOF (vec4)]; + } float_data = { + .f = { + long_data.l[0], + long_data.l[1], + long_data.l[2], + long_data.l[3], + } + }; + data = (pr_type_t *) float_data.t; + break; + case 'd': + type = &type_double; + volatile union { + pr_double_t d[4]; + pr_type_t t[PR_SIZEOF (dvec4)]; + } double_data = { + .d = { + long_data.l[0], + long_data.l[1], + long_data.l[2], + long_data.l[3], + } + }; + data = (pr_type_t *) double_data.t; + break; + case 0: + type = &type_int; + volatile union { + pr_int_t i[4]; + pr_type_t t[PR_SIZEOF (ivec4)]; + } int_data = { + .i = { + long_data.l[0], + long_data.l[1], + long_data.l[2], + long_data.l[3], + } + }; + data = (pr_type_t *) int_data.t; + break; + } + type = vector_type (type, width); + expr_t *expr = new_value_expr (new_type_value (type, data)); + expr->implicit = !t1; + return expr; +} + +static expr_t * +parse_float_vector (const char *token, int width) +{ + char t = 0; + type_t *type = 0; + + union { + pr_double_t d[4]; + pr_type_t t[PR_SIZEOF (dvec4)]; + } double_data = {}; + pr_type_t *data = __builtin_choose_expr ( + sizeof (pr_double_t) == sizeof (double), double_data.t, (void) 0); + + switch (width) { + case 4: + sscanf (token, "' %lf %lf %lf %lf '%c", + &double_data.d[0], &double_data.d[1], + &double_data.d[2], &double_data.d[3], &t); + break; + case 3: + sscanf (token, "' %lf %lf %lf '%c", + &double_data.d[0], &double_data.d[1], + &double_data.d[1], &t); + type = (t == 'f' || t == 'F') ? &type_vec3 : &type_dvec3; + break; + case 2: + sscanf (token, "' %lf %lf '%c", + &double_data.d[0], &double_data.d[1], &t); + type = (t == 'f' || t == 'F') ? &type_vec2 : &type_dvec2; + break; + } + if (t == 'f' || t == 'F') { + volatile union { + pr_float_t f[4]; + pr_type_t t[PR_SIZEOF (vec4)]; + } float_data = { + .f = { + double_data.d[0], + double_data.d[1], + double_data.d[2], + double_data.d[3], + } + }; + data = (pr_type_t *) float_data.t; + type = &type_float; + } else { + type = &type_double; + } + type = vector_type (type, width); + expr_t *expr = new_value_expr (new_type_value (type, data)); + expr->implicit = !t; + return expr; +} + #ifdef YY_FLEX_REALLOC_HACK static __attribute__ ((used)) void *(*const yy_flex_realloc_hack)(void *,yy_size_t) = yy_flex_realloc; #else diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index 29029e543..5355a7981 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -94,7 +94,7 @@ int yylex (void); %union { int op; - int size; + unsigned size; specifier_t spec; void *pointer; // for ensuring pointer values are null struct type_s *type; @@ -1131,11 +1131,13 @@ abs_decl array_decl : '[' expr ']' { - if (!is_int_val ($2) || expr_int ($2) < 1) { + if (is_int_val ($2) && expr_int ($2) > 0) { + $$ = expr_int ($2); + } else if (is_uint_val ($2) && expr_uint ($2) > 0) { + $$ = expr_uint ($2); + } else { error (0, "invalid array size"); $$ = 0; - } else { - $$ = expr_int ($2); } } | '[' ']' { $$ = 0; } diff --git a/tools/qfcc/source/qfcc.c b/tools/qfcc/source/qfcc.c index 5cc8c7aa4..98120e825 100644 --- a/tools/qfcc/source/qfcc.c +++ b/tools/qfcc/source/qfcc.c @@ -246,7 +246,7 @@ WriteProgs (dprograms_t *progs, int size) fielddefs[i].name = LittleLong (fielddefs[i].name); } for (i = 0; i < progs->globals.count; i++) - globals[i].int_var = LittleLong (globals[i].int_var); + globals[i].value = LittleLong (globals[i].value); if (!(h = Qopen (options.output_file, "wb"))) Sys_Error ("%s: %s\n", options.output_file, strerror(errno)); @@ -307,7 +307,7 @@ WriteSym (pr_debug_header_t *sym, int size) debug_defs[i].type_encoding = LittleLong (debug_defs[i].type_encoding); } for (i = 0; i < sym->debug_data_size; i++) { - debug_data[i].int_var = LittleLong (debug_data[i].int_var); + debug_data[i].value = LittleLong (debug_data[i].value); } if (!(h = Qopen (options.debug_file, "wb"))) diff --git a/tools/qfcc/source/reloc.c b/tools/qfcc/source/reloc.c index d235008d0..674be505f 100644 --- a/tools/qfcc/source/reloc.c +++ b/tools/qfcc/source/reloc.c @@ -73,7 +73,7 @@ static const char *reloc_name[] = { "rel_def_field_ofs", }; -#define RELOC(r) (r)->space->data[(r)->offset].int_var +#define RELOC(r) (r)->space->data[(r)->offset].value void relocate_refs (reloc_t *reloc, int offset) @@ -169,7 +169,7 @@ relocate_refs (reloc_t *reloc, int offset) case rel_def_field_ofs: //FIXME what is correct here? //RELOC (reloc) += pr.data->data[offset].int_var; - RELOC (reloc) += pr.near_data->data[offset].int_var; + RELOC (reloc) += PR_PTR (int, &pr.near_data->data[offset]); break; } reloc = reloc->next; diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index fda9e9a2e..28114dedf 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -123,63 +123,7 @@ operand_string (operand_t *op) case op_def: return op->def->name; case op_value: - switch (op->value->lltype) { - case ev_string: - return va (0, "\"%s\"", - quote_string (op->value->v.string_val)); - case ev_double: - return va (0, "%g", op->value->v.double_val); - case ev_float: - return va (0, "%g", op->value->v.float_val); - case ev_vector: - return va (0, "'%g %g %g'", - op->value->v.vector_val[0], - op->value->v.vector_val[1], - op->value->v.vector_val[2]); - case ev_quaternion: - return va (0, "'%g %g %g %g'", - op->value->v.quaternion_val[0], - op->value->v.quaternion_val[1], - op->value->v.quaternion_val[2], - op->value->v.quaternion_val[3]); - case ev_ptr: - if (op->value->v.pointer.def) { - return va (0, "ptr %s+%d", - op->value->v.pointer.def->name, - op->value->v.pointer.val); - } else if(op->value->v.pointer.tempop) { - operand_t *tempop = op->value->v.pointer.tempop; - return va (0, "ptr %s+%d", tempop_string (tempop), - op->value->v.pointer.val); - } else { - return va (0, "ptr %d", op->value->v.pointer.val); - } - case ev_field: - return va (0, "field %d", op->value->v.pointer.val); - case ev_entity: - return va (0, "ent %d", op->value->v.int_val); - case ev_func: - return va (0, "func %d", op->value->v.int_val); - case ev_int: - return va (0, "int %d", op->value->v.int_val); - case ev_uint: - return va (0, "uint %u", op->value->v.uint_val); - case ev_long: - return va (0, "long %"PRIi64, op->value->v.long_val); - case ev_ulong: - return va (0, "ulong %"PRIu64, op->value->v.ulong_val); - case ev_short: - return va (0, "short %d", op->value->v.short_val); - case ev_ushort: - return va (0, "ushort %d", op->value->v.ushort_val); - case ev_void: - return "(void)"; - case ev_invalid: - return "(invalid)"; - case ev_type_count: - return "(type_count)"; - } - break; + return get_value_string (op->value); case op_label: return op->label->name; case op_temp: @@ -205,76 +149,24 @@ _print_operand (operand_t *op) { switch (op->op_type) { case op_def: - printf ("(%s) ", pr_type_name[op->type->type]); + printf ("(%s) ", get_type_string (op->type)); printf ("%s", op->def->name); break; case op_value: - printf ("(%s) ", pr_type_name[op->type->type]); - switch (op->value->lltype) { - case ev_string: - printf ("\"%s\"", op->value->v.string_val); - break; - case ev_double: - printf ("%g", op->value->v.double_val); - break; - case ev_float: - printf ("%g", op->value->v.float_val); - break; - case ev_vector: - printf ("'%g", op->value->v.vector_val[0]); - printf (" %g", op->value->v.vector_val[1]); - printf (" %g'", op->value->v.vector_val[2]); - break; - case ev_quaternion: - printf ("'%g", op->value->v.quaternion_val[0]); - printf (" %g", op->value->v.quaternion_val[1]); - printf (" %g", op->value->v.quaternion_val[2]); - printf (" %g'", op->value->v.quaternion_val[3]); - break; - case ev_ptr: - printf ("(%s)[%d]", - pr_type_name[op->value->v.pointer.type->type], - op->value->v.pointer.val); - break; - case ev_field: - printf ("%d", op->value->v.pointer.val); - break; - case ev_entity: - case ev_func: - case ev_int: - printf ("%d", op->value->v.int_val); - break; - case ev_uint: - printf ("%u", op->value->v.uint_val); - break; - case ev_long: - printf ("%"PRIu64, op->value->v.long_val); - break; - case ev_ulong: - printf ("%"PRIu64, op->value->v.ulong_val); - break; - case ev_short: - printf ("%d", op->value->v.short_val); - break; - case ev_ushort: - printf ("%d", op->value->v.ushort_val); - break; - case ev_void: - case ev_invalid: - case ev_type_count: - internal_error (op->expr, "weird value type"); - } + printf ("(%s) %s", pr_type_name[op->type->type], + get_value_string (op->value)); break; case op_label: printf ("block %p", op->label->dest); break; case op_temp: - printf ("tmp (%s) %p", pr_type_name[op->type->type], op); + printf ("tmp (%s) %p", get_type_string (op->type), op); if (op->tempop.def) - printf (" %s", op->tempop.def->name); + printf (" %s:%04x", op->tempop.def->name, + op->tempop.def->offset); break; case op_alias: - printf ("alias(%s,", pr_type_name[op->type->type]); + printf ("alias(%s,", get_type_string (op->type)); _print_operand (op->alias); printf (")"); break; @@ -1742,10 +1634,13 @@ expr_expr (sblock_t *sblock, expr_t *e, operand_t **op) opcode = "cmp"; } if (strcmp (opcode, "dot") == 0) { - if (is_vector (get_type (e->e.expr.e1))) { + if (type_width (get_type (e->e.expr.e1)) == 2) { + opcode = "cdot"; + } + if (type_width (get_type (e->e.expr.e1)) == 3) { opcode = "vdot"; } - if (is_quaternion (get_type (e->e.expr.e1))) { + if (type_width (get_type (e->e.expr.e1)) == 4) { opcode = "qdot"; } } @@ -1760,17 +1655,6 @@ expr_expr (sblock_t *sblock, expr_t *e, operand_t **op) return sblock; } -static int type_map[ev_type_count] = { - [ev_int] = 0, - [ev_float] = 1, - [ev_long] = 2, - [ev_double] = 3, - [ev_uint] = 4, - //[ev_bool32] = 5, - [ev_ulong] = 6, - //[ev_bool64] = 7, -}; - static sblock_t * expr_cast (sblock_t *sblock, expr_t *e, operand_t **op) { @@ -1786,10 +1670,10 @@ expr_cast (sblock_t *sblock, expr_t *e, operand_t **op) s = new_statement (st_expr, "conv", e); s->opa = src; if (options.code.progsversion == PROG_VERSION) { - int from = type_map[src_type->type]; - int to = type_map[type->type]; + int from = type_cast_map[src_type->type]; + int to = type_cast_map[type->type]; int width = type_width (src_type) - 1; - int conv = (width << 6) | (from << 3) | to; + int conv = TYPE_CAST_CODE (from, to, width); s->opb = short_operand (conv, e); } s->opc = *op; @@ -1900,6 +1784,32 @@ expr_horizontal (sblock_t *sblock, expr_t *e, operand_t **op) return sblock; } +static sblock_t * +expr_swizzle (sblock_t *sblock, expr_t *e, operand_t **op) +{ + const char *opcode = "swizzle"; + statement_t *s; + int swiz = 0; + type_t *res_type = e->e.swizzle.type; + + for (int i = 0; i < 4; i++) { + swiz |= e->e.swizzle.source[i] & 3; + } + swiz |= (e->e.swizzle.neg & 0xf) << 8; + swiz |= (e->e.swizzle.zero & 0xf) << 12; + + s = new_statement (st_expr, opcode, e); + sblock = statement_subexpr (sblock, e->e.swizzle.src, &s->opa); + s->opb = short_operand (swiz, e); + if (!*op) { + *op = temp_operand (res_type, e); + } + s->opc = *op; + sblock_add_statement (sblock, s); + + return sblock; +} + static sblock_t * expr_def (sblock_t *sblock, expr_t *e, operand_t **op) { @@ -1937,13 +1847,28 @@ expr_temp (sblock_t *sblock, expr_t *e, operand_t **op) return sblock; } +static int +statement_copy_elements (sblock_t **sblock, expr_t *dst, expr_t *src, int base) +{ + int index = 0; + for (expr_t *e = src->e.vector.list; e; e = e->next) { + if (e->type == ex_vector) { + index += statement_copy_elements (sblock, dst, e, index + base); + } else { + int size = type_size (base_type (get_type (dst))); + type_t *src_type = get_type (e); + expr_t *dst_ele = new_offset_alias_expr (src_type, dst, + size * (index + base)); + index += type_width (src_type); + *sblock = statement_slist (*sblock, assign_expr (dst_ele, e)); + } + } + return index; +} + static sblock_t * expr_vector_e (sblock_t *sblock, expr_t *e, operand_t **op) { - expr_t *x, *y, *z, *w; - expr_t *s, *v; - expr_t *ax, *ay, *az, *aw; - expr_t *as, *av; expr_t *tmp; type_t *vec_type = get_type (e); int file = pr.source_file; @@ -1953,52 +1878,8 @@ expr_vector_e (sblock_t *sblock, expr_t *e, operand_t **op) pr.source_line = e->line; tmp = new_temp_def_expr (vec_type); - if (is_vector(vec_type)) { - // guaranteed to have three elements - x = e->e.vector.list; - y = x->next; - z = y->next; - ax = new_name_expr ("x"); - ay = new_name_expr ("y"); - az = new_name_expr ("z"); - ax = assign_expr (field_expr (tmp, ax), x); - ay = assign_expr (field_expr (tmp, ay), y); - az = assign_expr (field_expr (tmp, az), z); - sblock = statement_slist (sblock, ax); - sblock = statement_slist (sblock, ay); - sblock = statement_slist (sblock, az); - } else { - // guaranteed to have two or four elements - if (e->e.vector.list->next->next) { - // four vals: x, y, z, w - x = e->e.vector.list; - y = x->next; - z = y->next; - w = z->next; - ax = new_name_expr ("x"); - ay = new_name_expr ("y"); - az = new_name_expr ("z"); - aw = new_name_expr ("w"); - ax = assign_expr (field_expr (tmp, ax), x); - ay = assign_expr (field_expr (tmp, ay), y); - az = assign_expr (field_expr (tmp, az), z); - aw = assign_expr (field_expr (tmp, aw), w); - sblock = statement_slist (sblock, ax); - sblock = statement_slist (sblock, ay); - sblock = statement_slist (sblock, az); - sblock = statement_slist (sblock, aw); - } else { - // v, s - v = e->e.vector.list; - s = v->next; - av = new_name_expr ("v"); - as = new_name_expr ("s"); - av = assign_expr (field_expr (tmp, av), v); - as = assign_expr (field_expr (tmp, as), s); - sblock = statement_slist (sblock, av); - sblock = statement_slist (sblock, as); - } - } + statement_copy_elements (&sblock, tmp, e, 0); + pr.source_file = file; pr.source_line = line; sblock = statement_subexpr (sblock, tmp, op); @@ -2061,6 +1942,7 @@ statement_subexpr (sblock_t *sblock, expr_t *e, operand_t **op) [ex_expr] = expr_expr, [ex_uexpr] = expr_uexpr, [ex_horizontal] = expr_horizontal, + [ex_swizzle] = expr_swizzle, [ex_def] = expr_def, [ex_symbol] = expr_symbol, [ex_temp] = expr_temp, diff --git a/tools/qfcc/source/struct.c b/tools/qfcc/source/struct.c index 4a9f64bce..318efb420 100644 --- a/tools/qfcc/source/struct.c +++ b/tools/qfcc/source/struct.c @@ -365,7 +365,7 @@ emit_structure (const char *name, int su, struct_def_t *defs, type_t *type, if (!defs[i].emit) { //FIXME relocs? arrays? structs? pr_type_t *val = (pr_type_t *) data; - memcpy (D_POINTER (void, &field_def), val, + memcpy (D_POINTER (pr_type_t, &field_def), val, type_size (field_def.type) * sizeof (pr_type_t)); data = &val[type_size (field_def.type)]; } else { diff --git a/tools/qfcc/source/type.c b/tools/qfcc/source/type.c index a695e9f50..8b0901339 100644 --- a/tools/qfcc/source/type.c +++ b/tools/qfcc/source/type.c @@ -89,6 +89,11 @@ type_t type_invalid = { }; #include "tools/qfcc/include/vec_types.h" +#define VEC_TYPE(type_name, base_type) &type_##type_name, +static type_t *vec_types[] = { +#include "tools/qfcc/include/vec_types.h" + 0 +}; type_t *type_nil; type_t *type_default; type_t *type_long_int; @@ -145,6 +150,17 @@ type_t *ev_types[ev_type_count] = { &type_invalid, }; +int type_cast_map[ev_type_count] = { + [ev_int] = 0, + [ev_float] = 1, + [ev_long] = 2, + [ev_double] = 3, + [ev_uint] = 4, + //[ev_bool32] = 5, + [ev_ulong] = 6, + //[ev_bool64] = 7, +}; + static type_t *types_freelist; etype_t @@ -479,6 +495,20 @@ find_type (type_t *type) // allocate a new one check = new_type (); *check = *type; + if (is_func (type)) { + check->t.func.param_types = 0; + const type_t *t = unalias_type (type); + int num_params = t->t.func.num_params; + if (num_params < 0) { + num_params = ~num_params; + } + if (num_params) { + check->t.func.param_types = malloc (sizeof (type_t *) * num_params); + for (int i = 0; i < num_params; i++) { + check->t.func.param_types[i] = t->t.func.param_types[i]; + } + } + } check->freeable = 0; chain_type (check); @@ -524,6 +554,70 @@ pointer_type (type_t *aux) return new; } +type_t * +vector_type (const type_t *ele_type, int width) +{ + if (width == 1) { + for (type_t **t = ev_types; t - ev_types < ev_type_count; t++) { + if ((*t)->type == ele_type->type && (*t)->width == 1) { + return *t; + } + } + } + for (type_t **vtype = vec_types; *vtype; vtype++) { + if ((*vtype)->type == ele_type->type + && (*vtype)->width == width) { + return *vtype; + } + } + return 0; +} + +type_t * +base_type (const type_t *vec_type) +{ + if (!is_math (vec_type)) { + return 0; + } + // vec_type->type for quaternion and vector points back to itself + if (is_quaternion (vec_type) || is_vector (vec_type)) { + return &type_float; + } + return ev_types[vec_type->type]; +} + +type_t * +int_type (const type_t *base) +{ + int width = type_width (base); + base = base_type (base); + if (!base) { + return 0; + } + if (type_size (base) == 1) { + base = &type_int; + } else if (type_size (base) == 2) { + base = &type_long; + } + return vector_type (base, width); +} + +type_t * +float_type (const type_t *base) +{ + int width = type_width (base); + base = base_type (base); + if (!base) { + return 0; + } + if (type_size (base) == 1) { + base = &type_float; + } else if (type_size (base) == 2) { + base = &type_double; + } + return vector_type (base, width); +} + type_t * array_type (type_t *aux, int size) { @@ -711,7 +805,9 @@ print_type_str (dstring_t *str, const type_t *type) case ev_short: case ev_ushort: case ev_double: - dasprintf (str, " %s", pr_type_name[type->type]); + dasprintf (str, " %s%s", pr_type_name[type->type], + type->width > 1 ? va (0, "{%d}", type->width) + : ""); return; case ev_invalid: case ev_type_count: @@ -722,6 +818,25 @@ print_type_str (dstring_t *str, const type_t *type) internal_error (0, "bad type meta:type %d:%d", type->meta, type->type); } +const char * +get_type_string (const type_t *type) +{ + static dstring_t *type_str[8]; + static int str_index; + + if (!type_str[str_index]) { + type_str[str_index] = dstring_newstr (); + } + dstring_clearstr (type_str[str_index]); + print_type_str (type_str[str_index], type); + const char *str = type_str[str_index++]->str; + str_index %= sizeof (type_str) / sizeof (type_str[0]); + while (*str == ' ') { + str++; + } + return str; +} + void print_type (const type_t *type) { @@ -941,6 +1056,8 @@ is_integral (const type_t *type) type = unalias_type (type); if (is_int (type) || is_uint (type) || is_short (type)) return 1; + if (is_long (type) || is_ulong (type) || is_ushort (type)) + return 1; return is_enum (type); } @@ -1053,8 +1170,16 @@ type_assignable (const type_t *dst, const type_t *src) return 1; return 0; } - if (!is_ptr (dst) || !is_ptr (src)) - return is_scalar (dst) && is_scalar (src); + if (!is_ptr (dst) || !is_ptr (src)) { + if (is_scalar (dst) && is_scalar (src)) { + return 1; + } + if (is_nonscalar (dst) && is_nonscalar (src) + && type_width (dst) == type_width (src)) { + return 1; + } + return 0; + } // pointer = pointer // give the object system first shot because the pointee types might have @@ -1076,6 +1201,35 @@ type_assignable (const type_t *dst, const type_t *src) return 0; } +int +type_promotes (const type_t *dst, const type_t *src) +{ + dst = unalias_type (dst); + src = unalias_type (src); + // nothing promotes to int + if (is_int (dst)) { + return 0; + } + if (is_uint (dst) && is_int (src)) { + return 1; + } + if (is_long (dst) && (is_int (src) || is_uint (src))) { + return 1; + } + if (is_ulong (dst) && (is_int (src) || is_uint (src) || is_long (src))) { + return 1; + } + if (is_float (dst) && (is_int (src) || is_uint (src))) { + return 1; + } + //XXX what to do with (u)long<->float? + // everything promotes to double + if (is_double (dst)) { + return 1; + } + return 0; +} + int type_same (const type_t *dst, const type_t *src) { @@ -1201,6 +1355,33 @@ chain_initial_types (void) chain_structural_types (); } +static const char *vector_field_names[] = { "x", "y", "z", "w" }; +//static const char *color_field_names[] = { "r", "g", "b", "a" }; +//static const char *texture_field_names[] = { "s", "t", "p", "q" }; + +static void +build_vector_struct (type_t *type) +{ + ty_meta_e meta = type->meta; + etype_t etype = type->type; + type_t *ele_type = base_type (type); + int width = type_width (type); + + if (!ele_type || width < 2) { + internal_error (0, "%s not a vector type: %p %d", type->name, ele_type, width); + } + + struct_def_t fields[width + 1]; + for (int i = 0; i < width; i++) { + fields[i] = (struct_def_t) { vector_field_names[i], ele_type }; + } + fields[width] = (struct_def_t) {}; + + make_structure (va (0, "@%s", type->name), 's', fields, type); + type->type = etype; + type->meta = meta; +} + void init_types (void) { @@ -1234,17 +1415,6 @@ init_types (void) {"double_val", &type_double}, {0, 0} }; - static struct_def_t vector_struct[] = { - {"x", &type_float}, - {"y", &type_float}, - {"z", &type_float}, - {0, 0} - }; - static struct_def_t quaternion_struct[] = { - {"v", &type_vector}, - {"s", &type_float}, - {0, 0} - }; static struct_def_t type_encoding_struct[] = { {"types", &type_ptr}, {"size", &type_uint}, @@ -1290,9 +1460,7 @@ init_types (void) make_structure ("@zero", 'u', zero_struct, &type_zero); make_structure ("@param", 'u', param_struct, &type_param); - make_structure ("@vector", 's', vector_struct, &type_vector); - type_vector.type = ev_vector; - type_vector.meta = ty_basic; + build_vector_struct (&type_vector); make_structure ("@type_encodings", 's', type_encoding_struct, &type_type_encodings); @@ -1302,24 +1470,20 @@ init_types (void) va_list_struct[1].type = pointer_type (&type_param); make_structure ("@va_list", 's', va_list_struct, &type_va_list); - make_structure ("@quaternion", 's', quaternion_struct, &type_quaternion); - type_quaternion.type = ev_quaternion; - type_quaternion.meta = ty_basic; + build_vector_struct (&type_quaternion); { symbol_t *sym; - sym = new_symbol_type ("x", &type_float); + + sym = new_symbol_type ("v", &type_vector); sym->s.offset = 0; symtab_addsymbol (type_quaternion.t.symtab, sym); - sym = new_symbol_type ("y", &type_float); - sym->s.offset = 1; - symtab_addsymbol (type_quaternion.t.symtab, sym); - sym = new_symbol_type ("z", &type_float); - sym->s.offset = 2; - symtab_addsymbol (type_quaternion.t.symtab, sym); - sym = new_symbol_type ("w", &type_float); + + sym = new_symbol_type ("s", &type_float); sym->s.offset = 3; symtab_addsymbol (type_quaternion.t.symtab, sym); } +#define VEC_TYPE(type_name, base_type) build_vector_struct (&type_##type_name); +#include "tools/qfcc/include/vec_types.h" chain_structural_types (); } diff --git a/tools/qfcc/source/value.c b/tools/qfcc/source/value.c index f96e5c720..bd8ac599e 100644 --- a/tools/qfcc/source/value.c +++ b/tools/qfcc/source/value.c @@ -45,6 +45,8 @@ #include "QF/mathlib.h" #include "QF/va.h" +#include "QF/simd/types.h" + #include "tools/qfcc/include/qfcc.h" #include "tools/qfcc/include/def.h" #include "tools/qfcc/include/defspace.h" @@ -60,16 +62,11 @@ typedef struct { def_t *def; union { - pr_string_t string_val; - float float_val; - float vector_val[3]; - int entity_val; - int field_val; - int func_val; +#define EV_TYPE(type) pr_##type##_t type##_val; +#include "QF/progs/pr_type_names.h" +#define VEC_TYPE(type_name, base_type) pr_##type_name##_t type_name##_val; +#include "tools/qfcc/include/vec_types.h" ex_pointer_t pointer; - float quaternion_val[4]; - int int_val; - double double_val; } i; } immediate_t; @@ -243,6 +240,22 @@ new_uint_val (int uint_val) return find_value (&val); } +ex_value_t * +new_long_val (pr_long_t long_val) +{ + ex_value_t val = { .v = { .long_val = long_val } }; + set_val_type (&val, &type_long); + return find_value (&val); +} + +ex_value_t * +new_ulong_val (pr_ulong_t ulong_val) +{ + ex_value_t val = { .v = { .ulong_val = ulong_val } }; + set_val_type (&val, &type_ulong); + return find_value (&val); +} + ex_value_t * new_short_val (short short_val) { @@ -269,16 +282,197 @@ new_nil_val (type_t *type) return find_value (&val); } +ex_value_t * +new_type_value (const type_t *type, const pr_type_t *data) +{ + size_t typeSize = type_size (type) * sizeof (pr_type_t); + ex_value_t val = {}; + set_val_type (&val, (type_t *) type);//FIXME cast + memcpy (&val.v, data, typeSize); + return find_value (&val); +} + +void +value_store (pr_type_t *dst, const type_t *dstType, const expr_t *src) +{ + size_t dstSize = type_size (dstType) * sizeof (pr_type_t); + + if (src->type == ex_nil) { + memset (dst, 0, dstSize); + return; + } + if (src->type == ex_symbol && src->e.symbol->sy_type == sy_var) { + // initialized global def treated as a constant + // from the tests in cast_expr, the def is known to be constant + def_t *def = src->e.symbol->s.def; + memcpy (dst, &D_PACKED (pr_type_t, def), dstSize); + return; + } + ex_value_t *val = 0; + if (src->type == ex_value) { + val = src->e.value; + } + if (src->type == ex_symbol && src->e.symbol->sy_type == sy_const) { + val = src->e.symbol->s.value; + } + if (!val) { + internal_error (src, "unexpected constant expression type"); + } + memcpy (dst, &val->v, dstSize); +} + +const char * +get_value_string (const ex_value_t *value) +{ + const type_t *type = value->type; + const char *str = ""; + switch (type->type) { + case ev_string: + return va (0, "\"%s\"", quote_string (value->v.string_val)); + case ev_vector: + case ev_quaternion: + case ev_float: + switch (type_width (type)) { + case 1: + str = va (0, "%.9g", value->v.float_val); + break; + case 2: + str = va (0, VEC2F_FMT, VEC2_EXP (value->v.vec2_val)); + break; + case 3: + str = va (0, "[%.9g, %.9g, %.9g]", + VectorExpand (value->v.vec3_val)); + break; + case 4: + str = va (0, VEC4F_FMT, VEC4_EXP (value->v.vec4_val)); + break; + } + return va (0, "%s %s", type->name, str); + case ev_entity: + case ev_func: + return va (0, "%s %d", type->name, value->v.int_val); + case ev_field: + if (value->v.pointer.def) { + int offset = value->v.pointer.val; + offset += value->v.pointer.def->offset; + return va (0, "field %d", offset); + } else { + return va (0, "field %d", value->v.pointer.val); + } + case ev_ptr: + if (value->v.pointer.def) { + str = va (0, "<%s>", value->v.pointer.def->name); + } + return va (0, "(* %s)[%d]%s", + value->v.pointer.type + ? get_type_string (value->v.pointer.type) : "???", + value->v.pointer.val, str); + case ev_int: + switch (type_width (type)) { + case 1: + str = va (0, "%"PRIi32, value->v.int_val); + break; + case 2: + str = va (0, VEC2I_FMT, VEC2_EXP (value->v.ivec2_val)); + break; + case 3: + str = va (0, "[%"PRIi32", %"PRIi32", %"PRIi32"]", + VectorExpand (value->v.ivec3_val)); + break; + case 4: + str = va (0, VEC4I_FMT, VEC4_EXP (value->v.ivec4_val)); + break; + } + return va (0, "%s %s", type->name, str); + case ev_uint: + switch (type_width (type)) { + case 1: + str = va (0, "%"PRIu32, value->v.uint_val); + break; + case 2: + str = va (0, "[%"PRIu32", %"PRIi32"]", + VEC2_EXP (value->v.uivec2_val)); + break; + case 3: + str = va (0, "[%"PRIu32", %"PRIi32", %"PRIi32"]", + VectorExpand (value->v.uivec3_val)); + break; + case 4: + str = va (0, "[%"PRIu32", %"PRIi32", %"PRIi32", %"PRIi32"]", + VEC4_EXP (value->v.uivec4_val)); + break; + } + return va (0, "%s %s", type->name, str); + case ev_short: + return va (0, "%s %"PRIi16, type->name, value->v.short_val); + case ev_ushort: + return va (0, "%s %"PRIu16, type->name, value->v.ushort_val); + case ev_double: + switch (type_width (type)) { + case 1: + str = va (0, "%.17g", value->v.double_val); + break; + case 2: + str = va (0, VEC2D_FMT, VEC2_EXP (value->v.dvec2_val)); + break; + case 3: + str = va (0, "[%.17g, %.17g, %.17g]", + VectorExpand (value->v.dvec3_val)); + break; + case 4: + str = va (0, VEC4D_FMT, VEC4_EXP (value->v.dvec4_val)); + break; + } + return va (0, "%s %s", type->name, str); + case ev_long: + switch (type_width (type)) { + case 1: + str = va (0, "%"PRIi64, value->v.long_val); + break; + case 2: + str = va (0, VEC2L_FMT, VEC2_EXP (value->v.lvec2_val)); + break; + case 3: + str = va (0, "[%"PRIi64", %"PRIi64", %"PRIi64"]", + VectorExpand (value->v.lvec3_val)); + break; + case 4: + str = va (0, VEC4L_FMT, VEC4_EXP (value->v.lvec4_val)); + break; + } + return va (0, "%s %s", type->name, str); + case ev_ulong: + switch (type_width (type)) { + case 1: + str = va (0, "%"PRIu64, value->v.ulong_val); + break; + case 2: + str = va (0, "[%"PRIu64", %"PRIi64"]", + VEC2_EXP (value->v.ulvec2_val)); + break; + case 3: + str = va (0, "[%"PRIu64", %"PRIi64", %"PRIi64"]", + VectorExpand (value->v.ulvec3_val)); + break; + case 4: + str = va (0, "[%"PRIu64", %"PRIi64", %"PRIi64", %"PRIi64"]", + VEC4_EXP (value->v.ulvec4_val)); + break; + } + return va (0, "%s %s", type->name, str); + case ev_void: + return ""; + case ev_invalid: + return ""; + case ev_type_count: + return ""; + } + return "invalid type"; +} + static hashtab_t *string_imm_defs; -static hashtab_t *float_imm_defs; -static hashtab_t *vector_imm_defs; -static hashtab_t *entity_imm_defs; -static hashtab_t *field_imm_defs; -static hashtab_t *func_imm_defs; -static hashtab_t *pointer_imm_defs; -static hashtab_t *quaternion_imm_defs; -static hashtab_t *int_imm_defs; -static hashtab_t *double_imm_defs; +static hashtab_t *fldptr_imm_defs; +static hashtab_t *value_imm_defs; static void imm_free (void *_imm, void *unused) @@ -295,27 +489,13 @@ imm_get_hash (const void *_imm, void *_tab) if (tab == &string_imm_defs) { const char *str = pr.strings->strings + imm->i.string_val; return str ? Hash_String (str) : 0; - } else if (tab == &float_imm_defs) { - return imm->i.int_val; - } else if (tab == &vector_imm_defs) { - return Hash_Buffer (&imm->i.vector_val, sizeof (&imm->i.vector_val)); - } else if (tab == &entity_imm_defs) { - return imm->i.int_val; - } else if (tab == &field_imm_defs) { + } else if (tab == &fldptr_imm_defs) { return Hash_Buffer (&imm->i.pointer, sizeof (&imm->i.pointer)); - } else if (tab == &func_imm_defs) { - return imm->i.int_val; - } else if (tab == &pointer_imm_defs) { - return Hash_Buffer (&imm->i.pointer, sizeof (&imm->i.pointer)); - } else if (tab == &quaternion_imm_defs) { - return Hash_Buffer (&imm->i.quaternion_val, - sizeof (&imm->i.quaternion_val)); - } else if (tab == &double_imm_defs) { - return Hash_Buffer (&imm->i.double_val, sizeof (&imm->i.double_val)); - } else if (tab == &int_imm_defs) { - return imm->i.int_val; + } else if (tab == &value_imm_defs) { + size_t size = type_size (imm->def->type) * sizeof (pr_type_t); + return Hash_Buffer (&imm->i, size) ^ (uintptr_t) imm->def->type; } else { - internal_error (0, 0); + internal_error (0, "invalid immediate hash table"); } } @@ -330,28 +510,14 @@ imm_compare (const void *_imm1, const void *_imm2, void *_tab) const char *str1 = pr.strings->strings + imm1->i.string_val; const char *str2 = pr.strings->strings + imm2->i.string_val; return (str1 == str2 || (str1 && str2 && !strcmp (str1, str2))); - } else if (tab == &float_imm_defs) { - return imm1->i.float_val == imm2->i.float_val; - } else if (tab == &vector_imm_defs) { - return VectorCompare (imm1->i.vector_val, imm2->i.vector_val); - } else if (tab == &entity_imm_defs) { - return imm1->i.entity_val == imm2->i.entity_val; - } else if (tab == &field_imm_defs) { + } else if (tab == &fldptr_imm_defs) { return !memcmp (&imm1->i.pointer, &imm2->i.pointer, sizeof (imm1->i.pointer)); - } else if (tab == &func_imm_defs) { - return imm1->i.func_val == imm2->i.func_val; - } else if (tab == &pointer_imm_defs) { - return !memcmp (&imm1->i.pointer, &imm2->i.pointer, - sizeof (imm1->i.pointer)); - } else if (tab == &quaternion_imm_defs) { - return QuatCompare (imm1->i.quaternion_val, imm2->i.quaternion_val); - } else if (tab == &double_imm_defs) { - return imm1->i.double_val == imm2->i.double_val; - } else if (tab == &int_imm_defs) { - return imm1->i.int_val == imm2->i.int_val; + } else if (tab == &value_imm_defs) { + size_t size = type_size (imm1->def->type) * sizeof (pr_type_t); + return !memcmp (&imm1->i, &imm2->i, size); } else { - internal_error (0, 0); + internal_error (0, "invalid immediate hash table"); } } @@ -486,7 +652,6 @@ emit_value (ex_value_t *value, def_t *def) hashtab_t *tab = 0; type_t *type; ex_value_t val = *value; - immediate_t *imm, search; if (!string_imm_defs) { clear_immediates (); @@ -496,56 +661,36 @@ emit_value (ex_value_t *value, def_t *def) // val.type = type_nil->type; switch (val.lltype) { case ev_entity: - tab = entity_imm_defs; - type = &type_entity; - break; - case ev_field: - tab = field_imm_defs; - type = &type_field; - break; case ev_func: - tab = func_imm_defs; - type = &type_func; - break; - case ev_ptr: - tab = pointer_imm_defs; - type = &type_ptr; - break; case ev_int: case ev_uint: - if (!def || !is_float(def->type)) { - tab = int_imm_defs; - type = &type_int; - break; - } - val.v.float_val = val.v.int_val; - val.lltype = ev_float; case ev_float: - tab = float_imm_defs; - type = &type_float; + case ev_vector: + case ev_quaternion: + case ev_double: + tab = value_imm_defs; + type = val.type; + break; + case ev_field: + case ev_ptr: + tab = fldptr_imm_defs; + type = ev_types[val.lltype]; break; case ev_string: val.v.int_val = ReuseString (val.v.string_val); tab = string_imm_defs; type = &type_string; break; - case ev_vector: - tab = vector_imm_defs; - type = &type_vector; - break; - case ev_quaternion: - tab = quaternion_imm_defs; - type = &type_quaternion; - break; - case ev_double: - tab = double_imm_defs; - type = &type_double; - break; default: - internal_error (0, 0); + internal_error (0, "unexpected value type: %s", + val.type->type < ev_type_count + ? pr_type_name[val.lltype] + : va (0, "%d", val.lltype)); } + def_t search_def = { .type = type }; + immediate_t search = { .def = &search_def }; memcpy (&search.i, &val.v, sizeof (search.i)); - imm = (immediate_t *) Hash_FindElement (tab, &search); + immediate_t *imm = Hash_FindElement (tab, &search); if (imm && strcmp (imm->def->name, ".zero") == 0) { if (def) { imm = 0; //FIXME do full def aliasing @@ -614,7 +759,7 @@ emit_value (ex_value_t *value, def_t *def) break; } - memcpy (D_POINTER (void, cn), &val.v, 4 * type_size (type)); + memcpy (D_POINTER (pr_type_t, cn), &val.v, 4 * type_size (type)); make_def_imm (cn, tab, &val); @@ -630,15 +775,8 @@ clear_immediates (void) if (value_table) { Hash_FlushTable (value_table); Hash_FlushTable (string_imm_defs); - Hash_FlushTable (float_imm_defs); - Hash_FlushTable (vector_imm_defs); - Hash_FlushTable (entity_imm_defs); - Hash_FlushTable (field_imm_defs); - Hash_FlushTable (func_imm_defs); - Hash_FlushTable (pointer_imm_defs); - Hash_FlushTable (quaternion_imm_defs); - Hash_FlushTable (int_imm_defs); - Hash_FlushTable (double_imm_defs); + Hash_FlushTable (fldptr_imm_defs); + Hash_FlushTable (value_imm_defs); } else { value_table = Hash_NewTable (16381, 0, 0, 0, 0); Hash_SetHashCompare (value_table, value_get_hash, value_compare); @@ -647,49 +785,19 @@ clear_immediates (void) &string_imm_defs, 0); Hash_SetHashCompare (string_imm_defs, imm_get_hash, imm_compare); - float_imm_defs = Hash_NewTable (16381, 0, imm_free, - &float_imm_defs, 0); - Hash_SetHashCompare (float_imm_defs, imm_get_hash, imm_compare); + fldptr_imm_defs = Hash_NewTable (16381, 0, imm_free, + &fldptr_imm_defs, 0); + Hash_SetHashCompare (fldptr_imm_defs, imm_get_hash, imm_compare); - vector_imm_defs = Hash_NewTable (16381, 0, imm_free, - &vector_imm_defs, 0); - Hash_SetHashCompare (vector_imm_defs, imm_get_hash, imm_compare); - - entity_imm_defs = Hash_NewTable (16381, 0, imm_free, - &entity_imm_defs, 0); - Hash_SetHashCompare (entity_imm_defs, imm_get_hash, imm_compare); - - field_imm_defs = Hash_NewTable (16381, 0, imm_free, - &field_imm_defs, 0); - Hash_SetHashCompare (field_imm_defs, imm_get_hash, imm_compare); - - func_imm_defs = Hash_NewTable (16381, 0, imm_free, - &func_imm_defs, 0); - Hash_SetHashCompare (func_imm_defs, imm_get_hash, imm_compare); - - pointer_imm_defs = Hash_NewTable (16381, 0, imm_free, - &pointer_imm_defs, 0); - Hash_SetHashCompare (pointer_imm_defs, imm_get_hash, imm_compare); - - quaternion_imm_defs = Hash_NewTable (16381, 0, imm_free, - &quaternion_imm_defs, 0); - Hash_SetHashCompare (quaternion_imm_defs, imm_get_hash, imm_compare); - - int_imm_defs = Hash_NewTable (16381, 0, imm_free, - &int_imm_defs, 0); - Hash_SetHashCompare (int_imm_defs, imm_get_hash, imm_compare); - - double_imm_defs = Hash_NewTable (16381, 0, imm_free, - &double_imm_defs, 0); - Hash_SetHashCompare (double_imm_defs, imm_get_hash, imm_compare); + value_imm_defs = Hash_NewTable (16381, 0, imm_free, + &value_imm_defs, 0); + Hash_SetHashCompare (value_imm_defs, imm_get_hash, imm_compare); } def = make_symbol (".zero", &type_zero, 0, sc_extern)->s.def; memset (&zero_val, 0, sizeof (zero_val)); make_def_imm (def, string_imm_defs, &zero_val); - make_def_imm (def, float_imm_defs, &zero_val); - make_def_imm (def, entity_imm_defs, &zero_val); - make_def_imm (def, pointer_imm_defs, &zero_val); - make_def_imm (def, int_imm_defs, &zero_val); + make_def_imm (def, fldptr_imm_defs, &zero_val); + make_def_imm (def, value_imm_defs, &zero_val); } diff --git a/tools/qfcc/test/test-defspace.c b/tools/qfcc/test/test-defspace.c index 17d9ed12e..cbb80d623 100644 --- a/tools/qfcc/test/test-defspace.c +++ b/tools/qfcc/test/test-defspace.c @@ -104,6 +104,39 @@ test_init (void) return pass; } +static int +test_aligned_alloc (void) +{ + defspace_t *space = defspace_new (ds_virtual); + struct { + int size, align; + } allocations[6] = { + { 2, 2 }, + { 2, 2 }, + { 1, 1 }, + { 4, 4 }, + { 2, 2 }, + { 2, 2 }, + }; + int offsets[6]; + for (int i = 0; i < 6; i++) { + offsets[i] = defspace_alloc_aligned_loc (space, allocations[i].size, + allocations[i].align); + } + for (int i = 0; i < 5; i++) { + for (int j = i + 1; j < 6; j++) { + if (offsets[i] == offsets[j]) { + printf ("duplicate offset in allocations"); + printf ("%d %d %d %d %d %d\n", + offsets[0], offsets[1], offsets[2], + offsets[3], offsets[4], offsets[5]); + return 0; + } + } + } + return 1; +} + int main (int argc, const char **argv) { @@ -112,6 +145,7 @@ main (int argc, const char **argv) int pass = 1; pass &= test_init (); + pass &= test_aligned_alloc (); return !pass; } diff --git a/tools/qfcc/test/vecexpr.r b/tools/qfcc/test/vecexpr.r index 0365ed589..e4ca4489b 100644 --- a/tools/qfcc/test/vecexpr.r +++ b/tools/qfcc/test/vecexpr.r @@ -39,8 +39,8 @@ main () printf("t3(5) = %v\n", v); ret |= 1; } - v = [x, y] / 2; - if (v != [2, 2.5]) { + v = [x, y, 0] / 2; + if (v != [2, 2.5, 0]) { printf("v = %v\n", v); ret |= 1; }