[qfcc] Make the meaning of vec * vec selectable

Currently only via pragma (not command line options), but I needed to
test the concept. Converting legacy code is just too error prone.
Telling the compiler how to treat the operator makes more sense. When *
acts as @dot with Ruamoko progs, the result is automatically aliased as
a float as this is the legacy meaning (ie, float result for dot
product).
This commit is contained in:
Bill Currie 2022-02-06 20:05:35 +09:00
parent ff08ef3fa3
commit 5f6e0767d7
5 changed files with 57 additions and 3 deletions

View file

@ -49,6 +49,10 @@ typedef struct {
qboolean promote_float; // promote float through ...
} code_options_t;
typedef struct {
int vector_mult; // operation for vector * vector
} math_options_t;
typedef struct {
qboolean promote; // Promote warnings to errors
qboolean cow; // Warn on copy-on-write detection
@ -93,6 +97,7 @@ typedef struct {
typedef struct {
code_options_t code; // Code generation options
math_options_t math; // Various math options
warn_options_t warnings; // Warning options
notice_options_t notices; // Notice options
bug_options_t bug; // Bug options

View file

@ -745,9 +745,15 @@ vector_compare (int op, expr_t *e1, expr_t *e2)
static expr_t *vector_multiply (int op, expr_t *e1, expr_t *e2)
{
expr_t *e = new_binary_expr ('*', e1, e2);
if (options.code.progsversion < PROG_VERSION) {
if (options.math.vector_mult == DOT) {
// vector * vector is dot product in v6 progs (ick)
e->e.expr.type = &type_float;
e->e.expr.op = DOT;
if (options.code.progsversion == PROG_VERSION) {
e->e.expr.type = &type_vector;
e = new_alias_expr (&type_float, e);
} else {
e->e.expr.type = &type_float;
}
} else {
// component-wise multiplication
e->e.expr.type = &type_vector;

View file

@ -51,6 +51,9 @@
#include "tools/qfcc/include/options.h"
#include "tools/qfcc/include/qfcc.h"
#include "tools/qfcc/include/strpool.h"
#include "tools/qfcc/include/type.h"
#include "tools/qfcc/source/qc-parse.h"
const char *this_program;
const char **source_files;
@ -720,6 +723,8 @@ DecodeArgs (int argc, char **argv)
options.code.local_merging = false;
if (options.code.vector_components == (qboolean) -1)
options.code.vector_components = true;
if (options.math.vector_mult == 0)
options.math.vector_mult = DOT;
}
if (!options.code.progsversion)
options.code.progsversion = PROG_VERSION;
@ -736,6 +741,8 @@ DecodeArgs (int argc, char **argv)
options.code.local_merging = true;
if (options.code.vector_components == (qboolean) -1)
options.code.vector_components = false;
if (options.math.vector_mult == 0)
options.math.vector_mult = options.advanced == 1 ? DOT : '*';
} else {
options.code.promote_float = 0;
}

View file

@ -50,6 +50,8 @@
#include "tools/qfcc/include/strpool.h"
#include "tools/qfcc/include/type.h"
#include "tools/qfcc/source/qc-parse.h"
typedef struct pragma_arg_s {
struct pragma_arg_s *next;
const char *arg;
@ -139,7 +141,7 @@ static void
set_optimize (pragma_arg_t *args)
{
if (!args) {
warning (0, "missing warn flag");
warning (0, "missing optimize flag");
return;
}
const char *flag = args->arg;
@ -153,6 +155,37 @@ set_optimize (pragma_arg_t *args)
}
}
static pragma_arg_t *
set_vector_mult (pragma_arg_t *args)
{
if (!args) {
warning (0, "missing vector_mult arg");
return args;
}
const char *op = args->arg;
if (!strcmp (op, "@dot")) {
options.math.vector_mult = DOT;
} else {
warning (0, "unknown vector_mult arg: %s", op);
}
return args->next;
}
static void
set_math (pragma_arg_t *args)
{
if (!args) {
warning (0, "missing math arg");
return;
}
while (args) {
const char *a = args->arg;
if (!strcmp (a, "vector_mult")) {
args = set_vector_mult (args->next);
}
}
}
void
pragma_process ()
{
@ -175,6 +208,8 @@ pragma_process ()
set_warn (pragma_args->next);
} else if (!strcmp (id, "optimize")) {
set_optimize (pragma_args->next);
} else if (!strcmp (id, "math")) {
set_math (pragma_args->next);
} else {
warning (0, "unknown pragma: '%s'", id);
}

View file

@ -284,6 +284,7 @@ STRING \"(\\.|[^"\\])*\"
BEGIN (GRAB_OTHER); // ignore rest of line
}
<PRAGMA>{ID} { pragma_add_arg (yytext); }
<PRAGMA>@{ID} { pragma_add_arg (yytext); }
<*>\r*\n {
if (YY_START == PRAGMA) {