mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-10 15:22:04 +00:00
Basic debug info generation, just line numbers and local defs for each
function.
This commit is contained in:
parent
484f5494b8
commit
64e50e1ebd
6 changed files with 170 additions and 33 deletions
|
@ -59,8 +59,10 @@ expr_t *binary_expr (int op, expr_t *e1, expr_t *e2);
|
|||
expr_t *unary_expr (int op, expr_t *e);
|
||||
expr_t *function_expr (expr_t *e1, expr_t *e2);
|
||||
|
||||
def_t *emit_statement (opcode_t *op, def_t *var_a, def_t *var_b, def_t *var_c);
|
||||
def_t *emit_statement (int line, opcode_t *op, def_t *var_a, def_t *var_b, def_t *var_c);
|
||||
void emit_expr (expr_t *e);
|
||||
|
||||
expr_t *error (expr_t *e, const char *fmt, ...) __attribute__((format(printf, 2,3)));
|
||||
void warning (expr_t *e, const char *fmt, ...) __attribute__((format(printf, 2,3)));
|
||||
|
||||
extern int lineno_base;
|
||||
|
|
|
@ -346,6 +346,7 @@ struct function_s
|
|||
{
|
||||
struct function_s *next;
|
||||
dfunction_t *dfunc;
|
||||
pr_auxfunction_t *aux; // debug info;
|
||||
int builtin; // if non 0, call an internal function
|
||||
int code; // first statement
|
||||
const char *file; // source file with definition
|
||||
|
@ -536,6 +537,19 @@ extern char precache_files[MAX_FILES][MAX_DATA_PATH];
|
|||
extern int precache_files_block[MAX_SOUNDS];
|
||||
extern int numfiles;
|
||||
|
||||
extern int num_auxfunctions;
|
||||
extern pr_auxfunction_t *auxfunctions;
|
||||
|
||||
extern int num_linenos;
|
||||
extern pr_lineno_t *linenos;
|
||||
|
||||
extern int num_locals;
|
||||
extern ddef_t *locals;
|
||||
|
||||
pr_auxfunction_t *new_auxfunction (void);
|
||||
pr_lineno_t *new_lineno (void);
|
||||
ddef_t *new_local (void);
|
||||
|
||||
int CopyString (const char *str);
|
||||
int ReuseString (const char *str);
|
||||
|
||||
|
@ -544,6 +558,7 @@ typedef struct {
|
|||
int version; // maximum progs version to support (eg, 6 for id)
|
||||
int warn_error; // treat warnings as errors
|
||||
int quiet; // not so much chatter
|
||||
int debug; // produce debug info
|
||||
} options_t;
|
||||
|
||||
extern options_t options;
|
||||
|
|
|
@ -34,8 +34,8 @@ YFLAGS = -d
|
|||
bin_PROGRAMS= qfcc
|
||||
|
||||
if NEW_PARSER
|
||||
qfcc_SOURCES= cmdlib.c pr_comp.c pr_def.c pr_imm.c pr_lex.c pr_opcode.c qfcc.c qc-parse.y qc-lex.l expr.c
|
||||
qfcc_SOURCES= cmdlib.c debug.c pr_comp.c pr_def.c pr_imm.c pr_lex.c pr_opcode.c qfcc.c qc-parse.y qc-lex.l expr.c
|
||||
else
|
||||
qfcc_SOURCES= cmdlib.c pr_comp.c pr_def.c pr_imm.c pr_lex.c pr_opcode.c qfcc.c
|
||||
qfcc_SOURCES= cmdlib.c debug.c pr_comp.c pr_def.c pr_imm.c pr_lex.c pr_opcode.c qfcc.c
|
||||
endif
|
||||
qfcc_LDADD= -lQFutil
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
|
||||
extern function_t *current_func;
|
||||
|
||||
int lineno_base;
|
||||
|
||||
static etype_t qc_types[] = {
|
||||
ev_void, // ex_label
|
||||
ev_void, // ex_block
|
||||
|
@ -729,11 +731,20 @@ function_expr (expr_t *e1, expr_t *e2)
|
|||
}
|
||||
|
||||
def_t *
|
||||
emit_statement (opcode_t *op, def_t *var_a, def_t *var_b, def_t *var_c)
|
||||
emit_statement (int sline, opcode_t *op, def_t *var_a, def_t *var_b, def_t *var_c)
|
||||
{
|
||||
dstatement_t *statement;
|
||||
def_t *ret;
|
||||
|
||||
if (options.debug) {
|
||||
int line = sline - lineno_base;
|
||||
|
||||
if (line != linenos[num_linenos - 1].line) {
|
||||
pr_lineno_t *lineno = new_lineno ();
|
||||
lineno->line = line;
|
||||
lineno->fa.addr = numstatements;
|
||||
}
|
||||
}
|
||||
statement = &statements[numstatements];
|
||||
numstatements++;
|
||||
statement_linenums[statement - statements] = pr_source_line;
|
||||
|
@ -763,7 +774,7 @@ emit_statement (opcode_t *op, def_t *var_a, def_t *var_b, def_t *var_c)
|
|||
def_t *emit_sub_expr (expr_t *e, def_t *dest);
|
||||
|
||||
void
|
||||
emit_branch (opcode_t *op, expr_t *e, expr_t *l)
|
||||
emit_branch (int line, opcode_t *op, expr_t *e, expr_t *l)
|
||||
{
|
||||
dstatement_t *st;
|
||||
statref_t *ref;
|
||||
|
@ -772,7 +783,7 @@ emit_branch (opcode_t *op, expr_t *e, expr_t *l)
|
|||
if (e)
|
||||
def = emit_sub_expr (e, 0);
|
||||
st = &statements[numstatements];
|
||||
emit_statement (op, def, 0, 0);
|
||||
emit_statement (line, op, def, 0, 0);
|
||||
if (l->e.label.statement) {
|
||||
if (op == op_goto)
|
||||
st->a = l->e.label.statement - st;
|
||||
|
@ -805,16 +816,16 @@ emit_function_call (expr_t *e, def_t *dest)
|
|||
arg = emit_sub_expr (earg, &parm);
|
||||
if (earg->type != ex_expr) {
|
||||
op = PR_Opcode_Find ("=", 5, arg, &parm, &parm);
|
||||
emit_statement (op, arg, &parm, 0);
|
||||
emit_statement (e->line, op, arg, &parm, 0);
|
||||
}
|
||||
}
|
||||
op = PR_Opcode_Find (va ("<CALL%d>", count), -1, &def_function, &def_void, &def_void);
|
||||
emit_statement (op, func, 0, 0);
|
||||
emit_statement (e->line, op, func, 0, 0);
|
||||
|
||||
def_ret.type = func->type->aux_type;
|
||||
if (dest) {
|
||||
op = PR_Opcode_Find ("=", 5, dest, &def_ret, &def_ret);
|
||||
emit_statement (op, &def_ret, dest, 0);
|
||||
emit_statement (e->line, op, &def_ret, dest, 0);
|
||||
return dest;
|
||||
} else {
|
||||
return &def_ret;
|
||||
|
@ -833,7 +844,7 @@ emit_assign_expr (expr_t *e, def_t *dest)
|
|||
if (def_a->type == &type_pointer) {
|
||||
def_b = emit_sub_expr (e2, 0);
|
||||
op = PR_Opcode_Find ("=", 5, def_a, def_b, def_b);
|
||||
emit_statement (op, def_b, def_a, 0);
|
||||
emit_statement (e->line, op, def_b, def_a, 0);
|
||||
} else {
|
||||
if (def_a->initialized) {
|
||||
if (options.cow) {
|
||||
|
@ -852,11 +863,11 @@ emit_assign_expr (expr_t *e, def_t *dest)
|
|||
} else {
|
||||
def_b = emit_sub_expr (e2, 0);
|
||||
op = PR_Opcode_Find ("=", 5, def_a, def_b, def_b);
|
||||
emit_statement (op, def_b, def_a, 0);
|
||||
emit_statement (e->line, op, def_b, def_a, 0);
|
||||
}
|
||||
if (dest) {
|
||||
op = PR_Opcode_Find ("=", 5, dest, def_b, def_b);
|
||||
emit_statement (op, def_b, dest, 0);
|
||||
emit_statement (e->line, op, def_b, dest, 0);
|
||||
}
|
||||
}
|
||||
return def_b;
|
||||
|
@ -949,7 +960,7 @@ emit_sub_expr (expr_t *e, def_t *dest)
|
|||
if (!dest)
|
||||
dest = PR_GetTempDef (e->e.expr.type, pr_scope);
|
||||
op = PR_Opcode_Find (operator, priority, def_a, def_b, dest);
|
||||
return emit_statement (op, def_a, def_b, dest);
|
||||
return emit_statement (e->line, op, def_a, def_b, dest);
|
||||
case ex_uexpr:
|
||||
if (e->e.expr.op == '!') {
|
||||
operator = "!";
|
||||
|
@ -969,7 +980,7 @@ emit_sub_expr (expr_t *e, def_t *dest)
|
|||
abort ();
|
||||
}
|
||||
op = PR_Opcode_Find (operator, priority, def_a, def_b, dest);
|
||||
return emit_statement (op, def_a, def_b, dest);
|
||||
return emit_statement (e->line, op, def_a, def_b, dest);
|
||||
case ex_def:
|
||||
return e->e.def;
|
||||
case ex_int:
|
||||
|
@ -1021,10 +1032,10 @@ emit_expr (expr_t *e)
|
|||
emit_assign_expr (e, 0);
|
||||
break;
|
||||
case 'n':
|
||||
emit_branch (op_ifnot, e->e.expr.e1, e->e.expr.e2);
|
||||
emit_branch (e->line, op_ifnot, e->e.expr.e1, e->e.expr.e2);
|
||||
break;
|
||||
case 'i':
|
||||
emit_branch (op_if, e->e.expr.e1, e->e.expr.e2);
|
||||
emit_branch (e->line, op_if, e->e.expr.e1, e->e.expr.e2);
|
||||
break;
|
||||
case 'c':
|
||||
emit_function_call (e, 0);
|
||||
|
@ -1032,7 +1043,7 @@ emit_expr (expr_t *e)
|
|||
case 's':
|
||||
def_a = emit_sub_expr (e->e.expr.e1, 0);
|
||||
def_b = emit_sub_expr (e->e.expr.e2, 0);
|
||||
emit_statement (op_state, def_a, def_b, 0);
|
||||
emit_statement (e->line, op_state, def_a, def_b, 0);
|
||||
break;
|
||||
default:
|
||||
warning (e, "Ignoring useless expression");
|
||||
|
@ -1048,7 +1059,7 @@ emit_expr (expr_t *e)
|
|||
PR_Statement (op_return, def, 0);
|
||||
break;
|
||||
case 'g':
|
||||
emit_branch (op_goto, 0, e->e.expr.e1);
|
||||
emit_branch (e->line, op_goto, 0, e->e.expr.e1);
|
||||
break;
|
||||
default:
|
||||
warning (e, "Ignoring useless expression");
|
||||
|
|
|
@ -204,7 +204,7 @@ opt_initializer
|
|||
if (pr_scope) {
|
||||
def_t *imm = PR_ReuseConstant ($2, 0);
|
||||
opcode_t *op = PR_Opcode_Find ("=", 5, imm, imm, current_def);
|
||||
emit_statement (op, imm, current_def, 0);
|
||||
emit_statement (pr_source_line, op, imm, current_def, 0);
|
||||
} else {
|
||||
current_def = PR_ReuseConstant ($2, current_def);
|
||||
}
|
||||
|
@ -242,20 +242,24 @@ opt_initializer
|
|||
{
|
||||
current_def = $<def>5;
|
||||
}
|
||||
']' begin_function statement_block end_function
|
||||
']'
|
||||
{
|
||||
expr_t *e = new_expr ();
|
||||
build_function ($9);
|
||||
$<expr>$ = new_expr ();
|
||||
}
|
||||
begin_function statement_block end_function
|
||||
{
|
||||
expr_t *e = $<expr>9;
|
||||
build_function ($10);
|
||||
e->type = ex_expr;
|
||||
e->e.expr.op = 's';
|
||||
e->e.expr.e1 = $3;
|
||||
e->e.expr.e2 = new_expr ();
|
||||
e->e.expr.e2->type = ex_def;
|
||||
e->e.expr.e2->e.def = $6;
|
||||
e->next = $10;
|
||||
e->next = $11;
|
||||
|
||||
emit_function ($9, e);
|
||||
finish_function ($9);
|
||||
emit_function ($10, e);
|
||||
finish_function ($10);
|
||||
}
|
||||
;
|
||||
|
||||
|
@ -265,6 +269,15 @@ begin_function
|
|||
$$ = current_func = new_function ();
|
||||
$$->def = current_def;
|
||||
$$->code = numstatements;
|
||||
if (options.debug) {
|
||||
pr_lineno_t *lineno = new_lineno ();
|
||||
$$->aux = new_auxfunction ();
|
||||
$$->aux->source_line = pr_source_line;
|
||||
$$->aux->line_info = lineno - linenos;
|
||||
$$->aux->local_defs = num_locals;
|
||||
|
||||
lineno->fa.func = $$->aux - auxfunctions;
|
||||
}
|
||||
pr_scope = current_def;
|
||||
build_scope ($$, current_def);
|
||||
}
|
||||
|
@ -559,6 +572,21 @@ finish_function (function_t *f)
|
|||
df->parm_start = 0;
|
||||
for (i = 0; i < df->numparms; i++)
|
||||
df->parm_size[i] = type_size[f->def->type->parm_types[i]->type];
|
||||
|
||||
if (f->aux) {
|
||||
def_t *def;
|
||||
f->aux->function = df - functions;
|
||||
for (def = f->def->scope_next; def; def = def->scope_next) {
|
||||
if (def->name) {
|
||||
ddef_t *d = new_local ();
|
||||
d->type = def->type->type;
|
||||
d->ofs = def->ofs;
|
||||
d->s_name = ReuseString (def->name);
|
||||
|
||||
f->aux->num_locals++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -567,6 +595,8 @@ emit_function (function_t *f, expr_t *e)
|
|||
//PR_PrintType (f->def->type);
|
||||
//printf (" %s =\n", f->def->name);
|
||||
|
||||
lineno_base = f->aux->source_line;
|
||||
|
||||
pr_scope = f->def;
|
||||
while (e) {
|
||||
//print_expr (e);
|
||||
|
@ -575,7 +605,7 @@ emit_function (function_t *f, expr_t *e)
|
|||
emit_expr (e);
|
||||
e = e->next;
|
||||
}
|
||||
emit_statement (op_done, 0, 0, 0);
|
||||
emit_statement (pr_source_line, op_done, 0, 0, 0);
|
||||
PR_FlushScope (pr_scope);
|
||||
pr_scope = 0;
|
||||
PR_ResetTempDefs ();
|
||||
|
|
|
@ -41,6 +41,7 @@ options_t options;
|
|||
|
||||
char sourcedir[1024];
|
||||
char destfile[1024];
|
||||
char debugfile[1024];
|
||||
|
||||
float pr_globals[MAX_REGS];
|
||||
int numpr_globals;
|
||||
|
@ -57,7 +58,7 @@ int numfunctions;
|
|||
|
||||
ddef_t globals[MAX_GLOBALS];
|
||||
int numglobaldefs;
|
||||
int num_locals;
|
||||
int num_localdefs;
|
||||
|
||||
ddef_t fields[MAX_FIELDS];
|
||||
int numfielddefs;
|
||||
|
@ -232,6 +233,7 @@ WriteData (int crc)
|
|||
def_t *def;
|
||||
ddef_t *dd;
|
||||
dprograms_t progs;
|
||||
pr_debug_header_t debug;
|
||||
FILE *h;
|
||||
int i;
|
||||
|
||||
|
@ -272,7 +274,7 @@ WriteData (int crc)
|
|||
printf ("%6i statements\n", numstatements);
|
||||
printf ("%6i functions\n", numfunctions);
|
||||
printf ("%6i globaldefs\n", numglobaldefs);
|
||||
printf ("%6i locals size\n", num_locals);
|
||||
printf ("%6i locals size\n", num_localdefs);
|
||||
printf ("%6i fielddefs\n", numfielddefs);
|
||||
printf ("%6i pr_globals\n", numpr_globals);
|
||||
}
|
||||
|
@ -346,8 +348,55 @@ WriteData (int crc)
|
|||
|
||||
fseek (h, 0, SEEK_SET);
|
||||
SafeWrite (h, &progs, sizeof (progs));
|
||||
fclose (h);
|
||||
|
||||
fseek (h, 0, SEEK_SET);
|
||||
if (!options.debug) {
|
||||
fclose (h);
|
||||
return;
|
||||
}
|
||||
|
||||
debug.version = LittleLong (PROG_DEBUG_VERSION);
|
||||
CRC_Init (&debug.crc);
|
||||
while ((i = fgetc (h)) != EOF)
|
||||
CRC_ProcessByte (&debug.crc, i);
|
||||
fclose (h);
|
||||
debug.crc = LittleShort (debug.crc);
|
||||
debug.you_tell_me_and_we_will_both_know = 0;
|
||||
|
||||
h = SafeOpenWrite (debugfile);
|
||||
SafeWrite (h, &debug, sizeof (debug));
|
||||
|
||||
debug.auxfunctions = LittleLong (ftell (h));
|
||||
debug.num_auxfunctions = LittleLong (num_auxfunctions);
|
||||
for (i = 0; i < num_auxfunctions; i++) {
|
||||
auxfunctions[i].function = LittleLong (auxfunctions[i].function);
|
||||
auxfunctions[i].source_line = LittleLong (auxfunctions[i].source_line);
|
||||
auxfunctions[i].line_info = LittleLong (auxfunctions[i].line_info);
|
||||
auxfunctions[i].local_defs = LittleLong (auxfunctions[i].local_defs);
|
||||
auxfunctions[i].num_locals = LittleLong (auxfunctions[i].num_locals);
|
||||
}
|
||||
SafeWrite (h, auxfunctions, num_auxfunctions * sizeof (auxfunctions[0]));
|
||||
|
||||
debug.linenos = LittleLong (ftell (h));
|
||||
debug.num_linenos = LittleLong (num_linenos);
|
||||
for (i = 0; i < num_linenos; i++) {
|
||||
linenos[i].fa.addr = LittleLong (linenos[i].fa.addr);
|
||||
linenos[i].line = LittleLong (linenos[i].line);
|
||||
}
|
||||
SafeWrite (h, linenos, num_linenos * sizeof (linenos[0]));
|
||||
|
||||
debug.locals = LittleLong (ftell (h));
|
||||
debug.num_locals = LittleLong (num_locals);
|
||||
for (i = 0; i < num_locals; i++) {
|
||||
locals[i].type = LittleShort (locals[i].type);
|
||||
locals[i].ofs = LittleShort (locals[i].ofs);
|
||||
locals[i].s_name = LittleLong (locals[i].s_name);
|
||||
}
|
||||
SafeWrite (h, locals, num_locals * sizeof (locals[0]));
|
||||
|
||||
fseek (h, 0, SEEK_SET);
|
||||
SafeWrite (h, &debug, sizeof (debug));
|
||||
fclose (h);
|
||||
}
|
||||
|
||||
|
||||
|
@ -642,6 +691,7 @@ PR_FinishCompilation (void)
|
|||
qboolean errors = false;
|
||||
function_t *f;
|
||||
def_t *def;
|
||||
expr_t e;
|
||||
|
||||
// check to make sure all functions prototyped have code
|
||||
for (d = pr.def_head.def_next; d; d = d->def_next) {
|
||||
|
@ -658,6 +708,13 @@ PR_FinishCompilation (void)
|
|||
if (errors)
|
||||
return !errors;
|
||||
|
||||
if (options.debug) {
|
||||
e.type = ex_string;
|
||||
e.e.string_val = debugfile;
|
||||
PR_ReuseConstant (&e, PR_GetDef (&type_string, ".debug_file", 0,
|
||||
&numpr_globals));
|
||||
}
|
||||
|
||||
for (def = pr.def_head.def_next; def; def = def->def_next) {
|
||||
if (def->scope)
|
||||
continue;
|
||||
|
@ -667,15 +724,15 @@ PR_FinishCompilation (void)
|
|||
for (f = pr_functions; f; f = f->next) {
|
||||
if (f->builtin)
|
||||
continue;
|
||||
if (f->def->num_locals > num_locals)
|
||||
num_locals = f->def->num_locals;
|
||||
if (f->def->num_locals > num_localdefs)
|
||||
num_localdefs = f->def->num_locals;
|
||||
f->dfunc->parm_start = numpr_globals;
|
||||
for (def = f->def->scope_next; def; def = def->scope_next) {
|
||||
def->ofs += numpr_globals;
|
||||
PR_RelocateRefs (def);
|
||||
}
|
||||
}
|
||||
numpr_globals += num_locals;
|
||||
numpr_globals += num_localdefs;
|
||||
|
||||
return !errors;
|
||||
}
|
||||
|
@ -893,6 +950,10 @@ Options: \n\
|
|||
options.version = PROG_ID_VERSION;
|
||||
}
|
||||
|
||||
if (CheckParm ("--debug")) {
|
||||
options.debug = 1;
|
||||
}
|
||||
|
||||
// FIXME eww, really must go to getopt
|
||||
if (CheckParm ("--warn=error")) {
|
||||
options.warn_error = 1;
|
||||
|
@ -913,8 +974,26 @@ Options: \n\
|
|||
Error ("No destination filename. qfcc --help for info.\n");
|
||||
|
||||
strcpy (destfile, com_token);
|
||||
if (!options.quiet)
|
||||
if (!options.quiet) {
|
||||
printf ("outputfile: %s\n", destfile);
|
||||
}
|
||||
if (options.debug) {
|
||||
char *s;
|
||||
strcpy (debugfile, com_token);
|
||||
|
||||
s = debugfile + strlen (debugfile);
|
||||
while (s-- > debugfile) {
|
||||
if (*s == '.')
|
||||
break;
|
||||
if (*s == '/' || *s == '\\') {
|
||||
s = debugfile + strlen (debugfile);
|
||||
break;
|
||||
}
|
||||
}
|
||||
strcpy (s, ".sym");
|
||||
if (!options.quiet)
|
||||
printf ("debug file: %s\n", debugfile);
|
||||
}
|
||||
|
||||
pr_dumpasm = false;
|
||||
|
||||
|
|
Loading…
Reference in a new issue