mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-01-17 22:50:51 +00:00
pr_comp.h:
o add OP_JUMPB o OP_JUMPB renumberd some opcodes, so up PROG_VERSION pr_edict.c: o make the version error reporting more informative pr_exec.c: o implement OP_JUMPB (goto *(ptr + index)) pr_opcode.c: (libs/gamecode/engine) o add OP_JUMPB to the table expr.h: o ex_uinteger support o some const correctness o prototype new_label_expr qfcc.h: o uinteger ussport o add pointers for op_jump and op_jumpb o prototype PR_GetArray emit.c: o general uinteger support o new reference/reloc type 3: absolute statement address o jumpb support (binary goto) expr.c: o uinteger support o break the label name creation out of new_label_expr into new_label_name o some const correctness pr_def.c: o add PR_GetArray to allocate an array in global space o factor out some code common to PR_GetDef and PR_GetArray that would otherwise be duplicated pr_imm.c: o some const correctness o uinteger support pr_lex.c: o uinteger support pr_opcode.c: (tools/qfcc/source) o support jump and jumpb switch.c: o rewrite the binary search code to support ranges.
This commit is contained in:
parent
748dc49218
commit
07b59d2f07
13 changed files with 318 additions and 60 deletions
|
@ -211,6 +211,7 @@ typedef enum {
|
|||
OP_IFA,
|
||||
|
||||
OP_JUMP,
|
||||
OP_JUMPB,
|
||||
|
||||
OP_LT_UI,
|
||||
OP_GT_UI,
|
||||
|
@ -268,7 +269,7 @@ typedef struct
|
|||
|
||||
|
||||
#define PROG_ID_VERSION 6
|
||||
#define PROG_VERSION 0x00fff001 // MMmmmRRR 0.fff.001 (hex)
|
||||
#define PROG_VERSION 0x00fff002 // MMmmmRRR 0.fff.002 (hex)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
|
|
|
@ -1094,9 +1094,23 @@ PR_LoadProgsFile (progs_t * pr, const char *progsname)
|
|||
((int *) pr->progs)[i] = LittleLong (((int *) pr->progs)[i]);
|
||||
|
||||
if (pr->progs->version != PROG_VERSION
|
||||
&& pr->progs->version != PROG_ID_VERSION)
|
||||
PR_Error (pr, "%s has unrecognised version number (%08x)",
|
||||
progsname, pr->progs->version);
|
||||
&& pr->progs->version != PROG_ID_VERSION) {
|
||||
if (pr->progs->version < 0x00fff000) {
|
||||
PR_Error (pr, "%s has unrecognised version number (%d)",
|
||||
progsname, pr->progs->version);
|
||||
} else {
|
||||
PR_Error (pr,
|
||||
"%s has unrecognised version number (%02x.%03x.%03x)"
|
||||
" [%02x.%03x.%03x expected]",
|
||||
progsname,
|
||||
pr->progs->version >> 24,
|
||||
(pr->progs->version >> 12) & 0xfff,
|
||||
pr->progs->version & 0xfff,
|
||||
PROG_VERSION >> 24,
|
||||
(PROG_VERSION >> 12) & 0xfff,
|
||||
PROG_VERSION & 0xfff);
|
||||
}
|
||||
}
|
||||
|
||||
pr->progs_name = progsname; //XXX is this safe?
|
||||
|
||||
|
|
|
@ -623,6 +623,19 @@ PR_ExecuteProgram (progs_t * pr, func_t fnum)
|
|||
}
|
||||
st = &pr->pr_statements[OPA.uinteger_var];
|
||||
break;
|
||||
case OP_JUMPB:
|
||||
//FIXME put bounds checking in
|
||||
pointer = OPA.integer_var + OPB.integer_var;
|
||||
ptr = pr->pr_globals + pointer;
|
||||
pointer = ptr->integer_var;
|
||||
if (pr_boundscheck->int_val
|
||||
&& (pointer >= pr->progs->numstatements)) {
|
||||
pr->pr_xstatement = st - pr->pr_statements;
|
||||
PR_RunError (pr, "Invalid jump destination\n");
|
||||
return;
|
||||
}
|
||||
st = &pr->pr_statements[pointer];
|
||||
break;
|
||||
|
||||
case OP_CALL0:
|
||||
case OP_CALL1:
|
||||
|
|
|
@ -166,6 +166,7 @@ opcode_t pr_opcodes[] = {
|
|||
|
||||
{"<GOTO>", "goto", OP_GOTO, false, ev_integer, ev_void, ev_void, PROG_ID_VERSION},
|
||||
{"<JUMP>", "jump", OP_JUMP, false, ev_integer, ev_void, ev_void, PROG_VERSION},
|
||||
{"<JUMPB>", "jumpb", OP_JUMPB, false, ev_pointer, ev_integer, ev_void, PROG_VERSION},
|
||||
|
||||
{"&&", "and", OP_AND, false, ev_float, ev_float, ev_integer, PROG_ID_VERSION},
|
||||
{"||", "or", OP_OR, false, ev_float, ev_float, ev_integer, PROG_ID_VERSION},
|
||||
|
|
|
@ -16,12 +16,13 @@ typedef enum {
|
|||
ex_pointer,
|
||||
ex_quaternion,
|
||||
ex_integer,
|
||||
ex_uinteger,
|
||||
} expr_type;
|
||||
|
||||
typedef struct {
|
||||
statref_t *refs;
|
||||
dstatement_t *statement;
|
||||
char *name;
|
||||
const char *name;
|
||||
} elabel_t;
|
||||
|
||||
typedef struct {
|
||||
|
@ -56,7 +57,7 @@ typedef struct expr_s {
|
|||
def_t *def;
|
||||
temp_t temp;
|
||||
|
||||
char *string_val;
|
||||
const char *string_val;
|
||||
float float_val;
|
||||
float vector_val[3];
|
||||
int entity_val;
|
||||
|
@ -65,6 +66,7 @@ typedef struct expr_s {
|
|||
int pointer_val;
|
||||
float quaternion_val[4];
|
||||
int integer_val;
|
||||
int uinteger_val;
|
||||
} e;
|
||||
} expr_t;
|
||||
|
||||
|
@ -76,6 +78,7 @@ type_t *get_type (expr_t *e);
|
|||
etype_t extract_type (expr_t *e);
|
||||
|
||||
expr_t *new_expr (void);
|
||||
const char *new_label_name (void);
|
||||
expr_t *new_label_expr (void);
|
||||
expr_t *new_block_expr (void);
|
||||
expr_t *new_binary_expr (int op, expr_t *e1, expr_t *e2);
|
||||
|
|
|
@ -342,6 +342,7 @@ extern type_t type_pointer;
|
|||
extern type_t type_floatfield;
|
||||
extern type_t type_quaternion;
|
||||
extern type_t type_integer;
|
||||
extern type_t type_uinteger;
|
||||
|
||||
extern def_t def_void;
|
||||
extern def_t def_string;
|
||||
|
@ -353,6 +354,7 @@ extern def_t def_function;
|
|||
extern def_t def_pointer;
|
||||
extern def_t def_quaternion;
|
||||
extern def_t def_integer;
|
||||
extern def_t def_uinteger;
|
||||
|
||||
struct function_s
|
||||
{
|
||||
|
@ -397,6 +399,8 @@ extern opcode_t *op_ifae;
|
|||
extern opcode_t *op_ifa;
|
||||
extern opcode_t *op_state;
|
||||
extern opcode_t *op_goto;
|
||||
extern opcode_t *op_jump;
|
||||
extern opcode_t *op_jumpb;
|
||||
|
||||
statref_t *PR_NewStatref (dstatement_t *st, int field);
|
||||
void PR_AddStatementRef (def_t *def, dstatement_t *st, int field);
|
||||
|
@ -466,6 +470,9 @@ extern def_t *pr_scope;
|
|||
extern int pr_error_count;
|
||||
|
||||
void PR_NewLine (void);
|
||||
def_t *PR_GetArray (type_t *etype, const char *name, int size, def_t *scope,
|
||||
int *allocate);
|
||||
|
||||
def_t *PR_GetDef (type_t *type, const char *name, def_t *scope,
|
||||
int *allocate);
|
||||
def_t *PR_NewDef (type_t *type, const char *name, def_t *scope);
|
||||
|
|
|
@ -288,6 +288,7 @@ emit_sub_expr (expr_t *e, def_t *dest)
|
|||
case ex_pointer:
|
||||
case ex_quaternion:
|
||||
case ex_integer:
|
||||
case ex_uinteger:
|
||||
d = PR_ReuseConstant (e, 0);
|
||||
break;
|
||||
}
|
||||
|
@ -319,6 +320,9 @@ emit_expr (expr_t *e)
|
|||
case 2:
|
||||
ref->statement->c = label->statement - ref->statement;
|
||||
break;
|
||||
case 3:
|
||||
*(int*)ref->statement = label->statement - statements;
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
|
@ -366,6 +370,11 @@ emit_expr (expr_t *e)
|
|||
}
|
||||
e->e.expr.e2->e.temp.def = emit_sub_expr (e->e.expr.e1, e->e.expr.e2->e.temp.def);
|
||||
break;
|
||||
case 'g':
|
||||
def_a = emit_sub_expr (e->e.expr.e1, 0);
|
||||
def_b = emit_sub_expr (e->e.expr.e2, 0);
|
||||
emit_statement (e->line, op_jumpb, def_a, def_b, 0);
|
||||
break;
|
||||
default:
|
||||
warning (e, "Ignoring useless expression");
|
||||
break;
|
||||
|
@ -399,6 +408,7 @@ emit_expr (expr_t *e)
|
|||
case ex_pointer:
|
||||
case ex_quaternion:
|
||||
case ex_integer:
|
||||
case ex_uinteger:
|
||||
warning (e, "Ignoring useless expression");
|
||||
break;
|
||||
case ex_nil:
|
||||
|
|
|
@ -61,6 +61,7 @@ etype_t qc_types[] = {
|
|||
ev_pointer, // ex_pointer
|
||||
ev_quaternion, // ex_quaternion
|
||||
ev_integer, // ex_integer
|
||||
ev_uinteger, // ex_uinteger
|
||||
};
|
||||
|
||||
type_t *types[] = {
|
||||
|
@ -74,6 +75,7 @@ type_t *types[] = {
|
|||
&type_pointer,
|
||||
&type_quaternion,
|
||||
&type_integer,
|
||||
&type_uinteger,
|
||||
};
|
||||
|
||||
expr_type expr_types[] = {
|
||||
|
@ -87,6 +89,7 @@ expr_type expr_types[] = {
|
|||
ex_pointer, // ev_pointer
|
||||
ex_quaternion, // ev_quaternion
|
||||
ex_integer, // ev_integer
|
||||
ex_uinteger, // ev_uinteger
|
||||
};
|
||||
|
||||
type_t *
|
||||
|
@ -122,6 +125,7 @@ get_type (expr_t *e)
|
|||
case ex_func:
|
||||
case ex_pointer:
|
||||
case ex_quaternion:
|
||||
case ex_uinteger:
|
||||
return types[qc_types[e->type]];
|
||||
}
|
||||
return 0;
|
||||
|
@ -287,20 +291,27 @@ num_digits (int val)
|
|||
return num;
|
||||
}
|
||||
|
||||
expr_t *
|
||||
new_label_expr (void)
|
||||
const char *
|
||||
new_label_name (void)
|
||||
{
|
||||
static int label = 0;
|
||||
int lnum = ++label;
|
||||
const char *fname = current_func->def->name;
|
||||
int len = 1 + strlen (fname) + 1 + num_digits (lnum) + 1;
|
||||
char *lname = malloc (len);
|
||||
if (!lname)
|
||||
Sys_Error ("new_label_expr: Memory Allocation Failure\n");
|
||||
sprintf (lname, "$%s_%d", fname, lnum);
|
||||
return lname;
|
||||
}
|
||||
|
||||
expr_t *
|
||||
new_label_expr (void)
|
||||
{
|
||||
|
||||
expr_t *l = new_expr ();
|
||||
l->type = ex_label;
|
||||
l->e.label.name = malloc (len);
|
||||
if (!l->e.label.name)
|
||||
Sys_Error ("new_label_expr: Memory Allocation Failure\n");
|
||||
sprintf (l->e.label.name, "$%s_%d", fname, lnum);
|
||||
l->e.label.name = new_label_name ();
|
||||
return l;
|
||||
}
|
||||
|
||||
|
@ -482,7 +493,7 @@ do_op_string (int op, expr_t *e1, expr_t *e2)
|
|||
{
|
||||
int len;
|
||||
char *buf;
|
||||
char *s1, *s2;
|
||||
const char *s1, *s2;
|
||||
|
||||
s1 = e1->e.string_val ? e1->e.string_val : "";
|
||||
s2 = e2->e.string_val ? e2->e.string_val : "";
|
||||
|
|
|
@ -52,17 +52,10 @@ defs_get_key (void *_def, void *_tab)
|
|||
return "";
|
||||
}
|
||||
|
||||
/*
|
||||
PR_GetDef
|
||||
|
||||
If type is NULL, it will match any type
|
||||
If allocate is true, a new def will be allocated if it can't be found
|
||||
*/
|
||||
def_t *
|
||||
PR_GetDef (type_t *type, const char *name, def_t *scope, int *allocate)
|
||||
static def_t *
|
||||
check_for_name (type_t *type, const char *name, def_t *scope, int *allocate)
|
||||
{
|
||||
def_t *def;
|
||||
char element[MAX_NAME];
|
||||
|
||||
if (!defs_by_name) {
|
||||
defs_by_name = Hash_NewTable (16381, defs_get_key, 0, &defs_by_name);
|
||||
|
@ -77,9 +70,49 @@ PR_GetDef (type_t *type, const char *name, def_t *scope, int *allocate)
|
|||
if (!allocate || def->scope == scope)
|
||||
return def;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!allocate)
|
||||
return NULL;
|
||||
static inline type_t *
|
||||
find_type (type_t *type, type_t *aux_type)
|
||||
{
|
||||
type_t new;
|
||||
memset (&new, 0, sizeof (new));
|
||||
new.type = type->type;
|
||||
new.aux_type = aux_type;
|
||||
return PR_FindType (&new);
|
||||
}
|
||||
|
||||
def_t *
|
||||
PR_GetArray (type_t *etype, const char *name, int size, def_t *scope,
|
||||
int *allocate)
|
||||
{
|
||||
type_t *type = find_type (&type_pointer, etype);
|
||||
def_t *def = check_for_name (type, name, scope, allocate);
|
||||
if (def || !allocate)
|
||||
return def;
|
||||
def = PR_NewDef (type, name, scope);
|
||||
def->ofs = *allocate;
|
||||
*allocate += pr_type_size [type->type] * size + 1;
|
||||
pr_global_defs[def->ofs] = def;
|
||||
G_INT (def->ofs) = def->ofs + 1;
|
||||
return def;
|
||||
}
|
||||
|
||||
/*
|
||||
PR_GetDef
|
||||
|
||||
If type is NULL, it will match any type
|
||||
If allocate is true, a new def will be allocated if it can't be found
|
||||
*/
|
||||
def_t *
|
||||
PR_GetDef (type_t *type, const char *name, def_t *scope, int *allocate)
|
||||
{
|
||||
def_t *def = check_for_name (type, name, scope, allocate);
|
||||
char element[MAX_NAME];
|
||||
|
||||
if (def || !allocate)
|
||||
return def;
|
||||
|
||||
// allocate a new def
|
||||
def = PR_NewDef (type, name, scope);
|
||||
|
|
|
@ -87,7 +87,8 @@ def_t *
|
|||
PR_ReuseConstant (expr_t *expr, def_t *def)
|
||||
{
|
||||
def_t *cn = 0;
|
||||
char rep[60], *r = rep;
|
||||
char rep[60];
|
||||
const char *r = rep;
|
||||
hashtab_t *tab = 0;
|
||||
type_t *type;
|
||||
expr_t e = *expr;
|
||||
|
@ -131,13 +132,17 @@ PR_ReuseConstant (expr_t *expr, def_t *def)
|
|||
type = &type_pointer;
|
||||
break;
|
||||
case ex_integer:
|
||||
case ex_uinteger:
|
||||
if (!def || def->type != &type_float) {
|
||||
sprintf (rep, "\001integer:%08X\001", e.e.integer_val);
|
||||
tab = integer_imm_defs;
|
||||
type = &type_integer;
|
||||
break;
|
||||
}
|
||||
e.e.float_val = e.e.integer_val;
|
||||
if (e.type == ex_uinteger)
|
||||
e.e.float_val = e.e.uinteger_val;
|
||||
else
|
||||
e.e.float_val = e.e.integer_val;
|
||||
case ex_float:
|
||||
sprintf (rep, "\001float:%08X\001", e.e.integer_val);
|
||||
tab = float_imm_defs;
|
||||
|
|
|
@ -65,6 +65,7 @@ type_t type_function = { ev_func, &def_function, NULL, &type_void };
|
|||
type_t type_pointer = { ev_pointer, &def_pointer };
|
||||
type_t type_quaternion = { ev_quaternion, &def_quaternion };
|
||||
type_t type_integer = { ev_integer, &def_integer };
|
||||
type_t type_uinteger = { ev_uinteger, &def_uinteger };
|
||||
|
||||
type_t type_floatfield = { ev_field, &def_field, NULL, &type_float };
|
||||
|
||||
|
@ -78,6 +79,7 @@ def_t def_function = { &type_function, "temp" };
|
|||
def_t def_pointer = { &type_pointer, "temp" };
|
||||
def_t def_quaternion = { &type_quaternion, "temp"};
|
||||
def_t def_integer = { &type_integer, "temp"};
|
||||
def_t def_uinteger = { &type_uinteger, "temp"};
|
||||
|
||||
def_t def_ret, def_parms[MAX_PARMS];
|
||||
|
||||
|
|
|
@ -40,6 +40,8 @@ opcode_t *op_ifae;
|
|||
opcode_t *op_ifa;
|
||||
opcode_t *op_state;
|
||||
opcode_t *op_goto;
|
||||
opcode_t *op_jump;
|
||||
opcode_t *op_jumpb;
|
||||
|
||||
statref_t *
|
||||
PR_NewStatref (dstatement_t *st, int field)
|
||||
|
@ -167,6 +169,10 @@ PR_Opcode_Init_Tables (void)
|
|||
op_state = op;
|
||||
} else if (!strcmp (op->name, "<GOTO>")) {
|
||||
op_goto = op;
|
||||
} else if (!strcmp (op->name, "<JUMP>")) {
|
||||
op_jump = op;
|
||||
} else if (!strcmp (op->name, "<JUMPB>")) {
|
||||
op_jumpb = op;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,6 +38,14 @@ static const char rcsid[] =
|
|||
#include "scope.h"
|
||||
#include "qc-parse.h"
|
||||
|
||||
typedef struct case_node_s {
|
||||
expr_t *low;
|
||||
expr_t *high;
|
||||
expr_t **labels;
|
||||
expr_t *_label;
|
||||
struct case_node_s *left, *right;
|
||||
} case_node_t;
|
||||
|
||||
static unsigned long
|
||||
get_hash (void *_cl, void *unused)
|
||||
{
|
||||
|
@ -80,7 +88,6 @@ case_label_expr (switch_block_t *switch_block, expr_t *value)
|
|||
return 0;
|
||||
}
|
||||
cl->value = value;
|
||||
print_expr(value);puts("");
|
||||
if (Hash_FindElement (switch_block->labels, cl)) {
|
||||
error (value, "duplicate %s", value ? "case" : "default");
|
||||
free (cl);
|
||||
|
@ -128,18 +135,118 @@ label_compare (const void *_a, const void *_b)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
build_binary_jump_table (expr_t *sw, case_label_t **labels, int op, int base, int count, expr_t *sw_val, expr_t *temp, expr_t *default_label)
|
||||
static case_node_t *
|
||||
new_case_node (expr_t *low, expr_t *high)
|
||||
{
|
||||
case_node_t *node = malloc (sizeof (case_node_t));
|
||||
|
||||
if (!node)
|
||||
Sys_Error ("out of memory");
|
||||
node->low = low;
|
||||
node->high = high;
|
||||
if (low == high) {
|
||||
node->labels = &node->_label;
|
||||
node->_label = 0;
|
||||
} else {
|
||||
int size;
|
||||
if (low->type != ex_integer) {
|
||||
error (low, "switch: internal error");
|
||||
abort ();
|
||||
}
|
||||
size = high->e.integer_val - low->e.integer_val + 1;
|
||||
node->labels = calloc (size, sizeof (case_node_t *));
|
||||
}
|
||||
node->left = node->right = 0;
|
||||
return node;
|
||||
}
|
||||
|
||||
static case_node_t *
|
||||
balance_case_tree (case_node_t **nodes, int base, int count)
|
||||
{
|
||||
case_node_t *node;
|
||||
int index = count / 2;
|
||||
|
||||
if (!count)
|
||||
return 0;
|
||||
|
||||
node = nodes[base + index];
|
||||
|
||||
node->left = balance_case_tree (nodes, base, index);
|
||||
|
||||
base += index + 1;
|
||||
count -= index + 1;
|
||||
node->right = balance_case_tree (nodes, base, count);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
static case_node_t *
|
||||
build_case_tree (case_label_t **labels, int count)
|
||||
{
|
||||
case_node_t **nodes;
|
||||
int i, j, k;
|
||||
int num_nodes = 0;
|
||||
|
||||
qsort (labels, count, sizeof (*labels), label_compare);
|
||||
|
||||
nodes = (case_node_t **) malloc (count * sizeof (case_node_t*));
|
||||
if (!nodes)
|
||||
Sys_Error ("out of memory");
|
||||
|
||||
if (labels[0]->value->type == ex_integer) {
|
||||
for (i = 0; i < count - 1; i = j, num_nodes++) {
|
||||
for (j = i + 1; j < count; j++) {
|
||||
if (labels[j]->value->e.integer_val
|
||||
- labels[j - 1]->value->e.integer_val > 1)
|
||||
break;
|
||||
}
|
||||
nodes[num_nodes] = new_case_node (labels[i]->value,
|
||||
labels[j - 1]->value);
|
||||
for (k = i; k < j; k++)
|
||||
nodes[num_nodes]->labels[labels[k]->value->e.integer_val
|
||||
- labels[i]->value->e.integer_val]
|
||||
= labels[k]->label;
|
||||
}
|
||||
if (i < count) {
|
||||
nodes[num_nodes] = new_case_node (labels[i]->value,
|
||||
labels[i]->value);
|
||||
nodes[num_nodes]->labels[0] = labels[i]->label;
|
||||
num_nodes++;
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < count; i++, num_nodes++) {
|
||||
nodes[num_nodes] = new_case_node (labels[i]->value,
|
||||
labels[i]->value);
|
||||
nodes[num_nodes]->labels[0] = labels[i]->label;
|
||||
}
|
||||
}
|
||||
return balance_case_tree (nodes, 0, num_nodes);
|
||||
}
|
||||
|
||||
static void
|
||||
build_switch (expr_t *sw, case_node_t *tree, int op, expr_t *sw_val,
|
||||
expr_t *temp, expr_t *default_label)
|
||||
{
|
||||
case_label_t *l;
|
||||
expr_t *test;
|
||||
expr_t *branch;
|
||||
int index;
|
||||
expr_t *high_label = default_label;
|
||||
expr_t *low_label = default_label;
|
||||
|
||||
index = count / 2;
|
||||
l = labels [base + index];
|
||||
if (!tree)
|
||||
return;
|
||||
|
||||
test = binary_expr (op, l->value, sw_val);
|
||||
if (tree->right) {
|
||||
high_label = new_label_expr ();
|
||||
high_label->line = sw_val->line;
|
||||
high_label->file = sw_val->file;
|
||||
}
|
||||
if (tree->left) {
|
||||
low_label = new_label_expr ();
|
||||
low_label->line = sw_val->line;
|
||||
low_label->file = sw_val->file;
|
||||
}
|
||||
|
||||
test = binary_expr (op, sw_val, tree->low);
|
||||
test->line = sw_val->line;
|
||||
test->file = sw_val->file;
|
||||
|
||||
|
@ -147,37 +254,81 @@ build_binary_jump_table (expr_t *sw, case_label_t **labels, int op, int base, in
|
|||
test->line = sw_val->line;
|
||||
test->file = sw_val->file;
|
||||
|
||||
branch = new_binary_expr ('n', test, l->label);
|
||||
branch->line = sw_val->line;
|
||||
branch->file = sw_val->file;
|
||||
append_expr (sw, branch);
|
||||
|
||||
if (index) {
|
||||
expr_t *high_label;
|
||||
|
||||
if (count - (index + 1)) {
|
||||
high_label = new_label_expr ();
|
||||
high_label->line = sw_val->line;
|
||||
high_label->file = sw_val->file;
|
||||
} else {
|
||||
high_label = default_label;
|
||||
}
|
||||
branch = new_binary_expr (IFA, temp, high_label);
|
||||
if (tree->low == tree->high) {
|
||||
printf ("%3d\n", tree->low->e.integer_val);
|
||||
branch = new_binary_expr ('n', test, tree->labels[0]);
|
||||
branch->line = sw_val->line;
|
||||
branch->file = sw_val->file;
|
||||
append_expr (sw, branch);
|
||||
|
||||
build_binary_jump_table (sw, labels, op, base, index, sw_val, temp, default_label);
|
||||
if (tree->left) {
|
||||
branch = new_binary_expr (IFA, temp, high_label);
|
||||
branch->line = sw_val->line;
|
||||
branch->file = sw_val->file;
|
||||
append_expr (sw, branch);
|
||||
|
||||
if (count - (index + 1))
|
||||
build_switch (sw, tree->left, op, sw_val, temp, default_label);
|
||||
|
||||
if (tree->right)
|
||||
append_expr (sw, high_label);
|
||||
}
|
||||
if (tree->right)
|
||||
build_switch (sw, tree->right, op, sw_val, temp, default_label);
|
||||
} else {
|
||||
expr_t *utemp = new_temp_def_expr (&type_uinteger);
|
||||
int low = tree->low->e.integer_val;
|
||||
int high = tree->high->e.integer_val;
|
||||
def_t *def;
|
||||
expr_t *table = new_expr ();
|
||||
const char *name = new_label_name ();
|
||||
int i;
|
||||
expr_t *range = binary_expr ('-', tree->high, tree->low);
|
||||
|
||||
printf ("%3d %3d\n", low, high);
|
||||
|
||||
def = PR_GetArray (&type_uinteger, name, high - low + 1, 0,
|
||||
&numpr_globals);
|
||||
table->type = ex_def;
|
||||
table->e.def = def;
|
||||
|
||||
append_expr (sw, test);
|
||||
|
||||
if (tree->left) {
|
||||
branch = new_binary_expr (IFB, temp, low_label);
|
||||
branch->line = sw_val->line;
|
||||
branch->file = sw_val->file;
|
||||
append_expr (sw, branch);
|
||||
}
|
||||
tree->high->type = ex_uinteger;
|
||||
append_expr (sw, new_binary_expr ('b', temp, utemp));
|
||||
test = binary_expr (GT, utemp, range);
|
||||
test->line = sw_val->line;
|
||||
test->file = sw_val->file;
|
||||
branch = new_binary_expr ('i', test, high_label);
|
||||
branch->line = sw_val->line;
|
||||
branch->file = sw_val->file;
|
||||
append_expr (sw, branch);
|
||||
branch = new_binary_expr ('g', table, temp);
|
||||
branch->line = sw_val->line;
|
||||
branch->file = sw_val->file;
|
||||
append_expr (sw, branch);
|
||||
if (tree->left) {
|
||||
append_expr (sw, low_label);
|
||||
build_switch (sw, tree->left, op, sw_val, temp, default_label);
|
||||
}
|
||||
if (tree->right) {
|
||||
append_expr (sw, high_label);
|
||||
build_switch (sw, tree->right, op, sw_val, temp, default_label);
|
||||
}
|
||||
for (i = 0; i <= high - low; i++) {
|
||||
dstatement_t *st;
|
||||
statref_t *ref;
|
||||
st = (dstatement_t *) &pr_globals[G_INT (def->ofs) + i];
|
||||
ref = PR_NewStatref (st, 3);
|
||||
ref->next = tree->labels[i]->e.label.refs;
|
||||
tree->labels[i]->e.label.refs = ref;
|
||||
}
|
||||
}
|
||||
|
||||
base += index + 1;
|
||||
count -= index + 1;
|
||||
|
||||
if (count)
|
||||
build_binary_jump_table (sw, labels, op, base, count, sw_val, temp, default_label);
|
||||
}
|
||||
|
||||
struct expr_s *
|
||||
|
@ -229,12 +380,13 @@ switch_expr (switch_block_t *switch_block, expr_t *break_label,
|
|||
} else {
|
||||
expr_t *temp;
|
||||
int op;
|
||||
case_node_t *case_tree;
|
||||
|
||||
if (type == &type_string)
|
||||
temp = new_temp_def_expr (&type_integer);
|
||||
else
|
||||
temp = new_temp_def_expr (type);
|
||||
qsort (labels, num_labels, sizeof (*labels), label_compare);
|
||||
case_tree = build_case_tree (labels, num_labels);
|
||||
switch (type->type) {
|
||||
case ev_string:
|
||||
op = NE;
|
||||
|
@ -249,7 +401,7 @@ switch_expr (switch_block_t *switch_block, expr_t *break_label,
|
|||
error (0, "internal compiler error in switch");
|
||||
abort ();
|
||||
}
|
||||
build_binary_jump_table (sw, labels, op, 0, num_labels, sw_val, temp, default_label->label);
|
||||
build_switch (sw, case_tree, op, sw_val, temp, default_label->label);
|
||||
}
|
||||
append_expr (sw, default_expr);
|
||||
append_expr (sw, statements);
|
||||
|
|
Loading…
Reference in a new issue