More docs.

Enhance qfprogs qfo debugging.

Make sure functions marked as extern don't emit anything. Fixes the segfault
when building klik.
This commit is contained in:
Bill Currie 2008-08-01 13:54:24 +00:00 committed by Jeff Teunissen
parent d52df3a733
commit 9ac15436d9
12 changed files with 178 additions and 68 deletions

View file

@ -422,7 +422,7 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_
*/
#define G_EDICTNUM(p,o) NUM_FOR_EDICT(p, G_EDICT (p, o))
/** Access a a string global, converting it to a C string. Kills the program
/** Access a string global, converting it to a C string. Kills the program
if the string is invalid.
\par QC type:

View file

@ -85,6 +85,7 @@ struct def_s *get_function_def (const char *name, struct type_s *type,
struct expr_s *find_function (struct expr_s *fexpr, struct expr_s *params);
void build_scope (function_t *f, struct def_s *func, param_t *params);
function_t *new_function (const char *name);
void add_function (function_t *f);
function_t *build_code_function (function_t *f, struct expr_s *state_expr,
struct expr_s *statements);
function_t *build_builtin_function (struct def_s *def, struct expr_s *bi_val);

View file

@ -211,11 +211,33 @@ typedef struct qfo_func_s {
/** Evil source of many headaches. The whole reason I've started writing this
documentation.
relocs are always in the order:
referenced relocs
unreferenced relocs
For \c ref_op_* relocation types, \c ofs is the code section address of the
statement that needs to be adjusted.
For \c rel_def_* relocation types,
\c ofs refers to the data section address of the word that needs to be
adjusted.
For \c ref_*_def(_ofs) relocation types, \c def is the index of the
referenced def.
For \c ref_*_op relocation types, \c def is the address of
the referenced statement.
For \c ref_*_string relocation types, \c def is
always 0.
For \c ref_*_field(_ofs) relocation types, \c def is the index of
the referenced field def.
*/
typedef struct qfo_reloc_s {
pr_int_t ofs;
pr_int_t type;
pr_int_t def;
pr_int_t ofs; ///< offset of the relocation
pr_int_t type; ///< type of the relocation (::reloc_type)
pr_int_t def; ///< "def" this relocation is for
} qfo_reloc_t;
/** In-memory representation of a QFO object file.
@ -304,7 +326,37 @@ typedef struct qfo_s {
\hideinitializer
*/
#define QFO_STRING(q, o) G_GETSTR (QFO_var (q, string, o))
#define QFO_STRING(q, o) QFO_var (q, string, o)
/** Retrieve a string from the object file, converting it to a C string.
\param q pointer to ::qfo_t struct
\param s offset into object file string space
\return (char *)
\hideinitializer
*/
#define QFO_GETSTR(q, s) ((q)->strings + (s))
/** Retrieve a type string from the object file, converting it to a C string.
\param q pointer to ::qfo_t struct
\param s offset into object file type string space
\return (char *)
\hideinitializer
*/
#define QFO_TYPESTR(q, s) ((q)->types + (s))
/** Access a string global, converting it to a C string.
\param q pointer to ::qfo_t struct
\param o offset into object file data space
\return (char *)
\hideinitializer
*/
#define QFO_GSTRING(q, o) (QFO_GETSTR (q, (QFO_STRING (q, o))))
/** Access a function variable in the object file. Can be assigned to.

View file

@ -24,6 +24,7 @@ struct dfunction_s *func_find (int st_num);
void dump_strings (struct progs_s *pr);
void qfo_globals (struct qfo_s *qfo);
void qfo_functions (struct qfo_s *qfo);
void qfo_relocs (struct qfo_s *qfo);
#endif//__qfprogs_h

View file

@ -32,24 +32,34 @@
#ifndef __reloc_h
#define __reloc_h
/** \defgroup qfcc_reloc Relocation handling
\ingroup qfcc
*/
///@{
/** Relocation record types.
Types marked with * are relative and fixed up before the qfo is written.
Types marked with ! are handled by only by the linker.
Types marked with + use pr.relocs
*/
typedef enum {
rel_none,
rel_op_a_def,
rel_op_b_def,
rel_op_c_def,
rel_op_a_op,
rel_op_b_op,
rel_op_c_op,
rel_def_op,
rel_def_def,
rel_def_func,
rel_def_string,
rel_def_field,
rel_op_a_def_ofs,
rel_op_b_def_ofs,
rel_op_c_def_ofs,
rel_def_def_ofs,
rel_def_field_ofs,
rel_none, ///< no relocation
rel_op_a_def, ///< code[ref.ofs].a = def ofs
rel_op_b_def, ///< code[ref.ofs].b = def ofs
rel_op_c_def, ///< code[ref.ofs].c = def ofs
rel_op_a_op, ///< * code[ref.ofs].a = code ofs - ref.ofs
rel_op_b_op, ///< * code[ref.ofs].b = code ofs - ref.ofs
rel_op_c_op, ///< * code[ref.ofs].c = code ofs - ref.ofs
rel_def_op, ///< + data[ref.ofs] = code ofs
rel_def_def, ///< data[ref.ofs] = def ofs
rel_def_func, ///< +(sometimes) data[ref.ofs] = ofs
rel_def_string, ///< + ! data[ref.ofs] = string index
rel_def_field, ///< ! data[ref.ofs] = field def ofs
rel_op_a_def_ofs, ///< code[ref.ofs].a += def ofs
rel_op_b_def_ofs, ///< code[ref.ofs].b += def ofs
rel_op_c_def_ofs, ///< code[ref.ofs].c += def ofs
rel_def_def_ofs, ///< data[ref.ofs] += def ofs
rel_def_field_ofs, ///< data[ref.ofs] += field def ofs
} reloc_type;
typedef struct reloc_s {
@ -77,4 +87,6 @@ void reloc_def_field (struct def_s *def, int ofs);
void reloc_def_field_ofs (struct def_s *def, int ofs);
void reloc_def_op (struct ex_label_s *label, int ofs);
///@}
#endif//__reloc_h

View file

@ -49,6 +49,7 @@ static __attribute__ ((used)) const char rcsid[] =
#include "debug.h"
#include "emit.h"
#include "expr.h"
#include "function.h"
#include "immediate.h"
#include "opcodes.h"
#include "options.h"
@ -130,7 +131,7 @@ emit_statement (expr_t *e, opcode_t *op, def_t *var_a, def_t *var_b,
error (e, "ice ice baby");
abort ();
}
if (options.code.debug) {
if (options.code.debug && current_func->aux) {
pr_uint_t line = (e ? e->line : pr.source_line) - lineno_base;
if (line != pr.linenos[pr.num_linenos - 1].line) {

View file

@ -395,15 +395,19 @@ new_function (const char *name)
function_t *f;
ALLOC (1024, function_t, functions, f);
f->s_name = ReuseString (name);
f->s_file = pr.source_file;
return f;
}
void
add_function (function_t *f)
{
*pr.func_tail = f;
pr.func_tail = &f->next;
f->function_num = pr.num_functions++;
f->s_name = ReuseString (name);
f->s_file = pr.source_file;
if (options.code.debug)
f->aux = new_auxfunction ();
return f;
}
function_t *
@ -440,12 +444,12 @@ build_builtin_function (def_t *def, expr_t *bi_val)
}
f = new_function (def->name);
add_function (f);
f->builtin = bi_val->type == ex_integer ? bi_val->e.integer_val
: (int)bi_val->e.float_val;
f->def = def;
if (!def->external)
reloc_def_func (f, def->ofs);
reloc_def_func (f, def->ofs);
build_function (f);
finish_function (f);
return f;

View file

@ -190,8 +190,9 @@ qfo_globals (qfo_t *qfo)
for (i = 0; i < qfo->num_defs; i++) {
def = &qfo->defs[i];
printf ("%-5d %s %s", def->ofs, flags_string (def->flags),
qfo->strings + def->name);
printf ("%-5d %-5d %s %s %s", i, def->ofs, flags_string (def->flags),
QFO_GETSTR (qfo, def->name),
QFO_TYPESTR (qfo, def->full_type));
if (!(def->flags & QFOD_EXTERNAL))
printf (" %d", qfo->data[def->ofs].integer_var);
puts ("");
@ -222,8 +223,9 @@ qfo_relocs (qfo_t *qfo)
case rel_op_b_def:
case rel_op_c_def:
def = qfo->defs + reloc->def;
printf (" op.%c %d %d %s", reloc->type - rel_op_a_def + 'a',
reloc->ofs, def->ofs, qfo->strings + def->name);
printf (" op.%c@%d def@%d %s",
reloc->type - rel_op_a_def + 'a',
reloc->ofs, def->ofs, QFO_GETSTR (qfo, def->name));
break;
case rel_op_a_op:
case rel_op_b_op:
@ -237,41 +239,42 @@ qfo_relocs (qfo_t *qfo)
case rel_def_def:
def = qfo->defs + reloc->def;
printf (" def@%d def@%d %s", reloc->ofs, reloc->def,
qfo->strings + def->name);
QFO_GETSTR (qfo, def->name));
break;
case rel_def_func:
func = qfo->funcs + reloc->def;
printf (" def@%d func@%d %s", reloc->ofs, reloc->def,
qfo->strings + func->name);
QFO_GETSTR (qfo, func->name));
break;
case rel_def_string:
printf (" def@%d string:`%s'", reloc->ofs,
qfo->strings + qfo->data[reloc->ofs].string_var);
QFO_GSTRING (qfo, reloc->ofs));
break;
case rel_def_field:
def = qfo->defs + reloc->def;
printf (" def@%d def@%d %s", reloc->ofs, reloc->def,
qfo->strings + def->name);
QFO_GETSTR (qfo, def->name));
break;
case rel_op_a_def_ofs:
case rel_op_b_def_ofs:
case rel_op_c_def_ofs:
def = qfo->defs + reloc->def;
printf (" op.%c %d %d %s", reloc->type - rel_op_a_def + 'a',
reloc->ofs, def->ofs, qfo->strings + def->name);
printf (" op.%c@%d def@%d %s",
reloc->type - rel_op_a_def_ofs + 'a',
reloc->ofs, def->ofs, QFO_GETSTR (qfo, def->name));
break;
case rel_def_def_ofs:
def = qfo->defs + reloc->def;
printf (" def@%d def@%d+%d %s+%d", reloc->ofs, reloc->def,
qfo->data[reloc->ofs].integer_var,
qfo->strings + def->name,
QFO_GETSTR (qfo, def->name),
qfo->data[reloc->ofs].integer_var);
break;
case rel_def_field_ofs:
def = qfo->defs + reloc->def;
printf (" def@%d def@%d+%d %s+%d", reloc->ofs, reloc->def,
qfo->data[reloc->ofs].integer_var,
qfo->strings + def->name,
QFO_GETSTR (qfo, def->name),
qfo->data[reloc->ofs].integer_var);
break;
}
@ -286,3 +289,23 @@ qfo_relocs (qfo_t *qfo)
puts ("");
}
}
void
qfo_functions (qfo_t *qfo)
{
qfo_def_t *def;
qfo_func_t *func;
int i;
for (i = 0; i < qfo->num_funcs; i++) {
func = &qfo->funcs[i];
def = &qfo->defs[func->def];
printf ("%-5d %-5d %s %s %d %s", i, def->ofs,
flags_string (def->flags),
QFO_GETSTR (qfo, func->name), func->def,
QFO_GETSTR (qfo, def->name));
if (!(def->flags & QFOD_EXTERNAL))
printf (" %d", qfo->data[def->ofs].integer_var);
puts ("");
}
}

View file

@ -349,15 +349,18 @@ fixup_def (qfo_t *qfo, qfo_def_t *def, int def_num)
pr_int_t i;
qfo_reloc_t *reloc;
qfo_func_t *func;
const char *full_type = QFO_TYPESTR (qfo, def->full_type);
const char *name = QFO_GETSTR (qfo, def->name);
def->full_type = strpool_addstr (type_strings, full_type);
def->name = strpool_addstr (strings, name);
def->full_type = strpool_addstr (type_strings,
qfo->types + def->full_type);
def->name = strpool_addstr (strings, qfo->strings + def->name);
def->relocs += reloc_base;
for (i = 0, reloc = relocs.relocs + def->relocs;
i < def->num_relocs;
i++, reloc++)
reloc->def = def_num;
def->file = strpool_addstr (strings, qfo->strings + def->file);
if ((def->flags & (QFOD_LOCAL | QFOD_ABSOLUTE)))
@ -384,6 +387,9 @@ fixup_def (qfo_t *qfo, qfo_def_t *def, int def_num)
process_def (def);
}
/* Transfer global defs from the object file. Local defs are skipped because
they will be handled by add_funcs.
*/
static void
add_defs (qfo_t *qfo)
{
@ -392,12 +398,14 @@ add_defs (qfo_t *qfo)
for (s = e = qfo->defs; s - qfo->defs < qfo->num_defs; s = e) {
int def_num = global_defs.num_defs;
qfo_def_t *d;
// find the end of the current chunk of global defs
while (e - qfo->defs < qfo->num_defs && !(e->flags & QFOD_LOCAL))
e++;
defgroup_add_defs (&global_defs, s, e - s);
for (d = global_defs.defs + def_num; def_num < global_defs.num_defs;
d++, def_num++)
fixup_def (qfo, d, def_num);
// find the beginning of the next chunk of global defs
while (e - qfo->defs < qfo->num_defs && (e->flags & QFOD_LOCAL))
e++;
}
@ -647,18 +655,21 @@ define_def (const char *name, etype_t basic_type, const char *full_type,
val->integer_var = v;
memset (&d, 0, sizeof (d));
d.basic_type = basic_type;
d.full_type = strpool_addstr (type_strings, full_type);
d.name = strpool_addstr (strings, name);
d.ofs = data->size;
d.flags = QFOD_GLOBAL | flags;
if (basic_type == ev_field) {
d.relocs = relocs.num_relocs;
d.num_relocs = 1;
}
d.flags = QFOD_GLOBAL | flags;
defspace_adddata (data, val, size);
defgroup_add_defs (&global_defs, &d, 1);
process_def (global_defs.defs + global_defs.num_defs - 1);
if (basic_type == ev_field) {
int def_num = global_defs.num_defs - 1;
qfo_def_t *def = global_defs.defs + def_num;

View file

@ -79,21 +79,21 @@ count_relocs (reloc_t *reloc)
}
static void
allocate_stuff (void)
allocate_stuff (pr_info_t *pr)
{
def_t *def;
function_t *func;
num_defs = 0;
num_funcs = pr.num_functions - 1;
num_funcs = pr->num_functions - 1;
num_relocs = 0;
for (def = pr.scope->head; def; def = def->def_next) {
for (def = pr->scope->head; def; def = def->def_next) {
if (def->alias)
continue;
num_defs++;
num_relocs += count_relocs (def->refs);
}
for (func = pr.func_head; func; func = func->next) {
for (func = pr->func_head; func; func = func->next) {
num_relocs += count_relocs (func->refs);
if (func->scope) {
num_defs += func->scope->num_defs;
@ -102,7 +102,7 @@ allocate_stuff (void)
}
}
}
num_relocs += count_relocs (pr.relocs);
num_relocs += count_relocs (pr->relocs);
if (num_defs)
defs = calloc (num_defs, sizeof (qfo_def_t));
if (num_funcs)
@ -182,7 +182,7 @@ write_def (def_t *d, qfo_def_t *def, qfo_reloc_t **reloc)
}
static void
setup_data (void)
setup_data (pr_info_t *pr)
{
qfo_def_t *def = defs;
def_t *d;
@ -194,10 +194,10 @@ setup_data (void)
pr_type_t *var;
pr_lineno_t *line;
for (d = pr.scope->head; d; d = d->def_next)
for (d = pr->scope->head; d; d = d->def_next)
if (!d->alias)
write_def (d, def++, &reloc);
for (f = pr.func_head; f; f = f->next, func++) {
for (f = pr->func_head; f; f = f->next, func++) {
func->name = LittleLong (f->s_name);
func->file = LittleLong (f->s_file);
func->line = LittleLong (f->def->line);
@ -225,25 +225,25 @@ setup_data (void)
for (d = f->scope->head; d; d = d->def_next)
write_def (d, def++, &reloc);
}
for (r = pr.relocs; r; r = r->next)
for (r = pr->relocs; r; r = r->next)
if (r->type == rel_def_op)
write_one_reloc (r, &reloc, r->label->ofs);
else
write_one_reloc (r, &reloc, 0);
for (st = pr.code->code; st - pr.code->code < pr.code->size; st++) {
for (st = pr->code->code; st - pr->code->code < pr->code->size; st++) {
st->op = LittleLong (st->op);
st->a = LittleLong (st->a);
st->b = LittleLong (st->b);
st->c = LittleLong (st->c);
}
for (var = pr.near_data->data;
var - pr.near_data->data < pr.near_data->size; var++)
for (var = pr->near_data->data;
var - pr->near_data->data < pr->near_data->size; var++)
var->integer_var = LittleLong (var->integer_var);
if (pr.far_data)
for (var = pr.far_data->data;
var - pr.far_data->data < pr.far_data->size; var++)
if (pr->far_data)
for (var = pr->far_data->data;
var - pr->far_data->data < pr->far_data->size; var++)
var->integer_var = LittleLong (var->integer_var);
for (line = pr.linenos; line - pr.linenos < pr.num_linenos; line++) {
for (line = pr->linenos; line - pr->linenos < pr->num_linenos; line++) {
line->fa.addr = LittleLong (line->fa.addr);
line->line = LittleLong (line->line);
}
@ -263,8 +263,8 @@ qfo_from_progs (pr_info_t *pr)
qfo_t *qfo;
types = strpool_new ();
allocate_stuff ();
setup_data ();
allocate_stuff (pr);
setup_data (pr);
round_strings (pr->strings);
round_strings (types);

View file

@ -524,9 +524,12 @@ func_init
builtin_function
: /* emtpy */
{
$$ = build_builtin_function ($<def>-1, $<expr>0);
build_scope ($$, $$->def, current_params);
flush_scope ($$->scope, 1);
def_t *def = $<def>-1;
if (!def->external) {
$$ = build_builtin_function (def, $<expr>0);
build_scope ($$, $$->def, current_params);
flush_scope ($$->scope, 1);
}
}
;
@ -716,10 +719,12 @@ begin_function
error (0, "%s redefined", $<def>0->name);
$$ = current_func = new_function ($<def>0->name);
$$->def = $<def>0;
if (!$$->def->external)
if (!$$->def->external) {
add_function ($$);
reloc_def_func ($$, $$->def->ofs);
}
$$->code = pr.code->size;
if (options.code.debug) {
if (options.code.debug && current_func->aux) {
pr_lineno_t *lineno = new_lineno ();
$$->aux->source_line = $$->def->line;
$$->aux->line_info = lineno - pr.linenos;

View file

@ -481,7 +481,7 @@ operation_t operations[] = {
{dump_globals, qfo_globals}, // globals
{dump_strings, 0}, // strings
{dump_fields, 0}, // fields
{dump_functions, 0}, // functions
{dump_functions, qfo_functions}, // functions
{dump_lines, 0}, // lines
{dump_modules, 0}, // modules
{0, qfo_relocs}, // relocs