From 7251bc91fa9eb23e202ddf2474a73200b32618cc Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 18 Feb 2011 09:06:05 +0900 Subject: [PATCH] Enhanced type encoding. This creates a compact representation of types as seen by qfcc. This is intended mainly for debuggers. --- tools/qfcc/include/Makefile.am | 4 +- tools/qfcc/include/obj_type.h | 105 ++++++++++++++ tools/qfcc/include/qfcc.h | 1 + tools/qfcc/include/type.h | 2 + tools/qfcc/source/Makefile.am | 4 +- tools/qfcc/source/obj_type.c | 257 +++++++++++++++++++++++++++++++++ 6 files changed, 369 insertions(+), 4 deletions(-) create mode 100644 tools/qfcc/include/obj_type.h create mode 100644 tools/qfcc/source/obj_type.c diff --git a/tools/qfcc/include/Makefile.am b/tools/qfcc/include/Makefile.am index a913d784b..5b7f182dd 100644 --- a/tools/qfcc/include/Makefile.am +++ b/tools/qfcc/include/Makefile.am @@ -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 diff --git a/tools/qfcc/include/obj_type.h b/tools/qfcc/include/obj_type.h new file mode 100644 index 000000000..46ebf14a2 --- /dev/null +++ b/tools/qfcc/include/obj_type.h @@ -0,0 +1,105 @@ +/* + obj_type.h + + object file type encoding support + + Copyright (C) 2011 Bill Currie + + Author: Bill Currie + 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 diff --git a/tools/qfcc/include/qfcc.h b/tools/qfcc/include/qfcc.h index 442712636..a0058eaca 100644 --- a/tools/qfcc/include/qfcc.h +++ b/tools/qfcc/include/qfcc.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; diff --git a/tools/qfcc/include/type.h b/tools/qfcc/include/type.h index 7339e53b5..c2c3362e6 100644 --- a/tools/qfcc/include/type.h +++ b/tools/qfcc/include/type.h @@ -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 { diff --git a/tools/qfcc/source/Makefile.am b/tools/qfcc/source/Makefile.am index 372f498dc..ee0bde595 100644 --- a/tools/qfcc/source/Makefile.am +++ b/tools/qfcc/source/Makefile.am @@ -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) diff --git a/tools/qfcc/source/obj_type.c b/tools/qfcc/source/obj_type.c new file mode 100644 index 000000000..475e56584 --- /dev/null +++ b/tools/qfcc/source/obj_type.c @@ -0,0 +1,257 @@ +/* + obj_type.c + + object file type encoding support + + Copyright (C) 2011 Bill Currie + + Author: Bill Currie + 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 +#endif +#ifdef HAVE_STRINGS_H +# include +#endif +#include + +#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; +}