]> git.rm.cloudns.org Git - xonotic/gmqcc.git/commitdiff
Preparing to parse arrays: adding TYPE_ARRAY and union/struct TYPE_ constants to...
authorWolfgang (Blub) Bumiller <blub@speed.at>
Sat, 10 Nov 2012 18:35:52 +0000 (19:35 +0100)
committerWolfgang (Blub) Bumiller <blub@speed.at>
Sun, 11 Nov 2012 09:13:01 +0000 (10:13 +0100)
ast.h
gmqcc.h
ir.c
parser.c

diff --git a/ast.h b/ast.h
index ffad71052805b881f93b15104921675f724af979..76f2c26d5596e703219b1543e348b9a0d776d035 100644 (file)
--- a/ast.h
+++ b/ast.h
@@ -116,6 +116,8 @@ typedef struct
     ast_expression_codegen *codegen;
     int                     vtype;
     ast_expression         *next;
+    /* arrays get a member-count */
+    size_t                  count;
     MEM_VECTOR_MAKE(ast_value*, params);
     bool                    variadic;
     /* The codegen functions should store their output values
diff --git a/gmqcc.h b/gmqcc.h
index bf9f63f062eed0b826009320f98c52ca25628bfc..01ebd4a7b02a4fcdc5822d8fcc9a49105d2c2412 100644 (file)
--- a/gmqcc.h
+++ b/gmqcc.h
@@ -290,6 +290,9 @@ enum {
     TYPE_POINTER  ,
     TYPE_INTEGER  ,
     TYPE_VARIANT  ,
+    TYPE_STRUCT   ,
+    TYPE_UNION    ,
+    TYPE_ARRAY    ,
 
     TYPE_COUNT
 };
diff --git a/ir.c b/ir.c
index 940cfbb6fb050d943fa36cf3088a1d6ccd5ddfe6..7af6162d524876a290ee1ff6a1edd0cd279b8323 100644 (file)
--- a/ir.c
+++ b/ir.c
@@ -38,10 +38,11 @@ const char *type_name[TYPE_COUNT] = {
     "field",
     "function",
     "pointer",
-#if 0
     "integer",
-#endif
-    "variant"
+    "variant",
+    "struct",
+    "union",
+    "array"
 };
 
 size_t type_sizeof[TYPE_COUNT] = {
@@ -53,10 +54,11 @@ size_t type_sizeof[TYPE_COUNT] = {
     1, /* TYPE_FIELD    */
     1, /* TYPE_FUNCTION */
     1, /* TYPE_POINTER  */
-#if 0
     1, /* TYPE_INTEGER  */
-#endif
     3, /* TYPE_VARIANT  */
+    0, /* TYPE_STRUCT   */
+    0, /* TYPE_UNION    */
+    0, /* TYPE_ARRAY    */
 };
 
 uint16_t type_store_instr[TYPE_COUNT] = {
@@ -70,9 +72,15 @@ uint16_t type_store_instr[TYPE_COUNT] = {
     INSTR_STORE_ENT, /* should use I */
 #if 0
     INSTR_STORE_I, /* integer type */
+#else
+    INSTR_STORE_F,
 #endif
 
     INSTR_STORE_V, /* variant, should never be accessed */
+
+    AINSTR_END, /* struct */
+    AINSTR_END, /* union  */
+    AINSTR_END, /* array  */
 };
 
 uint16_t field_store_instr[TYPE_COUNT] = {
@@ -86,9 +94,15 @@ uint16_t field_store_instr[TYPE_COUNT] = {
     INSTR_STORE_FLD,
 #if 0
     INSTR_STORE_FLD, /* integer type */
+#else
+    INSTR_STORE_FLD,
 #endif
 
     INSTR_STORE_V, /* variant, should never be accessed */
+
+    AINSTR_END, /* struct */
+    AINSTR_END, /* union  */
+    AINSTR_END, /* array  */
 };
 
 uint16_t type_storep_instr[TYPE_COUNT] = {
@@ -102,9 +116,15 @@ uint16_t type_storep_instr[TYPE_COUNT] = {
     INSTR_STOREP_ENT, /* should use I */
 #if 0
     INSTR_STOREP_ENT, /* integer type */
+#else
+    INSTR_STOREP_F,
 #endif
 
     INSTR_STOREP_V, /* variant, should never be accessed */
+
+    AINSTR_END, /* struct */
+    AINSTR_END, /* union  */
+    AINSTR_END, /* array  */
 };
 
 uint16_t type_eq_instr[TYPE_COUNT] = {
@@ -118,9 +138,15 @@ uint16_t type_eq_instr[TYPE_COUNT] = {
     INSTR_EQ_E, /* should use I */
 #if 0
     INSTR_EQ_I,
+#else
+    INSTR_EQ_F,
 #endif
 
     INSTR_EQ_V, /* variant, should never be accessed */
+
+    AINSTR_END, /* struct */
+    AINSTR_END, /* union  */
+    AINSTR_END, /* array  */
 };
 
 uint16_t type_ne_instr[TYPE_COUNT] = {
@@ -134,9 +160,15 @@ uint16_t type_ne_instr[TYPE_COUNT] = {
     INSTR_NE_E, /* should use I */
 #if 0
     INSTR_NE_I,
+#else
+    INSTR_NE_F,
 #endif
 
     INSTR_NE_V, /* variant, should never be accessed */
+
+    AINSTR_END, /* struct */
+    AINSTR_END, /* union  */
+    AINSTR_END, /* array  */
 };
 
 MEM_VEC_FUNCTIONS(ir_value_vector, ir_value*, v)
@@ -1561,6 +1593,7 @@ ir_value* ir_block_create_load_from_ent(ir_block *self, const char *label, ir_va
         case TYPE_INTEGER: op = INSTR_LOAD_I;   break;
 #endif
         default:
+            irerror(self->context, "invalid type for ir_block_create_load_from_ent: %s", type_name[outype]);
             return NULL;
     }
 
@@ -1577,6 +1610,7 @@ ir_value* ir_block_create_add(ir_block *self,
     if (l == r) {
         switch (l) {
             default:
+                irerror(self->context, "invalid type for ir_block_create_add: %s", type_name[l]);
                 return NULL;
             case TYPE_FLOAT:
                 op = INSTR_ADD_F;
@@ -1598,7 +1632,10 @@ ir_value* ir_block_create_add(ir_block *self,
             op = INSTR_ADD_IF;
         else
 #endif
+        {
+            irerror(self->context, "invalid type for ir_block_create_add: %s", type_name[l]);
             return NULL;
+        }
     }
     return ir_block_create_binop(self, label, op, left, right);
 }
@@ -1614,6 +1651,7 @@ ir_value* ir_block_create_sub(ir_block *self,
 
         switch (l) {
             default:
+                irerror(self->context, "invalid type for ir_block_create_sub: %s", type_name[l]);
                 return NULL;
             case TYPE_FLOAT:
                 op = INSTR_SUB_F;
@@ -1635,7 +1673,10 @@ ir_value* ir_block_create_sub(ir_block *self,
             op = INSTR_SUB_IF;
         else
 #endif
+        {
+            irerror(self->context, "invalid type for ir_block_create_sub: %s", type_name[l]);
             return NULL;
+        }
     }
     return ir_block_create_binop(self, label, op, left, right);
 }
@@ -1651,6 +1692,7 @@ ir_value* ir_block_create_mul(ir_block *self,
 
         switch (l) {
             default:
+                irerror(self->context, "invalid type for ir_block_create_mul: %s", type_name[l]);
                 return NULL;
             case TYPE_FLOAT:
                 op = INSTR_MUL_F;
@@ -1679,8 +1721,10 @@ ir_value* ir_block_create_mul(ir_block *self,
         else if ( (l == TYPE_INTEGER && r == TYPE_FLOAT) )
             op = INSTR_MUL_IF;
 #endif
-        else
+        else {
+            irerror(self->context, "invalid type for ir_block_create_mul: %s", type_name[l]);
             return NULL;
+        }
     }
     return ir_block_create_binop(self, label, op, left, right);
 }
@@ -1696,6 +1740,7 @@ ir_value* ir_block_create_div(ir_block *self,
 
         switch (l) {
             default:
+                irerror(self->context, "invalid type for ir_block_create_div: %s", type_name[l]);
                 return NULL;
             case TYPE_FLOAT:
                 op = INSTR_DIV_F;
@@ -1716,7 +1761,10 @@ ir_value* ir_block_create_div(ir_block *self,
             op = INSTR_DIV_IF;
         else
 #endif
+        {
+            irerror(self->context, "invalid type for ir_block_create_div: %s", type_name[l]);
             return NULL;
+        }
     }
     return ir_block_create_binop(self, label, op, left, right);
 }
index ef8d0ae903a2b87ffce674fe288fe8c3b05e769f..0616b711b7fb97137a7d5fa9d6db5dc6e3517022 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -2314,29 +2314,25 @@ static ast_value *parse_typename(parser_t *parser, ast_value **storebase)
         return NULL;
     }
 
-    /* an opening paren now starts the parameter-list of a function */
+    /* an opening paren now starts the parameter-list of a function
+     * this is where original-QC has parameter lists.
+     * We allow a single parameter list here.
+     * Much like fteqcc we don't allow `float()() x`
+     */
     if (parser->tok == '(') {
         var = parse_parameter_list(parser, var);
         if (!var)
             return NULL;
     }
-    /* This is the point where we can turn it into a field */
-    if (isfield) {
-        /* turn it into a field if desired */
-        tmp = ast_value_new(ctx, "<type:f>", TYPE_FIELD);
-        tmp->expression.next = (ast_expression*)var;
-        var = tmp;
-    }
-
-    while (parser->tok == '(') {
-        var = parse_parameter_list(parser, var);
-        if (!var)
-            return NULL;
-    }
 
     /* store the base if requested */
     if (storebase) {
         *storebase = ast_value_copy(var);
+        if (isfield) {
+            tmp = ast_value_new(ctx, "<type:f>", TYPE_FIELD);
+            tmp->expression.next = (ast_expression*)*storebase;
+            *storebase = tmp;
+        }
     }
 
     /* there may be a name now */
@@ -2344,11 +2340,60 @@ static ast_value *parse_typename(parser_t *parser, ast_value **storebase)
         name = util_strdup(parser_tokval(parser));
         /* parse on */
         if (!parser_next(parser)) {
+            ast_delete(var);
             parseerror(parser, "error after variable or field declaration");
             return NULL;
         }
     }
 
+    /* now this may be an array */
+    if (parser->tok == '[') {
+        ast_expression *cexp = parse_expression_leave(parser, true);
+        ast_value      *cval;
+        if (!cexp || !ast_istype(cexp, ast_value)) {
+            if (cexp) ast_delete(cexp);
+            ast_delete(var);
+            parseerror(parser, "expected array-size as constant positive integer");
+            return NULL;
+        }
+        cval = (ast_value*)cexp;
+
+        tmp = ast_value_new(ctx, "<type[]>", TYPE_ARRAY);
+        tmp->expression.next = (ast_expression*)var;
+        var = tmp;
+
+        if (cval->expression.vtype == TYPE_INTEGER)
+            tmp->expression.count = cval->constval.vint;
+        else if (cval->expression.vtype == TYPE_FLOAT)
+            tmp->expression.count = cval->constval.vfloat;
+        else {
+            ast_delete(cexp);
+            ast_delete(var);
+            parseerror(parser, "array-size must be a positive integer constant");
+            return NULL;
+        }
+        ast_delete(cexp);
+
+        if (parser->tok != ']') {
+            ast_delete(var);
+            parseerror(parser, "expected ']' after array-size");
+            return NULL;
+        }
+        if (!parser_next(parser)) {
+            ast_delete(var);
+            parseerror(parser, "error after parsing array size");
+            return NULL;
+        }
+    }
+
+    /* This is the point where we can turn it into a field */
+    if (isfield) {
+        /* turn it into a field if desired */
+        tmp = ast_value_new(ctx, "<type:f>", TYPE_FIELD);
+        tmp->expression.next = (ast_expression*)var;
+        var = tmp;
+    }
+
     /* now there may be function parens again */
     if (parser->tok == '(' && opts_standard == COMPILER_QCC)
         parseerror(parser, "C-style function syntax is not allowed in -std=qcc");
@@ -2357,6 +2402,7 @@ static ast_value *parse_typename(parser_t *parser, ast_value **storebase)
         if (!var) {
             if (name)
                 mem_d((void*)name);
+            ast_delete(var);
             return NULL;
         }
     }