Fix several double-related bug

float is promoted to double through ... for non-v6 code.
PR_Sprintf has custom param access via P_*, messed up doubles.
This commit is contained in:
Bill Currie 2020-02-14 18:15:34 +09:00
parent eb7f825158
commit 2cd62fe01b
8 changed files with 27 additions and 6 deletions

View file

@ -202,6 +202,8 @@ PR_LoadProgsFile (progs_t *pr, QFile *file, int size)
base -= sizeof (progs); // offsets are from file start base -= sizeof (progs); // offsets are from file start
heap = ((byte *) pr->progs + pr->progs_size + pr->pr_edictareasize); heap = ((byte *) pr->progs + pr->progs_size + pr->pr_edictareasize);
pr->float_promoted = progs.version == PROG_VERSION;
if (pr->edicts) { if (pr->edicts) {
*pr->edicts = (edict_t *)((byte *) pr->progs + pr->progs_size); *pr->edicts = (edict_t *)((byte *) pr->progs + pr->progs_size);
} }

View file

@ -77,6 +77,7 @@ VISIBLE const char *pr_type_name[ev_type_count] = {
"integer", "integer",
"uinteger", "uinteger",
"short", "short",
"double",
"invalid", "invalid",
}; };

View file

@ -649,6 +649,8 @@ free_fmt_item (fmt_item_t *fi)
#undef P_var #undef P_var
#define P_var(p,n,t) (args[n]->t##_var) #define P_var(p,n,t) (args[n]->t##_var)
#undef P_DOUBLE
#define P_DOUBLE(p,n) (*(double *) (args[n]))
VISIBLE void VISIBLE void
PR_Sprintf (progs_t *pr, dstring_t *result, const char *name, PR_Sprintf (progs_t *pr, dstring_t *result, const char *name,
const char *format, int count, pr_type_t **args) const char *format, int count, pr_type_t **args)

View file

@ -305,6 +305,19 @@ enum {
*/ */
#define QFO_var(q, s, t, o) ((q)->spaces[s].d.data[o].t##_var) #define QFO_var(q, s, t, o) ((q)->spaces[s].d.data[o].t##_var)
/** Access a double variable in the object file. Can be assigned to.
\par QC type:
\c double
\param q pointer to ::qfo_t struct
\param s space index
\param o offset into object file data space
\return double lvalue
\hideinitializer
*/
#define QFO_DOUBLE(q, s, o) (*(double *) ((q)->spaces[s].d.data + o))
/** Access a float variable in the object file. Can be assigned to. /** Access a float variable in the object file. Can be assigned to.
\par QC type: \par QC type:

View file

@ -92,6 +92,7 @@ extern pr_info_t pr;
#define GETSTR(s) (pr.strings->strings + (s)) #define GETSTR(s) (pr.strings->strings + (s))
#define D_var(t, d) ((d)->space->data[(d)->offset].t##_var) #define D_var(t, d) ((d)->space->data[(d)->offset].t##_var)
#define D_DOUBLE(d) (*(double *) ((d)->space->data + (d)->offset))
#define D_FLOAT(d) D_var (float, d) #define D_FLOAT(d) D_var (float, d)
#define D_INT(d) D_var (integer, d) #define D_INT(d) D_var (integer, d)
#define D_VECTOR(d) D_var (vector, d) #define D_VECTOR(d) D_var (vector, d)

View file

@ -867,7 +867,7 @@ expr_double (expr_t *e)
if (e->type == ex_symbol && e->e.symbol->sy_type == sy_var if (e->type == ex_symbol && e->e.symbol->sy_type == sy_var
&& e->e.symbol->s.def->constant && e->e.symbol->s.def->constant
&& is_double (e->e.symbol->s.def->type)) && is_double (e->e.symbol->s.def->type))
return D_FLOAT (e->e.symbol->s.def); return D_DOUBLE (e->e.symbol->s.def);
internal_error (e, "not a double constant"); internal_error (e, "not a double constant");
} }
@ -1915,6 +1915,10 @@ build_function_call (expr_t *fexpr, type_t *ftype, expr_t *params)
if (is_integer_val (e) if (is_integer_val (e)
&& options.code.progsversion == PROG_ID_VERSION) && options.code.progsversion == PROG_ID_VERSION)
convert_int (e); convert_int (e);
if (is_float (get_type (e))
&& options.code.progsversion != PROG_ID_VERSION) {
t = &type_double;
}
if (is_integer_val (e) && options.warnings.vararg_integer) if (is_integer_val (e) && options.warnings.vararg_integer)
warning (e, "passing integer constant into ... function"); warning (e, "passing integer constant into ... function");
} }
@ -2611,8 +2615,7 @@ cast_expr (type_t *type, expr_t *e)
e->e.value = convert_value (val, type); e->e.value = convert_value (val, type);
e->type = ex_value; e->type = ex_value;
c = e; c = e;
} else if ((is_float (type) && is_integral (e_type)) } else if (is_scalar (type) && is_scalar (e_type)) {
|| (is_integral (type) && is_float (e_type))) {
c = new_unary_expr ('C', e); c = new_unary_expr ('C', e);
c->e.expr.type = type; c->e.expr.type = type;
} else if (e->type == ex_uexpr && e->e.expr.op == '.') { } else if (e->type == ex_uexpr && e->e.expr.op == '.') {

View file

@ -958,8 +958,7 @@ expr_cast (sblock_t *sblock, expr_t *e, operand_t **op)
statement_t *s; statement_t *s;
src_type = get_type (e->e.expr.e1); src_type = get_type (e->e.expr.e1);
if ((src_type->type == ev_integer && type->type == ev_float) if (is_scalar (src_type) && is_scalar (type)) {
|| (src_type->type == ev_float && type->type == ev_integer)) {
operand_t *src = 0; operand_t *src = 0;
sblock = statement_subexpr (sblock, e->e.expr.e1, &src); sblock = statement_subexpr (sblock, e->e.expr.e1, &src);
*op = temp_operand (e->e.expr.type); *op = temp_operand (e->e.expr.type);

View file

@ -1,6 +1,6 @@
void printf (string fmt, ...) = #0; void printf (string fmt, ...) = #0;
float (string s) stof = #0; float (string s) stof = #0;
float (float x) sqrt = #0; @overload float (float x) sqrt = #0;
float float
heron (float a, float b, float c) heron (float a, float b, float c)