"field",
"function",
"pointer",
-#if 0
"integer",
-#endif
- "variant"
+ "variant",
+ "struct",
+ "union",
+ "array"
};
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] = {
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] = {
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] = {
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] = {
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] = {
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)
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;
}
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;
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);
}
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;
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);
}
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;
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);
}
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;
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);
}
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 */
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");
if (!var) {
if (name)
mem_d((void*)name);
+ ast_delete(var);
return NULL;
}
}