mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-02-26 13:41:21 +00:00
Start work on getting expressions converted to internal statements.
This commit is contained in:
parent
cac2e04b18
commit
b5424bca7d
9 changed files with 513 additions and 51 deletions
tools/qfcc
|
@ -71,9 +71,9 @@ typedef struct ex_expr_s {
|
||||||
} ex_expr_t;
|
} ex_expr_t;
|
||||||
|
|
||||||
typedef struct ex_label_s {
|
typedef struct ex_label_s {
|
||||||
struct ex_label_s *next; ///< next lable in global list of labels
|
struct ex_label_s *next; ///< next label in global list of labels
|
||||||
struct reloc_s *refs; ///< relocations associated with this label
|
struct reloc_s *refs; ///< relocations associated with this label
|
||||||
int ofs; ///< the location of this label if known
|
struct sblock_s *dest; ///< the location of this label if known
|
||||||
const char *name; ///< the name of this label
|
const char *name; ///< the name of this label
|
||||||
} ex_label_t;
|
} ex_label_t;
|
||||||
|
|
||||||
|
|
71
tools/qfcc/include/statements.h
Normal file
71
tools/qfcc/include/statements.h
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
/*
|
||||||
|
statement.h
|
||||||
|
|
||||||
|
Internal statements
|
||||||
|
|
||||||
|
Copyright (C) 2011 Bill Currie <bill@taniwha.org>
|
||||||
|
|
||||||
|
Author: Bill Currie <bill@taniwha.org>
|
||||||
|
Date: 2011/01/18
|
||||||
|
|
||||||
|
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 statement_h
|
||||||
|
#define statement_h
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
op_symbol,
|
||||||
|
op_value,
|
||||||
|
op_label,
|
||||||
|
op_temp,
|
||||||
|
} op_type_e;
|
||||||
|
|
||||||
|
typedef struct operand_s {
|
||||||
|
struct operand_s *next;
|
||||||
|
op_type_e type;
|
||||||
|
union {
|
||||||
|
struct symbol_s *symbol;
|
||||||
|
struct ex_value_s *value;
|
||||||
|
struct ex_label_s *label;
|
||||||
|
int id;
|
||||||
|
} o;
|
||||||
|
} operand_t;
|
||||||
|
|
||||||
|
typedef struct statement_s {
|
||||||
|
struct statement_s *next;
|
||||||
|
const char *opcode;
|
||||||
|
operand_t *opa;
|
||||||
|
operand_t *opb;
|
||||||
|
operand_t *opc;
|
||||||
|
} statement_t;
|
||||||
|
|
||||||
|
typedef struct sblock_s {
|
||||||
|
struct sblock_s *next;
|
||||||
|
statement_t *statements;
|
||||||
|
statement_t **tail;
|
||||||
|
} sblock_t;
|
||||||
|
|
||||||
|
struct expr_s;
|
||||||
|
|
||||||
|
sblock_t *make_statements (struct expr_s *expr);
|
||||||
|
void print_statement (statement_t *s);
|
||||||
|
|
||||||
|
#endif//statement_h
|
|
@ -54,8 +54,8 @@ EXTRA_PROGRAMS= qfcc qfpc qfprogs
|
||||||
common_src=\
|
common_src=\
|
||||||
class.c codespace.c constfold.c cpp.c debug.c def.c defspace.c emit.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 \
|
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 \
|
obj_file.c opcodes.c options.c qfcc.c reloc.c statements.c strpool.c \
|
||||||
symtab.c type.c
|
struct.c switch.c symtab.c type.c
|
||||||
|
|
||||||
qfcc_SOURCES= qc-lex.l qc-parse.y $(common_src)
|
qfcc_SOURCES= qc-lex.l qc-parse.y $(common_src)
|
||||||
qfcc_LDADD= $(QFCC_LIBS)
|
qfcc_LDADD= $(QFCC_LIBS)
|
||||||
|
|
|
@ -2446,6 +2446,20 @@ is_indirect (expr_t *e)
|
||||||
static inline int
|
static inline int
|
||||||
is_lvalue (expr_t *e)
|
is_lvalue (expr_t *e)
|
||||||
{
|
{
|
||||||
|
if (e->type == ex_symbol) {
|
||||||
|
switch (e->e.symbol->sy_type) {
|
||||||
|
case sy_var:
|
||||||
|
return 1;
|
||||||
|
case sy_const:
|
||||||
|
return 0;
|
||||||
|
case sy_type:
|
||||||
|
return 0;
|
||||||
|
case sy_expr:
|
||||||
|
return 0;
|
||||||
|
case sy_func:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (e->type == ex_def || e->type == ex_temp)
|
if (e->type == ex_def || e->type == ex_temp)
|
||||||
return 1;
|
return 1;
|
||||||
if (e->type == ex_expr && e->e.expr.op == '.')
|
if (e->type == ex_expr && e->e.expr.op == '.')
|
||||||
|
|
|
@ -59,6 +59,7 @@ static __attribute__ ((used)) const char rcsid[] =
|
||||||
#include "opcodes.h"
|
#include "opcodes.h"
|
||||||
#include "options.h"
|
#include "options.h"
|
||||||
#include "reloc.h"
|
#include "reloc.h"
|
||||||
|
#include "statements.h"
|
||||||
#include "symtab.h"
|
#include "symtab.h"
|
||||||
#include "type.h"
|
#include "type.h"
|
||||||
|
|
||||||
|
@ -600,48 +601,18 @@ finish_function (function_t *f)
|
||||||
void
|
void
|
||||||
emit_function (function_t *f, expr_t *e)
|
emit_function (function_t *f, expr_t *e)
|
||||||
{
|
{
|
||||||
int last_is_label = 0;
|
sblock_t *sblock;
|
||||||
dstatement_t *s;
|
statement_t *s;
|
||||||
#define DUMP_EXPR
|
|
||||||
#ifdef DUMP_EXPR
|
|
||||||
printf (" %s =\n", f->sym->name);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (f->aux)
|
printf ("%s\n", f->name);
|
||||||
lineno_base = f->aux->source_line;
|
sblock = make_statements (e);
|
||||||
|
for (/**/; sblock; sblock = sblock->next) {
|
||||||
while (f->var_init) {
|
printf ("block %p\n", sblock);
|
||||||
emit_expr (f->var_init);
|
for (s = sblock->statements; s; s = s->next) {
|
||||||
f->var_init = f->var_init->next;
|
printf (" ");
|
||||||
|
print_statement (s);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//FIXME current_scope = f->scope;
|
|
||||||
while (e) {
|
|
||||||
#ifdef DUMP_EXPR
|
|
||||||
printf ("%d ", pr.source_line);
|
|
||||||
print_expr (e);
|
|
||||||
puts("");
|
|
||||||
#endif
|
|
||||||
last_is_label = (e->type == ex_label);
|
|
||||||
emit_expr (e);
|
|
||||||
e = e->next;
|
|
||||||
}
|
|
||||||
s = &pr.code->code[pr.code->size - 1];
|
|
||||||
if (last_is_label
|
|
||||||
|| !(s->op == op_return->opcode
|
|
||||||
|| (op_return_v && s->op == op_return_v->opcode))) {
|
|
||||||
if (!options.traditional && op_return_v)
|
|
||||||
emit_statement (0, op_return_v, 0, 0, 0);
|
|
||||||
else
|
|
||||||
emit_statement (0, op_done, 0, 0, 0);
|
|
||||||
}
|
|
||||||
//FIXME flush_scope (current_scope, 0);
|
|
||||||
//FIXME current_scope = pr.scope;
|
|
||||||
reset_tempdefs ();
|
|
||||||
|
|
||||||
#ifdef DUMP_EXPR
|
|
||||||
puts ("");
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
|
|
@ -227,9 +227,9 @@ setup_data (pr_info_t *pr)
|
||||||
//FIXME write_def (d, def++, &reloc);
|
//FIXME write_def (d, def++, &reloc);
|
||||||
}
|
}
|
||||||
for (r = pr->relocs; r; r = r->next)
|
for (r = pr->relocs; r; r = r->next)
|
||||||
if (r->type == rel_def_op)
|
//FIXME if (r->type == rel_def_op)
|
||||||
write_one_reloc (r, &reloc, r->label->ofs);
|
//FIXME write_one_reloc (r, &reloc, r->label->ofs);
|
||||||
else
|
//FIXME else
|
||||||
write_one_reloc (r, &reloc, 0);
|
write_one_reloc (r, &reloc, 0);
|
||||||
for (st = pr->code->code; st - pr->code->code < pr->code->size; st++) {
|
for (st = pr->code->code; st - pr->code->code < pr->code->size; st++) {
|
||||||
st->op = LittleLong (st->op);
|
st->op = LittleLong (st->op);
|
||||||
|
|
|
@ -577,7 +577,7 @@ finish_compilation (void)
|
||||||
function_t *f;
|
function_t *f;
|
||||||
def_t *def;
|
def_t *def;
|
||||||
expr_t e;
|
expr_t e;
|
||||||
ex_label_t *l;
|
//FIXME ex_label_t *l;
|
||||||
dfunction_t *df;
|
dfunction_t *df;
|
||||||
|
|
||||||
// check to make sure all functions prototyped have code
|
// check to make sure all functions prototyped have code
|
||||||
|
@ -663,8 +663,8 @@ finish_compilation (void)
|
||||||
G_INT (ofs) = 0;
|
G_INT (ofs) = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (l = pr.labels; l; l = l->next)
|
//FIXME for (l = pr.labels; l; l = l->next)
|
||||||
relocate_refs (l->refs, l->ofs);
|
//FIXME relocate_refs (l->refs, l->ofs);
|
||||||
|
|
||||||
return !errors;
|
return !errors;
|
||||||
}
|
}
|
||||||
|
|
406
tools/qfcc/source/statements.c
Normal file
406
tools/qfcc/source/statements.c
Normal file
|
@ -0,0 +1,406 @@
|
||||||
|
/*
|
||||||
|
statements.c
|
||||||
|
|
||||||
|
Internal statements
|
||||||
|
|
||||||
|
Copyright (C) 2011 Bill Currie <bill@taniwha.org>
|
||||||
|
|
||||||
|
Author: Bill Currie <bill@taniwha.org>
|
||||||
|
Date: 2011/06/18
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
*/
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include "config.h"
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_STRING_H
|
||||||
|
# include <string.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_STRINGS_H
|
||||||
|
# include <strings.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "QF/va.h"
|
||||||
|
|
||||||
|
#include "expr.h"
|
||||||
|
#include "options.h"
|
||||||
|
#include "qc-parse.h"
|
||||||
|
#include "qfcc.h"
|
||||||
|
#include "statements.h"
|
||||||
|
#include "symtab.h"
|
||||||
|
#include "type.h"
|
||||||
|
|
||||||
|
static __attribute__ ((used)) const char rcsid[] = "$Id$";
|
||||||
|
|
||||||
|
static sblock_t *free_sblocks;
|
||||||
|
static statement_t *free_statements;
|
||||||
|
static operand_t *free_operands;
|
||||||
|
|
||||||
|
static sblock_t *
|
||||||
|
new_sblock (void)
|
||||||
|
{
|
||||||
|
sblock_t *sblock;
|
||||||
|
ALLOC (256, sblock_t, sblocks, sblock);
|
||||||
|
sblock->tail = &sblock->statements;
|
||||||
|
return sblock;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
sblock_add_statement (sblock_t *sblock, statement_t *statement)
|
||||||
|
{
|
||||||
|
// this should normally be null, but might be inserting
|
||||||
|
statement->next = *sblock->tail;
|
||||||
|
*sblock->tail = statement;
|
||||||
|
sblock->tail = &statement->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
static statement_t *
|
||||||
|
new_statement (const char *opcode)
|
||||||
|
{
|
||||||
|
statement_t *statement;
|
||||||
|
ALLOC (256, statement_t, statements, statement);
|
||||||
|
statement->opcode = save_string (opcode);
|
||||||
|
return statement;
|
||||||
|
}
|
||||||
|
|
||||||
|
static operand_t *
|
||||||
|
new_operand (op_type_e op)
|
||||||
|
{
|
||||||
|
operand_t *operand;
|
||||||
|
ALLOC (256, operand_t, operands, operand);
|
||||||
|
operand->type = op;
|
||||||
|
return operand;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *
|
||||||
|
convert_op (int op)
|
||||||
|
{
|
||||||
|
switch (op) {
|
||||||
|
case PAS: return ".=";
|
||||||
|
case OR: return "||";
|
||||||
|
case AND: return "&&";
|
||||||
|
case EQ: return "==";
|
||||||
|
case NE: return "!=";
|
||||||
|
case LE: return "<=";
|
||||||
|
case GE: return ">=";
|
||||||
|
case LT: return "<";
|
||||||
|
case GT: return ">";
|
||||||
|
case '=': return "=";
|
||||||
|
case '+': return "+";
|
||||||
|
case '-': return "-";
|
||||||
|
case '*': return "*";
|
||||||
|
case '/': return "/";
|
||||||
|
case '%': return "%";
|
||||||
|
case '&': return "&";
|
||||||
|
case '|': return "|";
|
||||||
|
case '^': return "^";
|
||||||
|
case '~': return "~";
|
||||||
|
case '!': return "!";
|
||||||
|
case SHL: return "<<";
|
||||||
|
case SHR: return ">>";
|
||||||
|
case '.': return ".";
|
||||||
|
case 'i': return "<IF>";
|
||||||
|
case 'n': return "<IFNOT>";
|
||||||
|
case IFBE: return "<IFBE>";
|
||||||
|
case IFB: return "<IFB>";
|
||||||
|
case IFAE: return "<IFAE>";
|
||||||
|
case IFA: return "<IFA>";
|
||||||
|
case 'C': return "=";
|
||||||
|
case 'M': return "<MOVE>";
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static sblock_t *statement_subexpr (sblock_t *sblock, expr_t *e,
|
||||||
|
operand_t **op);
|
||||||
|
|
||||||
|
static sblock_t *
|
||||||
|
statement_call (sblock_t *sblock, expr_t *call)
|
||||||
|
{
|
||||||
|
expr_t *func = call->e.expr.e1;
|
||||||
|
expr_t *args = call->e.expr.e2;
|
||||||
|
expr_t *a;
|
||||||
|
int count = 0;
|
||||||
|
const char *opcode;
|
||||||
|
const char *pref = "";
|
||||||
|
statement_t *s;
|
||||||
|
|
||||||
|
for (a = args; a; a = a->next)
|
||||||
|
count++;
|
||||||
|
if (count && options.code.progsversion != PROG_ID_VERSION)
|
||||||
|
pref = "R";
|
||||||
|
opcode = va ("<%sCALL%d>", pref, count);
|
||||||
|
s = new_statement (opcode);
|
||||||
|
sblock = statement_subexpr (sblock, func, &s->opa);
|
||||||
|
sblock_add_statement (sblock, s);
|
||||||
|
sblock->next = new_sblock ();
|
||||||
|
return sblock->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
static sblock_t *
|
||||||
|
statement_branch (sblock_t *sblock, expr_t *e)
|
||||||
|
{
|
||||||
|
statement_t *s = 0;
|
||||||
|
|
||||||
|
if (e->type == ex_uexpr && e->e.expr.op == 'g') {
|
||||||
|
s = new_statement ("<GOTO>");
|
||||||
|
s->opa = new_operand (op_label);
|
||||||
|
s->opa->o.label = &e->e.label;
|
||||||
|
}
|
||||||
|
|
||||||
|
sblock_add_statement (sblock, s);
|
||||||
|
sblock->next = new_sblock ();
|
||||||
|
return sblock->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
static sblock_t *
|
||||||
|
statement_subexpr (sblock_t *sblock, expr_t *e, operand_t **op)
|
||||||
|
{
|
||||||
|
statement_t *s;
|
||||||
|
const char *opcode;
|
||||||
|
|
||||||
|
if (!e) {
|
||||||
|
*op = 0;
|
||||||
|
return sblock;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (e->type) {
|
||||||
|
case ex_error:
|
||||||
|
case ex_state:
|
||||||
|
case ex_bool:
|
||||||
|
case ex_label:
|
||||||
|
case ex_block:
|
||||||
|
case ex_nil:
|
||||||
|
internal_error (e, 0);
|
||||||
|
case ex_expr:
|
||||||
|
switch (e->e.expr.op) {
|
||||||
|
case 'c':
|
||||||
|
sblock = statement_call (sblock, e);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
opcode = convert_op (e->e.expr.op);
|
||||||
|
if (!opcode)
|
||||||
|
internal_error (e, "ice ice baby");
|
||||||
|
s = new_statement (opcode);
|
||||||
|
sblock = statement_subexpr (sblock, e->e.expr.e1, &s->opa);
|
||||||
|
sblock = statement_subexpr (sblock, e->e.expr.e2, &s->opb);
|
||||||
|
*op = s->opc = new_operand (op_temp);
|
||||||
|
sblock_add_statement (sblock, s);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ex_uexpr:
|
||||||
|
break;
|
||||||
|
case ex_def:
|
||||||
|
case ex_symbol:
|
||||||
|
*op = new_operand (op_symbol);
|
||||||
|
(*op)->o.symbol = e->e.symbol;
|
||||||
|
break;
|
||||||
|
case ex_temp:
|
||||||
|
*op = new_operand (op_temp);
|
||||||
|
break;
|
||||||
|
case ex_value:
|
||||||
|
*op = new_operand (op_value);
|
||||||
|
(*op)->o.value = &e->e.value;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return sblock;
|
||||||
|
}
|
||||||
|
|
||||||
|
static sblock_t *
|
||||||
|
statement_expr (sblock_t *sblock, expr_t *e)
|
||||||
|
{
|
||||||
|
sblock_t *start = sblock;
|
||||||
|
statement_t *s;
|
||||||
|
expr_t *se;
|
||||||
|
const char *opcode;
|
||||||
|
|
||||||
|
for (/**/; e && e->type == ex_label; e = e->next)
|
||||||
|
e->e.label.dest = sblock;
|
||||||
|
for (/**/; e; e = e->next) {
|
||||||
|
switch (e->type) {
|
||||||
|
case ex_error:
|
||||||
|
break;
|
||||||
|
case ex_state:
|
||||||
|
s = new_statement ("<STATE>");
|
||||||
|
sblock = statement_subexpr (sblock, e->e.state.frame, &s->opa);
|
||||||
|
sblock = statement_subexpr (sblock, e->e.state.think, &s->opb);
|
||||||
|
sblock = statement_subexpr (sblock, e->e.state.step, &s->opc);
|
||||||
|
sblock_add_statement (sblock, s);
|
||||||
|
break;
|
||||||
|
case ex_bool:
|
||||||
|
break;
|
||||||
|
case ex_label:
|
||||||
|
sblock->next = new_sblock ();
|
||||||
|
sblock = sblock->next;
|
||||||
|
e->e.label.dest = sblock;
|
||||||
|
for (/**/; e->next && e->next->type == ex_label; e = e->next)
|
||||||
|
e->e.label.dest = sblock;
|
||||||
|
break;
|
||||||
|
case ex_block:
|
||||||
|
sblock->next = new_sblock ();
|
||||||
|
sblock = sblock->next;
|
||||||
|
for (se = e->e.block.head; se; se = se->next)
|
||||||
|
sblock = statement_expr (sblock, se);
|
||||||
|
break;
|
||||||
|
case ex_expr:
|
||||||
|
switch (e->e.expr.op) {
|
||||||
|
case 'c':
|
||||||
|
sblock = statement_call (sblock, e);
|
||||||
|
break;
|
||||||
|
case 'i':
|
||||||
|
case 'n':
|
||||||
|
case IFBE:
|
||||||
|
case IFB:
|
||||||
|
case IFAE:
|
||||||
|
case IFA:
|
||||||
|
opcode = convert_op (e->e.expr.op);
|
||||||
|
s = new_statement (opcode);
|
||||||
|
sblock = statement_subexpr (sblock, e->e.expr.e1,
|
||||||
|
&s->opa);
|
||||||
|
s->opb = new_operand (op_label);
|
||||||
|
s->opb->o.label = &e->e.label;
|
||||||
|
sblock_add_statement (sblock, s);
|
||||||
|
sblock->next = new_sblock ();
|
||||||
|
sblock = sblock->next;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (e->e.expr.op < 256)
|
||||||
|
notice (e, "e e %c", e->e.expr.op);
|
||||||
|
else
|
||||||
|
notice (e, "e e %d", e->e.expr.op);
|
||||||
|
goto non_executable;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ex_uexpr:
|
||||||
|
switch (e->e.expr.op) {
|
||||||
|
case 'r':
|
||||||
|
notice (e, "RETURN");
|
||||||
|
opcode = "<RETURN>";
|
||||||
|
if (!e->e.expr.e1 && !options.traditional)
|
||||||
|
opcode = "<RETURN_V>";
|
||||||
|
s = new_statement (opcode);
|
||||||
|
sblock = statement_subexpr (sblock, e->e.expr.e1,
|
||||||
|
&s->opa);
|
||||||
|
sblock_add_statement (sblock, s);
|
||||||
|
sblock->next = new_sblock ();
|
||||||
|
sblock = sblock->next;
|
||||||
|
case 'g':
|
||||||
|
sblock = statement_branch (sblock, e);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
notice (e, "e ue %d", e->e.expr.op);
|
||||||
|
goto non_executable;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ex_def:
|
||||||
|
case ex_symbol:
|
||||||
|
case ex_temp:
|
||||||
|
case ex_nil:
|
||||||
|
case ex_value:
|
||||||
|
notice (e, "e %d", e->type);
|
||||||
|
non_executable:
|
||||||
|
warning (e, "Non-executable statement;"
|
||||||
|
" executing programmer instead.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return start;
|
||||||
|
}
|
||||||
|
|
||||||
|
sblock_t *
|
||||||
|
make_statements (expr_t *e)
|
||||||
|
{
|
||||||
|
return statement_expr (new_sblock (), e);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
print_operand (operand_t *op)
|
||||||
|
{
|
||||||
|
switch (op->type) {
|
||||||
|
case op_symbol:
|
||||||
|
printf ("%s", op->o.symbol->name);
|
||||||
|
break;
|
||||||
|
case op_value:
|
||||||
|
switch (op->o.value->type) {
|
||||||
|
case ev_string:
|
||||||
|
printf ("\"%s\"", op->o.value->v.string_val);
|
||||||
|
break;
|
||||||
|
case ev_float:
|
||||||
|
printf ("%g", op->o.value->v.float_val);
|
||||||
|
break;
|
||||||
|
case ev_vector:
|
||||||
|
printf ("'%g", op->o.value->v.vector_val[0]);
|
||||||
|
printf (" %g", op->o.value->v.vector_val[1]);
|
||||||
|
printf (" %g'", op->o.value->v.vector_val[2]);
|
||||||
|
break;
|
||||||
|
case ev_quat:
|
||||||
|
printf ("'%g", op->o.value->v.quaternion_val[0]);
|
||||||
|
printf (" %g", op->o.value->v.quaternion_val[1]);
|
||||||
|
printf (" %g", op->o.value->v.quaternion_val[2]);
|
||||||
|
printf (" %g'", op->o.value->v.quaternion_val[3]);
|
||||||
|
break;
|
||||||
|
case ev_pointer:
|
||||||
|
printf ("(%s)[%d]",
|
||||||
|
pr_type_name[op->o.value->v.pointer.type->type],
|
||||||
|
op->o.value->v.pointer.val);
|
||||||
|
break;
|
||||||
|
case ev_field:
|
||||||
|
printf ("%d", op->o.value->v.pointer.val);
|
||||||
|
break;
|
||||||
|
case ev_entity:
|
||||||
|
case ev_func:
|
||||||
|
case ev_integer:
|
||||||
|
printf ("%d", op->o.value->v.integer_val);
|
||||||
|
break;
|
||||||
|
case ev_short:
|
||||||
|
printf ("%d", op->o.value->v.short_val);
|
||||||
|
break;
|
||||||
|
case ev_void:
|
||||||
|
case ev_invalid:
|
||||||
|
case ev_type_count:
|
||||||
|
internal_error (0, "weird value type");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case op_label:
|
||||||
|
printf ("%p", op->o.label->dest);
|
||||||
|
break;
|
||||||
|
case op_temp:
|
||||||
|
printf ("%p", op);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
print_statement (statement_t *s)
|
||||||
|
{
|
||||||
|
printf ("(%s, ", s->opcode);
|
||||||
|
if (s->opa)
|
||||||
|
print_operand (s->opa);
|
||||||
|
printf (", ");
|
||||||
|
if (s->opb)
|
||||||
|
print_operand (s->opb);
|
||||||
|
printf (", ");
|
||||||
|
if (s->opc)
|
||||||
|
print_operand (s->opc);
|
||||||
|
printf (")\n");
|
||||||
|
}
|
|
@ -26,7 +26,7 @@ scope_t *new_scope (scope_type type, defspace_t *space, scope_t *parent) {return
|
||||||
string_t ReuseString (const char *str) {return 0;}
|
string_t ReuseString (const char *str) {return 0;}
|
||||||
void encode_type (struct dstring_s *str, type_t *type) {}
|
void encode_type (struct dstring_s *str, type_t *type) {}
|
||||||
codespace_t *codespace_new (void) {return 0;}
|
codespace_t *codespace_new (void) {return 0;}
|
||||||
void codespace_addcode (codespace_t *codespace, struct statement_s *code, int size) {}
|
void codespace_addcode (codespace_t *codespace, struct dstatement_s *code, int size) {}
|
||||||
type_t *parse_type (const char *str) {return 0;}
|
type_t *parse_type (const char *str) {return 0;}
|
||||||
int function_parms (function_t *f, byte *parm_size) {return 0;}
|
int function_parms (function_t *f, byte *parm_size) {return 0;}
|
||||||
pr_auxfunction_t *new_auxfunction (void) {return 0;}
|
pr_auxfunction_t *new_auxfunction (void) {return 0;}
|
||||||
|
|
Loading…
Reference in a new issue