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;
+ type_t *type = expression->right->datatype;
+ /* be careful with the modes, because in asithmetic assign nodes only
+ * the right operand has the mode of the arithmetic alread */
ir_mode *mode = get_ir_mode(type);
+ left = create_conv(dbgi, left, mode);
ir_node *res = func(dbgi, left, right, mode);
return res;
}
+static ir_node *create_arithmetic_assign_binop(
+ const binary_expression_t *expression, create_arithmetic_func func)
+{
+ dbg_info *dbgi = get_dbg_info(&expression->expression.source_position);
+ ir_node *value = create_arithmetic_binop(expression, func);
+ type_t *type = expression->expression.datatype;
+ ir_mode *mode = get_ir_mode(type);
+
+ value = create_conv(dbgi, value, mode);
+ set_value_for_expression(expression->left, value);
+
+ return value;
+}
+
static ir_node *create_add(const binary_expression_t *expression)
{
dbg_info *dbgi = get_dbg_info(&expression->expression.source_position);
return res;
}
+static ir_node *create_divmod(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);
+ ir_node *pin = new_Pin(new_NoMem());
+ type_t *type = expression->expression.datatype;
+ ir_mode *mode = get_ir_mode(type);
+ ir_node *op;
+ ir_node *res;
+
+ if(expression->type == BINEXPR_DIV) {
+ if(mode_is_float(mode)) {
+ op = new_d_Quot(dbgi, pin, left, right, mode, op_pin_state_floats);
+ res = new_d_Proj(dbgi, op, mode, pn_Quot_res);
+ } else {
+ op = new_d_Div(dbgi, pin, left, right, mode, op_pin_state_floats);
+ res = new_d_Proj(dbgi, op, mode, pn_Div_res);
+ }
+ } else {
+ assert(expression->type == BINEXPR_MOD);
+ assert(!mode_is_float(mode));
+ op = new_d_Mod(dbgi, pin, left, right, mode, op_pin_state_floats);
+ res = new_d_Proj(dbgi, op, mode, pn_Mod_res);
+ }
+
+ return res;
+}
+
static ir_node *binary_expression_to_firm(const binary_expression_t *expression)
return create_arithmetic_binop(expression, new_d_Shl);
case BINEXPR_SHIFTRIGHT:
return create_arithmetic_binop(expression, new_d_Shr);
+ case BINEXPR_DIV:
+ case BINEXPR_MOD:
+ return create_divmod(expression);
case BINEXPR_LOGICAL_AND:
case BINEXPR_LOGICAL_OR:
return create_lazy_op(expression);
+ case BINEXPR_COMMA:
+ expression_to_firm(expression->left);
+ return expression_to_firm(expression->right);
+ case BINEXPR_ADD_ASSIGN:
+ return create_arithmetic_assign_binop(expression, new_d_Add);
+ case BINEXPR_SUB_ASSIGN:
+ return create_arithmetic_assign_binop(expression, new_d_Sub);
+ case BINEXPR_MUL_ASSIGN:
+ return create_arithmetic_assign_binop(expression, new_d_Mul);
+ case BINEXPR_BITWISE_AND_ASSIGN:
+ return create_arithmetic_assign_binop(expression, new_d_And);
+ case BINEXPR_BITWISE_OR_ASSIGN:
+ return create_arithmetic_assign_binop(expression, new_d_Or);
+ case BINEXPR_BITWISE_XOR_ASSIGN:
+ return create_arithmetic_assign_binop(expression, new_d_Eor);
+ case BINEXPR_SHIFTLEFT_ASSIGN:
+ return create_arithmetic_assign_binop(expression, new_d_Shl);
+ case BINEXPR_SHIFTRIGHT_ASSIGN:
+ return create_arithmetic_assign_binop(expression, new_d_Shr);
default:
panic("TODO binexpr type");
}
return (expression_t*) select;
}
-static expression_t *parse_call_expression(unsigned precedence,
- expression_t *expression)
+static expression_t *create_cast_expression(expression_t *expression,
+ type_t *dest_type)
{
- (void) precedence;
- call_expression_t *call = allocate_ast_zero(sizeof(call[0]));
- call->expression.type = EXPR_CALL;
- call->function = expression;
-
- type_t *type = expression->datatype;
- if(type->type != TYPE_FUNCTION) {
- /* TODO calling pointers to functions is ok */
- parser_print_error_prefix();
- fputs("called object '", stderr);
- print_expression(expression);
- fputs("' (type ", stderr);
- print_type(type);
- fputs("is not a function\n", stderr);
-
- call->expression.datatype = NULL;
- } else {
- function_type_t *function_type = (function_type_t*) type;
- call->expression.datatype = function_type->result_type;
- }
-
- /* parse arguments */
- eat('(');
-
- if(token.type != ')') {
- call_argument_t *last_argument = NULL;
-
- while(true) {
- call_argument_t *argument = allocate_ast_zero(sizeof(argument[0]));
-
- argument->expression = parse_assignment_expression();
- if(last_argument == NULL) {
- call->arguments = argument;
- } else {
- last_argument->next = argument;
- }
- last_argument = argument;
+ unary_expression_t *cast = allocate_ast_zero(sizeof(cast[0]));
- if(token.type != ',')
- break;
- next_token();
- }
- }
- expect(')');
+ cast->expression.type = EXPR_UNARY;
+ cast->type = UNEXPR_CAST;
+ cast->value = expression;
+ cast->expression.datatype = dest_type;
- return (expression_t*) call;
+ return (expression_t*) cast;
}
static void type_error(const char *msg, const source_position_t source_position,
error();
}
-static type_t *get_type_after_conversion(const type_t *type1,
- const type_t *type2)
+static int get_rank(const type_t *type)
{
- /* TODO... */
- (void) type2;
- return (type_t*) type1;
+ /* The C-standard allows promoting to int or unsigned int (see § 7.2.2
+ * and esp. footnote 108). However we can't fold constants (yet), so we
+ * can't decide wether unsigned int is possible, while int always works.
+ * (unsigned int would be preferable when possible... for stuff like
+ * struct { enum { ... } bla : 4; } ) */
+ if(type->type == TYPE_ENUM)
+ return ATOMIC_TYPE_INT;
+
+ assert(type->type == TYPE_ATOMIC);
+ atomic_type_t *atomic_type = (atomic_type_t*) type;
+ atomic_type_type_t atype = atomic_type->atype;
+ return atype;
}
-static expression_t *create_cast_expression(expression_t *expression,
- type_t *dest_type)
+static type_t *promote_integer(type_t *type)
{
- unary_expression_t *cast = allocate_ast_zero(sizeof(cast[0]));
-
- cast->expression.type = EXPR_UNARY;
- cast->type = UNEXPR_CAST;
- cast->value = expression;
- cast->expression.datatype = dest_type;
+ if(get_rank(type) < ATOMIC_TYPE_INT)
+ type = type_int;
- return (expression_t*) cast;
+ return type;
}
-static expression_t *create_cast(expression_t *expression, type_t *dest_type)
+static expression_t *create_implicit_cast(expression_t *expression,
+ type_t *dest_type)
{
assert(expression->datatype != NULL);
type_t *source_type = expression->datatype;
panic("casting of non-atomic types not implemented yet");
}
+static expression_t *parse_call_expression(unsigned precedence,
+ expression_t *expression)
+{
+ (void) precedence;
+ call_expression_t *call = allocate_ast_zero(sizeof(call[0]));
+ call->expression.type = EXPR_CALL;
+ call->function = expression;
+
+ function_type_t *function_type;
+ type_t *type = expression->datatype;
+ if(type->type != TYPE_FUNCTION) {
+ /* TODO calling pointers to functions is ok */
+ parser_print_error_prefix();
+ fputs("called object '", stderr);
+ print_expression(expression);
+ fputs("' (type ", stderr);
+ print_type(type);
+ fputs("is not a function\n", stderr);
+
+ function_type = NULL;
+ call->expression.datatype = NULL;
+ } else {
+ function_type = (function_type_t*) type;
+ call->expression.datatype = function_type->result_type;
+ }
+
+ /* parse arguments */
+ eat('(');
+
+ if(token.type != ')') {
+ call_argument_t *last_argument = NULL;
+
+ while(true) {
+ call_argument_t *argument = allocate_ast_zero(sizeof(argument[0]));
+
+ argument->expression = parse_assignment_expression();
+ if(last_argument == NULL) {
+ call->arguments = argument;
+ } else {
+ last_argument->next = argument;
+ }
+ last_argument = argument;
+
+ if(token.type != ',')
+ break;
+ next_token();
+ }
+ }
+ expect(')');
+
+ if(function_type != NULL) {
+ function_parameter_t *parameter = function_type->parameters;
+ call_argument_t *argument = call->arguments;
+ for( ; parameter != NULL && argument != NULL;
+ parameter = parameter->next, argument = argument->next) {
+ type_t *expected_type = parameter->type;
+ /* TODO report context in error messages */
+ argument->expression = create_implicit_cast(argument->expression,
+ expected_type);
+ }
+ /* too few parameters */
+ if(parameter != NULL) {
+ parser_print_error_prefix();
+ fprintf(stderr, "too few arguments to function '");
+ print_expression(expression);
+ fprintf(stderr, "'\n");
+ } else if(argument != NULL) {
+ /* too many parameters */
+ if(!function_type->variadic
+ && !function_type->unspecified_parameters) {
+ parser_print_error_prefix();
+ fprintf(stderr, "too many arguments to function '");
+ print_expression(expression);
+ fprintf(stderr, "'\n");
+ } else {
+ /* do default promotion */
+ for( ; argument != NULL; argument = argument->next) {
+ type_t *type = argument->expression->datatype;
+
+ if(is_type_integer(type)) {
+ type = promote_integer(type);
+ } else if(type == type_float) {
+ type = type_double;
+ }
+ argument->expression
+ = create_implicit_cast(argument->expression, type);
+ }
+ }
+ }
+ }
+
+ return (expression_t*) call;
+}
+
+static type_t *get_type_after_conversion(const type_t *type1,
+ const type_t *type2)
+{
+ /* TODO... */
+ (void) type2;
+ return (type_t*) type1;
+}
+
static expression_t *parse_conditional_expression(unsigned precedence,
expression_t *expression)
{
CREATE_UNARY_POSTFIX_EXPRESSION_PARSER(T_MINUSMINUS, UNEXPR_POSTFIX_DECREMENT,
get_unexpr_arithmetic_type)
-static int get_rank(const type_t *type)
-{
- /* The C-standard allows promoting to int or unsigned int (see § 7.2.2
- * and esp. footnote 108). However we can't fold constants (yet), so we
- * can't decide wether unsigned int is possible, while int always works.
- * (unsigned int would be preferable when possible... for stuff like
- * struct { enum { ... } bla : 4; } ) */
- if(type->type == TYPE_ENUM)
- return ATOMIC_TYPE_INT;
-
- assert(type->type == TYPE_ATOMIC);
- atomic_type_t *atomic_type = (atomic_type_t*) type;
- atomic_type_type_t atype = atomic_type->atype;
- return atype;
-}
-
-static void semantic_arithmetic(expression_t **left, expression_t **right)
+static type_t *semantic_arithmetic(type_t *type_left, type_t *type_right)
{
- type_t *type_left = (*left)->datatype;
- type_t *type_right = (*right)->datatype;
- type_left = skip_typeref(type_left);
- type_right = skip_typeref(type_right);
-
/* TODO: handle complex + imaginary types */
/* § 6.3.1.8 Usual arithmetic conversions */
if(type_left == type_long_double || type_right == type_long_double) {
- type_left = type_long_double;
- type_right = type_long_double;
- goto finished;
+ return type_long_double;
} else if(type_left == type_double || type_right == type_double) {
- type_left = type_double;
- type_right = type_double;
- goto finished;
+ return type_double;
} else if(type_left == type_float || type_right == type_float) {
- type_left = type_float;
- type_right = type_float;
- goto finished;
+ return type_float;
}
- /* integer promotion */
- if(get_rank(type_left) < ATOMIC_TYPE_INT)
- type_left = type_int;
- if(get_rank(type_right) < ATOMIC_TYPE_INT)
- type_right = type_int;
+ type_right = promote_integer(type_right);
+ type_left = promote_integer(type_left);
if(type_left == type_right)
- goto finished;
+ return type_left;
bool signed_left = is_type_signed(type_left);
bool signed_right = is_type_signed(type_right);
if(get_rank(type_left) < get_rank(type_right)) {
if(signed_left == signed_right || !signed_right) {
- type_left = type_right;
+ return type_right;
} else {
- type_right = type_left;
+ return type_left;
}
} else {
if(signed_left == signed_right || !signed_left) {
- type_right = type_left;
+ return type_left;
} else {
- type_left = type_right;
+ return type_right;
}
}
-
-finished:
- assert(type_left == type_right);
- *left = create_cast(*left, type_left);
- *right = create_cast(*right, type_right);
}
static void semantic_binexpr_arithmetic(binary_expression_t *expression)
return;
}
- semantic_arithmetic(&expression->left, &expression->right);
- expression->expression.datatype = expression->left->datatype;
+ type_t *arithmetic_type = semantic_arithmetic(type_left, type_right);
+ expression->left = create_implicit_cast(left, arithmetic_type);
+ expression->right = create_implicit_cast(right, arithmetic_type);
+ expression->expression.datatype = arithmetic_type;
}
static void semantic_add(binary_expression_t *expression)
/* § 5.6.5 */
if(is_type_arithmetic(type_left) && is_type_arithmetic(type_right)) {
- semantic_arithmetic(&expression->left, &expression->right);
- expression->expression.datatype = expression->left->datatype;
+ type_t *arithmetic_type = semantic_arithmetic(type_left, type_right);
+ expression->left = create_implicit_cast(left, arithmetic_type);
+ expression->right = create_implicit_cast(right, arithmetic_type);
+ expression->expression.datatype = arithmetic_type;
return;
} else if(type_left->type == TYPE_POINTER && is_type_integer(type_right)) {
expression->expression.datatype = type_left;
/* § 5.6.5 */
if(is_type_arithmetic(type_left) && is_type_arithmetic(type_right)) {
- semantic_arithmetic(&expression->left, &expression->right);
- expression->expression.datatype = expression->left->datatype;
+ type_t *arithmetic_type = semantic_arithmetic(type_left, type_right);
+ expression->left = create_implicit_cast(left, arithmetic_type);
+ expression->right = create_implicit_cast(right, arithmetic_type);
+ expression->expression.datatype = arithmetic_type;
return;
} else if(type_left->type == TYPE_POINTER && is_type_integer(type_right)) {
expression->expression.datatype = type_left;
type_t *type_left = left->datatype;
type_t *type_right = right->datatype;
+ /* TODO non-arithmetic types */
if(is_type_arithmetic(type_left) && is_type_arithmetic(type_right)) {
- semantic_arithmetic(&expression->left, &expression->right);
+ type_t *arithmetic_type = semantic_arithmetic(type_left, type_right);
+ expression->left = create_implicit_cast(left, arithmetic_type);
+ expression->right = create_implicit_cast(right, arithmetic_type);
+ expression->expression.datatype = arithmetic_type;
}
expression->expression.datatype = type_int;
}
return;
}
- semantic_arithmetic(&expression->left, &expression->right);
- /* note that we assign the original type_left before casting */
+ /* combined instructions are tricky. We can't create an implicit cast on
+ * the left side, because we need the uncasted form for the store.
+ * The ast2firm pass has to know that left_type must be right_type
+ * for the arithmeitc operation and create a cast by itself */
+ type_t *arithmetic_type = semantic_arithmetic(type_left, type_right);
+ expression->right = create_implicit_cast(right, arithmetic_type);
expression->expression.datatype = type_left;
}
if(type_left == type_right) {
/* fine */
} else if(is_type_arithmetic(type_left) && is_type_arithmetic(type_right)) {
- *right = create_cast(*right, type_left);
+ *right = create_implicit_cast(*right, type_left);
} else if(type_left->type == TYPE_POINTER
&& type_right->type == TYPE_POINTER) {
/* TODO */