mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-01-31 05:00:35 +00:00
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:
parent
85de101aa3
commit
ea3895805b
30 changed files with 1096 additions and 2795 deletions
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 ();
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
@ -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));
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
;
|
||||
|
||||
%%
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue