mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-25 22:01:33 +00:00
Merge branch 'master' into wip-rua_scene
This commit is contained in:
commit
fe891dd70b
48 changed files with 2121 additions and 1408 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
#include <stdint.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#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"]"
|
||||
|
|
|
@ -31,8 +31,6 @@
|
|||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#define _GNU_SOURCE // for qsort_r
|
||||
|
||||
#ifdef HAVE_STRING_H
|
||||
# include <string.h>
|
||||
#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) {
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include <ctype.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#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);
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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++;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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}
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
||||
///@}
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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 = "<void>";
|
||||
break;
|
||||
case ev_invalid:
|
||||
label = "<invalid>";
|
||||
break;
|
||||
case ev_type_count:
|
||||
label = "<type_count>";
|
||||
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;
|
||||
|
||||
|
|
|
@ -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 ("");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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];
|
||||
|
|
145
tools/qfcc/source/expr_cast.c
Normal file
145
tools/qfcc/source/expr_cast.c
Normal file
|
@ -0,0 +1,145 @@
|
|||
/*
|
||||
expr_cast.c
|
||||
|
||||
expression casting
|
||||
|
||||
Copyright (C) 2022 Bill Currie <bill@taniwha.org>
|
||||
|
||||
Author: Bill Currie <bill@taniwha.org>
|
||||
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 <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#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;
|
||||
}
|
172
tools/qfcc/source/expr_vector.c
Normal file
172
tools/qfcc/source/expr_vector.c
Normal file
|
@ -0,0 +1,172 @@
|
|||
/*
|
||||
expr_vector.c
|
||||
|
||||
vector expressions
|
||||
|
||||
Copyright (C) 2022 Bill Currie <bill@taniwha.org>
|
||||
|
||||
Author: Bill Currie <bill@taniwha.org>
|
||||
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 <strings.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#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;
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
|
||||
#include <QF/hash.h>
|
||||
|
||||
#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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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")))
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 ();
|
||||
}
|
||||
|
|
|
@ -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 "<void>";
|
||||
case ev_invalid:
|
||||
return "<invalid>";
|
||||
case ev_type_count:
|
||||
return "<type_count>";
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue