diff --git a/tools/qfcc/include/class.h b/tools/qfcc/include/class.h index e8a5c803e..0e76bd7f5 100644 --- a/tools/qfcc/include/class.h +++ b/tools/qfcc/include/class.h @@ -52,7 +52,7 @@ typedef struct class_s { const char *name; struct class_s *super_class; struct category_s *categories; - struct struct_s *ivars; + struct symtab_s *ivars; struct methodlist_s *methods; struct protocollist_s *protocols; struct def_s *def; @@ -92,35 +92,35 @@ extern class_type_t *current_class; struct expr_s; struct method_s; struct protocol_s; +struct symbol_s; class_t *extract_class (class_type_t *class_type); const char *get_class_name (class_type_t *class_type, int pretty); struct def_s *class_def (class_type_t *class_type, int external); void class_init (void); -class_t *get_class (const char *name, int create); +class_t *get_class (struct symbol_s *sym, int create); void class_add_methods (class_t *class, struct methodlist_s *methods); void class_add_protocols (class_t *class, protocollist_t *protocols); -struct struct_s *class_new_ivars (class_t *class); -void class_add_ivars (class_t *class, struct struct_s *ivars); -void class_check_ivars (class_t *class, struct struct_s *ivars); +struct symtab_s *class_new_ivars (class_t *class); +void class_add_ivars (class_t *class, struct symtab_s *ivars); +void class_check_ivars (class_t *class, struct symtab_s *ivars); void class_begin (class_type_t *class_type); void class_finish (class_type_t *class_type); int class_access (class_type_t *current_class, class_t *class); -struct struct_field_s *class_find_ivar (class_t *class, int vis, - const char *name); +struct symbol_s *class_find_ivar (class_t *class, int vis, const char *name); struct expr_s *class_ivar_expr (class_type_t *class_type, const char *name); struct method_s *class_find_method (class_type_t *class_type, struct method_s *method); struct method_s *class_message_response (class_t *class, int class_msg, struct expr_s *sel); struct def_s *class_pointer_def (class_t *class_type); -category_t *get_category (const char *class_name, const char *category_name, - int create); +category_t *get_category (struct symbol_s *class_name, + const char *category_name, int create); void category_add_methods (category_t *category, struct methodlist_s *methods); void category_add_protocols (category_t *category, protocollist_t *protocols); void class_finish_module (void); -void class_to_struct (class_t *class, struct struct_s *strct); +struct symtab_s *class_to_struct (class_t *class, struct symtab_s *symtab); void emit_class_ref (const char *class_name); void emit_category_ref (const char *class_name, const char *category_name); diff --git a/tools/qfcc/include/def.h b/tools/qfcc/include/def.h index e38bec78b..005d03601 100644 --- a/tools/qfcc/include/def.h +++ b/tools/qfcc/include/def.h @@ -111,7 +111,6 @@ def_t *get_def (struct type_s *type, const char *name, scope_t *scope, storage_class_t storage); def_t *new_def (struct type_s *type, const char *name, scope_t *scope); void set_storage_bits (def_t *def, storage_class_t storage); -void free_location (def_t *def); def_t *get_tempdef (struct type_s *type, scope_t *scope); void free_tempdefs (void); void reset_tempdefs (void); diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index cab0f2b95..a734be0fd 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -52,7 +52,6 @@ typedef enum { ex_def, ///< non-temporary variable (::def_t) ex_symbol, ///< non-temporary variable (::symbol_t) ex_temp, ///< temporary variable (::ex_temp_t) - ex_name, ///< unresolved name (expr_t::e::string_val) ex_nil, ///< umm, nil, null. nuff said (0 of any type) ex_string, ///< string constant (expr_t::e::string_val) @@ -355,12 +354,10 @@ expr_t *new_temp_def_expr (struct type_s *type); */ expr_t *new_nil_expr (void); -/** Create a new name expression node. +/** Create a new symbol expression node from a name. - Name expression nodes represent as yet unresolved names. - - \param name The name being represented. - \return The new name expression node (expr_t::e::string_val). + \param name The name for the symbol. + \return The new symbol expression. */ expr_t *new_name_expr (const char *name); @@ -570,15 +567,6 @@ expr_t *inc_users (expr_t *e); */ expr_t *dec_users (expr_t *e); -/** Convert a name to an expression of the appropriate type. - - Converts the expression in-place. If the exprssion is not a name - expression (ex_name), no converision takes place. - - \param e The expression to convert. -*/ -void convert_name (expr_t *e); - expr_t *append_expr (expr_t *block, expr_t *e); void print_expr (expr_t *e); @@ -610,6 +598,14 @@ expr_t *array_expr (expr_t *array, expr_t *index); expr_t *pointer_expr (expr_t *pointer); expr_t *address_expr (expr_t *e1, expr_t *e2, struct type_s *t); expr_t *build_if_statement (expr_t *test, expr_t *s1, expr_t *s2); +expr_t *build_while_statement (expr_t *test, expr_t *statement, + expr_t *break_label, expr_t *continue_label); +expr_t *build_do_while_statement (expr_t *statement, expr_t *test, + expr_t *break_label, expr_t *continue_label); +expr_t *build_for_statement (expr_t *init, expr_t *test, expr_t *next, + expr_t *statement, + expr_t *break_label, expr_t *continue_label); +expr_t *build_state_expr (expr_t *frame, expr_t *think, expr_t *step); expr_t *assign_expr (expr_t *e1, expr_t *e2); expr_t *cast_expr (struct type_s *t, expr_t *e); diff --git a/tools/qfcc/include/function.h b/tools/qfcc/include/function.h index 20129d927..64cd839cf 100644 --- a/tools/qfcc/include/function.h +++ b/tools/qfcc/include/function.h @@ -39,27 +39,28 @@ typedef struct overloaded_function_s { struct overloaded_function_s *next; - const char *name; - const char *full_name; - struct type_s *type; - int overloaded; - string_t file; - int line; + const char *name; ///< source level name of function + const char *full_name; ///< progs name of function, with type + ///< encoding + struct type_s *type; ///< type of this function + int overloaded; ///< is this function overloaded + string_t file; ///< source file of the function + int line; ///< source line of this function } overloaded_function_t; typedef struct function_s { struct function_s *next; - pr_auxfunction_t *aux; // debug info; - int builtin; // if non 0, call an internal function - int code; // first statement + pr_auxfunction_t *aux; ///< debug info; + int builtin; ///< if non 0, call an internal function + int code; ///< first statement int function_num; - string_t s_file; // source file with definition + string_t s_file; ///< source file with definition string_t s_name; struct def_s *def; struct scope_s *scope; struct reloc_s *refs; struct expr_s *var_init; - const char *name; + const char *name; ///< nice name for __PRETTY_FUNCTION__ } function_t; extern function_t *current_func; @@ -98,7 +99,8 @@ function_t *begin_function (struct def_s *def, const char *nicename, param_t *params); 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); +function_t *build_builtin_function (struct def_s *def, struct expr_s *bi_val, + param_t *params); void build_function (function_t *f); void finish_function (function_t *f); void emit_function (function_t *f, struct expr_s *e); diff --git a/tools/qfcc/include/qfcc.h b/tools/qfcc/include/qfcc.h index bb2d04347..9e5a2e6c9 100644 --- a/tools/qfcc/include/qfcc.h +++ b/tools/qfcc/include/qfcc.h @@ -94,7 +94,6 @@ extern pr_info_t pr; extern char destfile[]; -extern struct scope_s *current_scope; extern struct symtab_s *current_symtab; #define G_GETSTR(s) (pr.strings->strings + (s)) diff --git a/tools/qfcc/include/struct.h b/tools/qfcc/include/struct.h index 67bd53c7e..4f9b0e131 100644 --- a/tools/qfcc/include/struct.h +++ b/tools/qfcc/include/struct.h @@ -32,63 +32,25 @@ #ifndef __struct_h #define __struct_h -typedef enum { - vis_private, - vis_protected, - vis_public, -} visibility_type; +struct symbol_s; +struct symtab_s; +struct type_s; -typedef enum { - str_none, - str_struct, - str_union, -} struct_type; - -typedef struct struct_field_s { - struct struct_field_s *next; - const char *name; - struct type_s *type; - int offset; - visibility_type visibility; -} struct_field_t; - -typedef struct struct_s { +typedef struct { const char *name; struct type_s *type; - struct_type stype; - struct hashtab_s *struct_fields; - struct_field_t *struct_head; - struct_field_t **struct_tail; - int size; - void *return_addr; // who allocated this -} struct_t; +} struct_def_t; -typedef struct enum_s { - const char *name; - int value; -} enum_t; +struct symbol_s *find_struct (int su, struct symbol_s *tag, + struct type_s *type); +struct symbol_s *build_struct (int su, struct symbol_s *tag, + struct symtab_s *symtab, struct type_s *type); +struct symbol_s *find_enum (struct symbol_s *tag); +struct symtab_s *start_enum (struct symbol_s *enm); +void add_enum (struct symbol_s *enm, struct symbol_s *name, + struct expr_s *val); -struct_field_t *new_struct_field (struct_t *strct, struct type_s *type, - const char *name, - visibility_type visibility); -struct_field_t *struct_find_field (struct_t *strct, const char *name); -int struct_compare_fields (struct_t *s1, struct_t *s2); -struct type_s *init_struct (struct_t *strct, struct type_s *type, - struct_type stype, const char *name); -struct_t *get_struct (const char *name, int create); -void copy_struct_fields (struct_t *dst, struct_t *src); - -struct def_s *emit_struct (struct_t *strct, const char *name); - -void process_enum (struct expr_s *enm); -struct expr_s *get_enum (const char *name); - -void clear_structs (void); -void clear_enums (void); - -struct_t *new_struct (const char *name); -struct_t *new_union (const char *name); -struct_t *decl_struct (const char *name); -struct_t *decl_union (const char *name); +struct symbol_s *make_structure (const char *name, int su, struct_def_t *defs, + struct type_s *type); #endif//__struct_h diff --git a/tools/qfcc/include/symtab.h b/tools/qfcc/include/symtab.h index 33aff8e52..8dd12620a 100644 --- a/tools/qfcc/include/symtab.h +++ b/tools/qfcc/include/symtab.h @@ -36,26 +36,47 @@ \ingroup qfcc */ //@{ -// + +typedef enum { + vis_public, + vis_protected, + vis_private, +} vis_e; + +typedef enum { + sy_var, ///< symbol refers to a variable + sy_const, ///< symbol refers to a constant + sy_type, ///< symbol refers to a type + sy_expr, ///< symbol refers to an expression +} sy_type_e; + typedef struct symbol_s { struct symbol_s *next; ///< chain of symbols in symbol table struct symtab_s *table; ///< symbol table that owns this symbol + vis_e visibility; ///< symbol visiblity. defaults to public const char *name; ///< symbol name - struct type_s *type; ///< symbol type + sy_type_e sy_type; ///< symbol type + struct type_s *type; ///< type of object to which symbol refers struct param_s *params; ///< the parameters if a function - int is_typedef; ///< true if symbol is a typedef + union { + int value; + struct expr_s *expr; + } s; } symbol_t; typedef enum { stab_global, ///< global (many symbols) - stab_local, ///< local (few symbols: func, struct) - stab_union, ///< offset always 0 + stab_local, ///< local (few symbols: func) + stab_struct, + stab_union, + stab_enum, } stab_type_e; typedef struct symtab_s { struct symtab_s *parent; ///< points to parent table struct symtab_s *next; ///< next in global collection of symtabs stab_type_e type; ///< type of symbol table + int size; ///< size of structure represented by symtab struct hashtab_s *tab; ///< symbols defined in this table symbol_t *symbols; ///< chain of symbols in this table symbol_t **symtail; ///< keep chain in declaration order diff --git a/tools/qfcc/include/type.h b/tools/qfcc/include/type.h index 59b30583b..68274dc4a 100644 --- a/tools/qfcc/include/type.h +++ b/tools/qfcc/include/type.h @@ -53,6 +53,8 @@ typedef struct ty_array_s { typedef enum { ty_none, ///< func/field/pointer or not used ty_struct, + ty_union, + ty_enum, ty_array, ty_class, } ty_type_e; @@ -66,18 +68,12 @@ typedef struct type_s { ty_func_t func; ty_fldptr_t fldptr; ty_array_t array; - struct struct_s *strct; + struct symtab_s *symtab; struct class_s *class; } t; struct type_s *next; } type_t; -typedef struct typedef_s { - struct typedef_s *next; - const char *name; - type_t *type; -} typedef_t; - extern type_t type_invalid; extern type_t type_void; extern type_t type_string; @@ -101,23 +97,22 @@ extern type_t type_supermsg; extern type_t type_obj_exec_class; extern type_t type_Method; extern type_t type_method_description; -extern type_t *type_category; -extern type_t *type_ivar; -extern type_t *type_module; +extern type_t type_category; +extern type_t type_ivar; +extern type_t type_module; extern type_t type_Super; extern type_t type_va_list; extern type_t type_param; extern type_t type_zero; -extern struct struct_s *vector_struct; -extern struct struct_s *quaternion_struct; +extern struct symtab_s *vector_struct; +extern struct symtab_s *quaternion_struct; struct dstring_s; type_t *new_type (void); type_t *find_type (type_t *new); void new_typedef (const char *name, type_t *type); -typedef_t *get_typedef (const char *name); type_t *field_type (type_t *aux); type_t *pointer_type (type_t *aux); type_t *array_type (type_t *aux, int size); diff --git a/tools/qfcc/source/Makefile.am b/tools/qfcc/source/Makefile.am index 6872220e2..ce83f7799 100644 --- a/tools/qfcc/source/Makefile.am +++ b/tools/qfcc/source/Makefile.am @@ -52,10 +52,10 @@ bin_SCRIPTS= $(qfpreqcc) EXTRA_PROGRAMS= qfcc qfpc qfprogs common_src=\ - class.c codespace.c constfold.c cpp.c debug.c def.c emit.c expr.c \ - function.c grab.c idstuff.c immediate.c linker.c method.c obj_file.c \ - opcodes.c options.c qfcc.c reloc.c strpool.c struct.c switch.c symtab.c \ - type.c + class.c codespace.c constfold.c cpp.c debug.c def.c defspace.c emit.c \ + expr.c function.c grab.c idstuff.c immediate.c linker.c method.c \ + obj_file.c opcodes.c options.c qfcc.c reloc.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/class.c b/tools/qfcc/source/class.c index 3fe206304..8b8aebb46 100644 --- a/tools/qfcc/source/class.c +++ b/tools/qfcc/source/class.c @@ -52,6 +52,7 @@ static __attribute__ ((used)) const char rcsid[] = #include "codespace.h" #include "class.h" #include "def.h" +#include "defspace.h" #include "emit.h" #include "expr.h" #include "immediate.h" @@ -60,15 +61,16 @@ static __attribute__ ((used)) const char rcsid[] = #include "reloc.h" #include "strpool.h" #include "struct.h" +#include "symtab.h" #include "type.h" static hashtab_t *class_hash; static hashtab_t *category_hash; static hashtab_t *protocol_hash; -class_t class_id = {1, "id", 0, 0, 0, 0, 0, 0, &type_id}; -class_t class_Class = {1, "Class", 0, 0, 0, 0, 0, 0, &type_Class}; -class_t class_Protocol = {1, "Protocl", 0, 0, 0, 0, 0, 0, &type_Protocol}; +class_t class_id = {1, "id"}; +class_t class_Class = {1, "Class"}; +class_t class_Protocol = {1, "Protocl"}; static const char * class_get_key (void *class, void *unused) @@ -107,7 +109,11 @@ get_class_name (class_type_t *class_type, int pretty) void class_init (void) { - class_Class.super_class = get_class ("Object", 1); + class_id.type = &type_id; + class_Class.type = &type_Class; + class_Protocol.type = &type_Protocol; + + class_Class.super_class = get_class (new_symbol ("Object"), 1); class_Class.methods = new_methodlist (); } @@ -123,7 +129,7 @@ class_def (class_type_t *class_type, int external) name = va ("_OBJ_CATEGORY_%s_%s", class_type->c.category->class->name, class_type->c.category->name); - type = type_category; + type = &type_category; break; case ct_class: name = va ("_OBJ_CLASS_%s", class_type->c.class->name); @@ -136,34 +142,29 @@ class_def (class_type_t *class_type, int external) } class_t * -get_class (const char *name, int create) +get_class (symbol_t *sym, int create) { class_t *c; type_t new; if (!class_hash) class_hash = Hash_NewTable (1021, class_get_key, 0, 0); - if (name) { - if (get_def (0, name, current_scope, st_none) - || get_enum (name)) { - if (create) - error (0, "redefinition of %s", name); - return 0; - } - c = Hash_Find (class_hash, name); + if (sym) { + c = Hash_Find (class_hash, sym->name); if (c || !create) return c; } c = calloc (sizeof (class_t), 1); - c->name = name; + if (sym) + c->name = sym->name; new = *type_Class.t.fldptr.type; new.t.class = c; c->type = find_type (&new); c->methods = new_methodlist (); c->class_type.type = ct_class; c->class_type.c.class = c; - if (name) + if (sym) Hash_Add (class_hash, c); return c; } @@ -259,10 +260,11 @@ begin_class (class_t *class) EMIT_STRING (meta->name, class->name); meta->info = _PR_CLS_META; meta->instance_size = type_size (type_Class.t.fldptr.type); +#if 0 //FIXME EMIT_DEF (meta->ivars, emit_struct (type_Class.t.fldptr.type->t.class->ivars, "Class")); - +#endif class->def->initialized = class->def->constant = 1; class->def->nosave = 1; cls = &G_STRUCT (pr_class_t, class->def->ofs); @@ -398,9 +400,10 @@ finish_class (class_t *class) EMIT_DEF (meta->methods, emit_methods (class->methods, class->name, 0)); - cls->instance_size = class->ivars ? type_size (class->ivars->type) - : 0; + cls->instance_size = class->ivars ? class->ivars->size : 0; +#if 0 // FIXME EMIT_DEF (cls->ivars, emit_struct (class->ivars, class->name)); +#endif EMIT_DEF (cls->methods, emit_methods (class->methods, class->name, 1)); if (class->super_class) @@ -456,19 +459,16 @@ class_access (class_type_t *class_type, class_t *class) return vis_public; } -struct_field_t * +symbol_t * class_find_ivar (class_t *class, int vis, const char *name) { - struct_field_t *ivar; - class_t *c; + symbol_t *ivar; - for (c = class; c; c = c->super_class) { - ivar = struct_find_field (c->ivars, name); - if (ivar) { - if (ivar->visibility < (visibility_type) vis) - goto access_error; - return ivar; - } + ivar = symtab_lookup (class->ivars, name); + if (ivar) { + if (ivar->visibility > (vis_e) vis) + goto access_error; + return ivar; } error (0, "%s.%s does not exist", class->name, name); return 0; @@ -480,20 +480,13 @@ access_error: expr_t * class_ivar_expr (class_type_t *class_type, const char *name) { - struct_field_t *ivar; - class_t *c, *class; + symbol_t *ivar; + class_t *class; if (!class_type || !(class = extract_class (class_type))) return 0; - ivar = struct_find_field (class->ivars, name); - if (!ivar) { - for (c = class->super_class; c; c = c->super_class) { - ivar = struct_find_field (c->ivars, name); - if (ivar) - break; - } - } + ivar = symtab_lookup (class->ivars, name); if (!ivar) return 0; return binary_expr ('.', new_name_expr ("self"), new_name_expr (name)); @@ -616,42 +609,39 @@ category_compare (void *_c1, void *_c2, void *unused) && strcmp (c1->class->name, c2->class->name) == 0; } -struct_t * +symtab_t * class_new_ivars (class_t *class) { - struct_t *ivars = new_struct (0); - if (class->super_class) { - if (!class->super_class->ivars) { - error (0, "cannot find interface declaration for `%s', " - "superclass of `%s'", class->super_class->name, - class->name); - } else { - new_struct_field (ivars, class->super_class->ivars->type, 0, - vis_private); - } - } + symtab_t *ivars; + symtab_t *super_ivars = 0; + + if (class->super_class) + super_ivars = class->super_class->ivars; + ivars = new_symtab (super_ivars, stab_local); return ivars; } void -class_add_ivars (class_t *class, struct_t *ivars) +class_add_ivars (class_t *class, symtab_t *ivars) { class->ivars = ivars; } void -class_check_ivars (class_t *class, struct_t *ivars) +class_check_ivars (class_t *class, symtab_t *ivars) { +#if 0 //FIXME if (!struct_compare_fields (class->ivars, ivars)) { //FIXME right option? if (options.warnings.interface_check) warning (0, "instance variable missmatch for %s", class->name); } +#endif class->ivars = ivars; } category_t * -get_category (const char *class_name, const char *category_name, int create) +get_category (symbol_t *class_name, const char *category_name, int create) { category_t *category; class_t *class; @@ -663,7 +653,7 @@ get_category (const char *class_name, const char *category_name, int create) } class = get_class (class_name, 0); if (!class) { - error (0, "undefined class %s", class_name); + error (0, "undefined class %s", class_name->name); return 0; } if (class_name && category_name) { @@ -746,13 +736,21 @@ class_pointer_def (class_t *class) void class_finish_module (void) { + static struct_def_t symtab_struct[] = { + {"sel_ref_cnt", &type_integer}, + {"refs", &type_SEL}, + {"cls_def_cnt", &type_integer}, + {"cat_def_cnt", &type_integer}, + {"defs", 0}, // type will be filled in at run time + {0, 0} + }; class_t **classes = 0, **cl; category_t **categories = 0, **ca; int num_classes = 0; int num_categories = 0; - int i; def_t *selector_table_def; - struct_t *symtab_type; + type_t *symtab_type; + //symbol_t *symtab_sym; def_t *symtab_def; pr_symtab_t *symtab; pointer_t *def_ptr; @@ -778,16 +776,10 @@ class_finish_module (void) } if (!selector_table_def && !num_classes && !num_categories) return; - symtab_type = get_struct (0, 1); - init_struct (symtab_type, new_type (), str_struct, 0); - new_struct_field (symtab_type, &type_integer, "sel_ref_cnt", vis_public); - new_struct_field (symtab_type, &type_SEL, "refs", vis_public); - new_struct_field (symtab_type, &type_integer, "cls_def_cnt", vis_public); - new_struct_field (symtab_type, &type_integer, "cat_def_cnt", vis_public); - for (i = 0; i < num_classes + num_categories; i++) - new_struct_field (symtab_type, &type_pointer, 0, vis_public); - symtab_def = get_def (symtab_type->type, "_OBJ_SYMTAB", pr.scope, - st_static); + symtab_struct[4].type = array_type (&type_pointer, + num_classes + num_categories); + symtab_type = make_structure (0, 's', symtab_struct, 0)->type; + symtab_def = get_def (symtab_type, "_OBJ_SYMTAB", pr.scope, st_static); symtab_def->initialized = symtab_def->constant = 1; symtab_def->nosave = 1; symtab = &G_STRUCT (pr_symtab_t, symtab_def->ofs); @@ -815,11 +807,11 @@ class_finish_module (void) } } - module_def = get_def (type_module, "_OBJ_MODULE", pr.scope, st_static); + module_def = get_def (&type_module, "_OBJ_MODULE", pr.scope, st_static); module_def->initialized = module_def->constant = 1; module_def->nosave = 1; module = &G_STRUCT (pr_module_t, module_def->ofs); - module->size = type_size (type_module); + module->size = type_size (&type_module); EMIT_STRING (module->name, G_GETSTR (pr.source_file)); EMIT_DEF (module->symtab, symtab_def); @@ -949,20 +941,23 @@ emit_protocol (protocol_t *protocol) def_t * emit_protocol_list (protocollist_t *protocols, const char *name) { + static struct_def_t proto_list_struct[] = { + {"next", &type_pointer}, + {"count", &type_integer}, + {"list", 0}, // type will be filled in at run time + {0, 0}, + }; + type_t *proto_list_type; def_t *proto_list_def; - struct_t *protocol_list; + //symbol_t *proto_list_sym; pr_protocol_list_t *proto_list; int i; if (!protocols) return 0; - protocol_list = get_struct (0, 1); - init_struct (protocol_list, new_type (), str_struct, 0); - new_struct_field (protocol_list, &type_pointer, "next", vis_public); - new_struct_field (protocol_list, &type_integer, "count", vis_public); - for (i = 0; i < protocols->count; i++) - new_struct_field (protocol_list, &type_pointer, 0, vis_public); - proto_list_def = get_def (&type_Protocol, + proto_list_struct[2].type = array_type (&type_pointer, protocols->count); + proto_list_type = make_structure (0, 's', proto_list_struct, 0)->type; + proto_list_def = get_def (proto_list_type, va ("_OBJ_PROTOCOLS_%s", name), pr.scope, st_static); proto_list_def->initialized = proto_list_def->constant = 1; @@ -985,19 +980,31 @@ clear_classes (void) if (category_hash) Hash_FlushTable (category_hash); if (class_hash) - class_Class.super_class = get_class ("Object", 1); + class_Class.super_class = get_class (new_symbol ("Object"), 1); } -void -class_to_struct (class_t *class, struct_t *strct) +symtab_t * +class_to_struct (class_t *class, symtab_t *symtab) { + symtab_t *parent = symtab->parent; + symtab_t *ivars = class->ivars; + symtab_t *ancestor; - struct_field_t *s = class->ivars->struct_head; + if (!ivars) + return symtab; - if (class->super_class) { - class_to_struct (class->super_class, strct); - s = s->next; - } - for (; s; s = s->next) - new_struct_field (strct, s->type, s->name, vis_public); + // disconnect the struct symbol table from the scope + symtab->parent = 0; + // find the ancestor of the ivars symbol table chain + for (ancestor = ivars; ancestor->parent; ancestor = ancestor->parent) + ; + // connect the ivars symbol table chain to the struct symbol table + ancestor->parent = symtab; + // create a new struct symbol table from the ivars symbol table chain + symtab = symtab_flat_copy (ivars, 0); + // disconnect the ivars symbol table chain + ancestor->parent = 0; + // connect the new struct symbol table to the scope + symtab->parent = parent; + return symtab; } diff --git a/tools/qfcc/source/def.c b/tools/qfcc/source/def.c index 86083e159..f0bfa40c5 100644 --- a/tools/qfcc/source/def.c +++ b/tools/qfcc/source/def.c @@ -58,9 +58,10 @@ static __attribute__ ((used)) const char rcsid[] = #include "struct.h" #include "type.h" -def_t def_void = { &type_void, "def void" }; -def_t def_invalid = { &type_invalid, "def invalid" }; -def_t def_function = { &type_function, "def function" }; +//FIXME +//def_t def_void = { type_void, "def void" }; +//def_t def_invalid = { type_invalid, "def invalid" }; +//def_t def_function = { type_function, "def function" }; static def_t *free_temps[4]; // indexted by type size static int tempdef_counter; diff --git a/tools/qfcc/source/emit.c b/tools/qfcc/source/emit.c index 2e100eaf0..729c1596e 100644 --- a/tools/qfcc/source/emit.c +++ b/tools/qfcc/source/emit.c @@ -60,867 +60,20 @@ static __attribute__ ((used)) const char rcsid[] = #include "type.h" #include "qc-parse.h" -static expr_t zero; - -static void -add_statement_ref (def_t *def, dstatement_t *st, int field) -{ - if (def) { - int st_ofs = st - pr.code->code; - - def->users--; - def->used = 1; - if (def->parent) - def->parent->used = 1; - - if (def->alias) { - def = def->alias; - def->users--; - def->used = 1; - if (def->parent) - def->parent->used = 1; - reloc_op_def_ofs (def, st_ofs, field); - } else - reloc_op_def (def, st_ofs, field); - } -} - def_t * emit_statement (expr_t *e, opcode_t *op, def_t *var_a, def_t *var_b, def_t *var_c) { - dstatement_t *statement; - def_t *ret; - - if (!op) { - error (e, "ice ice baby"); - abort (); - } - 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) { - pr_lineno_t *lineno = new_lineno (); - - lineno->line = line; - lineno->fa.addr = pr.code->size; - } - } - statement = codespace_newstatement (pr.code); - statement->op = op->opcode; - statement->a = var_a ? var_a->ofs : 0; - statement->b = var_b ? var_b->ofs : 0; - statement->c = 0; - if (op->type_c == ev_invalid || op->right_associative - || op->opcode == OP_DONE/*stupid opcode*/) { - // ifs, gotos, and assignments don't need vars allocated - if (var_c) - statement->c = var_c->ofs; - ret = var_a; - } else { // allocate result space - if (!var_c) { - var_c = get_tempdef (ev_types[op->type_c], current_scope); - var_c->users += 2; - } - statement->c = var_c->ofs; - ret = var_c; - } -#if 0 - printf ("%s %s(%d:%d) %s(%d:%d) %s(%d:%d)\n", op->opname, - var_a ? var_a->name : "", var_a ? var_a->users : 99, statement->a, - var_b ? var_b->name : "", var_b ? var_b->users : 99, statement->b, - var_c ? var_c->name : "", var_c ? var_c->users : 99, statement->c); -#endif - - add_statement_ref (var_a, statement, 0); - add_statement_ref (var_b, statement, 1); - add_statement_ref (var_c, statement, 2); - - if (op->right_associative) - return var_a; - return var_c; -} - -static void -emit_branch (expr_t *_e, opcode_t *op, expr_t *e, expr_t *l) -{ - dstatement_t *st; - reloc_t *ref; - def_t *def = 0; - int ofs; - - if (e) - def = emit_sub_expr (e, 0); - ofs = pr.code->size; - emit_statement (_e, op, def, 0, 0); - st = &pr.code->code[ofs]; - if (l->e.label.ofs) { - if (op == op_goto) - st->a = l->e.label.ofs - ofs; - else - st->b = l->e.label.ofs - ofs; - } else { - ref = new_reloc (ofs, op == op_goto ? rel_op_a_op : rel_op_b_op); - ref->next = l->e.label.refs; - l->e.label.refs = ref; - } -} - -static def_t * -vector_call (expr_t *earg, expr_t *parm, int ind) -{ - expr_t *a, *v, *n; - int i; - static const char *names[] = {"x", "y", "z"}; - - for (i = 0; i < 3; i++) { - n = new_name_expr (names[i]); - v = new_float_expr (earg->e.vector_val[i]); - a = assign_expr (binary_expr ('.', parm, n), v); - parm = new_param_expr (get_type (earg), ind); - a->line = earg->line; - a->file = earg->file; - emit_expr (a); - } - return emit_sub_expr (parm, 0); -} - -static def_t * -emit_function_call (expr_t *e, def_t *dest) -{ - def_t *func = emit_sub_expr (e->e.expr.e1, 0); - def_t *ret; - def_t *arg; - def_t *p; - def_t *a[2] = {0, 0}; - expr_t *earg; - expr_t *parm; - opcode_t *op; - type_t *t1 = &type_invalid; - type_t *t2 = &type_invalid; - int count = 0, ind; - const char *pref = ""; - - for (earg = e->e.expr.e2; earg; earg = earg->next) - count++; - ind = count; - for (earg = e->e.expr.e2; earg; earg = earg->next) { - ind--; - parm = new_param_expr (get_type (earg), ind); - if (options.code.progsversion != PROG_ID_VERSION && ind < 2) { - pref = "R"; - if (ind == 1) - t2 = &type_void; - if (ind == 0) - t1 = &type_void; - if (options.code.vector_calls && earg->type == ex_vector) { - a[ind] = vector_call (earg, parm, ind); - } else { - a[ind] = emit_sub_expr (earg, emit_sub_expr (parm, 0)); - } - continue; - } - if (is_struct (get_type (parm))) { - expr_t *a = assign_expr (parm, earg); - a->line = e->line; - a->file = e->file; - emit_expr (a); - } else { - if (options.code.vector_calls && earg->type == ex_vector) { - vector_call (earg, parm, ind); - } else { - p = emit_sub_expr (parm, 0); - arg = emit_sub_expr (earg, p); - if (arg != p) { - op = opcode_find ("=", arg->type, arg->type, &type_invalid); - emit_statement (e, op, arg, p, 0); - } - } - } - } - op = opcode_find (va ("<%sCALL%d>", pref, count), &type_function, t1, t2); - emit_statement (e, op, func, a[0], a[1]); - - ret = emit_sub_expr (new_ret_expr (func->type->t.func.type), 0); - if (dest) { - op = opcode_find ("=", dest->type, ret->type, &type_invalid); - emit_statement (e, op, ret, dest, 0); - return dest; - } else { - return ret; - } -} - -static def_t * -emit_assign_expr (int oper, expr_t *e) -{ - def_t *def_a, *def_b, *def_c, *a, *b; - opcode_t *op; - expr_t *e1 = e->e.expr.e1; - expr_t *e2 = e->e.expr.e2; - const char *operator = get_op_string (oper); - - if (e1->type == ex_temp && e1->e.temp.users < 2) { - e1->e.temp.users--; - return 0; - } - if (oper == '=') { - def_a = emit_sub_expr (e1, 0); - if (def_a->constant) { - if (options.code.cow) { - int size = type_size (def_a->type); - int ofs = new_location (def_a->type, pr.near_data); - - memcpy (G_POINTER (void, ofs), G_POINTER (void, def_a->ofs), - size); - def_a->ofs = ofs; - def_a->constant = 0; - def_a->nosave = 1; - if (options.warnings.cow) - warning (e1, "assignment to constant %s (Moooooooo!)", - def_a->name); - } else { - if (options.traditional) { - if (options.warnings.cow) - warning (e1, "assignment to constant %s (Moooooooo!)", - def_a->name); - } else - error (e1, "assignment to constant %s", def_a->name); - } - } - def_b = emit_sub_expr (e2, def_a); - a = def_a; - if (a->alias) - a = a->alias; - b = def_b; - if (b->alias) - b = b->alias; - if (b != a) { - op = opcode_find (operator, def_b->type, def_a->type, - &type_invalid); - emit_statement (e, op, def_b, def_a, 0); - } - return def_a; - } else { - def_b = emit_sub_expr (e2, 0); - if (e->rvalue && def_b->managed) - def_b->users++; - if (e1->type == ex_expr && extract_type (e1->e.expr.e1) == ev_pointer - && e1->e.expr.e1->type < ex_nil) { - def_a = emit_sub_expr (e1->e.expr.e1, 0); - def_c = emit_sub_expr (e1->e.expr.e2, 0); - op = opcode_find (operator, def_b->type, def_a->type, def_c->type); - } else { - def_a = emit_sub_expr (e1, 0); - def_c = 0; - op = opcode_find (operator, def_b->type, def_a->type, &type_invalid); - } - emit_statement (e, op, def_b, def_a, def_c); - return def_b; - } -} - -static def_t * -emit_bind_expr (expr_t *e1, expr_t *e2) -{ - type_t *t1 = get_type (e1); - type_t *t2 = get_type (e2); - def_t *def; - - if (!e2 || e2->type != ex_temp) { - error (e1, "internal error"); - abort (); - } - def = emit_sub_expr (e1, e2->e.temp.def); - if (t1 != t2) { - def_t *tmp = new_def (t2, 0, def->scope); - - tmp->ofs = 0; - tmp->alias = def; - tmp->users = e2->e.temp.users; - tmp->freed = 1; // don't free this offset when freeing def - def = tmp; - } - e2->e.temp.def = def; - return e2->e.temp.def; -} - -static def_t * -emit_move_expr (expr_t *e) -{ - expr_t *e1 = e->e.expr.e1; - expr_t *e2 = e->e.expr.e2; - expr_t *size_expr; - def_t *size, *src, *dst; - type_t *src_type, *dst_type; - opcode_t *op; - - dst_type = get_type (e1); - src_type = get_type (e2); - src = emit_sub_expr (e2, 0); - dst = emit_sub_expr (e1, 0); - - if (is_struct (dst_type) && is_struct (src_type)) { - size_expr = new_short_expr (type_size (dst->type)); - dst_type = src_type = &type_void; - } else if (is_struct (dst_type)) { - if (dst->alias) - dst = dst->alias; - dst = emit_sub_expr (address_expr (new_def_expr (dst), 0, 0), 0); - dst_type = dst->type; - size_expr = new_integer_expr (type_size (dst_type)); - } else if (is_struct (src_type)) { - if (src->alias) - src = src->alias; - src = emit_sub_expr (address_expr (new_def_expr (src), 0, 0), 0); - src_type = src->type; - size_expr = new_integer_expr (type_size (dst_type->t.fldptr.type)); - } else { - size_expr = new_integer_expr (type_size (dst_type->t.fldptr.type)); - } - size = emit_sub_expr (size_expr, 0); - - op = opcode_find ("", src_type, size->type, dst_type); - return emit_statement (e, op, src, size, dst); -} - -static def_t * -emit_address_expr (expr_t *e) -{ - def_t *def_a, *def_b, *d; - opcode_t *op; - - def_a = emit_sub_expr (e->e.expr.e1, 0); - def_b = emit_sub_expr (e->e.expr.e2, 0); - op = opcode_find ("&", def_a->type, def_b->type, 0); - d = emit_statement (e, op, def_a, def_b, 0); - return d; -} - -static def_t * -emit_deref_expr (expr_t *e, def_t *dest) -{ - def_t *d; - type_t *type = e->e.expr.type; - def_t *z; - opcode_t *op; - - e = e->e.expr.e1; - if (e->type == ex_pointer) { - if (e->e.pointer.def) { - d = new_def (e->e.pointer.type, 0, e->e.pointer.def->scope); - d->local = e->e.pointer.def->local; - d->ofs = e->e.pointer.val; - d->alias = e->e.pointer.def; - } else if (e->e.pointer.val >= 0 && e->e.pointer.val < 65536) { - d = new_def (e->e.pointer.type, 0, current_scope); - d->ofs = e->e.pointer.val; - } else { - d = ReuseConstant (e, 0); - zero.type = ex_short; - z = emit_sub_expr (&zero, 0); - op = opcode_find (".", d->type, z->type, dest->type); - d = emit_statement (e, op, d, z, dest); - } - return d; - } - if (e->type == ex_uexpr && e->e.expr.op == '&' - && e->e.expr.e1->type == ex_def) { - d = new_def (e->e.expr.type->t.fldptr.type, 0, current_scope); - d->alias = e->e.expr.e1->e.def; - d->local = d->alias->local; - d->ofs = d->alias->ofs; - return d; - } - if (!dest) { - dest = get_tempdef (type, current_scope); - dest->line = e->line; - dest->file = e->file; - dest->users += 2; - } - if (is_struct (dest->type)) { - expr_t *d = new_def_expr (dest); - expr_t *m = new_move_expr (d, e, dest->type); - d->line = dest->line; - d->file = dest->file; - m->line = e->line; - m->file = e->file; - emit_sub_expr (m, 0); - return dest; - } - - if (e->type == ex_expr - && e->e.expr.op == '&' - && e->e.expr.e1->type < ex_nil) - e->e.expr.op = '.'; - if (e->type == ex_uexpr && e->e.expr.op == '.') - d = emit_sub_expr (e, 0); - else - d = emit_sub_expr (e, dest); - - if (dest && d != dest) { - zero.type = ex_short; - z = emit_sub_expr (&zero, 0); - op = opcode_find (".", d->type, z->type, dest->type); - d = emit_statement (e, op, d, z, dest); - } else { - if (!d->name) - d->type = type; - } - return d; -} - -static void -build_bool_block (expr_t *block, expr_t *e) -{ - switch (e->type) { - case ex_bool: - build_bool_block (block, e->e.bool.e); - free_tempdefs (); - return; - case ex_label: - e->next = 0; - append_expr (block, e); - free_tempdefs (); - return; - case ex_expr: - if (e->e.expr.op == OR || e->e.expr.op == AND) { - build_bool_block (block, e->e.expr.e1); - build_bool_block (block, e->e.expr.e2); - } else if (e->e.expr.op == 'i') { - e->next = 0; - append_expr (block, e); - } else if (e->e.expr.op == 'n') { - e->next = 0; - append_expr (block, e); - } - free_tempdefs (); - return; - case ex_uexpr: - if (e->e.expr.op == 'g') { - e->next = 0; - append_expr (block, e); - free_tempdefs (); - return; - } - break; - case ex_block: - if (!e->e.block.result) { - expr_t *t; - for (e = e->e.block.head; e; e = t) { - t = e->next; - build_bool_block (block, e); - } - free_tempdefs (); - return; - } - break; - default: - ; - } - error (e, "internal error"); - abort (); -} - -static int -is_goto (expr_t *e) -{ - return e && e->type == ex_uexpr && e->e.expr.op == 'g'; -} - -static int -is_if (expr_t *e) -{ - return e && e->type == ex_expr && e->e.expr.op == 'i'; -} - -static int -is_ifnot (expr_t *e) -{ - return e && e->type == ex_expr && e->e.expr.op == 'n'; -} - -static void -emit_bool_expr (expr_t *e) -{ - expr_t *block = new_block_expr (); - expr_t **s; - expr_t *l; - - build_bool_block (block, e); - - s = &block->e.block.head; - while (*s) { - if (is_if (*s) && is_goto ((*s)->next)) { - l = (*s)->e.expr.e2; - for (e = (*s)->next->next; e && e->type == ex_label; e = e->next) { - if (e == l) { - e = *s; - e->e.expr.op = 'n'; - e->e.expr.e2 = e->next->e.expr.e1; - e->next = e->next->next; - break; - } - } - s = &(*s)->next; - } else if (is_ifnot (*s) && is_goto ((*s)->next)) { - l = (*s)->e.expr.e2; - for (e = (*s)->next->next; e && e->type == ex_label; e = e->next) { - if (e == l) { - e = *s; - e->e.expr.op = 'i'; - e->e.expr.e2 = e->next->e.expr.e1; - e->next = e->next->next; - break; - } - } - s = &(*s)->next; - } else if (is_goto (*s)) { - l = (*s)->e.expr.e1; - for (e = (*s)->next; e && e->type == ex_label; e = e->next) { - if (e == l) { - *s = (*s)->next; - l = 0; - break; - } - } - if (l) - s = &(*s)->next; - } else { - s = &(*s)->next; - } - } - - emit_expr (block); + return 0; } def_t * emit_sub_expr (expr_t *e, def_t *dest) { - opcode_t *op; - const char *operator; - def_t *def_a, *def_b, *d = 0; - def_t *tmp = 0; - - switch (e->type) { - case ex_block: - if (e->e.block.result) { - expr_t *res = e->e.block.result; - for (e = e->e.block.head; e; e = e->next) - emit_expr (e); - d = emit_sub_expr (res, dest); - } - break; - case ex_state: - case ex_bool: - case ex_name: - case ex_nil: - case ex_label: - case ex_error: - error (e, "internal error"); - abort (); - case ex_expr: - if (e->e.expr.op == 'M') { - d = emit_move_expr (e); - break; - } - if (e->e.expr.op == 'b') { - d = emit_bind_expr (e->e.expr.e1, e->e.expr.e2); - break; - } - if (e->e.expr.op == 'c') { - d = emit_function_call (e, dest); - break; - } - if (e->e.expr.op == '=' || e->e.expr.op == PAS) { - d = emit_assign_expr (e->e.expr.op, e); - if (!d->managed) - d->users++; - break; - } - if (e->e.expr.op == '&' && e->e.expr.type->type == ev_pointer) { - d = emit_address_expr (e); - break; - } - if (e->e.expr.e1->type == ex_block - && e->e.expr.e1->e.block.is_call) { - def_b = emit_sub_expr (e->e.expr.e2, 0); - def_a = emit_sub_expr (e->e.expr.e1, 0); - } else { - def_a = emit_sub_expr (e->e.expr.e1, 0); - def_b = emit_sub_expr (e->e.expr.e2, 0); - } - operator = get_op_string (e->e.expr.op); - if (!dest) { - dest = get_tempdef (e->e.expr.type, current_scope); - dest->file = e->file; - dest->line = e->line; - dest->users += 2; - } - op = opcode_find (operator, def_a->type, def_b->type, - dest->type); - d = emit_statement (e, op, def_a, def_b, dest); - break; - case ex_uexpr: - switch (e->e.expr.op) { - case '!': - operator = "!"; - def_a = emit_sub_expr (e->e.expr.e1, 0); - def_b = &def_invalid; - break; - case '~': - operator = "~"; - def_a = emit_sub_expr (e->e.expr.e1, 0); - def_b = &def_invalid; - break; - case '-': - zero.type = expr_types[extract_type (e->e.expr.e1)]; - - operator = "-"; - def_a = ReuseConstant (&zero, 0); - def_b = emit_sub_expr (e->e.expr.e1, 0); - if (!dest) { - dest = get_tempdef (e->e.expr.type, current_scope); - dest->file = e->file; - dest->line = e->line; - dest->users += 2; - } - break; - case '&': - zero.type = ex_short; - - operator = "&"; - if (e->e.expr.e1->type == ex_expr - && e->e.expr.e1->e.expr.op == '.') { - tmp = get_tempdef (e->e.expr.type, current_scope); - tmp->file = e->file; - tmp->line = e->line; - tmp->users += 2; - def_b = emit_sub_expr (&zero, 0); - } else { - def_b = &def_void; - } - def_a = emit_sub_expr (e->e.expr.e1, tmp); - if (!dest) { - dest = get_tempdef (e->e.expr.type, current_scope); - dest->file = e->file; - dest->line = e->line; - dest->users += 2; - } - break; - case '.': - return emit_deref_expr (e, dest); - case 'C': - def_a = emit_sub_expr (e->e.expr.e1, 0); - if ((def_a->type->type == ev_pointer - && e->e.expr.type->type == ev_pointer) - || (def_a->type->type == ev_func - && e->e.expr.type->type == ev_func)) { - return def_a; - } - if ((def_a->type->type == ev_pointer - && e->e.expr.type->type == ev_integer) - || (def_a->type->type == ev_integer - && e->e.expr.type->type == ev_pointer)) { - def_t *tmp; - tmp = new_def (e->e.expr.type, 0, def_a->scope); - tmp->ofs = 0; - tmp->alias = def_a; - tmp->users = def_a->users; - tmp->freed = 1; - return tmp; - } - def_b = &def_invalid; - if (!dest) { - dest = get_tempdef (e->e.expr.type, current_scope); - dest->file = e->file; - dest->line = e->line; - dest->users = 2; - } - operator = "="; - break; - default: - abort (); - } - op = opcode_find (operator, def_a->type, def_b->type, - dest ? dest->type : 0); - d = emit_statement (e, op, def_a, def_b, dest); - break; - case ex_def: - d = e->e.def; - break; - case ex_symbol: - d = get_def (e->e.symbol->type, e->e.symbol->name, pr.scope, - st_extern); //FIXME - break; - case ex_temp: - if (!e->e.temp.def) { - if (dest) - e->e.temp.def = dest; - else { - e->e.temp.def = get_tempdef (e->e.temp.type, current_scope); - e->e.temp.def->line = e->line; - e->e.temp.def->file = e->file; - } - e->e.temp.def->users = e->e.temp.users; - e->e.temp.def->expr = e; - e->e.temp.def->managed = 1; - } - d = e->e.temp.def; - break; - case ex_pointer: - case ex_string: - case ex_float: - case ex_vector: - case ex_entity: - case ex_field: - case ex_func: - case ex_quaternion: - case ex_integer: - case ex_uinteger: - d = ReuseConstant (e, 0); - break; - case ex_short: - d = new_def (&type_short, 0, 0); - d->ofs = e->e.short_val; - d->absolute = 1; - d->users = 1; - break; - } - free_tempdefs (); - return d; + return 0; } void emit_expr (expr_t *e) { - def_t *def; - def_t *def_a; - def_t *def_b; - def_t *def_c; - ex_label_t *label; - opcode_t *op; - - //printf ("%d ", e->line); - //print_expr (e); - //puts (""); - switch (e->type) { - case ex_error: - break; - case ex_state: - def_a = emit_sub_expr (e->e.state.frame, 0); - def_b = emit_sub_expr (e->e.state.think, 0); - if (e->e.state.step) { - def_c = emit_sub_expr (e->e.state.step, 0); - op = op_state_f; - } else { - def_c = 0; - op = op_state; - } - emit_statement (e, op, def_a, def_b, def_c); - break; - case ex_bool: - emit_bool_expr (e); - break; - case ex_label: - label = &e->e.label; - label->ofs = pr.code->size; - relocate_refs (label->refs, label->ofs); - break; - case ex_block: - for (e = e->e.block.head; e; e = e->next) - emit_expr (e); - break; - case ex_expr: - switch (e->e.expr.op) { - case 'M': - emit_move_expr (e); - break; - case PAS: - case '=': - emit_assign_expr (e->e.expr.op, e); - break; - case 'n': - emit_branch (e, op_ifnot, e->e.expr.e1, e->e.expr.e2); - break; - case 'i': - emit_branch (e, op_if, e->e.expr.e1, e->e.expr.e2); - break; - case IFBE: - emit_branch (e, op_ifbe, e->e.expr.e1, e->e.expr.e2); - break; - case IFB: - emit_branch (e, op_ifb, e->e.expr.e1, e->e.expr.e2); - break; - case IFAE: - emit_branch (e, op_ifae, e->e.expr.e1, e->e.expr.e2); - break; - case IFA: - emit_branch (e, op_ifa, e->e.expr.e1, e->e.expr.e2); - break; - case 'c': - emit_function_call (e, 0); - break; - case 'b': - emit_bind_expr (e->e.expr.e1, e->e.expr.e2); - break; - case 'g': - def_a = emit_sub_expr (e->e.expr.e1, 0); - def_b = emit_sub_expr (e->e.expr.e2, 0); - emit_statement (e, op_jumpb, def_a, def_b, 0); - break; - default: - if (options.warnings.executable) - warning (e, "Non-executable statement; " - "executing programmer instead."); - break; - } - break; - case ex_uexpr: - switch (e->e.expr.op) { - case 'r': - def = 0; - if (e->e.expr.e1) - def = emit_sub_expr (e->e.expr.e1, 0); - if ((!def || (def->alias - && !strcmp (def->alias->name, ".return")) - || (!def->alias && !strcmp (def->name, ".return"))) - && !options.traditional && op_return_v) - emit_statement (e, op_return_v, 0, 0, 0); - else - emit_statement (e, op_return, def, 0, 0); - break; - case 'g': - emit_branch (e, op_goto, 0, e->e.expr.e1); - break; - default: - if (options.warnings.executable) - warning (e, "Non-executable statement; " - "executing programmer instead."); - emit_expr (e->e.expr.e1); - break; - } - break; - case ex_symbol: - case ex_def: - case ex_temp: - case ex_string: - case ex_float: - case ex_vector: - case ex_entity: - case ex_field: - case ex_func: - case ex_pointer: - case ex_quaternion: - case ex_integer: - case ex_uinteger: - case ex_short: - case ex_name: - case ex_nil: - if (options.warnings.executable) - warning (e, "Non-executable statement; " - "executing programmer instead."); - break; - } - free_tempdefs (); } diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 6ebadd7ab..52b578b20 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -50,6 +50,7 @@ static __attribute__ ((used)) const char rcsid[] = #include "qfcc.h" #include "class.h" #include "def.h" +#include "defspace.h" #include "emit.h" #include "expr.h" #include "function.h" @@ -78,7 +79,6 @@ etype_t qc_types[] = { ev_void, // ex_def ev_void, // ex_symbol ev_void, // ex_temp - ev_void, // ex_name ev_void, // ex_nil ev_string, // ex_string @@ -129,60 +129,11 @@ expr_type expr_types[] = { ex_nil, // ev_array }; -void -convert_name (expr_t *e) -{ - if (e->type == ex_name) { - const char *name = e->e.string_val; - def_t *d; - expr_t *new; - class_t *class; - - /// Convert name to enum (integer constant). - new = get_enum (name); - if (new) - goto convert; - - /// Convert name to class. - class = get_class (name, 0); - if (class) { - e->type = ex_def; - e->e.def = class_pointer_def (class); - return; - } - - /// Convert name to def. - d = get_def (NULL, name, current_scope, st_none); - if (d) { - if (d->global) { - new = class_ivar_expr (current_class, name); - if (new) - goto convert; - } - e->type = ex_def; - e->e.def = d; - return; - } - - /// Convert name to a class ivar in a message body. - new = class_ivar_expr (current_class, name); - if (new) - goto convert; - error (e, "Undeclared variable \"%s\".", name); - return; - convert: - e->type = new->type; - e->e = new->e; - } -} - type_t * get_type (expr_t *e) { - convert_name (e); switch (e->type) { case ex_label: - case ex_name: case ex_error: return 0; // something went very wrong case ex_bool: @@ -418,7 +369,6 @@ copy_expr (expr_t *e) case ex_error: case ex_def: case ex_symbol: - case ex_name: case ex_nil: case ex_string: case ex_float: @@ -516,7 +466,7 @@ new_label_name (void) SYS_CHECKMEM (lname); return lname; } - +#if 0 static expr_t * new_error_expr (void) { @@ -524,7 +474,7 @@ new_error_expr (void) e->type = ex_error; return e; } - +#endif expr_t * new_state_expr (expr_t *frame, expr_t *think, expr_t *step) { @@ -649,8 +599,13 @@ expr_t * new_name_expr (const char *name) { expr_t *e = new_expr (); - e->type = ex_name; - e->e.string_val = name; + symbol_t *sym; + + sym = symtab_lookup (current_symtab, name); + if (!sym) + return error (0, "undefined symbol %s", name); + e->type = ex_symbol; + e->e.symbol = sym; return e; } @@ -771,8 +726,6 @@ constant_expr (expr_t *var) { def_t *def; - convert_name (var); - if (var->type != ex_def || !var->e.def->constant) return var; @@ -982,7 +935,6 @@ print_expr (expr_t *e) printf ("NIL"); break; case ex_string: - case ex_name: printf ("\"%s\"", e->e.string_val); break; case ex_float: @@ -1023,219 +975,6 @@ print_expr (expr_t *e) static expr_t * field_expr (expr_t *e1, expr_t *e2) { - type_t *t1, *t2; - expr_t *e; - def_t *d; - int i; - struct_field_t *field; - class_t *class; - struct_t *strct; - - if (e1->type == ex_error) - return e1; - t1 = get_type (e1); - switch (t1->type) { - case ev_invalid: - if (t1->ty == ty_struct || t1->ty == ty_class) { - check_initialized (e1); - if (e2->type != ex_name) - return error (e2, "structure field name expected"); - if (t1->ty == ty_struct) - strct = t1->t.strct; - else - strct = t1->t.class->ivars; - field = struct_find_field (strct, e2->e.string_val); - if (!field) - return error (e2, "structure has no field %s", - e2->e.string_val); - e2->type = ex_short; - e2->e.short_val = field->offset; - e = unary_expr ('.', address_expr (e1, e2, field->type)); - return e; - } - break; - case ev_pointer: - check_initialized (e1); - switch (t1->t.fldptr.type->type) { - case ev_invalid: - if (t1->t.fldptr.type->ty == ty_struct) { - if (e2->type == ex_name) { - field = struct_find_field (t1->t.fldptr.type->t.strct, - e2->e.string_val); - if (!field) - return error (e2, "structure has no field %s", - e2->e.string_val); - e2->type = ex_short; - e2->e.short_val = field->offset; - t1 = pointer_type (field->type); - } - } else if (t1->t.fldptr.type->ty == ty_class) { - if (e2->type == ex_name) { - int protected; - - class = t1->t.fldptr.type->t.class; - protected = class_access (current_class, class); - field = class_find_ivar (class, protected, - e2->e.string_val); - if (!field) - return new_error_expr (); - e2->type = ex_short; - e2->e.short_val = field->offset; - t1 = pointer_type (field->type); - } - } - break; - default: - break; - } - if (e1->type == ex_pointer) { - if (e2->type == ex_short) { - e1->e.pointer.val += e2->e.short_val; - } else if (e2->type == ex_integer) { - e1->e.pointer.val += e2->e.integer_val; - } else if (e2->type == ex_uinteger) { - e1->e.pointer.val += e2->e.uinteger_val; - } else { - break; - } - e1->e.pointer.type = t1->t.fldptr.type; - return unary_expr ('.', e1); - } else { - e = new_binary_expr ('&', e1, e2); - e->e.expr.type = t1; - return unary_expr ('.', e); - } - break; - case ev_entity: - check_initialized (e1); - if (e2->type == ex_name) { - def_t *d = field_def (e2->e.string_val); - - if (!d) { - t2 = get_type (e2); - if (e2->type == ex_error) - return e2; - break; - } - e2 = new_def_expr (d); - t2 = get_type (e2); - e = new_binary_expr ('.', e1, e2); - e->e.expr.type = t2->t.fldptr.type; - return e; - } else { - t2 = get_type (e2); - if (e2->type == ex_error) - return e2; - if (t2->type == ev_field) { - e = new_binary_expr ('.', e1, e2); - e->e.expr.type = t2->t.fldptr.type; - return e; - } - } - break; - case ev_vector: - case ev_quat: - if (e2->type == ex_name) { - if (t1->type == ev_quat) { - field = struct_find_field (quaternion_struct, - e2->e.string_val); - if (!field) - return error (e2, "quaternion has no field %s", - e2->e.string_val); - } else { - field = struct_find_field (vector_struct, - e2->e.string_val); - if (!field) - return error (e2, "vector has no field %s", - e2->e.string_val); - } - switch (e1->type) { - case ex_expr: - if (e1->e.expr.op == '.' - && extract_type (e1->e.expr.e1) == ev_entity) { - int ofs; - def_t *def; - type_t *type; - - if (e1->e.expr.e2->type == ex_def) { - ofs = 0; - def = e1->e.expr.e2->e.def; - type = def->type; - } else if (e1->e.expr.e2->type == ex_field) { - ofs = e1->e.expr.e2->e.pointer.val; - def = e1->e.expr.e2->e.pointer.def; - type = e1->e.expr.e2->e.pointer.type; - } else - break; - if (field->offset) { - e = new_field_expr (ofs + field->offset, - type, def); - e = new_binary_expr ('.', e1->e.expr.e1, e); - } else { - e = e1; - } - e->e.expr.type = field->type; - return e; - } - break; - case ex_uexpr: - if (e1->e.expr.op == '.') { - if (e1->e.expr.e1->type == ex_pointer) { - e = e1->e.expr.e1; - e->e.pointer.val += field->offset; - e->e.pointer.type = field->type; - e1->e.expr.type = field->type; - return e1; - } else if (extract_type (e1->e.expr.e1) - == ev_pointer) { - e = new_integer_expr (field->offset); - e = address_expr (e1, e, field->type); - return unary_expr ('.', e); - } - } - break; - case ex_block: - print_expr (e1); puts (""); -#if 0 - e1 = new_bind_expr (e1, new_temp_def_expr (t1)); - e2 = new_short_expr (field->offset); - e = address_expr (e1, e2, field->type); - e = unary_expr ('.', e); - return e; -#endif - break; - case ex_def: - if (t1->type == ev_quat) { - e = new_pointer_expr (field->offset, field->type, - e1->e.def); - e = unary_expr ('.', e); - return e; - } else { - d = e1->e.def->def_next; - for (i = field->offset; i; i--) - d = d->def_next; - e = new_def_expr (d); - } - return e; - case ex_vector: - e = new_float_expr (e1->e.vector_val[field->offset]); - return e; - case ex_quaternion: - if (field->type == &type_float) - e = new_float_expr (*(e1->e.quaternion_val - + field->offset)); - else - e = new_vector_expr (e1->e.quaternion_val - + field->offset); - return e; - default: - break; - } - } - break; - default: - break; - } return type_mismatch (e1, e2, '.'); } @@ -1678,8 +1417,6 @@ binary_expr (int op, expr_t *e1, expr_t *e2) if (e2->type == ex_error) return e2; - convert_name (e1); - if (e1->type == ex_block && e1->e.block.is_call && has_function_call (e2) && e1->e.block.result) { e = new_temp_def_expr (get_type (e1->e.block.result)); @@ -1691,7 +1428,6 @@ binary_expr (int op, expr_t *e1, expr_t *e2) return field_expr (e1, e2); check_initialized (e1); - convert_name (e2); check_initialized (e2); if (op == OR || op == AND) { @@ -1907,7 +1643,6 @@ asx_expr (int op, expr_t *e1, expr_t *e2) expr_t * unary_expr (int op, expr_t *e) { - convert_name (e); check_initialized (e); if (e->type == ex_error) return e; @@ -1916,7 +1651,6 @@ unary_expr (int op, expr_t *e) switch (e->type) { case ex_error: case ex_label: - case ex_name: case ex_state: error (e, "internal error"); abort (); @@ -1978,7 +1712,6 @@ unary_expr (int op, expr_t *e) switch (e->type) { case ex_error: case ex_label: - case ex_name: case ex_state: error (e, "internal error"); abort (); @@ -2044,7 +1777,6 @@ unary_expr (int op, expr_t *e) switch (e->type) { case ex_error: case ex_label: - case ex_name: case ex_state: error (e, "internal error"); abort (); @@ -2594,6 +2326,149 @@ build_if_statement (expr_t *test, expr_t *s1, expr_t *s2) return if_expr; } +expr_t * +build_while_statement (expr_t *test, expr_t *statement, + expr_t *break_label, expr_t *continue_label) +{ + int line = pr.source_line; + string_t file = pr.source_file; + expr_t *l1 = new_label_expr (); + expr_t *l2 = break_label; + expr_t *while_expr; + + pr.source_line = test->line; + pr.source_file = test->file; + + while_expr = new_block_expr (); + + append_expr (while_expr, new_unary_expr ('g', continue_label)); + append_expr (while_expr, l1); + append_expr (while_expr, statement); + append_expr (while_expr, continue_label); + + test = convert_bool (test, 1); + if (test->type != ex_error) { + backpatch (test->e.bool.true_list, l1); + backpatch (test->e.bool.false_list, l2); + append_expr (test->e.bool.e, l2); + append_expr (while_expr, test); + } + + pr.source_line = line; + pr.source_file = file; + + return while_expr; +} + +expr_t * +build_do_while_statement (expr_t *statement, expr_t *test, + expr_t *break_label, expr_t *continue_label) +{ + expr_t *l1 = new_label_expr (); + int line = pr.source_line; + string_t file = pr.source_file; + expr_t *do_while_expr; + + pr.source_line = test->line; + pr.source_file = test->file; + + do_while_expr = new_block_expr (); + + append_expr (do_while_expr, l1); + append_expr (do_while_expr, statement); + append_expr (do_while_expr, continue_label); + + test = convert_bool (test, 1); + if (test->type != ex_error) { + backpatch (test->e.bool.true_list, l1); + backpatch (test->e.bool.false_list, break_label); + append_expr (test->e.bool.e, break_label); + append_expr (do_while_expr, test); + } + + pr.source_line = line; + pr.source_file = file; + + return do_while_expr; +} + +expr_t * +build_for_statement (expr_t *init, expr_t *test, expr_t *next, + expr_t *statement, + expr_t *break_label, expr_t *continue_label) +{ + expr_t *tl = new_label_expr (); + expr_t *fl = break_label; + expr_t *l1 = 0; + expr_t *t; + int line = pr.source_line; + string_t file = pr.source_file; + expr_t *for_expr; + + if (next) + t = next; + else if (test) + t = test; + else if (init) + t = init; + else + t = continue_label; + pr.source_line = t->line; + pr.source_file = t->file; + + for_expr = new_block_expr (); + + append_expr (for_expr, init); + if (test) { + l1 = new_label_expr (); + append_expr (for_expr, new_unary_expr ('g', l1)); + } + append_expr (for_expr, tl); + append_expr (for_expr, statement); + append_expr (for_expr, continue_label); + append_expr (for_expr, next); + if (test) { + append_expr (for_expr, l1); + test = convert_bool (test, 1); + if (test->type != ex_error) { + backpatch (test->e.bool.true_list, tl); + backpatch (test->e.bool.false_list, fl); + append_expr (test->e.bool.e, fl); + append_expr (for_expr, test); + } + } else { + append_expr (for_expr, new_unary_expr ('g', tl)); + append_expr (for_expr, fl); + } + + pr.source_line = line; + pr.source_file = file; + + return for_expr; +} + +expr_t * +build_state_expr (expr_t *frame, expr_t *think, expr_t *step) +{ + if (frame->type == ex_integer) + convert_int (frame); + else if (frame->type == ex_uinteger) + convert_uint (frame); + if (!type_assignable (&type_float, get_type (frame))) + return error (frame, "invalid type for frame number"); + if (extract_type (think) != ev_func) + return error (think, "invalid type for think"); + if (step) { + if (step->type == ex_integer) + convert_int (step); + else if (step->type == ex_uinteger) + convert_uint (step); + if (!type_assignable (&type_float, get_type (step))) + return error (step, "invalid type for frame number"); + } + return new_state_expr (frame, think, step); +} + static int is_indirect (expr_t *e) { @@ -2629,9 +2504,6 @@ assign_expr (expr_t *e1, expr_t *e2) type_t *t1, *t2, *type; expr_t *e; - convert_name (e1); - convert_name (e2); - if (e1->type == ex_error) return e1; if (e2->type == ex_error) @@ -2773,8 +2645,6 @@ cast_expr (type_t *type, expr_t *e) expr_t *c; type_t *e_type; - convert_name (e); - if (e->type == ex_error) return e; @@ -2813,88 +2683,6 @@ cast_expr (type_t *type, expr_t *e) void init_elements (def_t *def, expr_t *eles) { - expr_t *e, *c; - int count, i, num_params, ofs; - pr_type_t *g; - def_t *elements; - - ofs = def->ofs; - if (def->local && local_expr) - ofs = 0; - if (is_array (def->type)) { - elements = calloc (def->type->t.array.size, sizeof (def_t)); - for (i = 0; i < def->type->t.array.size; i++) { - elements[i].type = def->type->t.array.type; - elements[i].ofs = ofs + i * type_size (def->type->t.array.type); - } - num_params = i; - } else if (is_struct (def->type)) { - struct_field_t *field; - - for (i = 0, field = def->type->t.strct->struct_head; field; - i++, field = field->next) - ; - elements = calloc (i, sizeof (def_t)); - for (i = 0, field = def->type->t.strct->struct_head; field; - i++, field = field->next) { - elements[i].type = field->type; - elements[i].ofs = ofs + field->offset; - } - num_params = i; - } else { - error (eles, "invalid initializer"); - return; - } - for (count = 0, e = eles->e.block.head; e; count++, e = e->next) - if (e->type == ex_error) { - free (elements); - return; - } - if (count > num_params) { - if (options.warnings.initializer) - warning (eles, "excessive elements in initializer"); - count = num_params; - } - for (i = 0, e = eles->e.block.head; i < count; i++, e = e->next) { - g = G_POINTER (pr_type_t, elements[i].ofs); - c = constant_expr (e); - if (c->type == ex_block) { - if (!is_array (elements[i].type) - && !is_struct (elements[i].type)) { - error (e, "type mismatch in initializer"); - continue; - } - init_elements (&elements[i], c); - continue; - } else if (c->type >= ex_nil) { - if (c->type == ex_integer - && elements[i].type->type == ev_float) - convert_int (c); - if (get_type (c) != elements[i].type) { - error (e, "type mismatch in initializer"); - continue; - } - } else { - if (!def->local || !local_expr) { - error (e, "non-constant initializer"); - continue; - } - } - if (def->local && local_expr) { - int ofs = elements[i].ofs; - type_t *type = elements[i].type; - expr_t *ptr = new_pointer_expr (ofs, type, def); - - append_expr (local_expr, assign_expr (unary_expr ('.', ptr), c)); - } else { - if (c->type == ex_string) { - EMIT_STRING (g->string_var, c->e.string_val); - } else { - memcpy (g, &c->e, type_size (get_type (c)) * 4); - } - } - } - free (elements); } expr_t * @@ -2946,13 +2734,12 @@ super_expr (class_type_t *class_type) class_type_t _class_type; if (!class_type) - return error (new_expr (), - "`super' used outside of class implementation"); + return error (0, "`super' used outside of class implementation"); class = extract_class (class_type); if (!class->super_class) - return error (new_expr (), "%s has no super class", class->name); + return error (0, "%s has no super class", class->name); super_d = get_def (&type_Super, ".super", current_func->scope, st_local); def_initialized (super_d); @@ -2987,8 +2774,8 @@ message_expr (expr_t *receiver, keywordarg_t *message) class_t *class; method_t *method; - if (receiver->type == ex_name - && strcmp (receiver->e.string_val, "super") == 0) { + if (receiver->type == ex_symbol + && strcmp (receiver->e.symbol->name, "super") == 0) { super = 1; receiver = super_expr (current_class); @@ -2998,10 +2785,10 @@ message_expr (expr_t *receiver, keywordarg_t *message) class = extract_class (current_class); rec_type = class->type; } else { - if (receiver->type == ex_name) { - if (strcmp (receiver->e.string_val, "self") == 0) + if (receiver->type == ex_symbol) { + if (strcmp (receiver->e.symbol->name, "self") == 0) self = 1; - if (get_class (receiver->e.string_val, 0)) + if (get_class (receiver->e.symbol, 0)) class_msg = 1; } rec_type = get_type (receiver); diff --git a/tools/qfcc/source/function.c b/tools/qfcc/source/function.c index 3f56a8641..02aa1e086 100644 --- a/tools/qfcc/source/function.c +++ b/tools/qfcc/source/function.c @@ -51,6 +51,7 @@ static __attribute__ ((used)) const char rcsid[] = #include "codespace.h" #include "debug.h" #include "def.h" +#include "defspace.h" #include "emit.h" #include "expr.h" #include "function.h" @@ -279,7 +280,7 @@ find_function (expr_t *fexpr, expr_t *params) type_t type; void **funcs, *dummy_p = &dummy; - if (fexpr->type != ex_name) + if (fexpr->type != ex_symbol) return fexpr; memset (&type, 0, sizeof (type)); @@ -296,7 +297,7 @@ find_function (expr_t *fexpr, expr_t *params) if (e->type == ex_error) return e; } - funcs = Hash_FindList (function_map, fexpr->e.string_val); + funcs = Hash_FindList (function_map, fexpr->e.symbol->name); if (!funcs) return fexpr; for (func_count = 0; funcs[func_count]; func_count++) @@ -309,14 +310,14 @@ find_function (expr_t *fexpr, expr_t *params) dummy.type = find_type (&type); qsort (funcs, func_count, sizeof (void *), func_compare); - dummy.full_name = save_string (va ("%s|%s", fexpr->e.string_val, + dummy.full_name = save_string (va ("%s|%s", fexpr->e.symbol->name, encode_params (&type))); dummy_p = bsearch (&dummy_p, funcs, func_count, sizeof (void *), func_compare); if (dummy_p) { f = (overloaded_function_t *) *(void **) dummy_p; if (f->overloaded) - fexpr->e.string_val = f->full_name; + fexpr->e.symbol->name = f->full_name; free (funcs); return fexpr; } @@ -360,7 +361,7 @@ find_function (expr_t *fexpr, expr_t *params) return fexpr; if (best) { if (best->overloaded) - fexpr->e.string_val = best->full_name; + fexpr->e.symbol->name = best->full_name; free (funcs); return fexpr; } @@ -507,7 +508,7 @@ build_code_function (function_t *f, expr_t *state_expr, expr_t *statements) } function_t * -build_builtin_function (def_t *def, expr_t *bi_val) +build_builtin_function (def_t *def, expr_t *bi_val, param_t *params) { function_t *f; @@ -519,11 +520,12 @@ build_builtin_function (def_t *def, expr_t *bi_val) error (bi_val, "%s redefined", def->name); return 0; } - if (bi_val->type != ex_integer && bi_val->type != ex_float) { error (bi_val, "invalid constant for = #"); return 0; } + if (def->external) + return 0; f = new_function (def, 0); add_function (f); @@ -533,6 +535,10 @@ build_builtin_function (def_t *def, expr_t *bi_val) reloc_def_func (f, def->ofs); build_function (f); finish_function (f); + + // for debug info + build_scope (f, f->def, params); + flush_scope (f->scope, 1); return f; } @@ -580,7 +586,7 @@ emit_function (function_t *f, expr_t *e) f->var_init = f->var_init->next; } - current_scope = f->scope; + //FIXME current_scope = f->scope; while (e) { #ifdef DUMP_EXPR printf ("%d ", pr.source_line); @@ -600,8 +606,8 @@ emit_function (function_t *f, expr_t *e) else emit_statement (0, op_done, 0, 0, 0); } - flush_scope (current_scope, 0); - current_scope = pr.scope; + //FIXME flush_scope (current_scope, 0); + //FIXME current_scope = pr.scope; reset_tempdefs (); #ifdef DUMP_EXPR diff --git a/tools/qfcc/source/idstuff.c b/tools/qfcc/source/idstuff.c index 349e8591f..9d441bda1 100644 --- a/tools/qfcc/source/idstuff.c +++ b/tools/qfcc/source/idstuff.c @@ -46,6 +46,7 @@ static __attribute__ ((used)) const char rcsid[] = #include #include "def.h" +#include "defspace.h" #include "qfcc.h" #include "expr.h" #include "idstuff.h" diff --git a/tools/qfcc/source/immediate.c b/tools/qfcc/source/immediate.c index 770f8c996..228bf2341 100644 --- a/tools/qfcc/source/immediate.c +++ b/tools/qfcc/source/immediate.c @@ -49,6 +49,7 @@ static __attribute__ ((used)) const char rcsid[] = #include "qfcc.h" #include "def.h" +#include "defspace.h" #include "emit.h" #include "expr.h" #include "immediate.h" @@ -237,7 +238,7 @@ ReuseConstant (expr_t *expr, def_t *def) if (imm) { cn = imm->def; if (def) { - free_location (def); + defsapce_free_loc (def->space, def->ofs, type_size (def->type)); def->ofs = cn->ofs; def->initialized = def->constant = 1; def->nosave = 1; @@ -263,7 +264,7 @@ ReuseConstant (expr_t *expr, def_t *def) } } else { cn = new_def (type, ".imm", pr.scope); - cn->ofs = new_location (type, pr.near_data); + cn->ofs = defspace_new_loc (pr.near_data, type_size (type)); } cn->initialized = cn->constant = 1; cn->nosave = 1; diff --git a/tools/qfcc/source/linker.c b/tools/qfcc/source/linker.c index 2e99151d6..1e9aec187 100644 --- a/tools/qfcc/source/linker.c +++ b/tools/qfcc/source/linker.c @@ -57,6 +57,7 @@ static __attribute__ ((used)) const char rcsid[] = "$Id$"; #include "codespace.h" #include "def.h" +#include "defspace.h" #include "emit.h" #include "expr.h" #include "immediate.h" @@ -666,7 +667,7 @@ define_def (const char *name, etype_t basic_type, const char *full_type, } d.flags = QFOD_GLOBAL | flags; - defspace_adddata (data, val, size); + defspace_add_data (data, val, size); defgroup_add_defs (&global_defs, &d, 1); process_def (global_defs.defs + global_defs.num_defs - 1); @@ -725,9 +726,9 @@ linker_add_qfo (qfo_t *qfo) entity_base = entity->size; codespace_addcode (code, qfo->code, qfo->code_size); - defspace_adddata (data, qfo->data, qfo->data_size); - defspace_adddata (far_data, qfo->far_data, qfo->far_data_size); - defspace_adddata (entity, 0, qfo->entity_fields); + defspace_add_data (data, qfo->data, qfo->data_size); + defspace_add_data (far_data, qfo->far_data, qfo->far_data_size); + defspace_add_data (entity, 0, qfo->entity_fields); add_strings (qfo); add_relocs (qfo); add_funcs (qfo); @@ -898,7 +899,7 @@ linker_finish (void) entity_base = 0; define_def (".this", ev_field, "F@", QFOD_NOSAVE, 1, entity->size); - defspace_adddata (entity, 0, 1); + defspace_add_data (entity, 0, 1); did_this = 1; } } diff --git a/tools/qfcc/source/method.c b/tools/qfcc/source/method.c index 81964badf..1a6f8568b 100644 --- a/tools/qfcc/source/method.c +++ b/tools/qfcc/source/method.c @@ -52,6 +52,7 @@ static __attribute__ ((used)) const char rcsid[] = #include "expr.h" #include "class.h" #include "def.h" +#include "defspace.h" #include "emit.h" #include "immediate.h" #include "method.h" @@ -59,6 +60,7 @@ static __attribute__ ((used)) const char rcsid[] = #include "reloc.h" #include "strpool.h" #include "struct.h" +#include "symtab.h" #include "type.h" static hashtab_t *known_methods; @@ -368,7 +370,7 @@ emit_selectors (void) sel_def = get_def (type_SEL.t.fldptr.type, "_OBJ_SELECTOR_TABLE", pr.scope, st_extern); sel_def->type = sel_type; - sel_def->ofs = new_location (sel_type, pr.near_data); + sel_def->ofs = defspace_new_loc (pr.near_data, type_size (sel_type)); set_storage_bits (sel_def, st_static); sel = G_POINTER (pr_sel_t, sel_def->ofs); selectors = (selector_t **) Hash_GetList (sel_hash); @@ -384,12 +386,18 @@ emit_selectors (void) def_t * emit_methods (methodlist_t *_methods, const char *name, int instance) { + static struct_def_t methods_struct[] = { + {"method_next", &type_pointer}, + {"method_count", &type_integer}, + {"method_list", 0}, // type will be filled in at run time + {0, 0} + }; const char *type = instance ? "INSTANCE" : "CLASS"; method_t *method; int i, count; def_t *methods_def; + type_t *methods_type; pr_method_list_t *methods; - struct_t *method_list; if (!_methods) return 0; @@ -404,14 +412,9 @@ emit_methods (methodlist_t *_methods, const char *name, int instance) } if (!count) return 0; - method_list = get_struct (0, 1); - init_struct (method_list, new_type (), str_struct, 0); - new_struct_field (method_list, &type_pointer, "method_next", vis_public); - new_struct_field (method_list, &type_integer, "method_count", vis_public); - for (i = 0; i < count; i++) - new_struct_field (method_list, &type_Method, 0, - vis_public); - methods_def = get_def (method_list->type, + methods_struct[2].type = array_type (&type_integer, count); + methods_type = make_structure (0, 's', methods_struct, 0)->type; + methods_def = get_def (methods_type, va ("_OBJ_%s_METHODS_%s", type, name), pr.scope, st_static); methods_def->initialized = methods_def->constant = 1; @@ -443,7 +446,8 @@ emit_method_descriptions (methodlist_t *_methods, const char *name, int i, count; def_t *methods_def; pr_method_description_list_t *methods; - struct_t *method_list; + symtab_t *method_list; + symbol_t *method_list_sym; if (!_methods) return 0; @@ -453,13 +457,12 @@ emit_method_descriptions (methodlist_t *_methods, const char *name, count++; if (!count) return 0; - method_list = get_struct (0, 1); - init_struct (method_list, new_type (), str_struct, 0); - new_struct_field (method_list, &type_integer, "count", vis_public); - for (i = 0; i < count; i++) - new_struct_field (method_list, &type_method_description, 0, - vis_public); - methods_def = get_def (method_list->type, + method_list = new_symtab (0, stab_local); + symtab_addsymbol (method_list, new_symbol_type ("count", &type_integer)); + symtab_addsymbol (method_list, new_symbol_type ("method_list", + array_type (&type_method_description, count))); + method_list_sym = build_struct ('s', 0, method_list, 0); + methods_def = get_def (method_list_sym->type, va ("_OBJ_%s_METHODS_%s", type, name), pr.scope, st_static); methods_def->initialized = methods_def->constant = 1; diff --git a/tools/qfcc/source/obj_file.c b/tools/qfcc/source/obj_file.c index 21a70be08..6742233db 100644 --- a/tools/qfcc/source/obj_file.c +++ b/tools/qfcc/source/obj_file.c @@ -48,6 +48,7 @@ static __attribute__ ((used)) const char rcsid[] = "$Id$"; #include "codespace.h" #include "debug.h" #include "def.h" +#include "defspace.h" #include "emit.h" #include "expr.h" #include "function.h" diff --git a/tools/qfcc/source/qc-lex.l b/tools/qfcc/source/qc-lex.l index cbc049f9c..f92f08431 100644 --- a/tools/qfcc/source/qc-lex.l +++ b/tools/qfcc/source/qc-lex.l @@ -56,6 +56,7 @@ static __attribute__ ((used)) const char rcsid[] = #include "immediate.h" #include "options.h" #include "struct.h" +#include "symtab.h" #include "type.h" #include "qc-parse.h" @@ -98,6 +99,7 @@ INT ({D}+|0[xX]{X}+) RANGE \.\. ELLIPSIS \.\.\. FRAMEID {ID}(\.{ID})* +STRING \"(\\.|[^"\\])*\" %x GRAB_FRAME GRAB_OTHER COMMENT @@ -144,13 +146,13 @@ FRAMEID {ID}(\.{ID})* REJECT; return tok; } -@ return '@'; -\"(\\.|[^"\\])*\" { +{STRING} { const char *s = make_string (yytext, 0); yylval.expr = new_string_expr (s); - return CONST; + return STRING; } +@ return '@'; '{s}*{m}?{FLOAT}{s}+{m}?{FLOAT}{s}+{m}?{FLOAT}{s}*' { vec3_t v; @@ -193,7 +195,7 @@ FRAMEID {ID}(\.{ID})* } [!(){}.*/&|^~+\-=\[\];,#%?:] { - yylval.op = yytext[0]; + yylval.pointer = 0; // ensure pointer values are null return yytext[0]; } @@ -252,9 +254,9 @@ yywrap (void) } typedef struct { - const char *name; - int value; - type_t *type; + const char *name; + int value; + type_t *type; unsigned int traditional; unsigned int version; } keyword_t; @@ -290,10 +292,9 @@ static keyword_t keywords[] = { {"default", DEFAULT, 0, 0, PROG_ID_VERSION}, {"nil", NIL, 0, 0, PROG_ID_VERSION}, {"struct", STRUCT, 0, 0, PROG_VERSION}, - {"union", UNION, 0, 0, PROG_VERSION}, + {"union", STRUCT, 0, 0, PROG_VERSION}, {"enum", ENUM, 0, 0, PROG_ID_VERSION}, {"typedef", TYPEDEF, 0, 0, PROG_ID_VERSION}, - {"super", SUPER, 0, 0, PROG_VERSION}, {"@class", CLASS, 0, 0, PROG_VERSION}, {"@defs", DEFS, 0, 0, PROG_VERSION}, @@ -330,8 +331,7 @@ keyword_or_id (char *token) { static hashtab_t *keyword_tab; keyword_t *keyword; - typedef_t *typename; - class_t *class; + symbol_t *sym; if (!keyword_tab) { size_t i; @@ -346,23 +346,25 @@ keyword_or_id (char *token) if (!options.traditional && token[0] == '@' && !class_Class.super_class) class_init (); - yylval.type = keyword->type; + if (keyword->value == STRUCT) { + yylval.op = token[0]; + } else { + yylval.type = 0; + yylval.type = keyword->type; + } return keyword->value; } if (token[0] == '@') { return '@'; } - if ((typename = get_typedef (token))) { - yylval.typename = typename; + sym = symtab_lookup (current_symtab, token); + if (!sym) + sym = new_symbol (token); + yylval.symbol = sym; + if (sym->sy_type == sy_type) return TYPE_NAME; - } - if (!get_enum (token)) { - if ((class = get_class (token, 0))) { - yylval.string_val = save_string (token); - return CLASS_NAME; - } - } - yylval.string_val = save_string (token); + if (is_class (sym->type)) + return CLASS_NAME; return NAME; } diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index a5b23ba19..590237fdf 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -59,6 +59,7 @@ static __attribute__ ((used)) const char rcsid[] = #include "reloc.h" #include "struct.h" #include "switch.h" +#include "symtab.h" #include "type.h" #define YYDEBUG 1 @@ -87,28 +88,16 @@ parse_error (void) int yylex (void); -hashtab_t *save_local_inits (scope_t *scope); -hashtab_t *merge_local_inits (hashtab_t *dl_1, hashtab_t *dl_2); -void restore_local_inits (hashtab_t *def_list); -void free_local_inits (hashtab_t *def_list); -static def_t *create_def (type_t *type, const char *name, scope_t *scope, - storage_class_t storage); - %} %union { int op; + void *pointer; // for ensuring pointer values are null struct def_s *def; struct hashtab_s *def_list; struct type_s *type; struct typedef_s *typename; struct expr_s *expr; - int integer_val; - unsigned uinteger_val; - float float_val; - const char *string_val; - float vector_val[3]; - float quaternion_val[4]; struct function_s *function; struct switch_block_s *switch_block; struct param_s *param; @@ -120,7 +109,8 @@ static def_t *create_def (type_t *type, const char *name, scope_t *scope, struct protocollist_s *protocol_list; struct keywordarg_s *keywordarg; struct methodlist_s *methodlist; - struct struct_s *strct; + struct symbol_s *symbol; + struct symtab_s *symtab; } %nonassoc IFX @@ -131,82 +121,117 @@ static def_t *create_def (type_t *type, const char *name, scope_t *scope, %nonassoc STORAGEX -%right '=' ASX PAS /* pointer assign */ -%right '?' ':' -%left OR -%left AND -%left '|' -%left '^' -%left '&' -%left EQ NE -%left LE GE LT GT -%left SHL SHR -%left '+' '-' -%left '*' '/' '%' -%right UNARY INCOP -%left HYPERUNARY -%left '.' '(' '[' +%right '=' ASX PAS /* pointer assign */ +%right '?' ':' +%left OR +%left AND +%left '|' +%left '^' +%left '&' +%left EQ NE +%left LE GE LT GT +%left SHL SHR +%left '+' '-' +%left '*' '/' '%' +%right UNARY INCOP +%left HYPERUNARY +%left '.' '(' '[' -%token CLASS_NAME NAME STRING_VAL -%token CONST +%token CLASS_NAME NAME +%token CONST STRING -%token LOCAL RETURN WHILE DO IF ELSE FOR BREAK CONTINUE ELLIPSIS NIL -%token IFBE IFB IFAE IFA -%token SWITCH CASE DEFAULT STRUCT UNION ENUM TYPEDEF SUPER SELF THIS -%token ARGS EXTERN STATIC SYSTEM SIZEOF OVERLOAD -%token TYPE -%token TYPE_NAME -%token CLASS DEFS ENCODE END IMPLEMENTATION INTERFACE PRIVATE PROTECTED -%token PROTOCOL PUBLIC SELECTOR REFERENCE +%token LOCAL RETURN WHILE DO IF ELSE FOR BREAK CONTINUE ELLIPSIS +%token NIL IFBE IFB IFAE IFA SWITCH CASE DEFAULT ENUM TYPEDEF +%token ARGS EXTERN STATIC SYSTEM SIZEOF OVERLOAD +%token STRUCT +%token TYPE +%token TYPE_NAME +%token CLASS DEFS ENCODE END IMPLEMENTATION INTERFACE PRIVATE +%token PROTECTED PROTOCOL PUBLIC SELECTOR REFERENCE SELF THIS -%type type non_field_type type_name def simple_def struct_def -%type struct_def_item ivar_decl ivar_declarator def_item def_list -%type struct_def_list ivars func_type non_func_type -%type non_code_func code_func func_init func_defs func_def_list -%type fdef_name cfunction_def func_def -%type function_decl -%type param param_list -%type opt_initializer methoddef var_initializer -%type const opt_expr fexpr expr element_list element_list1 element -%type opt_state_expr think opt_step array_decl texpr -%type statement statements statement_block -%type label break_label continue_label enum_list enum -%type unary_expr primary cast_expr opt_arg_list arg_list -%type begin_function builtin_function -%type save_inits +%type tag opt_tag +%type struct_def struct_def_item struct_def_list struct_spec +%type enum_spec +%type opt_enum_list enum_list enum enum_init + +%type const string + +%type type non_field_type type_name def simple_def +%type ivar_decl ivar_declarator def_item def_list +%type ivars func_type non_func_type +%type code_func func_defs func_def_list +%type fdef_name cfunction_def func_def +%type function_decl +%type param param_list +%type opt_initializer methoddef var_initializer +%type opt_expr fexpr expr element_list element_list1 element +%type opt_state_expr think opt_step array_decl texpr +%type statement statements statement_block +%type label break_label continue_label +%type unary_expr primary cast_expr opt_arg_list arg_list %type switch_block -%type def_name identifier +%type def_name identifier -%type selector reserved_word -%type optparmlist unaryselector keyworddecl keywordselector -%type methodproto methoddecl -%type obj_expr identifier_list obj_messageexpr obj_string receiver +%type identifier_list +%type selector reserved_word +%type optparmlist unaryselector keyworddecl keywordselector +%type methodproto methoddecl +%type obj_expr obj_messageexpr obj_string receiver %type protocolrefs protocol_list %type messageargs keywordarg keywordarglist selectorarg %type keywordnamelist keywordname -%type class_name new_class_name class_with_super new_class_with_super -%type classdef -%type category_name new_category_name -%type protocol_name +%type class_name new_class_name class_with_super +%type classdef new_class_with_super +%type category_name new_category_name +%type protocol_name %type methodprotolist methodprotolist2 -%type ivar_decl_list -%type ci +%type ivar_decl_list +%type ci %{ function_t *current_func; -param_t *current_params; -expr_t *current_init; +param_t *current_params; +expr_t *current_init; class_type_t *current_class; -expr_t *local_expr; -expr_t *break_label; -expr_t *continue_label; -switch_block_t *switch_block; -struct_t *current_struct; -visibility_type current_visibility; -struct_t *current_ivars; -scope_t *current_scope; +expr_t *local_expr; +vis_e current_visibility; storage_class_t current_storage = st_global; +symtab_t *current_symtab; + +static switch_block_t *switch_block; +static expr_t *break_label; +static expr_t *continue_label; + +/* When defining a new symbol, already existing symbols must be in a + different scope. However, when they are in a different scope, we want a + truly new symbol. +*/ +static symbol_t * +check_redefined (symbol_t *sym) +{ + if (sym->table == current_symtab) + error (0, "%s redefined", sym->name); + if (sym->table) // truly new symbols are not in any symbol table + sym = new_symbol (sym->name); + return sym; +} + +/* Check for undefined symbols. If the symbol is undefined, default its type + to float or int, depending on compiler mode. +*/ +static symbol_t * +check_undefined (symbol_t *sym) +{ + if (!sym->table) { // truly new symbols are not in any symbol table + error (0, "%s undefined", sym->name); + if (options.code.progsversion == PROG_ID_VERSION) + sym->type = &type_float; + else + sym->type = &type_integer; + } + return sym; +} %} @@ -228,28 +253,12 @@ def | storage_class simple_def { current_storage = st_global; } | storage_class '{' simple_defs '}' ';' { current_storage = st_global; } - | STRUCT identifier { current_struct = new_struct ($2); } - '{' struct_defs '}' ';' - { - if (!current_struct->struct_head) - new_struct_field (current_struct, &type_void, 0, vis_private); - } - | UNION identifier { current_struct = new_union ($2); } - '{' struct_defs '}' ';' - { - if (!current_struct->struct_head) - new_struct_field (current_struct, &type_void, 0, vis_private); - } - | STRUCT identifier ';' { decl_struct ($2); } - | UNION identifier ';' { decl_union ($2); } - | ENUM '{' enum_list opt_comma '}' ';' - { process_enum ($3); } | TYPEDEF type identifier ';' - { new_typedef ($3, $2); } - | TYPEDEF ENUM '{' enum_list opt_comma '}' identifier ';' { - process_enum ($4); - new_typedef ($7, &type_integer); + $3 = check_redefined ($3); + $3->type = $2; + $3->sy_type = sy_type; + symtab_addsymbol (current_symtab, $3); } ; @@ -264,49 +273,23 @@ simple_defs ; simple_def - : non_func_type def_list ';' { } - | func_type func_defs { } - | cfunction { } + : non_func_type def_list ';' + | func_type func_defs + | cfunction {} ; cfunction : cfunction_def ';' - { - } - | cfunction_def '=' '#' fexpr - { $$ = $1; } - { $$ = constant_expr ($4); } - builtin_function ';' - { - (void) ($5); - (void) ($6); - } - | cfunction_def opt_state_expr - { $$ = current_storage; } - { $$ = 0; } - { $$ = $1; } - begin_function statement_block { $$ = $3; } end_function - { - build_code_function ($6, $2, $7); - current_func = 0; - (void) ($4); - (void) ($5); - (void) ($8); - } + | cfunction_def '=' '#' fexpr ';' + | cfunction_def opt_state_expr statement_block ; cfunction_def : OVERLOAD non_func_type identifier function_decl { - type_t *type = parse_params ($2, current_params = $4); - $$ = get_function_def ($3, type, current_scope, - current_storage, 1, 1); } | non_func_type identifier function_decl { - type_t *type = parse_params ($1, current_params = $3); - $$ = get_function_def ($2, type, current_scope, - current_storage, 0, 1); } ; @@ -327,12 +310,15 @@ struct_defs | struct_defs struct_def ';' | DEFS '(' identifier ')' { - class_t *class = get_class ($3, 0); - - if (class) { - class_to_struct (class, current_struct); + $3 = check_undefined ($3); + if (!$3->type || !is_class ($3->type)) { + error (0, "`%s' is not a class", $3->name); } else { - error (0, "undefined symbol `%s'", $3); + // replace the struct symbol table with one built from + // the class ivars and the current struct fields. ivars + // will replace any fields of the same name. + current_symtab = class_to_struct ($3->type->t.class, + current_symtab); } } ; @@ -350,36 +336,9 @@ struct_def_list struct_def_item : identifier { - new_struct_field (current_struct, $0, $1, vis_public); - } - ; - -enum_list - : enum - | enum_list ',' enum - { - if ($3) { - $3->next = $1; - $$ = $3; - } else { - $$ = $1; - } - } - ; - -enum - : identifier { $$ = new_name_expr ($1); } - | identifier '=' fexpr - { - $$ = 0; - $3 = constant_expr ($3); - if ($3->type < ex_nil) { - error ($3, "non-constant initializer"); - } else if ($3->type != ex_integer) { - error ($3, "invalid initializer type"); - } else { - $$ = new_binary_expr ('=', new_name_expr ($1), $3); - } + $1 = check_redefined ($1); + $1->type = $0; + symtab_addsymbol (current_symtab, $1); } ; @@ -411,31 +370,74 @@ non_field_type $$ = pointer_type ($1); } | type_name { $$ = $1; } + | struct_spec + | enum_spec ; type_name : TYPE { $$ = $1; } | TYPE_NAME { $$ = $1->type; } - | CLASS_NAME + | CLASS_NAME { $$ = $1->type; } + ; + +opt_tag + : tag + | /* empty */ { $$ = 0; } + ; + +tag : NAME ; + +struct_spec + : STRUCT opt_tag '{' { - class_t *class = get_class ($1, 0); - if (!class) { - error (0, "undefined symbol `%s'", $1); - class = get_class (0, 1); - } - $$ = class->type; + current_symtab = new_symtab (current_symtab, stab_local); } - | STRUCT identifier { $$ = decl_struct ($2)->type; } - | UNION identifier { $$ = decl_union ($2)->type; } + struct_defs '}' + { + symtab_t *symtab = current_symtab; + current_symtab = symtab->parent; + + $$ = build_struct ($1, $2, symtab, 0)->type; + } + | STRUCT tag ';' + { + $$ = find_struct ($1, $2, 0)->type; + } + ; + +enum_spec + : ENUM tag opt_enum_list { $$ = $3->type; } + | ENUM '{' enum_init enum_list opt_comma '}' { $$ = $4->type; } + ; + +opt_enum_list + : '{' enum_init enum_list opt_comma '}' { $$ = $2; } + | /* empty */ { $$ = find_enum ($0); } + ; + +enum_init + : /* empty */ + { + $$ = find_enum ($-1); + start_enum ($$); + } + ; + +enum_list + : enum { $$ = $0; } + | enum_list ',' { $$ = $0; } enum { $$ = $0; } + ; + +enum + : identifier { add_enum ($0, $1, 0); } + | identifier '=' fexpr { add_enum ($0, $1, $3); } ; function_decl - : '(' param_list ')' { $$ = reverse_params ($2); } + : '(' param_list ')' { $$ = $2; } | '(' param_list ',' ELLIPSIS ')' { - $$ = new_param (0, 0, 0); - $$->next = $2; - $$ = reverse_params ($$); + $$ = param_append_identifiers ($2, 0, 0); } | '(' ELLIPSIS ')' { $$ = new_param (0, 0, 0); } | '(' TYPE ')' @@ -448,16 +450,15 @@ function_decl ; param_list - : param - | param_list ',' param - { - $3->next = $1; - $$ = $3; - } + : param { $$ = $0; } + | param_list ',' { $$ = $0; } param { $$ = $0; } ; param - : type identifier { $$ = new_param (0, $1, $2); } + : type identifier + { + $$ = param_append_identifiers ($0, $2, $1); + } ; array_decl @@ -510,13 +511,9 @@ fdef_name func_def : identifier { - $$ = get_function_def ($1, $0, current_scope, - current_storage, 0, 1); } | OVERLOAD identifier { - $$ = get_function_def ($2, $0, current_scope, - current_storage, 1, 1); } ; @@ -525,40 +522,13 @@ func_init | code_func ; -builtin_function - : /* emtpy */ - { - $$ = build_builtin_function ($-1, $0, current_params); - } - ; - non_code_func : '=' '#' fexpr - { $$ = $0; } - { $$ = constant_expr ($3); } - builtin_function - { - (void) ($4); - (void) ($5); - } | /* emtpy */ - { - } ; code_func - : '=' opt_state_expr - { $$ = current_storage; } - { $$ = 0; } - { $$ = $0; } - begin_function statement_block { $$ = $3; } end_function - { - build_code_function ($6, $2, $7); - current_func = 0; - (void) ($4); - (void) ($5); - (void) ($8); - } + : '=' opt_state_expr statement_block {} ; def_name @@ -568,8 +538,6 @@ def_name opt_initializer : /*empty*/ { - $$ = create_def ($-1, $0, current_scope, - current_storage); } | var_initializer { $$ = $1; } ; @@ -577,46 +545,9 @@ opt_initializer var_initializer : '=' expr // don't bother folding twice { - int local = 0; - const char *name = $0; - type_t *type = $-1; - - if (current_scope->type == sc_params) { - // In traditional mode, this is the only scope that functions - // have. - local = 0; - $$ = create_def (type, name, current_scope, st_static); - } else { - local = current_scope->type == sc_local; - $$ = create_def (type, name, current_scope, current_storage); - } - if (local) { - expr_t *expr = assign_expr (new_def_expr ($$), $2); - expr = fold_constants (expr); - append_expr (local_expr, expr); - def_initialized ($$); - } else { - $2 = constant_expr ($2); - if ($2->type >= ex_nil) { - if ($2->type != ex_nil - && !type_assignable ($$->type, get_type ($2))) { - error ($2, "incompatible types in initialization"); - } else if ($$->constant) { - error ($2, "%s re-initialized", $$->name); - } else { - ReuseConstant ($2, $$); - } - } else { - error ($2, "non-constant expression used for initializer"); - } - } } - | '=' '{' { current_init = new_block_expr (); } element_list '}' + | '=' '{' { } element_list '}' { - $$ = create_def ($-1, $0, current_scope, - current_storage); - init_elements ($$, $4); - current_init = 0; } ; @@ -627,34 +558,13 @@ opt_state_expr } | '[' fexpr ',' think opt_step ']' { - if ($2->type == ex_integer) - convert_int ($2); - else if ($2->type == ex_uinteger) - convert_uint ($2); - if (!type_assignable (&type_float, get_type ($2))) - error ($2, "invalid type for frame number"); - $2 = cast_expr (&type_float, $2); - if (extract_type ($4) != ev_func) - error ($2, "invalid type for think"); - if ($5) { - if ($5->type == ex_integer) - convert_int ($5); - else if ($5->type == ex_uinteger) - convert_uint ($5); - if (!type_assignable (&type_float, get_type ($5))) - error ($5, "invalid type for time step"); - } - - $$ = new_state_expr ($2, $4, $5); + $$ = build_state_expr ($2, $4, $5); } ; think : def_name { - $$ = new_def_expr (create_def (&type_function, $1, current_scope, - current_storage)); - (void) ($1); } | '(' fexpr ')' { @@ -714,49 +624,16 @@ opt_comma | ',' ; -begin_function - : /*empty*/ - { - $$ = begin_function ($0, $-1, current_params); - current_func = $$; - current_scope = $$->scope; - current_storage = st_local; - } - ; - -end_function - : /*empty*/ - { - current_scope = current_scope->parent; - current_storage = $0; - } - ; - statement_block : '{' { - if (!options.traditional) { - scope_t *scope = new_scope (sc_local, current_scope->space, - current_scope); - current_scope = scope; - } + if (!options.traditional) + current_symtab = new_symtab (current_symtab, stab_local); } statements '}' { - if (!options.traditional) { - def_t *defs = current_scope->head; - int num_defs = current_scope->num_defs; - - flush_scope (current_scope, 1); - - current_scope = current_scope->parent; - current_scope->num_defs += num_defs; - *current_scope->tail = defs; - while (*current_scope->tail) { - (*current_scope->tail)->scope = current_scope; - current_scope->tail = &(*current_scope->tail)->def_next; - } - } + if (!options.traditional) + current_symtab = current_symtab->parent; $$ = $3; } ; @@ -776,6 +653,18 @@ statement : ';' { $$ = 0; } | error ';' { $$ = 0; yyerrok; } | statement_block { $$ = $1; } + | local_storage_class type + { + $$ = $2; + local_expr = new_block_expr (); + } + def_list ';' + { + $$ = local_expr; + local_expr = 0; + (void) ($3); + current_storage = st_local; + } | RETURN opt_expr ';' { $$ = return_expr (current_func, $2); @@ -804,227 +693,41 @@ statement { $$ = case_label_expr (switch_block, 0); } - | SWITCH break_label switch_block '(' fexpr ')' + | SWITCH break_label switch_block '(' fexpr ')' statement_block { switch_block->test = $5; - } - save_inits statement_block - { - restore_local_inits ($8); - free_local_inits ($8); - $$ = switch_expr (switch_block, break_label, $9); + $$ = switch_expr (switch_block, break_label, $7); switch_block = $3; break_label = $2; } - | WHILE break_label continue_label '(' texpr ')' save_inits statement + | IF '(' texpr ')' statement %prec IFX { - expr_t *l1 = new_label_expr (); - expr_t *l2 = break_label; - int line = pr.source_line; - string_t file = pr.source_file; - - pr.source_line = $5->line; - pr.source_file = $5->file; - - restore_local_inits ($7); - free_local_inits ($7); - - $$ = new_block_expr (); - - append_expr ($$, new_unary_expr ('g', continue_label)); - append_expr ($$, l1); - append_expr ($$, $8); - append_expr ($$, continue_label); - - $5 = convert_bool ($5, 1); - if ($5->type != ex_error) { - backpatch ($5->e.bool.true_list, l1); - backpatch ($5->e.bool.false_list, l2); - append_expr ($5->e.bool.e, l2); - append_expr ($$, $5); - } - + $$ = build_if_statement ($3, $5, 0); + } + | IF '(' texpr ')' statement ELSE statement + { + $$ = build_if_statement ($3, $5, $7); + } + | FOR break_label continue_label + '(' opt_expr ';' opt_expr ';' opt_expr ')' statement + { + $$ = build_for_statement ($5, $7, $9, $11, + break_label, continue_label); + break_label = $2; + continue_label = $3; + } + | WHILE break_label continue_label '(' texpr ')' statement + { + $$ = build_while_statement ($5, $7, break_label, continue_label); break_label = $2; continue_label = $3; - - pr.source_line = line; - pr.source_file = file; } | DO break_label continue_label statement WHILE '(' texpr ')' ';' { - expr_t *l1 = new_label_expr (); - int line = pr.source_line; - string_t file = pr.source_file; - - pr.source_line = $7->line; - pr.source_file = $7->file; - - $$ = new_block_expr (); - - append_expr ($$, l1); - append_expr ($$, $4); - append_expr ($$, continue_label); - - $7 = convert_bool ($7, 1); - if ($7->type != ex_error) { - backpatch ($7->e.bool.true_list, l1); - backpatch ($7->e.bool.false_list, break_label); - append_expr ($7->e.bool.e, break_label); - append_expr ($$, $7); - } - + $$ = build_do_while_statement ($4, $7, + break_label, continue_label); break_label = $2; continue_label = $3; - - pr.source_line = line; - pr.source_file = file; - } - | local_storage_class type - { - $$ = $2; - local_expr = new_block_expr (); - } - def_list ';' - { - $$ = local_expr; - local_expr = 0; - (void) ($3); - current_storage = st_local; - } - | IF '(' texpr ')' save_inits statement %prec IFX - { - expr_t *tl = new_label_expr (); - expr_t *fl = new_label_expr (); - int line = pr.source_line; - string_t file = pr.source_file; - - pr.source_line = $3->line; - pr.source_file = $3->file; - - $$ = new_block_expr (); - - restore_local_inits ($5); - free_local_inits ($5); - - $3 = convert_bool ($3, 1); - if ($3->type != ex_error) { - backpatch ($3->e.bool.true_list, tl); - backpatch ($3->e.bool.false_list, fl); - append_expr ($3->e.bool.e, tl); - append_expr ($$, $3); - } - - append_expr ($$, $6); - append_expr ($$, fl); - - pr.source_line = line; - pr.source_file = file; - } - | IF '(' texpr ')' save_inits statement ELSE - { - $$ = save_local_inits (current_scope); - restore_local_inits ($5); - } - statement - { - expr_t *tl = new_label_expr (); - expr_t *fl = new_label_expr (); - expr_t *nl = new_label_expr (); - expr_t *e; - hashtab_t *merged; - hashtab_t *else_ini; - int line = pr.source_line; - string_t file = pr.source_file; - - pr.source_line = $3->line; - pr.source_file = $3->file; - - $$ = new_block_expr (); - - else_ini = save_local_inits (current_scope); - - restore_local_inits ($5); - free_local_inits ($5); - - $3 = convert_bool ($3, 1); - if ($3->type != ex_error) { - backpatch ($3->e.bool.true_list, tl); - backpatch ($3->e.bool.false_list, fl); - append_expr ($3->e.bool.e, tl); - append_expr ($$, $3); - } - - append_expr ($$, $6); - - e = new_unary_expr ('g', nl); - append_expr ($$, e); - - append_expr ($$, fl); - append_expr ($$, $9); - append_expr ($$, nl); - - merged = merge_local_inits ($8, else_ini); - restore_local_inits (merged); - free_local_inits (merged); - free_local_inits (else_ini); - free_local_inits ($8); - - pr.source_line = line; - pr.source_file = file; - } - | FOR break_label continue_label - '(' opt_expr ';' opt_expr ';' opt_expr ')' save_inits statement - { - expr_t *tl = new_label_expr (); - expr_t *fl = break_label; - expr_t *l1 = 0; - expr_t *t; - int line = pr.source_line; - string_t file = pr.source_file; - - if ($9) - t = $9; - else if ($7) - t = $7; - else if ($5) - t = $5; - else - t = continue_label; - pr.source_line = t->line; - pr.source_file = t->file; - - restore_local_inits ($11); - free_local_inits ($11); - - $$ = new_block_expr (); - - append_expr ($$, $5); - if ($7) { - l1 = new_label_expr (); - append_expr ($$, new_unary_expr ('g', l1)); - } - append_expr ($$, tl); - append_expr ($$, $12); - append_expr ($$, continue_label); - append_expr ($$, $9); - if ($7) { - append_expr ($$, l1); - $7 = convert_bool ($7, 1); - if ($7->type != ex_error) { - backpatch ($7->e.bool.true_list, tl); - backpatch ($7->e.bool.false_list, fl); - append_expr ($7->e.bool.e, fl); - append_expr ($$, $7); - } - } else { - append_expr ($$, new_unary_expr ('g', tl)); - append_expr ($$, fl); - } - break_label = $2; - continue_label = $3; - - pr.source_line = line; - pr.source_file = file; } | fexpr ';' { @@ -1063,13 +766,6 @@ switch_block } ; -save_inits - : /* empty */ - { - $$ = save_local_inits (current_scope); - } - ; - opt_expr : fexpr | /* empty */ @@ -1091,7 +787,7 @@ unary_expr ; primary - : NAME { $$ = new_name_expr ($1); } + : NAME { $$ = new_symbol_expr ($1); } | BREAK %prec BREAK_PRIMARY { $$ = new_name_expr (save_string ("break")); } | ARGS { $$ = new_name_expr (".args"); } | SELF { $$ = new_self_expr (); } @@ -1161,19 +857,23 @@ arg_list const : CONST | NIL { $$ = new_nil_expr (); } - | const CONST - { - if ($1->type != ex_string || $2->type != ex_string) - PARSE_ERROR; - $$ = binary_expr ('+', $1, $2); - } + | string + ; + +string + : STRING + | string STRING { $$ = binary_expr ('+', $1, $2); } ; identifier : NAME - | BREAK { $$ = save_string ("break"); } + | BREAK + { + if (!($$ = symtab_lookup (current_symtab, "break"))) + $$ = new_symbol ("break"); + } | CLASS_NAME - | TYPE_NAME { $$ = $1->name; } + | TYPE_NAME ; // Objective-QC stuff @@ -1196,13 +896,11 @@ obj_def identifier_list : identifier { - $$ = new_block_expr (); - append_expr ($$, new_name_expr ($1)); + $$ = append_expr (new_block_expr (), new_symbol_expr ($1)); } | identifier_list ',' identifier { - append_expr ($1, new_name_expr ($3)); - $$ = $1; + $$ = append_expr ($1, new_symbol_expr ($3)); } ; @@ -1211,17 +909,19 @@ classdecl { expr_t *e; for (e = $2->e.block.head; e; e = e->next) - get_class (e->e.string_val, 1); + get_class (e->e.symbol, 1); } ; class_name : identifier %prec CLASS_NOT_CATEGORY { - $$ = get_class ($1, 0); - if (!$$) { - error (0, "undefined symbol `%s'", $1); + $1 = check_undefined ($1); + if (!is_class ($1->type)) { + error (0, "`%s' is not a class", $1->name); $$ = get_class (0, 1); + } else { + $$ = $1->type->t.class; } } ; @@ -1229,9 +929,9 @@ class_name new_class_name : identifier { - $$ = get_class ($1, 1); - if ($$->defined) { - error (0, "redefinition of `%s'", $1); + $$ = get_class ($1, 0); + if (!$$) { + $1 = check_redefined ($1); $$ = get_class (0, 1); } current_class = &$$->class_type; @@ -1258,9 +958,9 @@ new_class_with_super category_name : identifier '(' identifier ')' { - $$ = get_category ($1, $3, 0); + $$ = get_category ($1, $3->name, 0); if (!$$) { - error (0, "undefined category `%s (%s)'", $1, $3); + error (0, "undefined category `%s (%s)'", $1->name, $3->name); $$ = get_category (0, 0, 1); } } @@ -1269,9 +969,10 @@ category_name new_category_name : identifier '(' identifier ')' { - $$ = get_category ($1, $3, 1); + $$ = get_category ($1, $3->name, 1); if ($$->defined) { - error (0, "redefinition of category `%s (%s)'", $1, $3); + error (0, "redefinition of category `%s (%s)'", + $1->name, $3->name); $$ = get_category (0, 0, 1); } current_class = &$$->class_type; @@ -1281,14 +982,14 @@ new_category_name class_reference : identifier { - emit_class_ref ($1); + emit_class_ref ($1->name); } ; category_reference : identifier '(' identifier ')' { - emit_category_ref ($1, $3); + emit_category_ref ($1->name, $3->name); } ; @@ -1296,12 +997,12 @@ category_reference protocol_name : identifier { - $$ = get_protocol ($1, 0); + $$ = get_protocol ($1->name, 0); if ($$) { - error (0, "redefinition of %s", $1); + error (0, "redefinition of %s", $1->name); $$ = get_protocol (0, 1); } else { - $$ = get_protocol ($1, 1); + $$ = get_protocol ($1->name, 1); } current_class = &$$->class_type; } @@ -1411,11 +1112,11 @@ protocolrefs protocol_list : identifier { - $$ = add_protocol ($0, $1); + $$ = add_protocol ($0, $1->name); } | protocol_list ',' identifier { - $$ = add_protocol ($1, $3); + $$ = add_protocol ($1, $3->name); } ; @@ -1423,12 +1124,14 @@ ivar_decl_list : /* */ { current_visibility = vis_protected; - current_ivars = class_new_ivars ($0); + current_symtab = class_new_ivars ($0); } ivar_decl_list_2 { - $$ = current_ivars; - current_ivars = 0; + $$ = current_symtab; + current_symtab = $$->parent; + + build_struct ('s', 0, $$, 0); } ; @@ -1460,46 +1163,16 @@ ivars ivar_declarator : identifier { - new_struct_field (current_ivars, $0, $1, current_visibility); + $1 = check_redefined ($1); + $1->type = $0; + $1->visibility = current_visibility; + symtab_addsymbol (current_symtab, $1); } ; methoddef - : ci methoddecl - { - $2->instance = $1; - $2 = class_find_method (current_class, $2); - } - opt_state_expr - { $$ = current_storage; } - { $$ = method_name ($2); } - { - $$ = $2->def = method_def (current_class, $2); - current_params = $2->params; - } - begin_function statement_block { $$ = $5; } end_function - { - $2->func = build_code_function ($8, $4, $9); - current_func = 0; - (void) ($6); - (void) ($7); - (void) ($10); - } - | ci methoddecl - { - $2->instance = $1; - $2 = class_find_method (current_class, $2); - } - '=' '#' const - { $$ = $2->def = method_def (current_class, $2); } - { $$ = $6; } - builtin_function ';' - { - $2->func = $9; - - (void) ($7); - (void) ($8); - } + : ci methoddecl opt_state_expr statement_block {} + | ci methoddecl '=' '#' const ';' {} ; ci @@ -1561,7 +1234,7 @@ optparmlist ; unaryselector - : selector { $$ = new_param ($1, 0, 0); } + : selector { $$ = new_param ($1->name, 0, 0); } ; keywordselector @@ -1570,49 +1243,47 @@ keywordselector ; selector - : NAME { $$ = save_string ($1); } - | CLASS_NAME { $$ = save_string ($1); } - | TYPE { $$ = save_string (yytext); } - | TYPE_NAME { $$ = save_string ($1->name); } + : NAME { $$ = $1; } + | CLASS_NAME { $$ = $1; } + | TYPE { $$ = new_symbol (yytext); } + | TYPE_NAME { $$ = $1; } | reserved_word ; reserved_word - : LOCAL { $$ = save_string (yytext); } - | RETURN { $$ = save_string (yytext); } - | WHILE { $$ = save_string (yytext); } - | DO { $$ = save_string (yytext); } - | IF { $$ = save_string (yytext); } - | ELSE { $$ = save_string (yytext); } - | FOR { $$ = save_string (yytext); } - | BREAK { $$ = save_string (yytext); } - | CONTINUE { $$ = save_string (yytext); } - | SWITCH { $$ = save_string (yytext); } - | CASE { $$ = save_string (yytext); } - | DEFAULT { $$ = save_string (yytext); } - | NIL { $$ = save_string (yytext); } - | STRUCT { $$ = save_string (yytext); } - | UNION { $$ = save_string (yytext); } - | ENUM { $$ = save_string (yytext); } - | TYPEDEF { $$ = save_string (yytext); } - | SUPER { $$ = save_string (yytext); } + : LOCAL { $$ = new_symbol (yytext); } + | RETURN { $$ = new_symbol (yytext); } + | WHILE { $$ = new_symbol (yytext); } + | DO { $$ = new_symbol (yytext); } + | IF { $$ = new_symbol (yytext); } + | ELSE { $$ = new_symbol (yytext); } + | FOR { $$ = new_symbol (yytext); } + | BREAK { $$ = new_symbol (yytext); } + | CONTINUE { $$ = new_symbol (yytext); } + | SWITCH { $$ = new_symbol (yytext); } + | CASE { $$ = new_symbol (yytext); } + | DEFAULT { $$ = new_symbol (yytext); } + | NIL { $$ = new_symbol (yytext); } + | STRUCT { $$ = new_symbol (yytext); } + | ENUM { $$ = new_symbol (yytext); } + | TYPEDEF { $$ = new_symbol (yytext); } ; keyworddecl : selector ':' '(' type ')' identifier - { $$ = new_param ($1, $4, $6); } + { $$ = new_param ($1->name, $4, $6->name); } | selector ':' identifier - { $$ = new_param ($1, &type_id, $3); } + { $$ = new_param ($1->name, &type_id, $3->name); } | ':' '(' type ')' identifier - { $$ = new_param ("", $3, $5); } + { $$ = new_param ("", $3, $5->name); } | ':' identifier - { $$ = new_param ("", &type_id, $2); } + { $$ = new_param ("", &type_id, $2->name); } ; obj_expr : obj_messageexpr | SELECTOR '(' selectorarg ')' { $$ = selector_expr ($3); } - | PROTOCOL '(' identifier ')' { $$ = protocol_expr ($3); } + | PROTOCOL '(' identifier ')' { $$ = protocol_expr ($3->name); } | ENCODE '(' type ')' { $$ = encode_expr ($3); } | obj_string /* FIXME string object? */ ; @@ -1623,12 +1294,11 @@ obj_messageexpr receiver : fexpr - | CLASS_NAME { $$ = new_name_expr ($1); } - | SUPER { $$ = new_name_expr ("super"); } + | CLASS_NAME { $$ = new_symbol_expr ($1); } ; messageargs - : selector { $$ = new_keywordarg ($1, 0); } + : selector { $$ = new_keywordarg ($1->name, 0); } | keywordarglist ; @@ -1642,12 +1312,12 @@ keywordarglist ; keywordarg - : selector ':' arg_list { $$ = new_keywordarg ($1, $3); } + : selector ':' arg_list { $$ = new_keywordarg ($1->name, $3); } | ':' arg_list { $$ = new_keywordarg ("", $2); } ; selectorarg - : selector { $$ = new_keywordarg ($1, 0); } + : selector { $$ = new_keywordarg ($1->name, 0); } | keywordnamelist ; @@ -1661,132 +1331,16 @@ keywordnamelist ; keywordname - : selector ':' { $$ = new_keywordarg ($1, new_nil_expr ()); } - | ':' { $$ = new_keywordarg ("", new_nil_expr ()); } + : selector ':' { $$ = new_keywordarg ($1->name, new_nil_expr ()); } + | ':' { $$ = new_keywordarg ("", new_nil_expr ()); } ; obj_string - : '@' STRING_VAL { $$ = new_string_expr ($2); } - | obj_string '@' STRING_VAL + : '@' STRING { - $$ = binary_expr ('+', $1, new_string_expr ($3)); + //FIXME string object + $$ = $2; } ; %% - -typedef struct def_state_s { - struct def_state_s *next; - def_t *def; - int state; -} def_state_t; - -static def_state_t *free_def_states; - -static const char * -ds_get_key (void *_d, void *unused) -{ - return ((def_state_t *)_d)->def->name; -} - -static void -ds_free_key (void *_d, void *unused) -{ - def_state_t *d = (def_state_t *)_d; - d->next = free_def_states; - free_def_states = d; -} - -static void -scan_scope (hashtab_t *tab, scope_t *scope) -{ - def_t *def; - if (scope->type == sc_local) - scan_scope (tab, scope->parent); - for (def = scope->head; def; def = def->def_next) { - if (def->name && !def->removed) { - def_state_t *ds; - ALLOC (1024, def_state_t, def_states, ds); - ds->def = def; - ds->state = def->initialized; - Hash_Add (tab, ds); - } - } -} - -static def_t * -create_def (type_t *type, const char *name, scope_t *scope, - storage_class_t storage) -{ - scope_type st = scope->type; - // traditional functions have only the one scope - //FIXME should the scope be set to local when the params scope - //is created in traditional mode? - if (options.traditional && st == sc_params) - st = sc_local; - if (st == sc_local) { - def_t *def = get_def (0, name, scope, st_none); - if (def) { - if (def->scope->type == sc_params - && scope->parent->type == sc_params) { - warning (0, "local %s shadows param %s", name, - def->name); - } - if (def->scope == scope && options.warnings.redeclared) { - expr_t e; - warning (0, "local %s redeclared", name); - e.file = def->file; - e.line = def->line; - warning (&e, "previously declared here"); - } - } - } - return get_def (type, name, scope, storage); -} - -hashtab_t * -save_local_inits (scope_t *scope) -{ - hashtab_t *tab = Hash_NewTable (61, ds_get_key, ds_free_key, 0); - scan_scope (tab, scope); - return tab; -} - -hashtab_t * -merge_local_inits (hashtab_t *dl_1, hashtab_t *dl_2) -{ - hashtab_t *tab = Hash_NewTable (61, ds_get_key, ds_free_key, 0); - def_state_t **ds_list = (def_state_t **)Hash_GetList (dl_1); - def_state_t **ds; - def_state_t *d; - def_state_t *nds; - - for (ds = ds_list; *ds; ds++) { - d = Hash_Find (dl_2, (*ds)->def->name); - (*ds)->def->initialized = (*ds)->state; - - ALLOC (1024, def_state_t, def_states, nds); - nds->def = (*ds)->def; - nds->state = (*ds)->state && d->state; - Hash_Add (tab, nds); - } - free (ds_list); - return tab; -} - -void -restore_local_inits (hashtab_t *def_list) -{ - def_state_t **ds_list = (def_state_t **)Hash_GetList (def_list); - def_state_t **ds; - - for (ds = ds_list; *ds; ds++) - (*ds)->def->initialized = (*ds)->state; - free (ds_list); -} - -void -free_local_inits (hashtab_t *def_list) -{ - Hash_DelTable (def_list); -} diff --git a/tools/qfcc/source/qfcc.c b/tools/qfcc/source/qfcc.c index 3386d01ab..964e33cf2 100644 --- a/tools/qfcc/source/qfcc.c +++ b/tools/qfcc/source/qfcc.c @@ -73,6 +73,7 @@ static __attribute__ ((used)) const char rcsid[] = "$Id$"; #include "cpp.h" #include "debug.h" #include "def.h" +#include "defspace.h" #include "emit.h" #include "expr.h" #include "function.h" @@ -342,7 +343,6 @@ InitData (void) pr.near_data->max_size = 65536; pr.near_data->grow = 0; pr.scope = new_scope (sc_global, pr.near_data, 0); - current_scope = pr.scope; pr.entity_data = new_defspace (); @@ -647,8 +647,8 @@ finish_compilation (void) } df->parm_start = pr.near_data->size; } else { - df->parm_start = new_location_size (f->scope->space->size, - pr.near_data); + df->parm_start = defspace_new_loc (pr.near_data, + f->scope->space->size); num_localdefs += f->scope->space->size; } for (def = f->scope->head; def; def = def->def_next) { @@ -660,7 +660,7 @@ finish_compilation (void) } if (options.code.local_merging) { int ofs; - for (ofs = new_location_size (num_localdefs, pr.near_data); + for (ofs = defspace_new_loc (pr.near_data, num_localdefs); ofs < pr.near_data->size; ofs++) G_INT (ofs) = 0; } @@ -726,9 +726,6 @@ compile_to_obj (const char *file, const char *obj) clear_defs (); clear_immediates (); clear_selectors (); - clear_structs (); - clear_enums (); - clear_typedefs (); chain_initial_types (); begin_compilation (); pr.source_file = ReuseString (strip_path (file)); diff --git a/tools/qfcc/source/qp-lex.l b/tools/qfcc/source/qp-lex.l index 5f757b3f1..c0921e1d4 100644 --- a/tools/qfcc/source/qp-lex.l +++ b/tools/qfcc/source/qp-lex.l @@ -258,9 +258,11 @@ keyword_or_id (const char *token) sym = symtab_lookup (current_symtab, token); if (!sym) sym = new_symbol (token); - yylval.symbol = sym; - if (sym->is_typedef) + if (sym->sy_type == sy_type) { + yylval.type = sym->type; return TYPE_NAME; + } + yylval.symbol = sym; return ID; } diff --git a/tools/qfcc/source/qp-parse.y b/tools/qfcc/source/qp-parse.y index 70878706c..9424978e5 100644 --- a/tools/qfcc/source/qp-parse.y +++ b/tools/qfcc/source/qp-parse.y @@ -150,19 +150,9 @@ program subprogram_declarations compound_statement '.' { - dstring_t *str = dstring_newstr (); - symbol_t *s; - // move the symbol for the program name to the end of the list symtab_removesymbol (current_symtab, $1); symtab_addsymbol (current_symtab, $1); - - for (s = current_symtab->symbols; s; s = s->next) { - dstring_clearstr (str); - print_type_str (str, s->type); - printf ("%s %s\n", s->name, str->str); - } - dstring_delete (str); } ; @@ -256,6 +246,9 @@ subprogram_declaration dstring_delete (str); } | subprogram_head ASSIGNOP '#' CONST ';' + { + //build_builtin_function ($1, $4, $1->params); + } ; subprogram_head @@ -351,32 +344,9 @@ statement } | WHILE expression DO statement { - int line = pr.source_line; - string_t file = pr.source_file; - expr_t *l1 = new_label_expr (); - expr_t *l2 = new_label_expr (); - expr_t *cont = new_label_expr (); - - pr.source_line = $2->line; - pr.source_file = $2->file; - - $$ = new_block_expr (); - - append_expr ($$, new_unary_expr ('g', cont)); - append_expr ($$, l1); - append_expr ($$, $4); - append_expr ($$, cont); - - $2 = convert_bool ($2, 1); - if ($2->type != ex_error) { - backpatch ($2->e.bool.true_list, l1); - backpatch ($2->e.bool.false_list, l2); - append_expr ($2->e.bool.e, l2); - append_expr ($$, $2); - } - - pr.source_line = line; - pr.source_file = file; + $$ = build_while_statement ($2, $4, + new_label_expr (), + new_label_expr ()); } ; @@ -449,7 +419,15 @@ sign ; name - : ID { $$ = new_symbol_expr ($1); } + : ID + { + if (!$1->table) { + error (0, "%s undefined", $1->name); + $1->type = &type_integer; + symtab_addsymbol (current_symtab, $1); + } + $$ = new_symbol_expr ($1); + } ; %% diff --git a/tools/qfcc/source/reloc.c b/tools/qfcc/source/reloc.c index 9035b2aff..ff750785f 100644 --- a/tools/qfcc/source/reloc.c +++ b/tools/qfcc/source/reloc.c @@ -44,6 +44,7 @@ static __attribute__ ((used)) const char rcsid[] = #include "codespace.h" #include "def.h" +#include "defspace.h" #include "emit.h" #include "expr.h" #include "function.h" diff --git a/tools/qfcc/source/struct.c b/tools/qfcc/source/struct.c index 1a4f0bdd0..ed037c7bb 100644 --- a/tools/qfcc/source/struct.c +++ b/tools/qfcc/source/struct.c @@ -54,298 +54,142 @@ static __attribute__ ((used)) const char rcsid[] = #include "immediate.h" #include "qfcc.h" #include "reloc.h" +#include "strpool.h" #include "struct.h" +#include "symtab.h" #include "type.h" -static hashtab_t *structs; -static hashtab_t *enums; - -static const char * -structs_get_key (void *s, void *unused) +static symbol_t * +find_tag (ty_type_e ty, symbol_t *tag, type_t *type) { - return ((struct_t *) s)->name; -} + const char *tag_name; + symbol_t *sym; + static int tag_num; -static const char * -struct_field_get_key (void *f, void *unused) -{ - return ((struct_field_t *) f)->name; -} - -static const char * -enums_get_key (void *e, void *unused) -{ - return ((enum_t *) e)->name; -} - -struct_field_t * -new_struct_field (struct_t *strct, type_t *type, const char *name, - visibility_type visibility) -{ - struct_field_t *field; - - if (!strct) - return 0; - field = calloc (sizeof (struct_field_t), 1); - field->visibility = visibility; - if (name) - field->name = save_string (name); - field->type = type; - if (strct->stype == str_union) { - int size = type_size (type); - field->offset = 0; - if (size > strct->size) - strct->size = size; - } else { - field->offset = strct->size; - strct->size += type_size (type); + if (tag) + tag_name = va ("tag %s", tag->name); + else + tag_name = va ("tag .%s.%d.%d", + G_GETSTR (pr.source_file), pr.source_line, tag_num++); + sym = symtab_lookup (current_symtab, tag_name); + if (sym) { + if (sym->table == current_symtab && sym->type->ty != ty) + error (0, "%s defined as wrong kind of tag", tag->name); + if (sym->type->ty == ty) + return sym; } - field->next = 0; - *strct->struct_tail = field; - strct->struct_tail = &field->next; - if (name) - Hash_Add (strct->struct_fields, field); - return field; + if (!type) + type = new_type (); + sym = new_symbol (tag_name); + sym->type = type; + sym->type->type = ev_invalid; + sym->type->ty = ty; + return sym; } -struct_field_t * -struct_find_field (struct_t *strct, const char *name) +symbol_t * +find_struct (int su, symbol_t *tag, type_t *type) { - if (!structs || !strct) - return 0; - return Hash_Find (strct->struct_fields, name); + ty_type_e ty = ty_struct; + + if (su == 'u') + ty = ty_union; + + return find_tag (ty, tag, type); } -type_t * -init_struct (struct_t *strct, type_t *type, struct_type stype, - const char *name) +symbol_t * +build_struct (int su, symbol_t *tag, symtab_t *symtab, type_t *type) { - if (name) - strct->name = save_string (name); - strct->type = type; - strct->type->type = ev_invalid; - strct->type->ty = ty_struct; - strct->struct_tail = &strct->struct_head; - strct->struct_fields = Hash_NewTable (61, struct_field_get_key, 0, 0); - strct->type->t.strct = strct; - strct->stype = stype; - if (name) { - strct->type->name = strct->name; - Hash_Add (structs, strct); + symbol_t *sym = find_struct (su, tag, type); + + symtab->parent = 0; // disconnect struct's symtab from parent scope + + if (sym->table == current_symtab && sym->type->t.symtab) { + error (0, "%s defined as wrong kind of tag", tag->name); + return sym; } - return strct->type; -} - -struct_t * -get_struct (const char *name, int create) -{ - struct_t *s; - - if (!structs) - structs = Hash_NewTable (16381, structs_get_key, 0, 0); - if (name) { - s = Hash_Find (structs, name); - if (s || !create) - return s; - } - s = calloc (sizeof (struct_t), 1); - if (name) - s->name = save_string (name); - s->return_addr = __builtin_return_address (0); - if (name) - Hash_Add (structs, s); - return s; -} - -int -struct_compare_fields (struct_t *s1, struct_t *s2) -{ - struct_field_t *f1 = s1->struct_head; - struct_field_t *f2 = s2->struct_head; - - while (f1 && f2) { - if (f1->name != f2->name) - if (!f1->name || !f2->name - || strcmp (f1->name, f2->name) - || f1->type != f2->type) - return 0; - f1 = f1->next; - f2 = f2->next; - } - return !((!f1) ^ !(f2)); -} - -static struct_t * -start_struct (const char *name, struct_type stype) -{ - struct_t *strct = get_struct (name, 1); - if (strct->struct_head) { - error (0, "%s redeclared", name); - goto err; - } - if (strct->stype != str_none && strct->stype != stype) { - error (0, "%s defined as wrong kind of tag", name); - goto err; - } - if (!strct->type) - init_struct (strct, new_type (), stype, 0); - return strct; -err: - strct = get_struct (0, 0); - init_struct (strct, new_type (), stype, 0); - return strct; -} - -struct_t * -new_struct (const char *name) -{ - return start_struct (name, str_struct); -} - -struct_t * -new_union (const char *name) -{ - return start_struct (name, str_union); -} - -static struct_t * -check_struct (const char *name, struct_type stype) -{ - struct_t *strct = get_struct (name, 0); - - if (!strct) - return start_struct (name, stype); - if (strct->stype != stype) { - error (0, "%s defined as wrong kind of tag", name); - strct = get_struct (0, 0); - init_struct (strct, new_type (), stype, 0); - } - return strct; -} - -struct_t * -decl_struct (const char *name) -{ - return check_struct (name, str_struct); -} - -struct_t * -decl_union (const char *name) -{ - return check_struct (name, str_union); -} - -def_t * -emit_struct(struct_t *strct, const char *name) -{ - struct_field_t *field; - int i, count; - def_t *ivars_def; - pr_ivar_list_t *ivars; - struct_t *ivar_list; - dstring_t *encoding = dstring_newstr (); - dstring_t *ivars_name = dstring_newstr (); - - if (!strct) - return 0; - for (count = 0, field = strct->struct_head; field; field = field->next) - if (field->name) - count++; - ivar_list = new_struct (0); - new_struct_field (ivar_list, &type_integer, "ivar_count", vis_public); - for (i = 0; i < count; i++) - new_struct_field (ivar_list, type_ivar, 0, vis_public); - dsprintf (ivars_name, "_OBJ_INSTANCE_VARIABLES_%s", name); - ivars_def = get_def (ivar_list->type, ivars_name->str, pr.scope, st_none); - if (ivars_def) - goto done; - ivars_def = get_def (ivar_list->type, ivars_name->str, pr.scope, - st_static); - ivars_def->initialized = ivars_def->constant = 1; - ivars_def->nosave = 1; - ivars = &G_STRUCT (pr_ivar_list_t, ivars_def->ofs); - ivars->ivar_count = count; - for (i = 0, field = strct->struct_head; field; field = field->next) { - if (!field->name) + for (sym = symtab->symbols; sym; sym = sym->next) { + if (sym->sy_type != sy_var) continue; - encode_type (encoding, field->type); - EMIT_STRING (ivars->ivar_list[i].ivar_name, field->name); - EMIT_STRING (ivars->ivar_list[i].ivar_type, encoding->str); - ivars->ivar_list[i].ivar_offset = field->offset; - dstring_clearstr (encoding); - i++; - } - done: - dstring_delete (encoding); - dstring_delete (ivars_name); - return ivars_def; -} - -void -clear_structs (void) -{ - if (structs) - Hash_FlushTable (structs); -} - -void -process_enum (expr_t *enm) -{ - expr_t *e = enm; - expr_t *c_enum = 0; - int enum_val = 0; - - if (!enums) { - enums = Hash_NewTable (16381, enums_get_key, 0, 0); - } - while (e) { - expr_t *t = e->next; - e->next = c_enum; - c_enum = e; - e = t; - } - for (e = c_enum; e; e = e->next) { - expr_t *name = e; - expr_t *val = 0; - enum_t *new_enum; - - if (name->type == ex_expr) { - val = name->e.expr.e2; - name = name->e.expr.e1; + if (su == 's') { + sym->s.value = symtab->size; + symtab->size += type_size (sym->type); + } else { + int size = type_size (sym->type); + if (size > symtab->size) + symtab->size = size; } - if (get_enum (name->e.string_val) - || get_def (NULL, name->e.string_val, pr.scope, st_none)) { - error (name, "%s redeclared", name->e.string_val); - continue; - } - if (val) - enum_val = val->e.integer_val; - new_enum = malloc (sizeof (enum_t)); - if (!new_enum) - Sys_Error ("out of memory"); - new_enum->name = name->e.string_val; - new_enum->value = enum_val++; - Hash_Add (enums, new_enum); - //printf ("%s = %d\n", new_enum->name, new_enum->value.e.integer_val); } + sym->sy_type = sy_type; + sym->type->t.symtab = symtab; + return sym; } -expr_t * -get_enum (const char *name) +symbol_t * +find_enum (symbol_t *tag) { - enum_t *e; + return find_tag (ty_enum, tag, 0); +} - if (!enums) - return 0; - e = (enum_t *) Hash_Find (enums, name); - if (!e) - return 0; - return new_integer_expr (e->value); +symtab_t * +start_enum (symbol_t *sym) +{ + if (sym->table == current_symtab && sym->type->t.symtab) { + error (0, "%s defined as wrong kind of tag", sym->name); + sym = find_enum (0); + } + sym->type->t.symtab = new_symtab (current_symtab, stab_local); + return sym->type->t.symtab; } void -clear_enums (void) +add_enum (symbol_t *enm, symbol_t *name, expr_t *val) { - if (enums) - Hash_FlushTable (enums); + type_t *enum_type = enm->type; + symtab_t *enum_tab; + int value; + + if (name->table == current_symtab) + error (0, "%s redefined", name->name); + if (name->table) + name = new_symbol (name->name); + name->sy_type = sy_const; + name->type = enum_type; + enum_tab = enum_type->t.symtab; + value = 0; + if (*enum_tab->symtail) + value = ((symbol_t *)(*enum_tab->symtail))->s.value + 1; + if (val) { + val = constant_expr (val); + if (val->type < ex_nil) + error (val, "non-constant initializer"); + else if (val->type != ex_integer) + error (val, "invalid initializer type"); + else + value = val->e.integer_val; + } + name->s.value = value; + symtab_addsymbol (enum_tab, name); +} + +symbol_t * +make_structure (const char *name, int su, struct_def_t *defs, type_t *type) +{ + symtab_t *strct; + symbol_t *field; + symbol_t *sym; + + if (su == 'u') + strct = new_symtab (0, stab_union); + else + strct = new_symtab (0, stab_struct); + while (defs->name) { + field = new_symbol_type (defs->name, defs->type); + if (!symtab_addsymbol (strct, field)) + internal_error (0, "duplicate symbol: %s", defs->name); + defs++; + } + sym = build_struct (su, new_symbol (name), strct, type); + return sym; } diff --git a/tools/qfcc/source/stub.c b/tools/qfcc/source/stub.c index febcff724..a1adcdefc 100644 --- a/tools/qfcc/source/stub.c +++ b/tools/qfcc/source/stub.c @@ -6,6 +6,7 @@ #include "codespace.h" #include "debug.h" #include "def.h" +#include "defspace.h" #include "emit.h" #include "function.h" #include "immediate.h" diff --git a/tools/qfcc/source/switch.c b/tools/qfcc/source/switch.c index dc68d976d..b169433e3 100644 --- a/tools/qfcc/source/switch.c +++ b/tools/qfcc/source/switch.c @@ -103,7 +103,6 @@ case_label_expr (switch_block_t *switch_block, expr_t *value) SYS_CHECKMEM (cl); if (value) { - convert_name (value); value = constant_expr (value); } if (value && value->type < ex_nil) { diff --git a/tools/qfcc/source/symtab.c b/tools/qfcc/source/symtab.c index 145874fee..286aa8dd3 100644 --- a/tools/qfcc/source/symtab.c +++ b/tools/qfcc/source/symtab.c @@ -108,7 +108,8 @@ copy_symbol (symbol_t *symbol) symbol_t *sym = new_symbol (symbol->name); sym->type = symbol->type; sym->params = copy_params (symbol->params); - sym->is_typedef = symbol->is_typedef; + sym->sy_type = symbol->sy_type; + sym->s = symbol->s; return sym; } diff --git a/tools/qfcc/source/type.c b/tools/qfcc/source/type.c index 4b1488d84..a709d32f4 100644 --- a/tools/qfcc/source/type.c +++ b/tools/qfcc/source/type.c @@ -55,6 +55,7 @@ static __attribute__ ((used)) const char rcsid[] = #include "options.h" #include "qfcc.h" #include "struct.h" +#include "symtab.h" #include "type.h" // simple types. function types are dynamically allocated @@ -87,16 +88,13 @@ type_t type_Method = { ev_invalid, "Method" }; type_t type_Super = { ev_invalid, "Super" }; type_t type_method_description = { ev_invalid, "obj_method_description", ty_struct }; -type_t *type_category; -type_t *type_ivar; -type_t *type_module; +type_t type_category; +type_t type_ivar; +type_t type_module; type_t type_va_list = { ev_invalid, "@va_list", ty_struct }; -type_t type_param = { ev_invalid, "@param", ty_struct }; +type_t type_param; type_t type_zero; -struct_t *vector_struct; -struct_t *quaternion_struct; - type_t type_floatfield = { ev_field, ".float", ty_none, {{&type_float}} }; static type_t *free_types; @@ -148,7 +146,9 @@ types_same (type_t *a, type_t *b) } break; case ty_struct: - if (a->t.strct != b->t.strct) + case ty_union: + case ty_enum: + if (a->t.symtab != b->t.symtab) return 0; return 1; case ty_array: @@ -191,41 +191,6 @@ find_type (type_t *type) return check; } -static hashtab_t *typedef_hash; -static typedef_t *free_typedefs; - -static const char * -typedef_get_key (void *t, void *unused) -{ - return ((typedef_t *)t)->name; -} - -void -new_typedef (const char *name, type_t *type) -{ - typedef_t *td; - - if (!typedef_hash) - typedef_hash = Hash_NewTable (1023, typedef_get_key, 0, 0); - td = Hash_Find (typedef_hash, name); - if (td) { - error (0, "%s redefined", name); - return; - } - ALLOC (1024, typedef_t, typedefs, td); - td->name = name; - td->type = type; - Hash_Add (typedef_hash, td); -} - -typedef_t * -get_typedef (const char *name) -{ - if (!typedef_hash) - return 0; - return Hash_Find (typedef_hash, name); -} - type_t * field_type (type_t *aux) { @@ -325,13 +290,17 @@ print_type_str (dstring_t *str, type_t *type) case ty_class: dasprintf (str, " %s", type->t.class->name); break; + case ty_enum: case ty_struct: + case ty_union: { const char *tag = "struct"; - if (type->t.strct->stype == str_union) + if (type->t.symtab->type == stab_union) tag = "union"; - dasprintf (str, " %s %s", tag, type->t.strct->name); + else if (type->t.symtab->type == stab_union) + tag = "enum"; + dasprintf (str, " %s %s", tag, type->name);//FIXME } break; case ty_array: @@ -386,12 +355,15 @@ encode_params (type_t *type) static void _encode_type (dstring_t *encoding, type_t *type, int level); static void -encode_struct_fields (dstring_t *encoding, struct_t *strct, int level) +encode_struct_fields (dstring_t *encoding, symtab_t *strct, int level) { - struct_field_t *field; + symbol_t *field; - for (field = strct->struct_head; field; field = field->next) + for (field = strct->symbols; field; field = field->next) { + if (field->sy_type != sy_var) + continue; _encode_type (encoding, field->type, level + 1); + } } static void @@ -402,22 +374,19 @@ encode_class (dstring_t *encoding, type_t *type, int level) if (class->name) name = class->name; - dasprintf (encoding, "{%s=", name); //FIXME loses info about being a class - if (level < 2 && class->ivars) - encode_struct_fields (encoding, class->ivars, level); - dasprintf (encoding, "}"); + dasprintf (encoding, "{%s@}", name); } static void encode_struct (dstring_t *encoding, type_t *type, int level) { - struct_t *strct = type->t.strct; + symtab_t *strct = type->t.symtab; const char *name ="?"; char su = '='; - if (strct->name) - name = strct->name; - if (strct->stype == str_union) + if (type->name) // FIXME + name = type->name; + if (strct->type == stab_union) su = '-'; dasprintf (encoding, "{%s%c", name, su); if (level < 2) @@ -425,6 +394,25 @@ encode_struct (dstring_t *encoding, type_t *type, int level) dasprintf (encoding, "}"); } +static void +encode_enum (dstring_t *encoding, type_t *type, int level) +{ + symtab_t *enm = type->t.symtab; + symbol_t *e; + const char *name ="?"; + + if (type->name) // FIXME + name = type->name; + dasprintf (encoding, "{%s#", name); + if (level < 2) { + for (e = enm->symbols; e; e = e->next) { + dasprintf (encoding, "%s=%d%s", e->name, e->s.value, + e->next ? "," : ""); + } + } + dasprintf (encoding, "}"); +} + static void _encode_type (dstring_t *encoding, type_t *type, int level) { @@ -486,7 +474,11 @@ _encode_type (dstring_t *encoding, type_t *type, int level) case ty_class: encode_class (encoding, type, level); break; + case ty_enum: + encode_enum (encoding, type, level); + break; case ty_struct: + case ty_union: encode_struct (encoding, type, level); break; case ty_array: @@ -515,13 +507,37 @@ encode_type (dstring_t *encoding, type_t *type) _encode_type (encoding, type, 0); } +static type_t * +parse_struct (const char **str) +{ + //FIXME + dstring_t *name; + const char *s; + + name = dstring_newstr (); + for (s = *str; *s && strchr ("=-@#}", *s); s++) + ; + if (!*s) + return 0; + dstring_appendsubstr (name, *str, s - *str); + *str = s; + switch (*(*str)++) { + case '=': + break; + case '-': + break; + case '@': + break; + case '#': + break; + } + return 0; +} + static type_t * _parse_type (const char **str) { type_t new; - struct_t *strct; - dstring_t *name; - const char *s; memset (&new, 0, sizeof (new)); switch (*(*str)++) { @@ -567,57 +583,7 @@ _parse_type (const char **str) case 's': return &type_short; case '{': - new.type = ev_invalid; - new.ty = ty_struct; - name = dstring_newstr (); - for (s = *str; - *s && *s != '=' && *s != '-' && *s != '#' && *s != '}'; s++) - ; - if (!*s) - return 0; - dstring_appendsubstr (name, *str, s - *str); - *str = s; - strct = 0; - if (name->str[0]) - strct = get_struct (name->str, 0); - if (strct && strct->struct_head) { - dstring_delete (name); - if (**str == '=' || **str == '-') { - (*str)++; - while (**str && **str != '}') - _parse_type (str); - } - if (**str != '}') - return 0; - (*str)++; - return strct->type; - } - if (**str != '=' && **str != '-' && **str != '}') { - if (( s = strchr (*str, '}'))) - *str = s + 1; - dstring_delete (name); - return 0; - } - if (!strct) { - strct = get_struct (*name->str ? name->str : 0, 1); - init_struct (strct, new_type (), str_none, 0); - } - dstring_delete (name); - if (**str == '}') { - (*str)++; - return strct->type; - } - if (**str == '-') - strct->stype = str_union; - else - strct->stype = str_struct; - (*str)++; - while (**str && **str != '}') - new_struct_field (strct, _parse_type (str), 0, vis_public); - if (**str != '}') - return 0; - (*str)++; - return strct->type; + return parse_struct (str); case '[': { type_t *type; @@ -674,7 +640,8 @@ is_scalar (type_t *type) int is_struct (type_t *type) { - if (type->type == ev_invalid && type->ty == ty_struct) + if (type->type == ev_invalid + && (type->ty == ty_struct || type->type == ty_union)) return 1; return 0; } @@ -756,8 +723,11 @@ type_size (type_t *type) return pr_type_size[type->type]; case ev_invalid: switch (type->ty) { + case ty_enum: + return type_size (&type_integer); case ty_struct: - return type->t.strct->size; + case ty_union: + return type->t.symtab->size; case ty_class: if (!type->t.class->ivars) return 0; @@ -776,138 +746,170 @@ void init_types (void) { type_t *type; - struct_t *strct; + static struct_def_t zero_struct[] = { + {"string_val", &type_string}, + {"float_val", &type_float}, + {"entity_val", &type_entity}, + {"field_val", &type_field}, + {"func_val", &type_function}, + {"pointer_val", &type_pointer}, + {"integer_val", &type_integer}, + {"vector_val", &type_vector}, + {"quaternion_val", &type_quaternion}, + {0, 0} + }; + static struct_def_t param_struct[] = { + {"string_val", &type_string}, + {"float_val", &type_float}, + {"vector_val", &type_vector}, + {"entity_val", &type_entity}, + {"field_val", &type_field}, + {"func_val", &type_function}, + {"pointer_val", &type_pointer}, + {"integer_val", &type_integer}, + {"quaternion_val", &type_quaternion}, + {0, 0} + }; + static struct_def_t vector_struct[] = { + {"x", &type_float}, + {"y", &type_float}, + {"z", &type_float}, + {0, 0} + }; + static struct_def_t quaternion_struct[] = { + {"s", &type_float}, + {"v", &type_vector}, + {0, 0} + }; + static struct_def_t sel_struct[] = { + {"sel_id", &type_string}, + {"sel_types", &type_string}, + {0, 0} + }; + static struct_def_t method_struct[] = { + {"method_name", &type_SEL}, + {"method_types", &type_string}, + {"method_imp", &type_IMP}, + {0, 0} + }; + static struct_def_t class_struct[] = { + {"class_pointer", &type_Class}, + {"super_class", &type_Class}, + {"name", &type_string}, + {"version", &type_integer}, + {"info", &type_integer}, + {"instance_size", &type_integer}, + {"ivars", &type_pointer}, + {"methods", &type_pointer}, + {"dtable", &type_pointer}, + {"subclass_list", &type_pointer}, + {"sibling_class", &type_pointer}, + {"protocols", &type_pointer}, + {"gc_object_type", &type_pointer}, + }; + static struct_def_t protocol_struct[] = { + {"class_pointer", &type_Class}, + {"protocol_name", &type_string}, + {"protocol_list", &type_pointer}, + {"instance_methods", &type_pointer}, + {"class_methods", &type_pointer}, + {0, 0} + }; + static struct_def_t id_struct[] = { + {"class_pointer", &type_Class}, + {0, 0} + }; + static struct_def_t method_desc_struct[] = { + {"name", &type_string}, + {"types", &type_string}, + {0, 0} + }; + static struct_def_t category_struct[] = { + {"category_name", &type_string}, + {"class_name", &type_string}, + {"instance_methods", &type_pointer}, + {"class_methods", &type_pointer}, + {"protocols", &type_pointer}, + {0, 0} + }; + static struct_def_t ivar_struct[] = { + {"ivar_name", &type_string}, + {"ivar_type", &type_string}, + {"ivar_offset", &type_integer}, + {0, 0} + }; + static struct_def_t super_struct[] = { + {"self", &type_id}, + {"class", &type_Class}, + {0, 0} + }; - strct = calloc (sizeof (struct_t), 1); - init_struct (strct, &type_zero, str_union, 0); - new_struct_field (strct, &type_string, "string_val", vis_public); - new_struct_field (strct, &type_float, "float_val", vis_public); - new_struct_field (strct, &type_entity, "entity_val", vis_public); - new_struct_field (strct, &type_field, "field_val", vis_public); - new_struct_field (strct, &type_function, "func_val", vis_public); - new_struct_field (strct, &type_pointer, "pointer_val", vis_public); - new_struct_field (strct, &type_integer, "integer_val", vis_public); + if (options.code.progsversion == PROG_ID_VERSION) { + // vector can't be part of .zero for v6 progs because for v6 progs, + // .zero is only one word wide. + zero_struct[7].name = 0; + // v6 progs don't have quaternions + zero_struct[8].name = 0; + param_struct[8].name = 0; + } - strct = calloc (sizeof (struct_t), 1); - init_struct (strct, &type_param, str_union, 0); - new_struct_field (strct, &type_string, "string_val", vis_public); - new_struct_field (strct, &type_float, "float_val", vis_public); - new_struct_field (strct, &type_vector, "vector_val", vis_public); - new_struct_field (strct, &type_entity, "entity_val", vis_public); - new_struct_field (strct, &type_field, "field_val", vis_public); - new_struct_field (strct, &type_function, "func_val", vis_public); - new_struct_field (strct, &type_pointer, "pointer_val", vis_public); - new_struct_field (strct, &type_integer, "integer_val", vis_public); - - strct = vector_struct = get_struct (0, 1); - init_struct (strct, new_type (), str_struct, 0); - new_struct_field (strct, &type_float, "x", vis_public); - new_struct_field (strct, &type_float, "y", vis_public); - new_struct_field (strct, &type_float, "z", vis_public); + make_structure (0, 'u', zero_struct, &type_zero); + make_structure (0, 'u', param_struct, &type_param); + make_structure (0, 's', vector_struct, &type_vector); + type_vector.type = ev_vector; if (options.traditional) return; - if (options.code.progsversion != PROG_ID_VERSION) { - strct = type_zero.t.strct; - // vector can't be part of .zero for v6 progs because for v6 progs, - // .zero is only one word wide. - new_struct_field (strct, &type_vector, "vector_val", vis_public); - new_struct_field (strct, &type_quaternion, "quaternion_val", - vis_public); + make_structure (0, 's', quaternion_struct, &type_quaternion); + type_quaternion.type = ev_vector; - strct = type_param.t.strct; - new_struct_field (strct, &type_quaternion, "quaternion_val", - vis_public); - } + type_SEL.t.fldptr.type = make_structure (0, 's', sel_struct, 0)->type; - strct = quaternion_struct = get_struct (0, 1); - init_struct (strct, new_type (), str_struct, 0); - new_struct_field (strct, &type_float, "s", vis_public); - new_struct_field (strct, &type_vector, "v", vis_public); + make_structure (0, 's', method_struct, &type_Method); - strct = get_struct (0, 1); - init_struct (strct, new_type (), str_struct, 0); - new_struct_field (strct, &type_string, "sel_id", vis_public); - new_struct_field (strct, &type_string, "sel_types", vis_public); - type_SEL.t.fldptr.type = strct->type; - - strct = get_struct (0, 1); - init_struct (strct, &type_Method, str_struct, 0); - new_struct_field (strct, &type_SEL, "method_name", vis_public); - new_struct_field (strct, &type_string, "method_types", vis_public); - new_struct_field (strct, &type_IMP, "method_imp", vis_public); - - strct = get_struct (0, 1); - init_struct (strct, type = new_type (), str_struct, 0); - type->ty = ty_class; - type->t.class = &class_Class; - new_struct_field (strct, &type_Class, "class_pointer", vis_public); - new_struct_field (strct, &type_Class, "super_class", vis_public); - new_struct_field (strct, &type_string, "name", vis_public); - new_struct_field (strct, &type_integer, "version", vis_public); - new_struct_field (strct, &type_integer, "info", vis_public); - new_struct_field (strct, &type_integer, "instance_size", vis_public); - new_struct_field (strct, &type_pointer, "ivars", vis_public); - new_struct_field (strct, &type_pointer, "methods", vis_public); - new_struct_field (strct, &type_pointer, "dtable", vis_public); - new_struct_field (strct, &type_pointer, "subclass_list", vis_public); - new_struct_field (strct, &type_pointer, "sibling_class", vis_public); - new_struct_field (strct, &type_pointer, "protocols", vis_public); - new_struct_field (strct, &type_pointer, "gc_object_type", vis_public); - type_Class.t.fldptr.type = strct->type; - class_Class.ivars = strct; + type = make_structure (0, 's', class_struct, 0)->type; + type_Class.t.fldptr.type = type; + class_Class.ivars = type->t.symtab; + make_structure (0, 's', protocol_struct, &type_Protocol); + /*FIXME strct = get_struct (0, 1); init_struct (strct, type = &type_Protocol, str_struct, 0); type->ty = ty_class; type->t.class = &class_Protocol; - new_struct_field (strct, &type_Class, "class_pointer", vis_public); - new_struct_field (strct, &type_string, "protocol_name", vis_public); - new_struct_field (strct, &type_pointer, "protocol_list", vis_public); - new_struct_field (strct, &type_pointer, "instance_methods", vis_public); - new_struct_field (strct, &type_pointer, "class_methods", vis_public); - class_Protocol.ivars = strct; + class_Protocol.ivars = strct;*/ - strct = get_struct (0, 1); - init_struct (strct, type = new_type (), str_struct, 0); - type->ty = ty_class; - type->t.class = &class_id; - new_struct_field (strct, &type_Class, "class_pointer", vis_public); - type_id.t.fldptr.type = strct->type; - class_id.ivars = strct; + type = make_structure (0, 's', id_struct, 0)->type; + //FIXME type->ty = ty_class; + //type->t.class = &class_id; + //type_id.t.fldptr.type = strct->type; + class_id.ivars = type->t.symtab; - strct = get_struct (0, 1); - init_struct (strct, &type_method_description, str_struct, 0); - new_struct_field (strct, &type_string, "name", vis_public); - new_struct_field (strct, &type_string, "types", vis_public); + make_structure (0, 's', method_desc_struct, &type_method_description); - strct = get_struct (0, 1); - init_struct (strct, new_type (), str_struct, 0); - new_struct_field (strct, &type_string, "category_name", vis_public); - new_struct_field (strct, &type_string, "class_name", vis_public); - new_struct_field (strct, &type_pointer, "instance_methods", vis_public); - new_struct_field (strct, &type_pointer, "class_methods", vis_public); - new_struct_field (strct, &type_pointer, "protocols", vis_public); - type_category = strct->type; + make_structure (0, 's', category_struct, &type_category); - strct = get_struct (0, 1); - init_struct (strct, new_type (), str_struct, 0); - new_struct_field (strct, &type_string, "ivar_name", vis_public); - new_struct_field (strct, &type_string, "ivar_type", vis_public); - new_struct_field (strct, &type_integer, "ivar_offset", vis_public); - type_ivar = strct->type; + make_structure (0, 's', ivar_struct, &type_ivar); - strct = get_struct ("Super", 1); - init_struct (strct, &type_Super, str_struct, 0); - new_struct_field (strct, &type_id, "self", vis_public); - new_struct_field (strct, &type_Class, "class", vis_public); + make_structure (0, 's', super_struct, &type_Super); } void chain_initial_types (void) { - struct_t *strct; + static struct_def_t va_list_struct[] = { + {"count", &type_integer}, + {"list", 0}, // type will be filled in at runtime + {0, 0} + }; + static struct_def_t module_struct[] = { + {"version", &type_integer}, + {"size", &type_integer}, + {"name", &type_string}, + {"symtab", &type_pointer}, + {0, 0} + }; chain_type (&type_void); chain_type (&type_string); @@ -922,10 +924,8 @@ chain_initial_types (void) chain_type (&type_param); chain_type (&type_zero); - strct = calloc (sizeof (struct_t), 1); - init_struct (strct, &type_va_list, str_struct, 0); - new_struct_field (strct, &type_integer, "count", vis_public); - new_struct_field (strct, pointer_type (&type_param), "list", vis_public); + va_list_struct[1].type = pointer_type (&type_param); + make_structure (0, 's', va_list_struct, &type_va_list); if (options.traditional) return; @@ -942,29 +942,16 @@ chain_initial_types (void) chain_type (&type_Protocol); chain_type (&type_id); chain_type (&type_method_description); - chain_type (type_category); - chain_type (type_ivar); + chain_type (&type_category); + chain_type (&type_ivar); type_supermsg.t.func.param_types[0] = pointer_type (&type_Super); chain_type (&type_supermsg); - strct = get_struct ("obj_module_s", 1); - init_struct (strct, new_type (), str_struct, 0); - new_struct_field (strct, &type_integer, "version", vis_public); - new_struct_field (strct, &type_integer, "size", vis_public); - new_struct_field (strct, &type_string, "name", vis_public); - new_struct_field (strct, &type_pointer, "symtab", vis_public); - type_module = strct->type; - new_typedef ("obj_module_t", type_module); - chain_type (type_module); + make_structure ("obj_module_s", 's', module_struct, &type_module); + //new_typedef ("obj_module_t", type_module); + chain_type (&type_module); - type_obj_exec_class.t.func.param_types[0] = pointer_type (type_module); + type_obj_exec_class.t.func.param_types[0] = pointer_type (&type_module); chain_type (&type_obj_exec_class); } - -void -clear_typedefs (void) -{ - if (typedef_hash) - Hash_FlushTable (typedef_hash); -}