Allow constant initialized globals in advanced code

Use -C const-initializers to enable (or no-const-initializers to disable
in traditional/extended code).
This commit is contained in:
Bill Currie 2020-02-23 22:51:00 +09:00
parent e23aa40994
commit 607fd2e30e
5 changed files with 38 additions and 9 deletions

View file

@ -85,7 +85,8 @@ No compilation or linking is done.
.TP .TP
.B \-\-extended .B \-\-extended
Allow extended keywords in traditional mode. Allow extended keywords in traditional mode. Otherwise, it has \fIall\fP
the implications of \fB\-\-traditional\fP.
.TP .TP
.B \-F, \-\-files .B \-F, \-\-files
@ -198,9 +199,9 @@ Look for \*[progs.src] in \fBDIR\fP instead of the current directory.
.TP .TP
.B \-\-traditional .B \-\-traditional
Use traditional QuakeC syntax, semantics and \*(lqbugs\*(rq. Use traditional QuakeC syntax, semantics and \*(lqbugs\*(rq.
Also implies the \fBv6only\fP, \fBno-short-circuit\fP and Also implies the \fBv6only\fP, \fBno-short-circuit\fP,
\fBno-local-merging\fP code generation options (see \fBconst-initializers\fP and \fBno-local-merging\fP code generation options
\fBCODE GENERATION OPTIONS\fP). (see \fBCODE GENERATION OPTIONS\fP).
This is the default when using \fBprogs.src\fP mode. This is the default when using \fBprogs.src\fP mode.
.TP .TP
@ -236,15 +237,23 @@ command line.
Unsupported options are ignored. Unsupported options are ignored.
The following options are supported by \*[qfcc]'s \fB\-\-code\fP argument: The following options are supported by \*[qfcc]'s \fB\-\-code\fP argument:
.TP
.B const-initializers
Treat initialized globals as constants.
This option is implied by \fB\-\-traditional\fP and \fB\-\-extended\fP, and is
turned off by \fB\-\-advanced\fP.
.TP .TP
.B cow .B cow
Allow assignment to initialized globals. Allow assignment to initialized globals.
In Quake-C and Ruamoko, a global that has been initialized to a value is not When initialized globals are treated as constants (traditional Quake-C, or
a variable, but a named constant. when const-initializers is activated), a global that has been initialized to a
value is not a variable, but a named constant.
However, \fBqcc\fP never really enforced this. However, \fBqcc\fP never really enforced this.
The \fBcow\fP option allows \*[qfcc] to gracefully cope with QuakeC source The \fBcow\fP option allows \*[qfcc] to gracefully cope with QuakeC source
that assigns values to initialized globals in this manner. that assigns values to initialized globals in this manner.
(also known as \*(lqcopy on write\*(rq\(emnever mind the bovine connotations) (also known as \*(lqcopy on write\*(rq\(emlo and behold the bovine
connotations)
.TP .TP
.B cpp .B cpp

View file

@ -45,6 +45,7 @@ typedef struct {
unsigned progsversion; // Progs version to generate code for unsigned progsversion; // Progs version to generate code for
qboolean vector_components; // add *_[xyz] symbols for vectors qboolean vector_components; // add *_[xyz] symbols for vectors
qboolean ifstring; // expand if (str) to if (str != "") qboolean ifstring; // expand if (str) to if (str != "")
qboolean const_initializers; // initialied globals are constant
} code_options_t; } code_options_t;
typedef struct { typedef struct {

View file

@ -626,7 +626,7 @@ initialize_def (symbol_t *sym, expr_t *init, defspace_t *space,
} }
} }
sym->s.def->initialized = 1; sym->s.def->initialized = 1;
if (options.traditional) { if (options.code.const_initializers) {
sym->s.def->constant = 1; sym->s.def->constant = 1;
sym->s.def->nosave = 1; sym->s.def->nosave = 1;
} }

View file

@ -2626,6 +2626,19 @@ cast_expr (type_t *type, expr_t *e)
ex_value_t *val = 0; ex_value_t *val = 0;
if (e->type == ex_symbol && e->e.symbol->sy_type == sy_const) { if (e->type == ex_symbol && e->e.symbol->sy_type == sy_const) {
val = e->e.symbol->s.value; 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_integer_val (D_INT (def));
}
} else if (e->type == ex_value) { } else if (e->type == ex_value) {
val = e->e.value; val = e->e.value;
} else if (e->type == ex_nil) { } else if (e->type == ex_nil) {

View file

@ -194,12 +194,13 @@ code_usage (void)
printf ("%s - QuakeForge Code Compiler\n", this_program); printf ("%s - QuakeForge Code Compiler\n", this_program);
printf ("Code generation options\n"); printf ("Code generation options\n");
printf ( printf (
" [no-]const-initializers Treat initialized globals as constants.\n"
" [no-]cow Allow assignment to initialized globals.\n" " [no-]cow Allow assignment to initialized globals.\n"
" [no-]cpp Preprocess all input files with cpp.\n" " [no-]cpp Preprocess all input files with cpp.\n"
" [no-]crc Write progdefs.h crc to progs.dat.\n" " [no-]crc Write progdefs.h crc to progs.dat.\n"
" [no-]debug Generate debug information.\n" " [no-]debug Generate debug information.\n"
" [no-]fast-float Use float values directly in \"if\" statements.\n" " [no-]fast-float Use float values directly in \"if\" statements.\n"
" help Display his text.\n" " help Display this text.\n"
" [no-]local-merging Merge the local variable blocks into one.\n" " [no-]local-merging Merge the local variable blocks into one.\n"
" [no-]optimize Perform various optimizations on the code.\n" " [no-]optimize Perform various optimizations on the code.\n"
" [no-]short-circuit Generate short circuit code for logical\n" " [no-]short-circuit Generate short circuit code for logical\n"
@ -392,16 +393,19 @@ DecodeArgs (int argc, char **argv)
options.traditional = 1; options.traditional = 1;
options.advanced = false; options.advanced = false;
options.code.progsversion = PROG_ID_VERSION; options.code.progsversion = PROG_ID_VERSION;
options.code.const_initializers = true;
break; break;
case OPT_TRADITIONAL: case OPT_TRADITIONAL:
options.traditional = 2; options.traditional = 2;
options.advanced = false; options.advanced = false;
options.code.progsversion = PROG_ID_VERSION; options.code.progsversion = PROG_ID_VERSION;
options.code.const_initializers = true;
break; break;
case OPT_ADVANCED: case OPT_ADVANCED:
options.traditional = 0; options.traditional = 0;
options.advanced = true; options.advanced = true;
options.code.progsversion = PROG_VERSION; options.code.progsversion = PROG_VERSION;
options.code.const_initializers = false;
break; break;
case OPT_BLOCK_DOT: case OPT_BLOCK_DOT:
if (optarg) { if (optarg) {
@ -506,6 +510,8 @@ DecodeArgs (int argc, char **argv)
options.code.progsversion = PROG_ID_VERSION; options.code.progsversion = PROG_ID_VERSION;
else else
options.code.progsversion = PROG_VERSION; options.code.progsversion = PROG_VERSION;
} else if (!(strcasecmp (temp, "const-initializers"))) {
options.code.const_initializers = flag;
} }
temp = strtok (NULL, ","); temp = strtok (NULL, ",");
} }