linker.[ch]:

start working on the linker.
class.[ch]:
	redo class defs so the pointer works (needs relocs still)
obj_file.h:
	add prototype for read_obj_file, QFO_* data access macros and include
	pr_debug.h
type.[ch]:
	separate type system initialisation and recording of the standard types
	so find_type works properly in multiple compilation
def.c:
	don't mark static defs as initialized
expr.c:
	proper class pointer def stuff
immediate.c:
	clean out dead vars/code
obj_file.c:
	allocate space for the line info and bail if the file can't be opened.
qfcc.c:
	register the standard types for each compile pass and start linking the
	files
This commit is contained in:
Bill Currie 2002-07-03 20:16:32 +00:00
parent 9332ea30bc
commit 102eab0d84
14 changed files with 297 additions and 59 deletions

View file

@ -1,5 +1,5 @@
AUTOMAKE_OPTIONS= foreign
EXTRA_DIST= class.h cmdlib.h cpp.h debug.h def.h expr.h function.h idstuff.h \
immediate.h method.h obj_file.h opcodes.h options.h qfcc.h \
reloc.h struct.h switch.h type.h
immediate.h linker.h method.h obj_file.h opcodes.h options.h \
qfcc.h reloc.h struct.h switch.h type.h

View file

@ -55,6 +55,7 @@ struct method_s;
struct protocol_s;
struct type_s;
struct def_s *class_def (class_t *class, int external);
void class_init (void);
class_t *get_class (const char *name, int create);
void class_add_methods (class_t *class, struct methodlist_s *methods);
@ -69,7 +70,7 @@ struct struct_field_s *class_find_ivar (class_t *class, int protected,
struct expr_s *class_ivar_expr (class_t *class, const char *name);
struct method_s *class_find_method (class_t *class, struct method_s *method);
struct method_s *class_message_response (class_t *class, struct expr_s *sel);
struct def_s *class_def (class_t *class);
struct def_s *class_pointer_def (class_t *class);
class_t *get_category (const char *class_name, const char *category_name,
int create);
void class_finish_module (void);

View file

@ -0,0 +1,39 @@
/*
link.h
qc object file linking
Copyright (C) 2001 Bill Currie <bill@taniwha.org>
Author: Bill Currie <bill@taniwha.org>
Date: 2002/7/3
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
$Id$
*/
#ifndef __linker_h
#define __linker_h
void linker_begin (void);
void linker_add_object_file (const char *filename);
void linker_finish (void);
#endif//__linker_h

View file

@ -33,6 +33,7 @@
#define __obj_file_h
#include "QF/pr_comp.h"
#include "QF/pr_debug.h"
#define QFO "QFO"
#define QFO_VERSION 0x00001001 // MMmmmRRR 0.001.001 (hex)
@ -118,6 +119,16 @@ typedef struct qfo_s {
int num_lines;
} qfo_t;
#define QFO_var(q, t, o) ((q)->data[o].t##_var)
#define QFO_FLOAT(q, o) QFO_var (q, float, o)
#define QFO_INT(q, o) QFO_var (q, integer, o)
#define QFO_VECTOR(q, o) QFO_var (q, vector, o)
#define QFO_STRING(q, o) (pr.strings + QFO_var (q, string, o))
#define QFO_FUNCTION(q, o) QFO_var (q, func, o)
#define QFO_POINTER(q, t,o) ((t *)((q)->data + o))
#define QFO_STRUCT(q, t,o) (*QFO_POINTER (q, t, o))
int write_obj_file (const char *filename);
qfo_t *read_obj_file (const char *filename);
#endif//__obj_file_h

View file

@ -88,6 +88,7 @@ int type_assignable (type_t *dst, type_t *src);
int type_size (type_t *type);
void init_types (void);
void chain_initial_types (void);
void clear_typedefs (void);

View file

@ -39,8 +39,8 @@ bin_PROGRAMS= qfcc
qfcc_SOURCES= \
class.c cmdlib.c cpp.c debug.c def.c emit.c expr.c function.c idstuff.c \
immediate.c method.c obj_file.c opcodes.c options.c qc-lex.l qc-parse.y \
qfcc.c reloc.c struct.c switch.c type.c
immediate.c linker.c method.c obj_file.c opcodes.c options.c qc-lex.l \
qc-parse.y qfcc.c reloc.c struct.c switch.c type.c
qfcc_LDADD= $(QFCC_LIBS)
qfcc_DEPENDENCIES= $(QFCC_DEPS)

View file

@ -84,6 +84,22 @@ class_init (void)
class_Class.super_class = get_class ("Object", 1);
}
def_t *
class_def (class_t *class, int external)
{
const char *name;
storage_class_t storage = external ? st_extern : st_global;
if (!class->class_name)
return 0;
if (class->category_name)
name = va ("_OBJ_CATEGORY_%s_%s",
class->class_name, class->category_name);
else
name = va ("_OBJ_CLASS_%s", class->class_name);
return get_def (type_category, name, pr.scope, storage);
}
class_t *
get_class (const char *name, int create)
{
@ -152,16 +168,10 @@ void
class_begin (class_t *class)
{
current_class = class;
if (class->def)
return;
class->def = class_def (class, 0);
if (class->class_name && class->category_name) {
pr_category_t *category;
class->def = get_def (type_category,
va ("_OBJ_CATEGORY_%s_%s",
class->class_name,
class->category_name),
pr.scope, st_static);
class->def->initialized = class->def->constant = 1;
category = &G_STRUCT (pr_category_t, class->def->ofs);
category->category_name = ReuseString (class->category_name);
@ -190,9 +200,6 @@ class_begin (class_t *class)
meta->protocols = emit_protocol_list (class->protocols,
class->class_name);
class->def = get_def (type_Class.aux_type,
va ("_OBJ_CLASS_%s", class->class_name),
pr.scope, st_static);
class->def->initialized = class->def->constant = 1;
cls = &G_STRUCT (pr_class_t, class->def->ofs);
cls->class_pointer = meta_def->ofs;
@ -394,7 +401,7 @@ get_category (const char *class_name, const char *category_name, int create)
}
def_t *
class_def (class_t *class)
class_pointer_def (class_t *class)
{
def_t *def;
@ -403,12 +410,12 @@ class_def (class_t *class)
pr.scope, st_static);
if (def->initialized)
return def;
if (class->def) { //FIXME need externals?
G_INT (def->ofs) = class->def->ofs;
} else {
warning (0, "%s not implemented", class->class_name);
}
def->initialized = def->constant = 1;
if (!class->def)
class->def = class_def (class, 1);
if (!class->def->external)
G_INT (def->ofs) = class->def->ofs;
//FIXME need reloc
return def;
}

View file

@ -247,7 +247,7 @@ get_def (type_t *type, const char *name, scope_t *scope,
}
}
set_storage_bits (def, storage);
if (storage == st_extern || storage == st_static)
if (storage == st_extern)
def_initialized (def);
return def;

View file

@ -138,7 +138,7 @@ convert_name (expr_t *e)
class = get_class (name, 0);
if (class) {
e->type = ex_def;
e->e.def = class_def (class);
e->e.def = class_pointer_def (class);
return;
}
d = get_def (NULL, name, current_scope, st_none);
@ -1648,8 +1648,8 @@ function_expr (expr_t *e1, expr_t *e2)
e->type = expr_types[t->type];
}
if (!type_assignable (ftype->parm_types[i], t)) {
print_type (ftype->parm_types[i]); puts("");
print_type (t); puts("");
print_type (ftype->parm_types[i]); puts ("");
print_type (t); puts ("");
err = error (e, "type mismatch for parameter %d of %s",
i + 1, e1->e.def->name);
}

View file

@ -63,44 +63,36 @@ static const char *
float_imm_get_key (void *_def, void *unused)
{
def_t *def = (def_t *) _def;
static char rep[20];
return va ("\001float:%08X\001", G_INT (def->ofs));
return rep;
}
static const char *
vector_imm_get_key (void *_def, void *unused)
{
def_t *def = (def_t *) _def;
static char rep[60];
return va ("\001vector:%08X\001%08X\001%08X\001",
G_INT (def->ofs), G_INT (def->ofs + 1), G_INT (def->ofs + 2));
return rep;
}
static const char *
quaternion_imm_get_key (void *_def, void *unused)
{
def_t *def = (def_t *) _def;
static char rep[60];
return va ("\001quaternion:%08X\001%08X\001%08X\001%08X\001",
G_INT (def->ofs), G_INT (def->ofs + 1),
G_INT (def->ofs + 2), G_INT (def->ofs + 3));
return rep;
}
static const char *
int_imm_get_key (void *_def, void *_str)
{
def_t *def = (def_t *) _def;
static char rep[60];
char *str = (char *) _str;
return va ("\001%s:%08X\001", str, G_INT (def->ofs));
return rep;
}
static const char *

165
tools/qfcc/source/linker.c Normal file
View file

@ -0,0 +1,165 @@
/*
link.c
qc object file linking
Copyright (C) 2001 Bill Currie <bill@taniwha.org>
Author: Bill Currie <bill@taniwha.org>
Date: 2002/7/3
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
*/
static const char rcsid[] =
"$Id$";
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <stdlib.h>
#include "QF/hash.h"
#include "def.h"
#include "expr.h"
#include "immediate.h"
#include "obj_file.h"
#include "qfcc.h"
static hashtab_t *extern_defs;
static hashtab_t *defined_defs;
static const char *
defs_get_key (void *_def, void *unused)
{
qfo_def_t *def = (qfo_def_t *) _def;
return pr.strings + def->name;
}
void
add_code (qfo_t *qfo)
{
int num_statements = pr.num_statements;
pr.num_statements += qfo->code_size;
if (pr.num_statements >= pr.statements_size) {
pr.statements_size = (pr.num_statements + 16383) & ~16384;
pr.statements = realloc (pr.statements,
pr.statements_size * sizeof (dstatement_t));
}
memcpy (pr.statements + num_statements, qfo->code,
qfo->code_size * sizeof (dstatement_t));
}
void
add_defs (qfo_t *qfo)
{
qfo_def_t *def;
qfo_def_t *d;
for (def = qfo->defs; def - qfo->defs < qfo->num_defs; def++) {
def->full_type = ReuseString (qfo->strings + def->full_type);
def->name = ReuseString (qfo->strings + def->name);
def->file = ReuseString (qfo->strings + def->file);
if (def->flags & QFOD_EXTERNAL) {
Hash_Add (extern_defs, def);
} else {
if (def->flags & QFOD_GLOBAL) {
if ((d = Hash_Find (defined_defs, pr.strings + def->name))) {
error (0, "%s redefined", pr.strings + def->name);
}
}
if (def->basic_type == ev_string && def->ofs
&& QFO_var (qfo, string, def->ofs)) {
string_t s;
s = ReuseString (QFO_STRING (qfo, def->ofs));
QFO_var (qfo, string, def->ofs) = s;
}
if (def->ofs)
def->ofs += pr.near_data->size;
if (def->flags & QFOD_GLOBAL) {
while ((d = Hash_Find (extern_defs, pr.strings + def->name))) {
Hash_Del (extern_defs, pr.strings + d->name);
if (d->full_type != def->full_type) {
error (0, "type mismatch %s %s",
pr.strings + def->full_type,
pr.strings + d->full_type);
}
}
Hash_Add (defined_defs, def);
}
}
}
}
void
add_functions (qfo_t *qfo)
{
qfo_function_t *func;
for (func = qfo->functions; func - qfo->functions < qfo->num_functions;
func++) {
func->name = ReuseString (qfo->strings + func->name);
func->file = ReuseString (qfo->strings + func->file);
if (func->code)
func->code += pr.num_statements;
}
}
void
linker_begin (void)
{
extern_defs = Hash_NewTable (16381, defs_get_key, 0, 0);
defined_defs = Hash_NewTable (16381, defs_get_key, 0, 0);
if (pr.statements)
free (pr.statements);
memset (&pr, 0, sizeof (pr));
pr.num_statements = 1;
pr.statements_size = 16384;
pr.statements = calloc (pr.statements_size, sizeof (dstatement_t));
pr.statement_linenums = calloc (pr.statements_size, sizeof (int));
CopyString ("");
pr.num_functions = 1;
pr.near_data = new_defspace ();
pr.near_data->data = calloc (65536, sizeof (pr_type_t));
}
void
linker_add_object_file (const char *filename)
{
qfo_t *qfo;
qfo = read_obj_file (filename);
if (!qfo)
return;
puts(filename);
add_defs (qfo);
add_functions (qfo);
add_code (qfo);
//add_data (qfo);
//add_far_data (qfo);
//add_strings (qfo);
}
void
linker_finish (void)
{
}

View file

@ -287,6 +287,10 @@ read_obj_file (const char *filename)
pr_lineno_t *line;
file = Qopen (filename, "rbz");
if (!file) {
perror (filename);
return 0;
}
Qread (file, &hdr, sizeof (hdr));
@ -325,6 +329,7 @@ read_obj_file (const char *filename)
qfo->relocs = malloc (qfo->num_relocs * sizeof (qfo_reloc_t));
qfo->defs = malloc (qfo->num_defs * sizeof (qfo_def_t));
qfo->functions = malloc (qfo->num_functions * sizeof (qfo_function_t));
qfo->lines = malloc (qfo->num_lines * sizeof (pr_lineno_t));
Qread (file, qfo->code, qfo->code_size * sizeof (dstatement_t));
Qread (file, qfo->data, qfo->data_size * sizeof (pr_type_t));
@ -388,5 +393,5 @@ read_obj_file (const char *filename)
line->line = LittleLong (line->line);
}
return 0;
return qfo;
}

View file

@ -71,6 +71,7 @@ static const char rcsid[] =
#include "function.h"
#include "idstuff.h"
#include "immediate.h"
#include "linker.h"
#include "method.h"
#include "obj_file.h"
#include "opcodes.h"
@ -131,6 +132,7 @@ InitData (void)
free (pr.statements);
memset (&pr, 0, sizeof (pr));
}
chain_initial_types ();
pr_source_line = 1;
pr_error_count = 0;
pr.num_statements = 1;
@ -538,8 +540,11 @@ separate_compile (void)
}
}
if (!err && !options.compile) {
linker_begin ();
for (file = source_files; *file; file++) {
linker_add_object_file (*file);
}
linker_finish ();
}
return err;
}

View file

@ -276,6 +276,9 @@ print_type (type_t *type)
class->category_name ? va (" (%s)", class->category_name)
: "");
break;
case ev_struct:
printf (" %s %s", pr_type_name[type->type], type->name);
break;
default:
printf(" %s", pr_type_name[type->type]);
break;
@ -340,7 +343,11 @@ _encode_type (dstring_t *encoding, type_t *type, int level)
case ev_object:
case ev_class:
dstring_appendstr (encoding, "{");
dstring_appendstr (encoding, type->name);
if (type->name) {
dstring_appendstr (encoding, type->name);
} else if (type->type == ev_object || type->type == ev_class) {
dstring_appendstr (encoding, type->class->class_name);
}
if (level < 2) {
dstring_appendstr (encoding, "=");
for (field = type->struct_head; field; field = field->next)
@ -441,32 +448,14 @@ init_types (void)
{
type_t *type;
chain_type (&type_void);
chain_type (&type_string);
chain_type (&type_float);
chain_type (&type_vector);
chain_type (&type_entity);
chain_type (&type_field);
chain_type (&type_function);
chain_type (&type_pointer);
chain_type (&type_floatfield);
chain_type (&type_quaternion);
chain_type (&type_integer);
chain_type (&type_uinteger);
chain_type (&type_short);
chain_type (&type_struct);
chain_type (&type_IMP);
type = type_SEL.aux_type = new_struct (0);
new_struct_field (type, &type_string, "sel_id", vis_public);
new_struct_field (type, &type_string, "sel_types", vis_public);
chain_type (&type_SEL);
type = type_Method.aux_type = new_struct (0);
new_struct_field (type, type_SEL.aux_type, "method_name", vis_public);
new_struct_field (type, &type_string, "method_types", vis_public);
new_struct_field (type, &type_IMP, "method_imp", vis_public);
chain_type (&type_Method);
type = type_Class.aux_type = new_struct (0);
type->type = ev_class;
@ -485,7 +474,6 @@ init_types (void)
new_struct_field (type, &type_pointer, "sibling_class", vis_public);
new_struct_field (type, &type_pointer, "protocols", vis_public);
new_struct_field (type, &type_pointer, "gc_object_type", vis_public);
chain_type (&type_Class);
type = type_Protocol.aux_type = new_struct (0);
type->type = ev_class;
@ -496,14 +484,12 @@ init_types (void)
new_struct_field (type, &type_pointer, "protocol_list", vis_public);
new_struct_field (type, &type_pointer, "instance_methods", vis_public);
new_struct_field (type, &type_pointer, "class_methods", vis_public);
chain_type (&type_Protocol);
type = type_id.aux_type = new_struct ("id");
type->type = ev_object;
type->class = &class_id;
class_id.ivars = type_id.aux_type;
new_struct_field (type, &type_Class, "class_pointer", vis_public);
chain_type (&type_id);
type = type_category = new_struct (0);
new_struct_field (type, &type_string, "category_name", vis_public);
@ -511,22 +497,48 @@ init_types (void)
new_struct_field (type, &type_pointer, "instance_methods", vis_public);
new_struct_field (type, &type_pointer, "class_methods", vis_public);
new_struct_field (type, &type_pointer, "protocols", vis_public);
chain_type (type_category);
type = type_ivar = new_struct (0);
new_struct_field (type, &type_string, "ivar_name", vis_public);
new_struct_field (type, &type_string, "ivar_type", vis_public);
new_struct_field (type, &type_integer, "ivar_offset", vis_public);
chain_type (type_ivar);
type = type_module = new_struct (0);
new_struct_field (type, &type_integer, "version", vis_public);
new_struct_field (type, &type_integer, "size", vis_public);
new_struct_field (type, &type_string, "name", vis_public);
new_struct_field (type, &type_pointer, "symtab", vis_public);
chain_type (type_module);
type_obj_exec_class.parm_types[0] = pointer_type (type_module);
}
void
chain_initial_types (void)
{
chain_type (&type_void);
chain_type (&type_string);
chain_type (&type_float);
chain_type (&type_vector);
chain_type (&type_entity);
chain_type (&type_field);
chain_type (&type_function);
chain_type (&type_pointer);
chain_type (&type_floatfield);
chain_type (&type_quaternion);
chain_type (&type_integer);
chain_type (&type_uinteger);
chain_type (&type_short);
chain_type (&type_struct);
chain_type (&type_IMP);
chain_type (&type_SEL);
chain_type (&type_Method);
chain_type (&type_Class);
chain_type (&type_Protocol);
chain_type (&type_id);
chain_type (type_category);
chain_type (type_ivar);
chain_type (type_module);
chain_type (&type_obj_exec_class);
}