Basic debug info generation, just line numbers and local defs for each

function.
This commit is contained in:
Bill Currie 2001-07-14 01:15:40 +00:00
parent 484f5494b8
commit 64e50e1ebd
6 changed files with 170 additions and 33 deletions

View file

@ -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;

View file

@ -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;

View file

@ -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

View file

@ -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");

View file

@ -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 ();

View file

@ -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;