Rewrite much to use symbols and symtabs. Gut emit.c. Massive breakage.

That which isn't rewritten is horribly broken. However, this does include a
nice mechanism for building QC structs for emitting data.

emit.c has been gutted in the spirit of "throw one away".

There is much work to be done to get even variables emitted, let alone
code. Things should be a little more fun from here on.
This commit is contained in:
Bill Currie 2011-01-17 22:33:33 +09:00
parent 85de101aa3
commit ea3895805b
30 changed files with 1096 additions and 2795 deletions

View file

@ -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);

View file

@ -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);

View file

@ -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);

View file

@ -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);

View file

@ -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))

View file

@ -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

View file

@ -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

View file

@ -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);

View file

@ -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)

View file

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

View file

@ -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;

View file

@ -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 ("<MOVE>", 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 ();
}

View file

@ -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);

View file

@ -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

View file

@ -46,6 +46,7 @@ static __attribute__ ((used)) const char rcsid[] =
#include <QF/dstring.h>
#include "def.h"
#include "defspace.h"
#include "qfcc.h"
#include "expr.h"
#include "idstuff.h"

View file

@ -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;

View file

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

View file

@ -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;

View file

@ -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"

View file

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

File diff suppressed because it is too large Load diff

View file

@ -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));

View file

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

View file

@ -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);
}
;
%%

View file

@ -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"

View file

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

View file

@ -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"

View file

@ -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) {

View file

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

View file

@ -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);
}