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:
Bill Currie 2011-02-18 09:06:05 +09:00
parent 0f0ed3dae2
commit 7251bc91fa
6 changed files with 369 additions and 4 deletions

View file

@ -2,5 +2,5 @@ AUTOMAKE_OPTIONS= foreign
EXTRA_DIST= class.h codespace.h cpp.h debug.h def.h emit.h expr.h \ 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 \ 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 \ obj_file.h obj_type.h opcodes.h options.h qfcc.h qfprogs.h reloc.h \
struct.h switch.h symtab.h type.h strpool.h struct.h switch.h symtab.h type.h

View 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

View file

@ -67,6 +67,7 @@ typedef struct pr_info_s {
struct defspace_s *near_data; struct defspace_s *near_data;
struct defspace_s *far_data; struct defspace_s *far_data;
struct defspace_s *entity_data; struct defspace_s *entity_data;
struct defspace_s *type_data;
struct symtab_s *symtab; struct symtab_s *symtab;

View file

@ -75,6 +75,8 @@ typedef struct type_s {
} t; } t;
struct type_s *next; struct type_s *next;
int freeable; int freeable;
const char *encoding; ///< Objective-QC encoding
struct def_s *type_def; ///< offset of qfo encodoing
} type_t; } type_t;
typedef struct { typedef struct {

View file

@ -55,8 +55,8 @@ common_src=\
class.c codespace.c constfold.c cpp.c debug.c def.c defspace.c \ class.c codespace.c constfold.c cpp.c debug.c def.c defspace.c \
diagnostic.c dot_expr.c dot_flow.c emit.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 \ 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 \ obj_stub.c obj_type.c opcodes.c options.c qfcc.c reloc.c statements.c \
struct.c switch.c symtab.c type.c strpool.c struct.c switch.c symtab.c type.c
qfcc_SOURCES= qc-lex.l qc-parse.y $(common_src) qfcc_SOURCES= qc-lex.l qc-parse.y $(common_src)
qfcc_LDADD= $(QFCC_LIBS) qfcc_LDADD= $(QFCC_LIBS)

View 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;
}