diff --git a/include/QF/pr_obj.h b/include/QF/pr_obj.h index 46fed75d0..94b12ab62 100644 --- a/include/QF/pr_obj.h +++ b/include/QF/pr_obj.h @@ -145,4 +145,19 @@ typedef struct pr_ivar_list_s { } pr_ivar_list_t; typedef struct pr_ivar_s pr_ivar_t; +typedef struct pr_symtab_s { + int sel_ref_cnt; + int cls_def_cnt; + int cat_def_cnt; + pointer_t defs[1]; // variable array of class pointers then + // category pointers +} pr_symtab_t; + +typedef struct pr_module_s { + int version; + int size; + string_t name; + pointer_t symtab; // pr_symtab_t +} pr_module_t; + #endif//__pr_obj_h diff --git a/tools/qfcc/include/class.h b/tools/qfcc/include/class.h index 41dc841ec..2134fd62f 100644 --- a/tools/qfcc/include/class.h +++ b/tools/qfcc/include/class.h @@ -71,6 +71,7 @@ struct method_s *class_message_response (class_t *class, struct expr_s *sel); struct def_s *class_def (class_t *class); class_t *get_category (const char *class_name, const char *category_name, int create); +void class_finish_module (void); typedef struct protocol_s { const char *name; diff --git a/tools/qfcc/include/qfcc.h b/tools/qfcc/include/qfcc.h index df48a7289..100eb5aa2 100644 --- a/tools/qfcc/include/qfcc.h +++ b/tools/qfcc/include/qfcc.h @@ -415,6 +415,7 @@ extern def_t *pr_global_defs[MAX_REGS]; // to find def for a global def_t *PR_ReuseConstant (expr_t *expr, def_t *def); +extern char destfile[]; extern int pr_source_line; extern def_t *pr_scope; diff --git a/tools/qfcc/include/type.h b/tools/qfcc/include/type.h index 0854cd42d..7fa53be18 100644 --- a/tools/qfcc/include/type.h +++ b/tools/qfcc/include/type.h @@ -51,9 +51,11 @@ extern type_t type_Class; extern type_t type_Protocol; extern type_t type_SEL; extern type_t type_IMP; +extern type_t type_obj_exec_class; extern type_t *type_method; extern type_t *type_category; extern type_t *type_ivar; +extern type_t *type_module; extern def_t def_void; extern def_t def_function; diff --git a/tools/qfcc/source/class.c b/tools/qfcc/source/class.c index 4a081675b..f8671a622 100644 --- a/tools/qfcc/source/class.c +++ b/tools/qfcc/source/class.c @@ -134,14 +134,21 @@ class_begin (class_t *class) if (class->def) return; if (class->class_name && class->category_name) { - def_t *category_def; + pr_category_t *category; - category_def = PR_GetDef (type_category, - va ("_OBJ_CATEGORY_%s_%s", - class->class_name, - class->category_name), - 0, &numpr_globals); - category_def->initialized = category_def->constant = 1; + class->def = PR_GetDef (type_category, + va ("_OBJ_CATEGORY_%s_%s", + class->class_name, + class->category_name), + 0, &numpr_globals); + class->def->initialized = class->def->constant = 1; + category = &G_STRUCT (pr_category_t, class->def->ofs); + category->category_name = ReuseString (class->category_name); + category->class_name = ReuseString (class->class_name); + category->protocols = emit_protocol_list (class->protocols, + va ("%s_%s", + class->class_name, + class->category_name)); } else if (class->class_name) { def_t *meta_def; pr_class_t *meta; @@ -182,6 +189,16 @@ class_finish (class_t *class) pr_category_t *category; category = &G_STRUCT (pr_category_t, class->def->ofs); + category->instance_methods = emit_methods (class->methods, + va ("%s_%s", + class->class_name, + class->category_name), + 1); + category->class_methods = emit_methods (class->methods, + va ("%s_%s", + class->class_name, + class->category_name), + 0); } else if (class->class_name) { pr_class_t *meta; pr_class_t *cls; @@ -347,7 +364,7 @@ get_category (const char *class_name, const char *category_name, int create) c = calloc (sizeof (class_t), 1); c->class_name = class_name; - c->class_name = category_name; + c->category_name = category_name; if (class_name && category_name) Hash_AddElement (category_hash, c); return c; @@ -372,6 +389,88 @@ class_def (class_t *class) return def; } +void +class_finish_module (void) +{ + class_t **classes = 0; + class_t **categories = 0; + class_t **t; + int num_classes = 0; + int num_categories = 0; + int i; + type_t *symtab_type; + def_t *symtab_def; + pr_symtab_t *symtab; + pointer_t *def_ptr; + def_t *module_def; + pr_module_t *module; + def_t *exec_class_def; + function_t *exec_class_func; + def_t *init_def; + function_t *init_func; + expr_t *init_expr; + + if (class_hash) { + classes = (class_t **) Hash_GetList (class_hash); + for (t = classes; *t; t++) + if ((*t)->def) + num_classes++; + } + if (category_hash) { + categories = (class_t **) Hash_GetList (category_hash); + for (t = categories; *t; t++) + if ((*t)->def) + num_categories++; + } + if (!num_classes && !num_categories) + return; + symtab_type = new_struct (0); + new_struct_field (symtab_type, &type_integer, "sel_ref_cnt", 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 = PR_GetDef (symtab_type, "_OBJ_SYMTAB", 0, &numpr_globals); + symtab_def->initialized = symtab_def->constant = 1; + symtab = &G_STRUCT (pr_symtab_t, symtab_def->ofs); + symtab->cls_def_cnt = num_classes; + symtab->cat_def_cnt = num_categories; + def_ptr = symtab->defs; + for (i = 0, t = classes; i < num_classes; i++, t++) + if ((*t)->def) + *def_ptr++ = (*t)->def->ofs; + for (i = 0, t = categories; i < num_categories; i++, t++) + if ((*t)->def) + *def_ptr++ = (*t)->def->ofs; + + module_def = PR_GetDef (type_module, "_OBJ_MODULE", 0, &numpr_globals); + module_def->initialized = module_def->constant = 1; + module = &G_STRUCT (pr_module_t, module_def->ofs); + module->size = type_size (type_module); + module->name = ReuseString (destfile); + module->symtab = symtab_def->ofs; + + exec_class_def = PR_GetDef (&type_obj_exec_class, "__obj_exec_class", + 0, &numpr_globals); + exec_class_func = new_function (); + exec_class_func->builtin = 0; + exec_class_func->def = exec_class_def; + build_function (exec_class_func); + finish_function (exec_class_func); + + init_def = PR_GetDef (&type_function, ".ctor", 0, &numpr_globals); + init_func = new_function (); + init_func->def = init_def; + init_func->code = numstatements; + build_function (init_func); + init_expr = new_block_expr (); + append_expr (init_expr, + function_expr (new_def_expr (exec_class_def), + address_expr (new_def_expr (module_def), 0, 0))); + emit_function (init_func, init_expr); + finish_function (init_func); +} + protocol_t * get_protocol (const char *name, int create) { diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index f062189b3..34491aaa5 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -85,6 +85,10 @@ type_t *types[] = { &type_integer, &type_uinteger, &type_short, + &type_void, // FIXME what type? + &type_void, // FIXME what type? + &type_void, // FIXME what type? + &type_SEL, }; expr_type expr_types[] = { diff --git a/tools/qfcc/source/qc-lex.l b/tools/qfcc/source/qc-lex.l index 93127aeb5..17d82a8f3 100644 --- a/tools/qfcc/source/qc-lex.l +++ b/tools/qfcc/source/qc-lex.l @@ -243,6 +243,7 @@ static keyword_t keywords[] = { {"integer", TYPE, &type_integer, 0, PROG_VERSION}, {"function", TYPE, &type_function, 0, PROG_VERSION}, {"id", TYPE, &type_id, 0, PROG_VERSION}, + {"Class", TYPE, &type_Class, 0, PROG_VERSION}, {"SEL", TYPE, &type_SEL, 0, PROG_VERSION}, {"IMP", TYPE, &type_IMP, 0, PROG_VERSION}, {"local", LOCAL, 0, 1, PROG_ID_VERSION}, diff --git a/tools/qfcc/source/qfcc.c b/tools/qfcc/source/qfcc.c index 40c4eb6bb..e334c5a1c 100644 --- a/tools/qfcc/source/qfcc.c +++ b/tools/qfcc/source/qfcc.c @@ -63,6 +63,7 @@ static const char rcsid[] = #include #include "qfcc.h" +#include "class.h" #include "type.h" options_t options; @@ -531,6 +532,7 @@ qboolean PR_FinishCompilation (void) def_t *def; expr_t e; + class_finish_module (); // check to make sure all functions prototyped have code if (options.warnings.undefined_function) for (d = pr.def_head.def_next; d; d = d->def_next) { diff --git a/tools/qfcc/source/struct.c b/tools/qfcc/source/struct.c index 69e42569a..40af9a7ef 100644 --- a/tools/qfcc/source/struct.c +++ b/tools/qfcc/source/struct.c @@ -181,7 +181,8 @@ emit_struct(type_t *strct, const char *name) if (!strct) return 0; for (count = 0, field = strct->struct_head; field; field = field->next) - count++; + 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++) @@ -194,12 +195,15 @@ emit_struct(type_t *strct, const char *name) ivars_def->initialized = ivars_def->constant = 1; ivars = &G_STRUCT (pr_ivar_list_t, ivars_def->ofs); ivars->ivar_count = count; - for (i = 0, field = strct->struct_head; field; i++, field = field->next) { + for (i = 0, field = strct->struct_head; field; field = field->next) { + if (!field->name) + continue; encode_type (encoding, field->type); ivars->ivar_list[i].ivar_name = ReuseString (field->name); ivars->ivar_list[i].ivar_type = ReuseString (encoding->str); ivars->ivar_list[i].ivar_offset = field->offset; dstring_clearstr (encoding); + i++; } done: dstring_delete (encoding); diff --git a/tools/qfcc/source/type.c b/tools/qfcc/source/type.c index dc72cfa84..11fc103cb 100644 --- a/tools/qfcc/source/type.c +++ b/tools/qfcc/source/type.c @@ -70,9 +70,11 @@ type_t type_Class = { ev_pointer }; type_t type_Protocol = { ev_pointer }; type_t type_SEL = { ev_pointer }; type_t type_IMP = { ev_func, NULL, &type_id, -3, { &type_id, &type_SEL }}; +type_t type_obj_exec_class = { ev_func, NULL, &type_void, 1, { 0 }}; type_t *type_method; type_t *type_category; type_t *type_ivar; +type_t *type_module; type_t type_floatfield = { ev_field, NULL, &type_float }; @@ -428,7 +430,7 @@ init_types (void) new_struct_field (type_method, &type_IMP, "method_imp", vis_public); chain_type (type_method); - type = type_Class.aux_type = new_struct ("Class"); + type = type_Class.aux_type = new_struct (0); type->type = ev_class; type->class = &class_Class; class_Class.ivars = type_Class.aux_type; @@ -478,4 +480,14 @@ init_types (void) new_struct_field (type, &type_string, "ivar_type", vis_public); new_struct_field (type, &type_integer, "ivar_offset", vis_public); chain_type (type_ivar); + + type = type_module = new_struct (0); + new_struct_field (type, &type_integer, "version", vis_public); + new_struct_field (type, &type_integer, "size", vis_public); + new_struct_field (type, &type_string, "name", vis_public); + new_struct_field (type, &type_pointer, "symtab", vis_public); + chain_type (type_module); + + type_obj_exec_class.parm_types[0] = pointer_type (type_module); + chain_type (&type_obj_exec_class); }