Support assigning non-constant vector expressions.

This commit is contained in:
Bill Currie 2018-10-12 22:05:17 +09:00
parent e03dfa29b4
commit 78e0a8dc52
17 changed files with 536 additions and 253 deletions

View file

@ -171,7 +171,8 @@ typedef struct {
typedef struct ex_value_s {
struct ex_value_s *next;
struct daglabel_s *daglabel;///< dag label for this value
etype_t type;
struct type_s *type;
etype_t lltype;
union {
const char *string_val; ///< string constant
float float_val; ///< float constant

View file

@ -155,10 +155,13 @@ int is_enum (const type_t *type) __attribute__((pure));
int is_integral (const type_t *type) __attribute__((pure));
int is_float (const type_t *type) __attribute__((pure));
int is_scalar (const type_t *type) __attribute__((pure));
int is_vector (const type_t *type) __attribute__((pure));
int is_quaternion (const type_t *type) __attribute__((pure));
int is_math (const type_t *type) __attribute__((pure));
int is_pointer (const type_t *type) __attribute__((pure));
int is_struct (const type_t *type) __attribute__((pure));
int is_array (const type_t *type) __attribute__((pure));
int is_func (const type_t *type) __attribute__((pure));
int type_assignable (const type_t *dst, const type_t *src);
int type_size (const type_t *type) __attribute__((pure));

View file

@ -41,7 +41,8 @@ bin_SCRIPTS= qfpreqcc
common_src=\
class.c codespace.c constfold.c cpp.c dags.c debug.c def.c defspace.c \
diagnostic.c dot.c dot_dag.c dot_expr.c dot_flow.c dot_sblock.c emit.c \
expr.c expr_binary.c flow.c function.c grab.c idstuff.c linker.c method.c \
expr.c expr_assign.c expr_binary.c flow.c function.c grab.c idstuff.c \
linker.c method.c \
obj_file.c \
obj_type.c opcodes.c options.c pragma.c qfcc.c reloc.c shared.c \
statements.c strpool.c struct.c switch.c symtab.c type.c value.c

View file

@ -140,7 +140,7 @@ convert_to_float (expr_t *e)
switch (e->type) {
case ex_value:
switch (e->e.value->type) {
switch (e->e.value->lltype) {
case ev_integer:
convert_int (e);
return e;

View file

@ -356,7 +356,7 @@ dagnode_set_edges (dag_t *dag, dagnode_t *n)
if (node != child && node != n)
set_add (node->edges, n->number);
if (op->op_type == op_value
&& op->o.value->type == ev_pointer
&& op->o.value->lltype == ev_pointer
&& op->o.value->v.pointer.def)
def_visit_all (op->o.value->v.pointer.def, 1,
dagnode_set_edges_visit, n);

View file

@ -350,7 +350,7 @@ init_elements (struct def_s *def, expr_t *eles)
reloc_def_op (c->e.labelref.label, &loc);
continue;
} else if (c->type == ex_value) {
if (c->e.value->type == ev_integer
if (c->e.value->lltype == ev_integer
&& elements[i].type->type == ev_float)
convert_int (c);
if (get_type (c) != elements[i].type) {
@ -372,7 +372,7 @@ init_elements (struct def_s *def, expr_t *eles)
} else {
if (c->type != ex_value)
internal_error (c, "bogus expression type in init_elements()");
if (c->e.value->type == ev_string) {
if (c->e.value->lltype == ev_string) {
EMIT_STRING (def->space, g->string_var,
c->e.value->v.string_val);
} else {
@ -407,7 +407,7 @@ init_vector_components (symbol_t *vector_sym, int is_field)
expr = sym->s.expr;
if (is_field) {
if (expr->type != ex_value
|| expr->e.value->type != ev_field) {
|| expr->e.value->lltype != ev_field) {
error (0, "%s redefined", name);
sym = 0;
} else {
@ -574,8 +574,8 @@ initialize_def (symbol_t *sym, type_t *type, expr_t *init, defspace_t *space,
error (0, "non-constant initializier");
return;
}
if (init->e.value->type == ev_pointer
|| init->e.value->type == ev_field) {
if (init->e.value->lltype == ev_pointer
|| init->e.value->lltype == ev_field) {
// FIXME offset pointers
D_INT (sym->s.def) = init->e.value->v.pointer.val;
if (init->e.value->v.pointer.def)
@ -584,7 +584,7 @@ initialize_def (symbol_t *sym, type_t *type, expr_t *init, defspace_t *space,
ex_value_t *v = init->e.value;
if (is_scalar (sym->type))
v = convert_value (v, sym->type);
if (v->type == ev_string) {
if (v->lltype == ev_string) {
EMIT_STRING (sym->s.def->space, D_STRING (sym->s.def),
v->v.string_val);
} else {

View file

@ -386,7 +386,7 @@ print_value (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next)
type_t *type;
const char *label = "?!?";
switch (e->e.value->type) {
switch (e->e.value->lltype) {
case ev_string:
label = va ("\\\"%s\\\"", quote_string (e->e.value->v.string_val));
break;

View file

@ -159,6 +159,13 @@ convert_vector (expr_t *e)
val[2] = expr_float(z);
return new_vector_expr (val);
}
// at least one of x, y, z is not constant, so rebuild the
// list incase any of them are new expressions
z->next = 0;
y->next = z;
x->next = y;
e->e.vector.list = x;
return e;
}
if (e->e.vector.type == &type_quaternion) {
// guaranteed to have two or four elements
@ -180,6 +187,14 @@ convert_vector (expr_t *e)
val[3] = expr_float(w);
return new_quaternion_expr (val);
}
// at least one of x, y, z, w is not constant, so rebuild the
// list incase any of them are new expressions
w->next = 0;
z->next = w;
y->next = z;
x->next = y;
e->e.vector.list = x;
return e;
} else {
// v, s
expr_t *v = e->e.vector.list;
@ -192,7 +207,7 @@ convert_vector (expr_t *e)
val[3] = expr_float (s);
return new_quaternion_expr (val);
}
// Either v or is is not constant, so can't convert to a quaternion
// Either v or s is not constant, so can't convert to a quaternion
// constant.
// Rebuild the list in case v or s is a new expression
s->next = 0;
@ -233,17 +248,7 @@ get_type (expr_t *e)
case ex_temp:
return e->e.temp.type;
case ex_value:
if (e->e.value->type == ev_func)
return e->e.value->v.func_val.type;
if (e->e.value->type == ev_pointer)
return pointer_type (e->e.value->v.pointer.type);
if (e->e.value->type == ev_field)
return field_type (e->e.value->v.pointer.type);
if (e->e.value->type == ev_integer
&& options.code.progsversion == PROG_ID_VERSION) {
convert_int (e);
}
return ev_types[e->e.value->type];
return e->e.value->type;
case ex_vector:
return e->e.vector.type;
}
@ -801,7 +806,7 @@ is_string_val (expr_t *e)
{
if (e->type == ex_nil)
return 1;
if (e->type == ex_value && e->e.value->type == ev_string)
if (e->type == ex_value && e->e.value->lltype == ev_string)
return 1;
if (e->type == ex_symbol && e->e.symbol->sy_type == sy_const
&& e->e.symbol->type->type == ev_string)
@ -814,7 +819,7 @@ expr_string (expr_t *e)
{
if (e->type == ex_nil)
return 0;
if (e->type == ex_value && e->e.value->type == ev_string)
if (e->type == ex_value && e->e.value->lltype == ev_string)
return e->e.value->v.string_val;
internal_error (e, "not a string constant");
}
@ -824,7 +829,7 @@ is_float_val (expr_t *e)
{
if (e->type == ex_nil)
return 1;
if (e->type == ex_value && e->e.value->type == ev_float)
if (e->type == ex_value && e->e.value->lltype == ev_float)
return 1;
if (e->type == ex_symbol && e->e.symbol->sy_type == sy_const
&& e->e.symbol->type->type == ev_float)
@ -837,7 +842,7 @@ expr_float (expr_t *e)
{
if (e->type == ex_nil)
return 0;
if (e->type == ex_value && e->e.value->type == ev_float)
if (e->type == ex_value && e->e.value->lltype == ev_float)
return e->e.value->v.float_val;
if (e->type == ex_symbol && e->e.symbol->sy_type == sy_const
&& e->e.symbol->type->type == ev_float)
@ -854,7 +859,7 @@ is_vector_val (expr_t *e)
{
if (e->type == ex_nil)
return 1;
if (e->type == ex_value && e->e.value->type == ev_vector)
if (e->type == ex_value && e->e.value->lltype == ev_vector)
return 1;
if (e->type == ex_symbol && e->e.symbol->sy_type == sy_const
&& e->e.symbol->type->type == ev_vector)
@ -867,7 +872,7 @@ expr_vector (expr_t *e)
{
if (e->type == ex_nil)
return vec3_origin;
if (e->type == ex_value && e->e.value->type == ev_vector)
if (e->type == ex_value && e->e.value->lltype == ev_vector)
return e->e.value->v.vector_val;
if (e->type == ex_symbol && e->e.symbol->sy_type == sy_const
&& e->e.symbol->type->type == ev_vector)
@ -884,7 +889,7 @@ is_quaternion_val (expr_t *e)
{
if (e->type == ex_nil)
return 1;
if (e->type == ex_value && e->e.value->type == ev_quat)
if (e->type == ex_value && e->e.value->lltype == ev_quat)
return 1;
if (e->type == ex_symbol && e->e.symbol->sy_type == sy_const
&& e->e.symbol->type->type == ev_quat)
@ -897,7 +902,7 @@ expr_quaternion (expr_t *e)
{
if (e->type == ex_nil)
return quat_origin;
if (e->type == ex_value && e->e.value->type == ev_quat)
if (e->type == ex_value && e->e.value->lltype == ev_quat)
return e->e.value->v.quaternion_val;
if (e->type == ex_symbol && e->e.symbol->sy_type == sy_const
&& e->e.symbol->type->type == ev_quat)
@ -914,7 +919,7 @@ is_integer_val (expr_t *e)
{
if (e->type == ex_nil)
return 1;
if (e->type == ex_value && e->e.value->type == ev_integer)
if (e->type == ex_value && e->e.value->lltype == ev_integer)
return 1;
if (e->type == ex_symbol && e->e.symbol->sy_type == sy_const
&& (e->e.symbol->type->type == ev_integer
@ -928,7 +933,7 @@ expr_integer (expr_t *e)
{
if (e->type == ex_nil)
return 0;
if (e->type == ex_value && e->e.value->type == ev_integer)
if (e->type == ex_value && e->e.value->lltype == ev_integer)
return e->e.value->v.integer_val;
if (e->type == ex_symbol && e->e.symbol->sy_type == sy_const
&& (e->e.symbol->type->type == ev_integer
@ -946,7 +951,7 @@ expr_uinteger (expr_t *e)
{
if (e->type == ex_nil)
return 0;
if (e->type == ex_value && e->e.value->type == ev_uinteger)
if (e->type == ex_value && e->e.value->lltype == ev_uinteger)
return e->e.value->v.uinteger_val;
if (e->type == ex_symbol && e->e.symbol->sy_type == sy_const
&& e->e.symbol->type->type == ev_uinteger)
@ -963,7 +968,7 @@ is_short_val (expr_t *e)
{
if (e->type == ex_nil)
return 1;
if (e->type == ex_value && e->e.value->type == ev_short)
if (e->type == ex_value && e->e.value->lltype == ev_short)
return 1;
if (e->type == ex_symbol && e->e.symbol->sy_type == sy_const
&& e->e.symbol->type->type == ev_short)
@ -976,7 +981,7 @@ expr_short (expr_t *e)
{
if (e->type == ex_nil)
return 0;
if (e->type == ex_value && e->e.value->type == ev_short)
if (e->type == ex_value && e->e.value->lltype == ev_short)
return e->e.value->v.short_val;
if (e->type == ex_symbol && e->e.symbol->sy_type == sy_const
&& e->e.symbol->type->type == ev_short)
@ -1172,7 +1177,8 @@ field_expr (expr_t *e1, expr_t *e2)
}
def = sym->s.def;
e2 = new_field_expr (0, field->type, def);
} else if (e2->type != ex_value || e2->e.value->type != ev_field) {
} else if (e2->type != ex_value
|| e2->e.value->lltype != ev_field) {
internal_error (e2, "unexpected field exression");
}
e2->e.value = new_field_val (e2->e.value->v.pointer.val + field->s.offset, field->type, e2->e.value->v.pointer.def);
@ -2215,7 +2221,7 @@ address_expr (expr_t *e1, expr_t *e2, type_t *t)
if (e2) {
if (e2->type == ex_error)
return e2;
if (e->type == ex_value && e->e.value->type == ev_pointer
if (e->type == ex_value && e->e.value->lltype == ev_pointer
&& is_short_val (e2)) {
e->e.value = new_pointer_val (e->e.value->v.pointer.val + expr_short (e2), t, e->e.value->v.pointer.def);
} else {
@ -2479,24 +2485,6 @@ think_expr (symbol_t *think_sym)
return new_symbol_expr (think_sym);
}
static __attribute__((pure)) int
is_indirect (expr_t *e)
{
if (e->type == ex_block && e->e.block.result)
return is_indirect (e->e.block.result);
if (e->type == ex_expr && e->e.expr.op == '.')
return 1;
if (!(e->type == ex_uexpr && e->e.expr.op == '.'))
return 0;
e = e->e.expr.e1;
if (e->type != ex_value || e->e.value->type != ev_pointer
|| !(POINTER_VAL (e->e.value->v.pointer) >= 0
&& POINTER_VAL (e->e.value->v.pointer) < 65536)) {
return 1;
}
return 0;
}
static inline __attribute__((pure)) int
is_lvalue (expr_t *e)
{
@ -2527,150 +2515,6 @@ is_lvalue (expr_t *e)
return 0;
}
expr_t *
assign_expr (expr_t *e1, expr_t *e2)
{
int op = '=';
type_t *t1, *t2, *type;
expr_t *e;
convert_name (e1);
convert_name (e2);
e2 = convert_vector (e2);
if (e1->type == ex_error)
return e1;
if (e2->type == ex_error)
return e2;
e1 = fold_constants (e1);
e2 = fold_constants (e2);
if (options.traditional) {
if (e2->type == ex_expr && !e2->paren
&& (e2->e.expr.op == AND || e2->e.expr.op == OR)) {
notice (e2, "precedence of `%s' and `%s' inverted for "
"traditional code", get_op_string (op),
get_op_string (e2->e.expr.op));
e1 = assign_expr (e1, e2->e.expr.e1);
e1->paren = 1;
return binary_expr (e2->e.expr.op, e1, e2->e.expr.e2);
}
}
if (!is_lvalue (e1)) {
if (options.traditional)
warning (e1, "invalid lvalue in assignment");
else
return error (e1, "invalid lvalue in assignment");
}
t1 = get_type (e1);
t2 = get_type (e2);
if (!t1 || !t2)
internal_error (e1, 0);
//XXX func = func ???
if (t1->type == ev_pointer && is_array (t2)) {
e2 = address_expr (e2, 0, t2->t.fldptr.type);
t2 = get_type (e2);
}
if (e2->type == ex_bool)
e2 = convert_from_bool (e2, t1);
if (t1->type != ev_void && e2->type == ex_nil) {
t2 = t1;
convert_nil (e2, t2);
}
e2->rvalue = 1;
if (!type_assignable (t1, t2)) {
if (options.traditional) {
if (t1->type == ev_func && t2->type == ev_func) {
warning (e1, "assignment between disparate function types");
} else if (t1->type == ev_float && t2->type == ev_vector) {
warning (e1, "assignment of vector to float");
e2 = field_expr (e2, new_name_expr ("x"));
} else if (t1->type == ev_vector && t2->type == ev_float) {
warning (e1, "assignment of float to vector");
e1 = field_expr (e1, new_name_expr ("x"));
} else {
return type_mismatch (e1, e2, op);
}
} else {
return type_mismatch (e1, e2, op);
}
}
type = t1;
if (is_indirect (e1) && is_indirect (e2)) {
if (is_struct (get_type (e2))) {
e1 = address_expr (e1, 0, 0);
e2 = address_expr (e2, 0, 0);
e = new_move_expr (e1, e2, t2, 1);
} else {
expr_t *temp = new_temp_def_expr (t1);
e = new_block_expr ();
append_expr (e, assign_expr (temp, e2));
append_expr (e, assign_expr (e1, temp));
e->e.block.result = temp;
}
return e;
} else if (is_indirect (e1)) {
if (is_struct (get_type (e1))) {
e1 = address_expr (e1, 0, 0);
e2 = address_expr (e2, 0, 0);
return new_move_expr (e1, e2, t1, 1);
}
if (e1->type == ex_expr) {
if (get_type (e1->e.expr.e1) == &type_entity) {
type = e1->e.expr.type;
e1->e.expr.type = pointer_type (type);
e1->e.expr.op = '&';
}
op = PAS;
} else {
e = e1->e.expr.e1;
if ((e->type != ex_value || e->e.value->type != ev_pointer)
|| !(POINTER_VAL (e->e.value->v.pointer) > 0
&& POINTER_VAL (e->e.value->v.pointer) < 65536)) {
e1 = e;
op = PAS;
}
}
} else if (is_indirect (e2)) {
if (is_struct (get_type (e1))) {
e1 = address_expr (e1, 0, 0);
e2 = address_expr (e2, 0, 0);
e2->rvalue = 1;
return new_move_expr (e1, e2, t2, 1);
}
if (e2->type == ex_uexpr) {
e = e2->e.expr.e1;
if ((e->type != ex_value || e->e.value->type != ev_pointer)
|| !(POINTER_VAL (e->e.value->v.pointer) > 0
&& POINTER_VAL (e->e.value->v.pointer) < 65536)) {
if (e->type == ex_expr && e->e.expr.op == '&'
&& e->e.expr.type->type == ev_pointer
&& !is_constant (e)) {
e2 = e;
e2->e.expr.op = '.';
e2->e.expr.type = t2;
e2->rvalue = 1;
}
}
}
}
if (is_struct (get_type (e1))) {
return new_move_expr (e1, e2, get_type (e1), 0);
}
if (!type)
internal_error (e1, 0);
e = new_binary_expr (op, e1, e2);
e->e.expr.type = type;
return e;
}
expr_t *
cast_expr (type_t *type, expr_t *e)
{

View file

@ -0,0 +1,396 @@
/*
expr_assign.c
assignment expression construction and manipulations
Copyright (C) 2001 Bill Currie <bill@taniwha.org>
Author: Bill Currie <bill@taniwha.org>
Date: 2001/06/15
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/alloc.h"
#include "QF/dstring.h"
#include "QF/mathlib.h"
#include "QF/sys.h"
#include "QF/va.h"
#include "qfcc.h"
#include "class.h"
#include "def.h"
#include "defspace.h"
#include "diagnostic.h"
#include "emit.h"
#include "expr.h"
#include "function.h"
#include "idstuff.h"
#include "method.h"
#include "options.h"
#include "reloc.h"
#include "shared.h"
#include "strpool.h"
#include "struct.h"
#include "symtab.h"
#include "type.h"
#include "value.h"
#include "qc-parse.h"
static expr_t *
check_assign_logic_precedence (expr_t *dst, expr_t *src)
{
if (src->type == ex_expr && !src->paren && is_logic (src->e.expr.op)) {
// traditional QuakeC gives = higher precedence than && and ||
expr_t *assignment;
notice (src, "precedence of `=' and `%s' inverted for "
"traditional code", get_op_string (src->e.expr.op));
// change {a = (b logic c)} to {(a = b) logic c}
assignment = assign_expr (dst, src->e.expr.e1);
assignment->paren = 1; // protect assignment from binary_expr
return binary_expr (src->e.expr.op, assignment, src->e.expr.e2);
}
return 0;
}
static expr_t *
check_valid_lvalue (expr_t *expr)
{
switch (expr->type) {
case ex_symbol:
switch (expr->e.symbol->sy_type) {
case sy_var:
return 0;
case sy_const:
break;
case sy_type:
break;
case sy_expr:
break;
case sy_func:
break;
case sy_class:
break;
}
break;
case ex_temp:
return 0;
case ex_expr:
if (expr->e.expr.op == '.') {
return 0;
}
break;
case ex_uexpr:
if (expr->e.expr.op == '.') {
return 0;
}
if (expr->e.expr.op == 'A') {
return check_valid_lvalue (expr->e.expr.e1);
}
break;
case ex_state:
case ex_bool:
case ex_label:
case ex_labelref:
case ex_block:
case ex_vector:
case ex_nil:
case ex_value:
case ex_error:
break;
}
if (options.traditional) {
warning (expr, "invalid lvalue in assignment");
return 0;
}
return error (expr, "invalid lvalue in assignment");
}
static expr_t *
check_types_compatible (expr_t *dst, expr_t *src)
{
type_t *dst_type = get_type (dst);
type_t *src_type = get_type (src);
if (type_assignable (dst_type, src_type)) {
return 0;
}
// traditional qcc is a little sloppy
if (!options.traditional) {
return type_mismatch (dst, src, '=');
}
if (is_func (dst_type) && is_func (src_type)) {
warning (dst, "assignment between disparate function types");
return 0;
}
if (is_float (dst_type) && is_vector (src_type)) {
warning (dst, "assignment of vector to float");
src = field_expr (src, new_name_expr ("x"));
return assign_expr (dst, src);
}
if (is_vector (dst_type) && is_float (src_type)) {
warning (dst, "assignment of float to vector");
dst = field_expr (dst, new_name_expr ("x"));
return assign_expr (dst, src);
}
return type_mismatch (dst, src, '=');
}
static expr_t *
assign_vector_expr (expr_t *dst, expr_t *src)
{
expr_t *dx, *sx;
expr_t *dy, *sy;
expr_t *dz, *sz;
expr_t *dw, *sw;
expr_t *ds, *ss;
expr_t *dv, *sv;
expr_t *block;
if (src->type == ex_vector) {
src = convert_vector (src);
if (src->type != ex_vector) {
// src was constant and thus converted
return assign_expr (dst, src);
}
}
if (src->type == ex_vector && dst->type != ex_vector) {
if (src->e.vector.type == &type_vector) {
// guaranteed to have three elements
sx = src->e.vector.list;
sy = sx->next;
sz = sy->next;
dx = field_expr (dst, new_name_expr ("x"));
dy = field_expr (dst, new_name_expr ("y"));
dz = field_expr (dst, new_name_expr ("z"));
block = new_block_expr ();
append_expr (block, assign_expr (dx, sx));
append_expr (block, assign_expr (dy, sy));
append_expr (block, assign_expr (dz, sz));
block->e.block.result = dst;
return block;
}
if (src->e.vector.type == &type_quaternion) {
// guaranteed to have two or four elements
if (src->e.vector.list->next->next) {
// four vals: x, y, z, w
sx = src->e.vector.list;
sy = sx->next;
sz = sy->next;
sw = sz->next;
dx = field_expr (dst, new_name_expr ("x"));
dy = field_expr (dst, new_name_expr ("y"));
dz = field_expr (dst, new_name_expr ("z"));
dw = field_expr (dst, new_name_expr ("w"));
block = new_block_expr ();
append_expr (block, assign_expr (dx, sx));
append_expr (block, assign_expr (dy, sy));
append_expr (block, assign_expr (dz, sz));
append_expr (block, assign_expr (dw, sw));
block->e.block.result = dst;
return block;
} else {
// v, s
sv = src->e.vector.list;
ss = sv->next;
dv = field_expr (dst, new_name_expr ("v"));
ds = field_expr (dst, new_name_expr ("s"));
block = new_block_expr ();
append_expr (block, assign_expr (dv, sv));
append_expr (block, assign_expr (ds, ss));
block->e.block.result = dst;
return block;
}
}
internal_error (src, "bogus vector expression");
}
return 0;
}
static __attribute__((pure)) int
is_const_ptr (expr_t *e)
{
if ((e->type != ex_value || e->e.value->lltype != ev_pointer)
|| !(POINTER_VAL (e->e.value->v.pointer) > 0
&& POINTER_VAL (e->e.value->v.pointer) < 65536)) {
return 1;
}
return 0;
}
static __attribute__((pure)) int
is_indirect (expr_t *e)
{
if (e->type == ex_block && e->e.block.result)
return is_indirect (e->e.block.result);
if (e->type == ex_expr && e->e.expr.op == '.')
return 1;
if (!(e->type == ex_uexpr && e->e.expr.op == '.'))
return 0;
return is_const_ptr (e->e.expr.e1);
}
expr_t *
aassign_expr (expr_t *dst, expr_t *src);
expr_t *
assign_expr (expr_t *dst, expr_t *src)
{
int op = '=';
expr_t *expr;
type_t *dst_type, *src_type;
convert_name (dst);
convert_name (src);
if (dst->type == ex_error) {
return dst;
}
if (src->type == ex_error) {
return src;
}
if (options.traditional
&& (expr = check_assign_logic_precedence (dst, src))) {
return expr;
}
dst = fold_constants (dst);
src = fold_constants (src);
if ((expr = check_valid_lvalue (dst))) {
return expr;
}
dst_type = get_type (dst);
src_type = get_type (src);
if (!dst_type) {
internal_error (dst, "dst_type broke in assign_expr");
}
if (!src_type) {
internal_error (src, "src_type broke in assign_expr");
}
if (is_pointer (dst_type) && is_array (src_type)) {
// assigning an array to a pointer is the same as taking the address of
// the array but using the type of the array elements
src = address_expr (src, 0, src_type->t.fldptr.type);
src_type = get_type (src);
}
if (src->type == ex_bool) {
src = convert_from_bool (src, dst_type);
if (src->type == ex_error) {
return src;
}
src_type = get_type (src);
}
if (!is_void (dst_type) && src->type == ex_nil) {
// nil is a type-agnostic 0
// FIXME: assignment to compound types? error or memset?
src_type = dst_type;
convert_nil (src, src_type);
}
if ((expr = check_types_compatible (dst, src))) {
// expr might be a valid expression, but if so, check_types_compatible
// will take care of everything
return expr;
}
if ((expr = assign_vector_expr (dst, src))) {
return expr;
}
if (is_indirect (dst) && is_indirect (src)) {
debug (dst, "here");
if (is_struct (src_type)) {
dst = address_expr (dst, 0, 0);
src = address_expr (src, 0, 0);
expr = new_move_expr (dst, src, src_type, 1);
} else {
expr_t *temp = new_temp_def_expr (dst_type);
expr = new_block_expr ();
append_expr (expr, assign_expr (temp, src));
append_expr (expr, assign_expr (dst, temp));
expr->e.block.result = temp;
}
return expr;
} else if (is_indirect (dst)) {
debug (dst, "here");
if (is_struct (dst_type)) {
dst = address_expr (dst, 0, 0);
src = address_expr (src, 0, 0);
return new_move_expr (dst, src, dst_type, 1);
}
if (dst->type == ex_expr) {
if (get_type (dst->e.expr.e1) == &type_entity) {
dst_type = dst->e.expr.type;
dst->e.expr.type = pointer_type (dst_type);
dst->e.expr.op = '&';
}
op = PAS;
} else {
if (is_const_ptr (dst->e.expr.e1)) {
dst = dst->e.expr.e1;
op = PAS;
}
}
} else if (is_indirect (src)) {
debug (dst, "here");
if (is_struct (dst_type)) {
dst = address_expr (dst, 0, 0);
src = address_expr (src, 0, 0);
src->rvalue = 1;
return new_move_expr (dst, src, src_type, 1);
}
if (src->type == ex_uexpr) {
expr = src->e.expr.e1;
if (is_const_ptr (expr)) {
if (expr->type == ex_expr && expr->e.expr.op == '&'
&& expr->e.expr.type->type == ev_pointer
&& !is_constant (expr)) {
src = expr;
src->e.expr.op = '.';
src->e.expr.type = src_type;
src->rvalue = 1;
}
}
}
}
if (is_struct (dst_type)) {
return new_move_expr (dst, src, dst_type, 0);
}
expr = new_binary_expr (op, dst, src);
expr->e.expr.type = dst_type;
return expr;
}

View file

@ -830,7 +830,7 @@ flow_analyze_statement (statement_t *s, set_t *use, set_t *def, set_t *kill,
} else if (!strcmp (s->opcode, "<MOVEP>")) {
flow_add_op_var (use, s->opc);
if (s->opc->op_type == op_value
&& s->opc->o.value->type == ev_pointer
&& s->opc->o.value->lltype == ev_pointer
&& s->opc->o.value->v.pointer.def) {
operand_t *op;
ex_pointer_t *ptr = &s->opc->o.value->v.pointer;

View file

@ -428,8 +428,10 @@ qfo_write (qfo_t *qfo, const char *filename)
QFile *file;
file = Qopen (filename, options.gzip ? "wbz9" : "wb");
if (!file)
if (!file) {
perror (va ("failed to open %s for writing", filename));
return -1;
}
size = sizeof (qfo_header_t);
size += sizeof (qfo_space_t) * qfo->num_spaces;

View file

@ -396,9 +396,12 @@ compile_to_obj (const char *file, const char *obj, lang_t lang)
qfo_t *qfo;
class_finish_module ();
qfo = qfo_from_progs (&pr);
err = qfo_write (qfo, obj);
qfo_delete (qfo);
err = pr.error_count;
if (!err) {
qfo = qfo_from_progs (&pr);
err = qfo_write (qfo, obj);
qfo_delete (qfo);
}
}
return err;
}

View file

@ -83,7 +83,7 @@ operand_string (operand_t *op)
case op_def:
return op->o.def->name;
case op_value:
switch (op->o.value->type) {
switch (op->o.value->lltype) {
case ev_string:
return va ("\"%s\"",
quote_string (op->o.value->v.string_val));
@ -154,7 +154,7 @@ print_operand (operand_t *op)
break;
case op_value:
printf ("(%s) ", pr_type_name[op->type]);
switch (op->o.value->type) {
switch (op->o.value->lltype) {
case ev_string:
printf ("\"%s\"", op->o.value->v.string_val);
break;
@ -316,7 +316,7 @@ value_operand (ex_value_t *value)
{
operand_t *op;
op = new_operand (op_value);
op->type = value->type;
op->type = value->lltype;
op->o.value = value;
return op;
}
@ -337,8 +337,11 @@ alias_operand (etype_t type, operand_t *op)
{
operand_t *aop;
if (pr_type_size[type] != pr_type_size[op->type])
internal_error (0, "aliasing operand with type of diffent size");
if (pr_type_size[type] != pr_type_size[op->type]) {
internal_error (0, "\naliasing operand with type of diffent size"
" (%d, %d)", pr_type_size[type],
pr_type_size[op->type]);
}
aop = new_operand (op_alias);
aop->o.alias = op;
aop->type = type;
@ -659,7 +662,7 @@ expr_call (sblock_t *sblock, expr_t *call, operand_t **op)
pref = "R";
sblock = statement_subexpr (sblock, param, &arguments[ind]);
if (options.code.vector_calls && a->type == ex_value
&& a->e.value->type == ev_vector)
&& a->e.value->lltype == ev_vector)
sblock = vector_call (sblock, a, param, ind, &arguments[ind]);
else
sblock = statement_subexpr (sblock, a, &arguments[ind]);
@ -673,7 +676,7 @@ expr_call (sblock_t *sblock, expr_t *call, operand_t **op)
sblock = statement_slist (sblock, mov);
} else {
if (options.code.vector_calls && a->type == ex_value
&& a->e.value->type == ev_vector) {
&& a->e.value->lltype == ev_vector) {
sblock = vector_call (sblock, a, param, ind, 0);
} else {
operand_t *p = 0;
@ -774,7 +777,7 @@ expr_deref (sblock_t *sblock, expr_t *deref, operand_t **op)
s->opc = *op;
sblock_add_statement (sblock, s);
}
} else if (e->type == ex_value && e->e.value->type == ev_pointer) {
} else if (e->type == ex_value && e->e.value->lltype == ev_pointer) {
ex_pointer_t *ptr = &e->e.value->v.pointer;
*op = def_operand (alias_def (ptr->def, ptr->type, ptr->val),
ptr->type);
@ -1017,7 +1020,7 @@ statement_subexpr (sblock_t *sblock, expr_t *e, operand_t **op)
if (e->type > ex_value)
internal_error (e, "bad expression type");
if (!sfuncs[e->type])
internal_error (e, "unexpected expression type; %s",
internal_error (e, "unexpected expression type: %s",
expr_names[e->type]);
sblock = sfuncs[e->type] (sblock, e, op);

View file

@ -82,7 +82,7 @@ get_hash (const void *_cl, void *unused)
if (!cl->value)
return 0;
val = get_value (cl->value);
return Hash_Buffer (&val->v, sizeof (val->v)) + val->type;
return Hash_Buffer (&val->v, sizeof (val->v)) + val->lltype;
}
static int

View file

@ -681,6 +681,18 @@ is_scalar (const type_t *type)
return is_float (type) || is_integral (type);
}
int
is_vector (const type_t *type)
{
return type->type == ev_vector;
}
int
is_quaternion (const type_t *type)
{
return type->type == ev_quat;
}
int
is_math (const type_t *type)
{
@ -714,6 +726,14 @@ is_array (const type_t *type)
return 0;
}
int
is_func (const type_t *type)
{
if (type->type == ev_func)
return 1;
return 0;
}
int
type_assignable (const type_t *dst, const type_t *src)
{

View file

@ -79,7 +79,7 @@ static uintptr_t
value_get_hash (const void *_val, void *unused)
{
const ex_value_t *val = (const ex_value_t *) _val;
return Hash_Buffer (&val->v, sizeof (val->v)) + val->type;
return Hash_Buffer (&val->v, sizeof (val->v)) + val->lltype;
}
static int
@ -87,7 +87,7 @@ value_compare (const void *_val1, const void *_val2, void *unused)
{
const ex_value_t *val1 = (const ex_value_t *) _val1;
const ex_value_t *val2 = (const ex_value_t *) _val2;
if (val1->type != val2->type)
if (val1->lltype != val2->lltype)
return 0;
return memcmp (&val1->v, &val2->v, sizeof (val1->v)) == 0;
}
@ -100,6 +100,13 @@ new_value (void)
return value;
}
static void
set_val_type (ex_value_t *val, type_t *type)
{
val->type = type;
val->lltype = low_level_type (type);
}
static ex_value_t *
find_value (const ex_value_t *val)
{
@ -119,7 +126,7 @@ new_string_val (const char *string_val)
{
ex_value_t val;
memset (&val, 0, sizeof (val));
val.type = ev_string;
set_val_type (&val, &type_string);
if (string_val)
val.v.string_val = save_string (string_val);
return find_value (&val);
@ -130,7 +137,7 @@ new_float_val (float float_val)
{
ex_value_t val;
memset (&val, 0, sizeof (val));
val.type = ev_float;
set_val_type (&val, &type_float);
val.v.float_val = float_val;
return find_value (&val);
}
@ -140,7 +147,7 @@ new_vector_val (const float *vector_val)
{
ex_value_t val;
memset (&val, 0, sizeof (val));
val.type = ev_vector;
set_val_type (&val, &type_vector);
VectorCopy (vector_val, val.v.vector_val);
return find_value (&val);
}
@ -150,7 +157,7 @@ new_entity_val (int entity_val)
{
ex_value_t val;
memset (&val, 0, sizeof (val));
val.type = ev_entity;
set_val_type (&val, &type_entity);
val.v.entity_val = entity_val;
return find_value (&val);
}
@ -160,7 +167,7 @@ new_field_val (int field_val, type_t *type, def_t *def)
{
ex_value_t val;
memset (&val, 0, sizeof (val));
val.type = ev_field;
set_val_type (&val, field_type (type));
val.v.pointer.val = field_val;
val.v.pointer.type = type;
val.v.pointer.def = def;
@ -172,7 +179,7 @@ new_func_val (int func_val, type_t *type)
{
ex_value_t val;
memset (&val, 0, sizeof (val));
val.type = ev_func;
set_val_type (&val, type);
val.v.func_val.val = func_val;
val.v.func_val.type = type;
return find_value (&val);
@ -183,7 +190,7 @@ new_pointer_val (int pointer_val, type_t *type, def_t *def)
{
ex_value_t val;
memset (&val, 0, sizeof (val));
val.type = ev_pointer;
set_val_type (&val, pointer_type (type));
val.v.pointer.val = pointer_val;
val.v.pointer.type = type;
val.v.pointer.def = def;
@ -195,7 +202,7 @@ new_quaternion_val (const float *quaternion_val)
{
ex_value_t val;
memset (&val, 0, sizeof (val));
val.type = ev_quat;
set_val_type (&val, &type_quaternion);
QuatCopy (quaternion_val, val.v.quaternion_val);
return find_value (&val);
}
@ -205,7 +212,7 @@ new_integer_val (int integer_val)
{
ex_value_t val;
memset (&val, 0, sizeof (val));
val.type = ev_integer;
set_val_type (&val, &type_integer);
val.v.integer_val = integer_val;
return find_value (&val);
}
@ -215,7 +222,7 @@ new_uinteger_val (int uinteger_val)
{
ex_value_t val;
memset (&val, 0, sizeof (val));
val.type = ev_uinteger;
set_val_type (&val, &type_uinteger);
val.v.uinteger_val = uinteger_val;
return find_value (&val);
}
@ -225,7 +232,7 @@ new_short_val (short short_val)
{
ex_value_t val;
memset (&val, 0, sizeof (val));
val.type = ev_short;
set_val_type (&val, &type_short);
val.v.short_val = short_val;
return find_value (&val);
}
@ -235,10 +242,13 @@ new_nil_val (type_t *type)
{
ex_value_t val;
memset (&val, 0, sizeof (val));
val.type = low_level_type (type);
if (val.type == ev_pointer|| val.type == ev_field )
set_val_type (&val, type);
if (val.lltype == ev_void) {
val.lltype = type_nil->type;
}
if (val.lltype == ev_pointer || val.lltype == ev_field )
val.v.pointer.type = type->t.fldptr.type;
if (val.type == ev_func)
if (val.lltype == ev_func)
val.v.func_val.type = type;
return find_value (&val);
}
@ -333,13 +343,13 @@ ReuseString (const char *str)
static float
value_as_float (ex_value_t *value)
{
if (value->type == ev_uinteger)
if (value->lltype == ev_uinteger)
return value->v.uinteger_val;
if (value->type == ev_integer)
if (value->lltype == ev_integer)
return value->v.integer_val;
if (value->type == ev_short)
if (value->lltype == ev_short)
return value->v.short_val;
if (value->type == ev_float)
if (value->lltype == ev_float)
return value->v.float_val;
return 0;
}
@ -347,13 +357,13 @@ value_as_float (ex_value_t *value)
static int
value_as_int (ex_value_t *value)
{
if (value->type == ev_uinteger)
if (value->lltype == ev_uinteger)
return value->v.uinteger_val;
if (value->type == ev_integer)
if (value->lltype == ev_integer)
return value->v.integer_val;
if (value->type == ev_short)
if (value->lltype == ev_short)
return value->v.short_val;
if (value->type == ev_float)
if (value->lltype == ev_float)
return value->v.float_val;
return 0;
}
@ -361,13 +371,13 @@ value_as_int (ex_value_t *value)
static unsigned
value_as_uint (ex_value_t *value)
{
if (value->type == ev_uinteger)
if (value->lltype == ev_uinteger)
return value->v.uinteger_val;
if (value->type == ev_integer)
if (value->lltype == ev_integer)
return value->v.integer_val;
if (value->type == ev_short)
if (value->lltype == ev_short)
return value->v.short_val;
if (value->type == ev_float)
if (value->lltype == ev_float)
return value->v.float_val;
return 0;
}
@ -375,7 +385,7 @@ value_as_uint (ex_value_t *value)
ex_value_t *
convert_value (ex_value_t *value, type_t *type)
{
if (!is_scalar (type) || !is_scalar (ev_types[value->type])) {
if (!is_scalar (type) || !is_scalar (ev_types[value->lltype])) {
error (0, "unable to convert non-scalar value");
return value;
}
@ -400,12 +410,12 @@ alias_value (ex_value_t *value, type_t *type)
{
ex_value_t new;
if (type_size (type) != type_size (ev_types[value->type])) {
if (type_size (type) != type_size (ev_types[value->lltype])) {
error (0, "unable to alias different sized values");
return value;
}
new = *value;
new.type = type->type;
set_val_type (&new, type);
return find_value (&new);
}
@ -436,9 +446,9 @@ emit_value (ex_value_t *value, def_t *def)
clear_immediates ();
}
cn = 0;
if (val.type == ev_void)
val.type = type_nil->type;
switch (val.type) {
// if (val.type == ev_void)
// val.type = type_nil->type;
switch (val.lltype) {
case ev_entity:
tab = entity_imm_defs;
type = &type_entity;
@ -463,7 +473,7 @@ emit_value (ex_value_t *value, def_t *def)
break;
}
val.v.float_val = val.v.integer_val;
val.type = ev_float;
val.lltype = ev_float;
case ev_float:
tab = float_imm_defs;
type = &type_float;
@ -528,7 +538,7 @@ emit_value (ex_value_t *value, def_t *def)
cn->initialized = cn->constant = 1;
cn->nosave = 1;
// copy the immediate to the global area
switch (val.type) {
switch (val.lltype) {
case ev_string:
reloc_def_string (cn);
break;

View file

@ -43,7 +43,7 @@ test_format ()
printf ("q = [[5, 6, 7], 8] -> %v, %g\n", q.v, q.s);
fail = 1;
}
/* q = [s, v];
q = [s, v];
if (q.x != v.x || q.y != v.y || q.z != v.z || q.w != s) {
printf ("q = [s, v] -> %q (%v)\n", q, v);
fail = 1;
@ -60,7 +60,7 @@ test_format ()
if (q.v != v || q.s != s) {
printf ("q = [v, s] -> %v, %g (%v %s)\n", q.v, q.s, v, s);
fail = 1;
}*/
}
return fail;
}