From 6ce3c5a59a50b4558c3b5d80b6526f238ebe1d48 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 25 Jan 2011 15:46:48 +0900 Subject: [PATCH] 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). --- tools/qfcc/include/emit.h | 11 ++-- tools/qfcc/include/opcodes.h | 6 +-- tools/qfcc/include/statements.h | 2 +- tools/qfcc/source/emit.c | 91 +++++++++++++++++++++++++++++---- tools/qfcc/source/function.c | 21 ++++---- tools/qfcc/source/immediate.c | 2 +- tools/qfcc/source/opcodes.c | 57 +++++---------------- tools/qfcc/source/statements.c | 1 + 8 files changed, 117 insertions(+), 74 deletions(-) diff --git a/tools/qfcc/include/emit.h b/tools/qfcc/include/emit.h index 2bc6ffdc6..d7ae2f841 100644 --- a/tools/qfcc/include/emit.h +++ b/tools/qfcc/include/emit.h @@ -3,10 +3,10 @@ statement emittion - Copyright (C) 2002 Bill Currie + Copyright (C) 2011 Bill Currie Author: Bill Currie - 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 { \ diff --git a/tools/qfcc/include/opcodes.h b/tools/qfcc/include/opcodes.h index eb9af8769..fd0526ee9 100644 --- a/tools/qfcc/include/opcodes.h +++ b/tools/qfcc/include/opcodes.h @@ -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 diff --git a/tools/qfcc/include/statements.h b/tools/qfcc/include/statements.h index 72105ac1b..84003481d 100644 --- a/tools/qfcc/include/statements.h +++ b/tools/qfcc/include/statements.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; diff --git a/tools/qfcc/source/emit.c b/tools/qfcc/source/emit.c index 729c1596e..a6da0dcba 100644 --- a/tools/qfcc/source/emit.c +++ b/tools/qfcc/source/emit.c @@ -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 @@ -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); } diff --git a/tools/qfcc/source/function.c b/tools/qfcc/source/function.c index eeea4bdb9..39d3efb65 100644 --- a/tools/qfcc/source/function.c +++ b/tools/qfcc/source/function.c @@ -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 diff --git a/tools/qfcc/source/immediate.c b/tools/qfcc/source/immediate.c index 7ad7b6f27..c02be355d 100644 --- a/tools/qfcc/source/immediate.c +++ b/tools/qfcc/source/immediate.c @@ -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) { diff --git a/tools/qfcc/source/opcodes.c b/tools/qfcc/source/opcodes.c index dd787f450..9c2ddb0f0 100644 --- a/tools/qfcc/source/opcodes.c +++ b/tools/qfcc/source/opcodes.c @@ -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, "")) { op_done = op; } else if (!strcmp (op->name, "")) { diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index ccf38cde7..b9d02a937 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -726,6 +726,7 @@ statement_uexpr (sblock_t *sblock, expr_t *e) opcode = ""; 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;