mode_uint = atomic_modes[ATOMIC_TYPE_UINT];
/* there's no real void type in firm */
- atomic_modes[ATOMIC_TYPE_VOID] = mode_int;
+ atomic_modes[ATOMIC_TYPE_VOID] = atomic_modes[ATOMIC_TYPE_CHAR];
/* initialize pointer modes */
char name[64];
ir_node *size_node = type->array.size_node;
if (size_node == NULL) {
size_node = expression_to_firm(type->array.size_expression);
- assert(!is_Const(size_node));
type->array.size_node = size_node;
}
ir_node *const load_mem = new_d_Proj(dbgi, load, mode_M, pn_Load_M);
ir_node *const load_res = new_d_Proj(dbgi, load, mode, pn_Load_res);
- if (type->base.qualifiers & TYPE_QUALIFIER_VOLATILE) {
+ if (type->base.qualifiers & TYPE_QUALIFIER_VOLATILE && !is_Bad(load)) {
set_Load_volatility(load, volatility_is_volatile);
}
return _expression_to_firm(argument);
}
case T___builtin_va_end:
+ /* evaluate the argument of va_end for its side effects */
+ _expression_to_firm(call->arguments->expression);
return NULL;
default:
panic("Unsupported builtin found\n");
if (is_type_scalar(type)) {
ir_node *store = new_d_Store(dbgi, memory, addr, value);
ir_node *store_mem = new_d_Proj(dbgi, store, mode_M, pn_Store_M);
- if (type->base.qualifiers & TYPE_QUALIFIER_VOLATILE)
+ if (type->base.qualifiers & TYPE_QUALIFIER_VOLATILE && !is_Bad(store))
set_Store_volatility(store, volatility_is_volatile);
set_store(store_mem);
} else {
set_store(store_mem);
if (set_volatile) {
- set_Load_volatility(load, volatility_is_volatile);
- set_Store_volatility(store, volatility_is_volatile);
+ if (!is_Bad(load))
+ set_Load_volatility(load, volatility_is_volatile);
+ if (!is_Bad(store))
+ set_Store_volatility(store, volatility_is_volatile);
}
}
* produces a 0/1 depending of the value of a mode_b node
*/
static ir_node *produce_condition_result(const expression_t *expression,
- dbg_info *dbgi)
+ ir_mode *mode, dbg_info *dbgi)
{
- ir_mode *mode = get_ir_mode(expression->base.type);
ir_node *cur_block = get_cur_block();
ir_node *one_block = new_immBlock();
static ir_node *adjust_for_pointer_arithmetic(dbg_info *dbgi,
ir_node *value, type_t *type)
{
+ ir_mode *const mode = get_ir_mode(type_ptrdiff_t);
+ assert(is_type_pointer(type));
pointer_type_t *const pointer_type = &type->pointer;
type_t *const points_to = skip_typeref(pointer_type->points_to);
unsigned elem_size = get_type_size_const(points_to);
+ value = create_conv(dbgi, value, mode);
+
/* gcc extension: allow arithmetic with void * and function * */
if ((elem_size == 0 && is_type_atomic(points_to, ATOMIC_TYPE_VOID)) ||
is_type_function(points_to)) {
if (elem_size == 1)
return value;
- value = create_conv(dbgi, value, mode_int);
- ir_node *const cnst = new_Const_long(mode_int, (long)elem_size);
- ir_node *const mul = new_d_Mul(dbgi, value, cnst, mode_int);
+ ir_node *const cnst = new_Const_long(mode, (long)elem_size);
+ ir_node *const mul = new_d_Mul(dbgi, value, cnst, mode);
return mul;
}
default:
normal_node:
- mode = get_irn_mode(right);
+ mode = get_ir_mode(type_right);
left = create_conv(dbgi, left, mode);
break;
}
long val = fold_constant(expression->left);
expression_kind_t ekind = expression->base.kind;
assert(ekind == EXPR_BINARY_LOGICAL_AND || ekind == EXPR_BINARY_LOGICAL_OR);
- if ((ekind == EXPR_BINARY_LOGICAL_AND && val != 0) ||
- (ekind == EXPR_BINARY_LOGICAL_OR && val == 0)) {
- return expression_to_firm(expression->right);
+ if (ekind == EXPR_BINARY_LOGICAL_AND) {
+ if (val == 0) {
+ return new_Const(get_mode_null(mode));
+ }
} else {
- return new_Const(get_mode_one(mode));
+ if (val != 0) {
+ return new_Const(get_mode_one(mode));
+ }
+ }
+
+ if (is_constant_expression(expression->right)) {
+ long const valr = fold_constant(expression->left);
+ return valr != 0 ?
+ new_Const(get_mode_one(mode)) :
+ new_Const(get_mode_null(mode));
}
+
+ return produce_condition_result(expression->right, mode, dbgi);
}
- return produce_condition_result((const expression_t*) expression, dbgi);
+ return produce_condition_result((const expression_t*) expression, mode,
+ dbgi);
}
typedef ir_node * (*create_arithmetic_func)(dbg_info *dbgi, ir_node *left,
static ir_node *array_access_addr(const array_access_expression_t *expression)
{
- dbg_info *dbgi = get_dbg_info(&expression->base.source_position);
- ir_node *base_addr = expression_to_firm(expression->array_ref);
- ir_node *offset = expression_to_firm(expression->index);
-
- type_t *offset_type = skip_typeref(expression->index->base.type);
- ir_mode *mode;
- if (is_type_signed(offset_type)) {
- mode = get_ir_mode(type_ssize_t);
- } else {
- mode = get_ir_mode(type_size_t);
- }
- offset = create_conv(dbgi, offset, mode);
-
- type_t *ref_type = skip_typeref(expression->array_ref->base.type);
- assert(is_type_pointer(ref_type));
- pointer_type_t *pointer_type = &ref_type->pointer;
-
- ir_node *elem_size_const = get_type_size(pointer_type->points_to);
- elem_size_const = create_conv(dbgi, elem_size_const, mode);
- ir_node *real_offset = new_d_Mul(dbgi, offset, elem_size_const,
- mode);
- ir_node *result = new_d_Add(dbgi, base_addr, real_offset, mode_P_data);
+ dbg_info *dbgi = get_dbg_info(&expression->base.source_position);
+ ir_node *base_addr = expression_to_firm(expression->array_ref);
+ ir_node *offset = expression_to_firm(expression->index);
+ type_t *ref_type = skip_typeref(expression->array_ref->base.type);
+ ir_node *real_offset = adjust_for_pointer_arithmetic(dbgi, offset, ref_type);
+ ir_node *result = new_d_Add(dbgi, base_addr, real_offset, mode_P_data);
return result;
}
entity_t *entry = expression->compound_entry;
assert(entry->kind == ENTITY_COMPOUND_MEMBER);
assert(entry->declaration.kind == DECLARATION_KIND_COMPOUND_MEMBER);
- ir_entity *irentity = entry->compound_member.entity;
-
- assert(irentity != NULL);
- ir_node *sel = new_d_simpleSel(dbgi, new_NoMem(), compound_addr, irentity);
-
- return sel;
+ if (constant_folding) {
+ ir_mode *mode = get_irn_mode(compound_addr);
+ /* FIXME: here, we need an integer mode with the same number of bits as mode */
+ ir_node *ofs = new_Const_long(mode_uint, entry->compound_member.offset);
+ return new_d_Add(dbgi, compound_addr, ofs, mode);
+ } else {
+ ir_entity *irentity = entry->compound_member.entity;
+ assert(irentity != NULL);
+ return new_d_simpleSel(dbgi, new_NoMem(), compound_addr, irentity);
+ }
}
static ir_node *select_to_firm(const select_expression_t *expression)
tc = void_type_class;
goto make_const;
+ case ATOMIC_TYPE_WCHAR_T: /* gcc handles this as integer */
case ATOMIC_TYPE_CHAR: /* gcc handles this as integer */
case ATOMIC_TYPE_SCHAR: /* gcc handles this as integer */
case ATOMIC_TYPE_UCHAR: /* gcc handles this as integer */
static ir_node *expression_to_addr(const expression_t *expression)
{
switch(expression->kind) {
- case EXPR_REFERENCE:
- return reference_addr(&expression->reference);
case EXPR_ARRAY_ACCESS:
return array_access_addr(&expression->array_access);
- case EXPR_SELECT:
- return select_addr(&expression->select);
case EXPR_CALL:
return call_expression_to_firm(&expression->call);
- case EXPR_UNARY_DEREFERENCE: {
+ case EXPR_COMPOUND_LITERAL:
+ return compound_literal_to_firm(&expression->compound_literal);
+ case EXPR_REFERENCE:
+ return reference_addr(&expression->reference);
+ case EXPR_SELECT:
+ return select_addr(&expression->select);
+ case EXPR_UNARY_DEREFERENCE:
return dereference_addr(&expression->unary);
- }
default:
break;
}
/* we have to produce a 0/1 from the mode_b expression */
dbg_info *dbgi = get_dbg_info(&expression->base.source_position);
- return produce_condition_result(expression, dbgi);
+ ir_mode *mode = get_ir_mode(expression->base.type);
+ return produce_condition_result(expression, mode, dbgi);
}
/**
}
add_immBlock_pred(true_block, true_proj);
- if (false_block != NULL) {
- add_immBlock_pred(false_block, false_proj);
- }
+ add_immBlock_pred(false_block, false_proj);
set_cur_block(NULL);
return cond_expr;
create_condition_evaluation(statement->condition, body_block, false_block);
mature_immBlock(body_block);
mature_immBlock(header_block);
- if (false_block != NULL) {
- mature_immBlock(false_block);
- }
+ mature_immBlock(false_block);
set_cur_block(false_block);
}
ir_node *const false_block = new_immBlock();
/* the loop body */
- ir_node * body_block;
+ ir_node *body_block;
if (statement->body != NULL) {
ir_node *const old_continue_label = continue_label;
ir_node *const old_break_label = break_label;