From ef2ad46f7a11874673fd37877083ef5a65e16cf7 Mon Sep 17 00:00:00 2001
From: Bill Currie <bill@taniwha.org>
Date: Mon, 7 Feb 2011 10:55:09 +0900
Subject: [PATCH] Convert complex types to a suitable low-level type.

This takes care of moving structures etc around.
---
 tools/qfcc/include/type.h      |  1 +
 tools/qfcc/source/statements.c | 13 +++++--------
 tools/qfcc/source/type.c       | 18 ++++++++++++++++++
 3 files changed, 24 insertions(+), 8 deletions(-)

diff --git a/tools/qfcc/include/type.h b/tools/qfcc/include/type.h
index d38bed8c7..2ad7c387c 100644
--- a/tools/qfcc/include/type.h
+++ b/tools/qfcc/include/type.h
@@ -116,6 +116,7 @@ extern struct symtab_s *quaternion_struct;
 
 struct dstring_s;
 
+etype_t low_level_type (type_t *type);
 type_t *new_type (void);
 void free_type (type_t *type);
 void chain_type (type_t *type);
diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c
index 94626c5fa..4838c382c 100644
--- a/tools/qfcc/source/statements.c
+++ b/tools/qfcc/source/statements.c
@@ -420,7 +420,7 @@ expr_deref (sblock_t *sblock, expr_t *e, operand_t **op)
 	if (e->type == ex_uexpr && e->e.expr.op == '&'
 		&& e->e.expr.e1->type == ex_symbol) {
 		*op = new_operand (op_symbol);
-		(*op)->type = type->type;
+		(*op)->type = low_level_type (type);
 		(*op)->o.symbol = e->e.expr.e1->e.symbol;
 	}
 	return sblock;
@@ -455,7 +455,7 @@ expr_expr (sblock_t *sblock, expr_t *e, operand_t **op)
 			sblock = statement_subexpr (sblock, e->e.expr.e2, &s->opb);
 			if (!*op) {
 				*op = new_operand (op_temp);
-				(*op)->type = e->e.expr.type->type;
+				(*op)->type = low_level_type (e->e.expr.type);
 			}
 			s->opc = *op;
 			sblock_add_statement (sblock, s);
@@ -469,7 +469,7 @@ expr_cast (sblock_t *sblock, expr_t *e, operand_t **op)
 {
 	if (!*op) {
 		(*op) = new_operand (op_temp);
-		(*op)->type = e->e.expr.type->type;
+		(*op)->type = low_level_type (e->e.expr.type);
 	}
 	sblock = statement_subexpr (sblock, e->e.expr.e1, op);
 	return sblock;
@@ -498,10 +498,7 @@ static sblock_t *
 expr_symbol (sblock_t *sblock, expr_t *e, operand_t **op)
 {
 	*op = new_operand (op_symbol);
-	if (is_enum (e->e.symbol->type))
-		(*op)->type = type_default->type;
-	else
-		(*op)->type = e->e.symbol->type->type;
+	(*op)->type = low_level_type (e->e.symbol->type);
 	(*op)->o.symbol = e->e.symbol;
 	return sblock;
 }
@@ -511,7 +508,7 @@ expr_temp (sblock_t *sblock, expr_t *e, operand_t **op)
 {
 	if (!e->e.temp.op) {
 		e->e.temp.op = new_operand (op_temp);
-		e->e.temp.op->type = e->e.temp.type->type;
+		e->e.temp.op->type = low_level_type (e->e.temp.type);
 	}
 	*op = e->e.temp.op;
 	return sblock;
diff --git a/tools/qfcc/source/type.c b/tools/qfcc/source/type.c
index 673ca7bca..41d83da87 100644
--- a/tools/qfcc/source/type.c
+++ b/tools/qfcc/source/type.c
@@ -88,6 +88,24 @@ type_t      type_floatfield = { ev_field, ".float", ty_none, {{&type_float}} };
 
 static type_t *free_types;
 
+etype_t
+low_level_type (type_t *type)
+{
+	if (type->type < 0 || type->type >= ev_type_count)
+		internal_error (0, "invalid type");
+	if (type->type == ev_type_count)
+		internal_error (0, "found 'type count' type");
+	if (type->type < ev_invalid)
+		return type->type;
+	if (is_enum (type))
+		return type_default->type;
+	if (is_struct (type) || is_class (type))
+		return ev_void;
+	if (is_array (type))
+		return ev_void;
+	internal_error (0, "invalid complex type");
+}
+
 void
 chain_type (type_t *type)
 {