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:
Bill Currie 2011-01-25 15:46:48 +09:00
parent fd3b594ca5
commit 6ce3c5a59a
8 changed files with 117 additions and 74 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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