mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-23 04:42:32 +00:00
Get statments being emitted to the code segment.
The first function seems to work fine, but there's a problems with the scope of params causing params to get their knickers in a twist (tangled linked list).
This commit is contained in:
parent
fd3b594ca5
commit
6ce3c5a59a
8 changed files with 117 additions and 74 deletions
|
@ -3,10 +3,10 @@
|
|||
|
||||
statement emittion
|
||||
|
||||
Copyright (C) 2002 Bill Currie <bill@taniwha.org>
|
||||
Copyright (C) 2011 Bill Currie <bill@taniwha.org>
|
||||
|
||||
Author: Bill Currie <bill@taniwha.org>
|
||||
Date: 2002/07/08
|
||||
Date: 2011/01/25
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
|
@ -32,10 +32,9 @@
|
|||
#ifndef __emit_h
|
||||
#define __emit_h
|
||||
|
||||
struct expr_s;
|
||||
struct def_s *emit_statement (struct expr_s *e, opcode_t *op, struct def_s *var_a, struct def_s *var_b, struct def_s *var_c);
|
||||
struct def_s *emit_sub_expr (struct expr_s*e, struct def_s *dest);
|
||||
void emit_expr (struct expr_s *e);
|
||||
struct sblock_s;
|
||||
|
||||
void emit_statements (struct sblock_s *first_sblock);
|
||||
|
||||
#define EMIT_STRING(s,dest,str) \
|
||||
do { \
|
||||
|
|
|
@ -47,10 +47,10 @@ extern struct opcode_s *op_goto;
|
|||
extern struct opcode_s *op_jump;
|
||||
extern struct opcode_s *op_jumpb;
|
||||
|
||||
struct type_s;
|
||||
struct def_s;
|
||||
|
||||
struct opcode_s *opcode_find (const char *name, struct type_s *type_a,
|
||||
struct type_s *type_b, struct type_s *type_c);
|
||||
struct opcode_s *opcode_find (const char *name, struct def_s *def_a,
|
||||
struct def_s *def_b, struct def_s *def_c);
|
||||
void opcode_init (void);
|
||||
|
||||
#endif//__opcodes_h
|
||||
|
|
|
@ -46,7 +46,7 @@ typedef struct operand_s {
|
|||
struct symbol_s *symbol;
|
||||
struct ex_value_s *value;
|
||||
struct ex_label_s *label;
|
||||
int id;
|
||||
struct def_s *def;
|
||||
} o;
|
||||
} operand_t;
|
||||
|
||||
|
|
|
@ -31,8 +31,7 @@
|
|||
# include "config.h"
|
||||
#endif
|
||||
|
||||
static __attribute__ ((used)) const char rcsid[] =
|
||||
"$Id$";
|
||||
static __attribute__ ((used)) const char rcsid[] = "$Id$";
|
||||
|
||||
#ifdef HAVE_STRING_H
|
||||
# include <string.h>
|
||||
|
@ -47,33 +46,103 @@ static __attribute__ ((used)) const char rcsid[] =
|
|||
|
||||
#include "codespace.h"
|
||||
#include "def.h"
|
||||
#include "defspace.h"
|
||||
#include "debug.h"
|
||||
#include "diagnostic.h"
|
||||
#include "emit.h"
|
||||
#include "expr.h"
|
||||
#include "function.h"
|
||||
#include "immediate.h"
|
||||
#include "opcodes.h"
|
||||
#include "options.h"
|
||||
#include "qfcc.h"
|
||||
#include "reloc.h"
|
||||
#include "statements.h"
|
||||
#include "symtab.h"
|
||||
#include "type.h"
|
||||
#include "qc-parse.h"
|
||||
|
||||
def_t *
|
||||
emit_statement (expr_t *e, opcode_t *op, def_t *var_a, def_t *var_b,
|
||||
def_t *var_c)
|
||||
static def_t zero_def;
|
||||
|
||||
static def_t *
|
||||
get_operand_def (operand_t *op)
|
||||
{
|
||||
def_t *def;
|
||||
|
||||
if (!op)
|
||||
return 0;
|
||||
switch (op->op_type) {
|
||||
case op_symbol:
|
||||
if (op->type != op->o.symbol->type->type)
|
||||
return alias_def (op->o.symbol->s.def, ev_types[op->type]);
|
||||
return op->o.symbol->s.def;
|
||||
case op_value:
|
||||
//FIXME share immediates
|
||||
def = new_def (".imm", ev_types[op->type], pr.near_data,
|
||||
st_static);
|
||||
memcpy (D_POINTER (pr_type_t, def), &op->o.value,
|
||||
pr_type_size[op->type]);
|
||||
return def;
|
||||
case op_label:
|
||||
return &zero_def; //FIXME
|
||||
case op_temp:
|
||||
if (!op->o.def)
|
||||
op->o.def = new_def (".tmp", ev_types[op->type],
|
||||
current_func->symtab->space, st_local);
|
||||
return op->o.def;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
def_t *
|
||||
emit_sub_expr (expr_t *e, def_t *dest)
|
||||
static void
|
||||
add_statement_ref (def_t *def, dstatement_t *st, int field)
|
||||
{
|
||||
return 0;
|
||||
if (def) {
|
||||
int st_ofs = st - pr.code->code;
|
||||
|
||||
if (def->alias) {
|
||||
reloc_op_def (def->alias, st_ofs, field);
|
||||
free_def (def);
|
||||
} else {
|
||||
reloc_op_def (def, st_ofs, field);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
emit_statement (statement_t *statement)
|
||||
{
|
||||
const char *opcode = statement->opcode;
|
||||
def_t *def_a = get_operand_def (statement->opa);
|
||||
def_t *def_b = get_operand_def (statement->opb);
|
||||
def_t *def_c = get_operand_def (statement->opc);
|
||||
opcode_t *op = opcode_find (opcode, def_a, def_b, def_c);
|
||||
dstatement_t *s;
|
||||
|
||||
puts (opcode);
|
||||
if (!op)
|
||||
internal_error (0, "ice ice baby");
|
||||
s = codespace_newstatement (pr.code);
|
||||
s->op = op->opcode;
|
||||
s->a = def_a ? def_a->offset : 0;
|
||||
s->b = def_b ? def_b->offset : 0;
|
||||
s->c = def_c ? def_c->offset : 0;
|
||||
|
||||
add_statement_ref (def_a, s, 0);
|
||||
add_statement_ref (def_b, s, 0);
|
||||
add_statement_ref (def_c, s, 0);
|
||||
}
|
||||
|
||||
void
|
||||
emit_expr (expr_t *e)
|
||||
emit_statements (sblock_t *first_sblock)
|
||||
{
|
||||
sblock_t *sblock;
|
||||
statement_t *s;
|
||||
|
||||
for (sblock = first_sblock; sblock; sblock = sblock->next) {
|
||||
sblock->offset = pr.code->size;
|
||||
for (s = sblock->statements; s; s = s->next)
|
||||
emit_statement (s);
|
||||
}
|
||||
|
||||
for (sblock = first_sblock; sblock; sblock = sblock->next)
|
||||
relocate_refs (sblock->relocs, sblock->offset);
|
||||
}
|
||||
|
|
|
@ -593,17 +593,20 @@ void
|
|||
emit_function (function_t *f, expr_t *e)
|
||||
{
|
||||
sblock_t *sblock;
|
||||
statement_t *s;
|
||||
//statement_t *s;
|
||||
|
||||
printf ("%s\n", f->name);
|
||||
f->code = pr.code->size;
|
||||
printf ("%s %d\n", f->name, f->code);
|
||||
sblock = make_statements (e);
|
||||
for (/**/; sblock; sblock = sblock->next) {
|
||||
printf ("block %p\n", sblock);
|
||||
for (s = sblock->statements; s; s = s->next) {
|
||||
printf (" ");
|
||||
print_statement (s);
|
||||
}
|
||||
}
|
||||
//for (/**/; sblock; sblock = sblock->next) {
|
||||
// printf ("block %p\n", sblock);
|
||||
// for (s = sblock->statements; s; s = s->next) {
|
||||
// printf (" ");
|
||||
// print_statement (s);
|
||||
// }
|
||||
//}
|
||||
|
||||
emit_statements (sblock);
|
||||
}
|
||||
|
||||
int
|
||||
|
|
|
@ -230,7 +230,7 @@ ReuseConstant (expr_t *expr, def_t *def)
|
|||
st_extern));
|
||||
e = address_expr (e, 0, type);
|
||||
e = unary_expr ('.', e);
|
||||
return emit_sub_expr (e, 0);
|
||||
return 0;//FIXME emit_sub_expr (e, 0);
|
||||
}
|
||||
}
|
||||
if (imm) {
|
||||
|
|
|
@ -50,8 +50,7 @@ static __attribute__ ((used)) const char rcsid[] =
|
|||
#include "qfcc.h"
|
||||
#include "type.h"
|
||||
|
||||
hashtab_t *opcode_type_table_ab;
|
||||
hashtab_t *opcode_type_table_abc;
|
||||
hashtab_t *opcode_type_table;
|
||||
|
||||
opcode_t *op_done;
|
||||
opcode_t *op_return;
|
||||
|
@ -74,17 +73,10 @@ static uintptr_t
|
|||
get_hash (void *_op, void *_tab)
|
||||
{
|
||||
opcode_t *op = (opcode_t *) _op;
|
||||
hashtab_t **tab = (hashtab_t **) _tab;
|
||||
uintptr_t hash;
|
||||
|
||||
if (tab == &opcode_type_table_ab) {
|
||||
hash = ROTL (~op->type_a, 8) + ROTL (~op->type_b, 16);
|
||||
} else if (tab == &opcode_type_table_abc) {
|
||||
hash = ROTL (~op->type_a, 8) + ROTL (~op->type_b, 16)
|
||||
+ ROTL (~op->type_c, 24);
|
||||
} else {
|
||||
abort ();
|
||||
}
|
||||
hash = ROTL (~op->type_a, 8) + ROTL (~op->type_b, 16)
|
||||
+ ROTL (~op->type_c, 24);
|
||||
return hash + Hash_String (op->name);
|
||||
}
|
||||
|
||||
|
@ -93,42 +85,24 @@ compare (void *_opa, void *_opb, void *_tab)
|
|||
{
|
||||
opcode_t *opa = (opcode_t *) _opa;
|
||||
opcode_t *opb = (opcode_t *) _opb;
|
||||
hashtab_t **tab = (hashtab_t **) _tab;
|
||||
int cmp;
|
||||
|
||||
if (tab == &opcode_type_table_ab) {
|
||||
cmp = (opa->type_a == opb->type_a)
|
||||
&& (opa->type_b == opb->type_b);
|
||||
} else if (tab == &opcode_type_table_abc) {
|
||||
cmp = (opa->type_a == opb->type_a)
|
||||
&& (opa->type_b == opb->type_b)
|
||||
&& (opa->type_c == opb->type_c);
|
||||
} else {
|
||||
abort ();
|
||||
}
|
||||
cmp = (opa->type_a == opb->type_a)
|
||||
&& (opa->type_b == opb->type_b)
|
||||
&& (opa->type_c == opb->type_c);
|
||||
return cmp && !strcmp (opa->name, opb->name);
|
||||
}
|
||||
|
||||
opcode_t *
|
||||
opcode_find (const char *name, type_t *type_a, type_t *type_b, type_t *type_c)
|
||||
opcode_find (const char *name, def_t *def_a, def_t *def_b, def_t *def_c)
|
||||
{
|
||||
opcode_t op;
|
||||
hashtab_t **tab;
|
||||
|
||||
op.name = name;
|
||||
if (type_a && type_b && type_c) {
|
||||
op.type_a = type_a->type;
|
||||
op.type_b = type_b->type;
|
||||
op.type_c = type_c->type;
|
||||
tab = &opcode_type_table_abc;
|
||||
} else if (type_a && type_b) {
|
||||
op.type_a = type_a->type;
|
||||
op.type_b = type_b->type;
|
||||
tab = &opcode_type_table_ab;
|
||||
} else {
|
||||
tab = 0;
|
||||
}
|
||||
return Hash_FindElement (*tab, &op);
|
||||
op.type_a = def_a ? def_a->type->type : ev_invalid;
|
||||
op.type_b = def_b ? def_b->type->type : ev_invalid;
|
||||
op.type_c = def_c ? def_c->type->type : ev_invalid;
|
||||
return Hash_FindElement (opcode_type_table, &op);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -137,18 +111,15 @@ opcode_init (void)
|
|||
opcode_t *op;
|
||||
|
||||
PR_Opcode_Init ();
|
||||
opcode_type_table_ab = Hash_NewTable (1021, 0, 0, &opcode_type_table_ab);
|
||||
opcode_type_table_abc = Hash_NewTable (1021, 0, 0, &opcode_type_table_abc);
|
||||
Hash_SetHashCompare (opcode_type_table_ab, get_hash, compare);
|
||||
Hash_SetHashCompare (opcode_type_table_abc, get_hash, compare);
|
||||
opcode_type_table = Hash_NewTable (1021, 0, 0, 0);
|
||||
Hash_SetHashCompare (opcode_type_table, get_hash, compare);
|
||||
for (op = pr_opcodes; op->name; op++) {
|
||||
if (op->min_version > options.code.progsversion)
|
||||
continue;
|
||||
if (options.code.progsversion == PROG_ID_VERSION
|
||||
&& op->type_c == ev_integer)
|
||||
op->type_c = ev_float;
|
||||
Hash_AddElement (opcode_type_table_ab, op);
|
||||
Hash_AddElement (opcode_type_table_abc, op);
|
||||
Hash_AddElement (opcode_type_table, op);
|
||||
if (!strcmp (op->name, "<DONE>")) {
|
||||
op_done = op;
|
||||
} else if (!strcmp (op->name, "<RETURN>")) {
|
||||
|
|
|
@ -726,6 +726,7 @@ statement_uexpr (sblock_t *sblock, expr_t *e)
|
|||
opcode = "<RETURN_V>";
|
||||
s = new_statement (opcode);
|
||||
sblock = statement_subexpr (sblock, e->e.expr.e1, &s->opa);
|
||||
s->opa->type = ev_void;
|
||||
sblock_add_statement (sblock, s);
|
||||
sblock->next = new_sblock ();
|
||||
sblock = sblock->next;
|
||||
|
|
Loading…
Reference in a new issue