return res;
}
+static ir_node *create_shift(const binary_expression_t *expression)
+{
+ dbg_info *dbgi = get_dbg_info(&expression->expression.source_position);
+ ir_node *left = expression_to_firm(expression->left);
+ ir_node *right = expression_to_firm(expression->right);
+ type_t *type = expression->expression.datatype;
+ ir_mode *mode = get_ir_mode(type);
+
+ /* firm always wants the shift count to be unsigned */
+ right = create_conv(dbgi, right, mode_Iu);
+
+ ir_node *res;
+
+ switch(expression->type) {
+ case BINEXPR_SHIFTLEFT:
+ res = new_d_Shl(dbgi, left, right, mode);
+ break;
+ case BINEXPR_SHIFTRIGHT: {
+ expression_t *expr_left = expression->left;
+ type_t *type_left = skip_typeref(expr_left->datatype);
+
+ if(is_type_signed(type_left)) {
+ res = new_d_Shrs(dbgi, left, right, mode);
+ } else {
+ res = new_d_Shr(dbgi, left, right, mode);
+ }
+ break;
+ }
+ default:
+ panic("create shift op called for non-shift op");
+ }
+
+ return res;
+}
+
+
static ir_node *create_divmod(const binary_expression_t *expression)
{
dbg_info *dbgi = get_dbg_info(&expression->expression.source_position);
case BINEXPR_BITWISE_XOR:
return create_arithmetic_binop(expression, new_d_Eor);
case BINEXPR_SHIFTLEFT:
- return create_arithmetic_binop(expression, new_d_Shl);
case BINEXPR_SHIFTRIGHT:
- return create_arithmetic_binop(expression, new_d_Shr);
+ return create_shift(expression);
case BINEXPR_DIV:
case BINEXPR_MOD:
return create_divmod(expression);
return create_cast_expression(expression, dest_type);
}
if(dest_type->type == TYPE_POINTER) {
+ pointer_type_t *pointer_type
+ = (pointer_type_t*) dest_type;
if(source_type->type == TYPE_POINTER) {
if(!pointers_compatible(source_type, dest_type)) {
type_error_incompatible("can't implicitely cast types",
expression->source_position,
source_type, dest_type);
+ return expression;
} else {
return create_cast_expression(expression, dest_type);
}
+ } else if(source_type->type == TYPE_ARRAY) {
+ array_type_t *array_type = (array_type_t*) source_type;
+ if(!types_compatible(array_type->element_type,
+ pointer_type->points_to)) {
+ type_error_incompatible("can't implicitely cast types",
+ expression->source_position,
+ source_type, dest_type);
+ return expression;
+ }
+ return create_cast_expression(expression, dest_type);
}
}
expression->expression.datatype = arithmetic_type;
}
+static void semantic_shift_op(binary_expression_t *expression)
+{
+ expression_t *left = expression->left;
+ expression_t *right = expression->right;
+ type_t *orig_type_left = left->datatype;
+ type_t *orig_type_right = right->datatype;
+
+ if(orig_type_left == NULL || orig_type_right == NULL)
+ return;
+
+ type_t *type_left = skip_typeref(orig_type_left);
+ type_t *type_right = skip_typeref(orig_type_right);
+
+ if(!is_type_integer(type_left) || !is_type_integer(type_right)) {
+ /* TODO: improve error message */
+ parser_print_error_prefix();
+ fprintf(stderr, "operation needs integer types\n");
+ return;
+ }
+
+ type_left = promote_integer(type_left);
+ type_right = promote_integer(type_right);
+
+ expression->left = create_implicit_cast(left, type_left);
+ expression->right = create_implicit_cast(right, type_right);
+ expression->expression.datatype = type_left;
+}
+
static void semantic_add(binary_expression_t *expression)
{
expression_t *left = expression->left;
CREATE_BINEXPR_PARSER(T_PIPEPIPE, BINEXPR_LOGICAL_OR, semantic_logical_op, 1)
/* TODO shift has a bit special semantic */
CREATE_BINEXPR_PARSER(T_LESSLESS, BINEXPR_SHIFTLEFT,
- semantic_binexpr_arithmetic, 1)
+ semantic_shift_op, 1)
CREATE_BINEXPR_PARSER(T_GREATERGREATER, BINEXPR_SHIFTRIGHT,
- semantic_binexpr_arithmetic, 1)
+ semantic_shift_op, 1)
CREATE_BINEXPR_PARSER(T_PLUSEQUAL, BINEXPR_ADD_ASSIGN,
semantic_arithmetic_assign, 0)
CREATE_BINEXPR_PARSER(T_MINUSEQUAL, BINEXPR_SUB_ASSIGN,
return is_type_arithmetic(type);
}
+bool is_type_incomplete(const type_t *type)
+{
+ switch(type->type) {
+ case TYPE_COMPOUND_STRUCT:
+ case TYPE_COMPOUND_UNION: {
+ const compound_type_t *compound_type
+ = (const compound_type_t*) type;
+ declaration_t *declaration = compound_type->declaration;
+ return !declaration->init.is_defined;
+ }
+ case TYPE_FUNCTION:
+ return true;
+
+ case TYPE_ARRAY:
+ case TYPE_ATOMIC:
+ case TYPE_POINTER:
+ case TYPE_ENUM:
+ return false;
+
+ case TYPE_TYPEDEF:
+ case TYPE_TYPEOF:
+ case TYPE_BUILTIN:
+ panic("is_type_incomplete called without typerefs skipped");
+ case TYPE_INVALID:
+ break;
+ }
+
+ panic("invalid type found");
+}
+
+bool types_compatible(const type_t *type1, const type_t *type2)
+{
+ (void) type1;
+ (void) type2;
+ return true;
+}
+
bool pointers_compatible(const type_t *type1, const type_t *type2)
{
assert(type1->type == TYPE_POINTER);
assert(type2->type == TYPE_POINTER);
- return true;
+ pointer_type_t *pointer_type1 = (pointer_type_t*) type1;
+ pointer_type_t *pointer_type2 = (pointer_type_t*) type2;
+ return types_compatible(pointer_type1->points_to,
+ pointer_type2->points_to);
}
type_t *skip_typeref(type_t *type)
*/
bool is_type_scalar(const type_t *type);
+bool is_type_incomplete(const type_t *type);
+
+bool types_compatible(const type_t *type1, const type_t *type2);
+
bool pointers_compatible(const type_t *type1, const type_t *type2);
type_t *skip_typeref(type_t *type);