mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-10 23:32:09 +00:00
Enhanced type encoding.
This creates a compact representation of types as seen by qfcc. This is intended mainly for debuggers.
This commit is contained in:
parent
0f0ed3dae2
commit
7251bc91fa
6 changed files with 369 additions and 4 deletions
|
@ -2,5 +2,5 @@ AUTOMAKE_OPTIONS= foreign
|
|||
|
||||
EXTRA_DIST= class.h codespace.h cpp.h debug.h def.h emit.h expr.h \
|
||||
function.h grab.h idstuff.h immediate.h linker.h method.h \
|
||||
obj_file.h opcodes.h options.h qfcc.h qfprogs.h reloc.h strpool.h \
|
||||
struct.h switch.h symtab.h type.h
|
||||
obj_file.h obj_type.h opcodes.h options.h qfcc.h qfprogs.h reloc.h \
|
||||
strpool.h struct.h switch.h symtab.h type.h
|
||||
|
|
105
tools/qfcc/include/obj_type.h
Normal file
105
tools/qfcc/include/obj_type.h
Normal file
|
@ -0,0 +1,105 @@
|
|||
/*
|
||||
obj_type.h
|
||||
|
||||
object file type encoding support
|
||||
|
||||
Copyright (C) 2011 Bill Currie <bill@taniwha.org>
|
||||
|
||||
Author: Bill Currie <bill@taniwha.org>
|
||||
Date: 2011/02/18
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to:
|
||||
|
||||
Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA
|
||||
|
||||
$Id$
|
||||
*/
|
||||
|
||||
#ifndef __obj_type_h
|
||||
#define __obj_type_h
|
||||
|
||||
/** \defgroup qfcc_qfo_type Object file type encoding
|
||||
\ingroup qfcc_qfo
|
||||
|
||||
All \c pointer_t \c type fields are pointers within the type qfo_space.
|
||||
*/
|
||||
//@{
|
||||
|
||||
#include "QF/pr_comp.h"
|
||||
|
||||
#include "type.h"
|
||||
|
||||
typedef struct qfot_ptrfld_s {
|
||||
pointer_t type; ///< referenced type
|
||||
} qfot_ptrfld_t;
|
||||
|
||||
typedef struct qfot_func_s {
|
||||
pointer_t return_type; ///< return type of function
|
||||
pr_int_t num_params; ///< ones compliment count of paramenters
|
||||
///< -ve values indicate number of real
|
||||
///< params
|
||||
pointer_t param_types[1]; ///< variable length list of parameter
|
||||
///< types
|
||||
} qfot_func_t;
|
||||
|
||||
typedef struct qfot_var_t {
|
||||
pointer_t type; ///< type of field or self reference for
|
||||
///< enum
|
||||
string_t name; ///< name of field/enumerator
|
||||
pr_int_t offset; ///< value for enum, 0 for union
|
||||
} qfot_var_t;
|
||||
|
||||
typedef struct qfot_struct_s {
|
||||
string_t tag; ///< struct/union/enum tag
|
||||
pr_int_t num_fields; ///< number of fields/enumerators
|
||||
qfot_var_t fields[1]; ///< variable length list of
|
||||
///< fields/enumerators
|
||||
} qfot_struct_t;
|
||||
|
||||
typedef struct qfot_array_s {
|
||||
pointer_t type; ///< element type
|
||||
pr_int_t base; ///< start index of array
|
||||
pr_int_t size; ///< number of elements in array
|
||||
} qfot_array_t;
|
||||
|
||||
/** QFO type encoding.
|
||||
|
||||
\note As this holds a union of all type representations, and those
|
||||
representations may contain variable arrays, sizeof() will return only
|
||||
one, rather useless, value. It is also not suitable for direct use in
|
||||
arrays.
|
||||
*/
|
||||
typedef struct qfot_type_s {
|
||||
pr_int_t ty; ///< meta type: ty_type_e
|
||||
pr_int_t size; ///< total word size of this encoding
|
||||
string_t encoding; ///< Objective-QC encoding
|
||||
union {
|
||||
pr_int_t type; ///< basic type: etype_t
|
||||
qfot_ptrfld_t ptrfld; ///< ty_none, ev_pointer/ev_field
|
||||
qfot_func_t func; ///< ty_none, ev_func
|
||||
qfot_struct_t strct; ///< ty_struct/ty_union/ty_enum
|
||||
qfot_array_t array; ///< ty_array
|
||||
pointer_t class; ///< ty_class
|
||||
} t;
|
||||
} qfot_type_t;
|
||||
|
||||
struct type_s;
|
||||
struct def_s *qfo_encode_type (struct type_s *type);
|
||||
|
||||
//@}
|
||||
|
||||
#endif//__obj_type_h
|
|
@ -67,6 +67,7 @@ typedef struct pr_info_s {
|
|||
struct defspace_s *near_data;
|
||||
struct defspace_s *far_data;
|
||||
struct defspace_s *entity_data;
|
||||
struct defspace_s *type_data;
|
||||
|
||||
struct symtab_s *symtab;
|
||||
|
||||
|
|
|
@ -75,6 +75,8 @@ typedef struct type_s {
|
|||
} t;
|
||||
struct type_s *next;
|
||||
int freeable;
|
||||
const char *encoding; ///< Objective-QC encoding
|
||||
struct def_s *type_def; ///< offset of qfo encodoing
|
||||
} type_t;
|
||||
|
||||
typedef struct {
|
||||
|
|
|
@ -55,8 +55,8 @@ common_src=\
|
|||
class.c codespace.c constfold.c cpp.c debug.c def.c defspace.c \
|
||||
diagnostic.c dot_expr.c dot_flow.c emit.c \
|
||||
expr.c function.c grab.c idstuff.c immediate.c linker.c method.c \
|
||||
obj_stub.c opcodes.c options.c qfcc.c reloc.c statements.c strpool.c \
|
||||
struct.c switch.c symtab.c type.c
|
||||
obj_stub.c obj_type.c opcodes.c options.c qfcc.c reloc.c statements.c \
|
||||
strpool.c struct.c switch.c symtab.c type.c
|
||||
|
||||
qfcc_SOURCES= qc-lex.l qc-parse.y $(common_src)
|
||||
qfcc_LDADD= $(QFCC_LIBS)
|
||||
|
|
257
tools/qfcc/source/obj_type.c
Normal file
257
tools/qfcc/source/obj_type.c
Normal file
|
@ -0,0 +1,257 @@
|
|||
/*
|
||||
obj_type.c
|
||||
|
||||
object file type encoding support
|
||||
|
||||
Copyright (C) 2011 Bill Currie <bill@taniwha.org>
|
||||
|
||||
Author: Bill Currie <bill@taniwha.org>
|
||||
Date: 2011/02/18
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to:
|
||||
|
||||
Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA
|
||||
|
||||
$Id$
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
static __attribute__ ((used)) const char rcsid[] = "$Id$";
|
||||
|
||||
#ifdef HAVE_STRING_H
|
||||
# include <string.h>
|
||||
#endif
|
||||
#ifdef HAVE_STRINGS_H
|
||||
# include <strings.h>
|
||||
#endif
|
||||
#include <alloca.h>
|
||||
|
||||
#include "compat.h"
|
||||
|
||||
#include "class.h"
|
||||
#include "def.h"
|
||||
#include "defspace.h"
|
||||
#include "diagnostic.h"
|
||||
#include "emit.h"
|
||||
#include "immediate.h"
|
||||
#include "obj_type.h"
|
||||
#include "qfcc.h"
|
||||
#include "reloc.h"
|
||||
#include "symtab.h"
|
||||
|
||||
typedef def_t *(*encode_f) (type_t *type);
|
||||
|
||||
static int
|
||||
encoding_string (const char *string)
|
||||
{
|
||||
int str;
|
||||
|
||||
str = ReuseString (string);
|
||||
return str;
|
||||
}
|
||||
|
||||
static def_t *
|
||||
qfo_new_encoding (type_t *type, int size)
|
||||
{
|
||||
qfot_type_t *enc;
|
||||
def_t *def;
|
||||
def_t dummy;
|
||||
string_t enc_str = encoding_string (type->encoding);
|
||||
|
||||
size += sizeof (qfot_type_t) - sizeof (enc->t);
|
||||
size /= sizeof (pr_type_t);
|
||||
|
||||
def = new_def (type->encoding, 0, pr.type_data, st_static);
|
||||
def->offset = defspace_new_loc (pr.type_data, size);
|
||||
|
||||
enc = D_POINTER (qfot_type_t, def);
|
||||
enc->ty = type->ty;
|
||||
enc->size = size;
|
||||
enc->encoding = enc_str;
|
||||
dummy.space = pr.type_data;
|
||||
dummy.offset = POINTER_OFS (pr.type_data, &enc->encoding);
|
||||
reloc_def_string (&dummy);
|
||||
return def;
|
||||
}
|
||||
|
||||
static def_t *
|
||||
qfo_encode_func (type_t *type)
|
||||
{
|
||||
int param_count;
|
||||
int size;
|
||||
qfot_type_t *enc;
|
||||
qfot_func_t *func;
|
||||
def_t *return_type_def;
|
||||
def_t **param_type_defs;
|
||||
def_t *def;
|
||||
int i;
|
||||
|
||||
param_count = type->t.func.num_params;
|
||||
if (param_count < 0)
|
||||
param_count = ~param_count;
|
||||
param_type_defs = alloca (param_count * sizeof (def_t *));
|
||||
return_type_def = qfo_encode_type (type->t.func.type);
|
||||
for (i = 0; i < param_count; i++)
|
||||
param_type_defs[i] = qfo_encode_type (type->t.func.param_types[i]);
|
||||
size = field_offset (qfot_func_t, param_types[param_count]);
|
||||
|
||||
def = qfo_new_encoding (type, size);
|
||||
enc = D_POINTER (qfot_type_t, def);
|
||||
func = &enc->t.func;
|
||||
EMIT_DEF (pr.type_data, func->return_type, return_type_def);
|
||||
func->num_params = type->t.func.num_params;
|
||||
for (i = 0; i < param_count; i++)
|
||||
EMIT_DEF (pr.type_data, func->param_types[i], param_type_defs[i]);
|
||||
return def;
|
||||
}
|
||||
|
||||
static def_t *
|
||||
qfo_encode_ptrfld (type_t *type)
|
||||
{
|
||||
qfot_type_t *enc;
|
||||
def_t *def;
|
||||
def_t *type_def;
|
||||
|
||||
type_def = qfo_encode_type (type->t.fldptr.type);
|
||||
def = qfo_new_encoding (type, sizeof (enc->t.ptrfld));
|
||||
enc = D_POINTER (qfot_type_t, def);
|
||||
EMIT_DEF (pr.type_data, enc->t.ptrfld.type, type_def);
|
||||
return def;
|
||||
}
|
||||
|
||||
static def_t *
|
||||
qfo_encode_none (type_t *type)
|
||||
{
|
||||
qfot_type_t *enc;
|
||||
def_t *def;
|
||||
|
||||
if (type->type == ev_func)
|
||||
return qfo_encode_func (type);
|
||||
else if (type->type == ev_pointer || type->type == ev_field)
|
||||
return qfo_encode_ptrfld (type);
|
||||
|
||||
def = qfo_new_encoding (type, sizeof (enc->t.type));
|
||||
enc = D_POINTER (qfot_type_t, def);
|
||||
enc->t.type = type->type;
|
||||
return def;
|
||||
}
|
||||
|
||||
static def_t *
|
||||
qfo_encode_struct (type_t *type)
|
||||
{
|
||||
sy_type_e sy;
|
||||
int num_fields;
|
||||
symbol_t *sym;
|
||||
qfot_type_t *enc;
|
||||
qfot_struct_t *strct;
|
||||
def_t *def;
|
||||
def_t **field_types = &def;
|
||||
int i;
|
||||
int size;
|
||||
int offset;
|
||||
|
||||
sy = sy_var;
|
||||
if (type->ty == ty_enum)
|
||||
sy = sy_const;
|
||||
for (num_fields = 0, sym = type->t.symtab->symbols; sym; sym = sym->next) {
|
||||
if (sym->sy_type != sy)
|
||||
continue;
|
||||
num_fields++;
|
||||
}
|
||||
if (type->ty != ty_enum) {
|
||||
field_types = alloca (num_fields * sizeof (def_t *));
|
||||
for (i = 0, sym = type->t.symtab->symbols; sym; sym = sym->next) {
|
||||
if (sym->sy_type != sy)
|
||||
continue;
|
||||
if (i == num_fields)
|
||||
internal_error (0, "whoa, what happened?");
|
||||
field_types[i++] = qfo_encode_type (sym->type);
|
||||
}
|
||||
}
|
||||
|
||||
size = field_offset (qfot_struct_t, fields[num_fields]);
|
||||
def = qfo_new_encoding (type, size);
|
||||
enc = D_POINTER (qfot_type_t, def);
|
||||
strct = &enc->t.strct;
|
||||
strct->tag = encoding_string (type->name);//FIXME reloc
|
||||
strct->num_fields = num_fields;
|
||||
for (i = 0, sym = type->t.symtab->symbols; sym; sym = sym->next) {
|
||||
if (sym->sy_type != sy)
|
||||
continue;
|
||||
if (i == num_fields)
|
||||
internal_error (0, "whoa, what happened?");
|
||||
if (sym->sy_type == sy_const)
|
||||
offset = sym->s.value.v.integer_val;
|
||||
else
|
||||
offset = sym->s.offset;
|
||||
EMIT_DEF (pr.type_data, strct->fields[i].type, field_types[i]);
|
||||
strct->fields[i].name = encoding_string (sym->name);//FIXME reloc
|
||||
strct->fields[i].offset = offset;
|
||||
}
|
||||
return def;
|
||||
}
|
||||
|
||||
static def_t *
|
||||
qfo_encode_array (type_t *type)
|
||||
{
|
||||
qfot_type_t *enc;
|
||||
def_t *def;
|
||||
def_t *array_type_def;
|
||||
|
||||
array_type_def = qfo_encode_type (type->t.array.type);
|
||||
|
||||
def = qfo_new_encoding (type, sizeof (enc->t.array));
|
||||
enc = D_POINTER (qfot_type_t, def);
|
||||
EMIT_DEF (pr.type_data, enc->t.array.type, array_type_def);
|
||||
enc->t.array.base = type->t.array.base;
|
||||
enc->t.array.size = type->t.array.size;
|
||||
return def;
|
||||
}
|
||||
|
||||
static def_t *
|
||||
qfo_encode_class (type_t *type)
|
||||
{
|
||||
qfot_type_t *enc;
|
||||
def_t *def;
|
||||
|
||||
def = qfo_new_encoding (type, sizeof (enc->t.class));
|
||||
enc = D_POINTER (qfot_type_t, def);
|
||||
EMIT_DEF (pr.type_data, enc->t.class, type->t.class->def);
|
||||
return def;
|
||||
}
|
||||
|
||||
def_t *
|
||||
qfo_encode_type (type_t *type)
|
||||
{
|
||||
static encode_f funcs[] = {
|
||||
qfo_encode_none, // ty_none
|
||||
qfo_encode_struct, // ty_struct
|
||||
qfo_encode_struct, // ty_union
|
||||
qfo_encode_struct, // ty_enum
|
||||
qfo_encode_array, // ty_array
|
||||
qfo_encode_class, // ty_class
|
||||
};
|
||||
|
||||
if (type->type_def)
|
||||
return type->type_def;
|
||||
if (type->ty < 0 || type->ty > ty_class)
|
||||
internal_error (0, "bad type meta type");
|
||||
type->type_def = funcs[type->ty] (type);
|
||||
return type->type_def;
|
||||
}
|
Loading…
Reference in a new issue