/*
* This file is part of cparser.
- * Copyright (C) 2007-2009 Matthias Braun <matze@braunis.de>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
+ * Copyright (C) 2012 Matthias Braun <matze@braunis.de>
*/
#include <config.h>
#include <string.h>
#include <stdbool.h>
#include <unistd.h>
-#include <limits.h>
#include <libfirm/firm.h>
#include <libfirm/adt/obst.h>
#include "adt/util.h"
#include "jump_target.h"
#include "symbol_t.h"
+#include "symbol_table.h"
#include "token_t.h"
#include "type_t.h"
#include "ast_t.h"
#include "diagnostic.h"
#include "lang_features.h"
#include "types.h"
-#include "type_hash.h"
#include "mangle.h"
+#include "unicode.h"
#include "walk.h"
#include "warning.h"
#include "printer.h"
static ir_node *uninitialized_local_var(ir_graph *irg, ir_mode *mode, int pos)
{
const entity_t *entity = get_irg_loc_description(irg, pos);
-
- if (entity != NULL) {
- position_t const *const pos = &entity->base.pos;
- warningf(WARN_UNINITIALIZED, pos, "'%N' might be used uninitialized", entity);
- }
+ if (entity)
+ warningf(WARN_UNINITIALIZED, &entity->base.pos, "'%N' might be used uninitialized", entity);
return new_r_Unknown(irg, mode);
}
{
if (architecture_modulo_shift == 0)
return 0;
- if (type_size < architecture_modulo_shift)
- return architecture_modulo_shift;
- return type_size;
+ return MAX(type_size, architecture_modulo_shift);
}
static ir_mode *init_atomic_ir_mode(atomic_type_kind_t kind)
}
}
-ir_mode *get_atomic_mode(atomic_type_kind_t kind)
-{
- assert(kind <= ATOMIC_TYPE_LAST);
- return atomic_modes[kind];
-}
-
static ir_node *get_vla_size(array_type_t *const type)
{
ir_node *size_node = type->size_node;
return type;
}
+static ir_type *get_ir_type(type_t *type);
+
static ir_type *create_method_type(const function_type_t *function_type, bool for_closure)
{
type_t *return_type = skip_typeref(function_type->return_type);
mode = s_modes[size];
if (mode == NULL) {
- char name[32];
+ ir_mode *base_mode = get_type_mode(base_tp);
+ unsigned modulo_shift = get_mode_modulo_shift(base_mode);
+ char name[32];
snprintf(name, sizeof(name), "bf_I%u", size);
- mode = new_int_mode(name, irma_twos_complement, size, 1, 0);
+ mode = new_int_mode(name, irma_twos_complement, size, 1, modulo_shift);
s_modes[size] = mode;
}
mode = u_modes[size];
if (mode == NULL) {
- char name[32];
+ ir_mode *base_mode = get_type_mode(base_tp);
+ unsigned modulo_shift = get_mode_modulo_shift(base_mode);
+ char name[32];
snprintf(name, sizeof(name), "bf_U%u", size);
- mode = new_int_mode(name, irma_twos_complement, size, 0, 0);
+ mode = new_int_mode(name, irma_twos_complement, size, 0, modulo_shift);
u_modes[size] = mode;
}
symbol_t *symbol = entry->base.symbol;
type_t *entry_type = entry->declaration.type;
- ident *ident;
+ ident *member_id;
if (symbol == NULL) {
/* anonymous bitfield member, skip */
if (entry->compound_member.bitfield)
continue;
assert(is_type_compound(entry_type));
- ident = id_unique("anon.%u");
+ member_id = id_unique("anon.%u");
} else {
- ident = new_id_from_str(symbol->string);
+ member_id = new_id_from_str(symbol->string);
}
dbg_info *dbgi = get_dbg_info(&entry->base.pos);
} else {
entry_irtype = get_ir_type(entry_type);
}
- ir_entity *entity = new_d_entity(irtype, ident, entry_irtype, dbgi);
+ ir_entity *entity = new_d_entity(irtype, member_id, entry_irtype, dbgi);
set_entity_offset(entity, entry->compound_member.offset);
set_entity_offset_bits_remainder(entity,
}
}
-ir_type *get_ir_type(type_t *type)
+static ir_type *get_ir_type(type_t *type)
{
type = skip_typeref(type);
switch (entity->kind) {
case ENTITY_VARIABLE:
return entity->declaration.storage_class != STORAGE_CLASS_EXTERN;
+// TODO: alias provides a definition
+// || entity->variable.alias != NULL;
case ENTITY_FUNCTION:
return entity->function.body != NULL;
case ENTITY_PARAMETER:
if ((modifiers & DM_USED) && declaration_is_definition(entity)) {
add_entity_linkage(irentity, IR_LINKAGE_HIDDEN_USER);
}
- if ((modifiers & DM_WEAK) && declaration_is_definition(entity)
- && entity->declaration.storage_class != STORAGE_CLASS_EXTERN) {
+// TODO: i dont understand this logic
+// if ((modifiers & DM_WEAK) && declaration_is_definition(entity)
+// && entity->declaration.storage_class != STORAGE_CLASS_EXTERN) {
+ if (modifiers & DM_WEAK) {
add_entity_linkage(irentity, IR_LINKAGE_WEAK);
}
}
const call_argument_t *argument = call->arguments;
for (int n = 0; n < n_parameters; ++n) {
expression_t *expression = argument->expression;
- type_t *arg_type = skip_typeref(expression->base.type);
- ir_node *arg_node;
+ type_t *const arg_type = skip_typeref(expression->base.type);
if (is_type_complex(arg_type)) {
complex_value value = expression_to_complex(expression);
- arg_node = complex_to_memory(dbgi, arg_type, value);
+ in[n] = complex_to_memory(dbgi, arg_type, value);
} else {
- arg_node = expression_to_value(expression);
- if (!is_type_compound(arg_type)) {
- ir_mode *const mode = get_ir_mode_storage(arg_type);
- arg_node = create_conv(dbgi, arg_node, mode);
- }
+ in[n] = conv_to_storage_type(dbgi, expression_to_value(expression), arg_type);
}
- in[n] = arg_node;
-
argument = argument->next;
}
}
expression_t *con = NULL;
- if (is_local_variable(op1) && is_constant_expression(op2) == EXPR_CLASS_CONSTANT) {
+ if (is_local_variable(op1) && is_constant_expression(op2) != EXPR_CLASS_VARIABLE) {
var = op1->reference.entity;
con = op2;
- } else if (is_constant_expression(op1) == EXPR_CLASS_CONSTANT && is_local_variable(op2)) {
+ } else if (is_constant_expression(op1) != EXPR_CLASS_VARIABLE && is_local_variable(op2)) {
relation = get_inversed_relation(relation);
var = op2->reference.entity;
con = op1;
static ir_node *create_cast(unary_expression_t const *const expr)
{
+ type_t *const from_type = skip_typeref(expr->value->base.type);
+ ir_node *value = is_type_complex(from_type)
+ ? expression_to_complex(expr->value).real
+ : expression_to_value(expr->value);
+
type_t *const type = skip_typeref(expr->base.type);
if (is_type_void(type))
return NULL;
- ir_node *value = expression_to_value(expr->value);
- dbg_info *const dbgi = get_dbg_info(&expr->base.pos);
- type_t *const from_type = skip_typeref(expr->value->base.type);
- ir_mode *const mode = get_ir_mode_storage(type);
+ dbg_info *const dbgi = get_dbg_info(&expr->base.pos);
+ ir_mode *const mode = get_ir_mode_storage(type);
/* check for conversion from / to __based types */
if (is_type_pointer(type) && is_type_pointer(from_type)) {
const variable_t *from_var = from_type->pointer.base_variable;
/* set branch prediction info based on __builtin_expect */
if (is_builtin_expect(expr) && is_Cond(cond)) {
call_argument_t *const argument = expr->call.arguments->next;
- if (is_constant_expression(argument->expression) == EXPR_CLASS_CONSTANT) {
+ if (is_constant_expression(argument->expression) != EXPR_CLASS_VARIABLE) {
bool const cnst = fold_constant_to_bool(argument->expression);
cond_jmp_predicate const pred = cnst ? COND_JMP_PRED_TRUE : COND_JMP_PRED_FALSE;
set_Cond_jmp_pred(cond, pred);
type_t *type = expression->type;
initializer_t *initializer = expression->initializer;
- if (expression->global_scope ||
- ((type->base.qualifiers & TYPE_QUALIFIER_CONST)
- && is_constant_initializer(initializer) == EXPR_CLASS_CONSTANT)) {
+ if (expression->global_scope || (
+ type->base.qualifiers & TYPE_QUALIFIER_CONST &&
+ is_constant_initializer(initializer) != EXPR_CLASS_VARIABLE
+ )) {
ir_entity *entity = create_initializer_entity(dbgi, initializer, type);
return create_symconst(dbgi, entity);
} else {
return get_type_size_node(type);
}
-static entity_t *get_expression_entity(const expression_t *expression)
-{
- if (expression->kind != EXPR_REFERENCE)
- return NULL;
+static unsigned get_object_alignment(expression_t const *expr);
- return expression->reference.entity;
+static unsigned get_address_alignment(expression_t const *const expr)
+{
+ if (expr->kind == EXPR_UNARY_TAKE_ADDRESS) {
+ return get_object_alignment(expr->unary.value);
+ } else {
+ type_t *const type = skip_typeref(expr->base.type);
+ assert(is_type_pointer(type));
+ return get_type_alignment(type->pointer.points_to);
+ }
}
-static unsigned get_cparser_entity_alignment(const entity_t *entity)
+static unsigned get_object_alignment(expression_t const *const expr)
{
- switch (entity->kind) {
- case DECLARATION_KIND_CASES:
- return entity->declaration.alignment;
- case ENTITY_STRUCT:
- case ENTITY_UNION:
- return entity->compound.alignment;
- case ENTITY_TYPEDEF:
- return entity->typedefe.alignment;
- default:
- break;
+ entity_t *ent;
+ switch (expr->kind) {
+ case EXPR_ARRAY_ACCESS: return get_address_alignment(expr->array_access.array_ref);
+ case EXPR_UNARY_DEREFERENCE: return get_address_alignment(expr->unary.value);
+ case EXPR_REFERENCE: ent = expr->reference.entity; break;
+ case EXPR_SELECT: ent = expr->select.compound_entry; break;
+ default: return get_type_alignment(expr->base.type);
}
- return 0;
+ assert(is_declaration(ent));
+ return ent->declaration.alignment;
}
/**
*/
static ir_node *alignof_to_firm(const typeprop_expression_t *expression)
{
- unsigned alignment = 0;
-
- const expression_t *tp_expression = expression->tp_expression;
- if (tp_expression != NULL) {
- entity_t *entity = get_expression_entity(tp_expression);
- if (entity != NULL) {
- alignment = get_cparser_entity_alignment(entity);
- }
- }
-
- if (alignment == 0) {
- type_t *type = expression->type;
- alignment = get_type_alignment(type);
- }
+ unsigned const alignment = expression->tp_expression
+ ? get_object_alignment(expression->tp_expression)
+ : get_type_alignment(expression->type);
dbg_info *dbgi = get_dbg_info(&expression->base.pos);
ir_mode *mode = get_ir_mode_storage(expression->base.type);
ir_tarval *fold_constant_to_tarval(const expression_t *expression)
{
- assert(is_constant_expression(expression) == EXPR_CLASS_CONSTANT);
+ assert(is_constant_expression(expression) >= EXPR_CLASS_CONSTANT);
bool constant_folding_old = constant_folding;
constant_folding = true;
static complex_constant fold_complex_constant(const expression_t *expression)
{
- assert(is_constant_expression(expression) == EXPR_CLASS_CONSTANT);
+ assert(is_constant_expression(expression) >= EXPR_CLASS_CONSTANT);
bool constant_folding_old = constant_folding;
constant_folding = true;
const builtin_constant_expression_t *expression)
{
ir_mode *const mode = get_ir_mode_storage(expression->base.type);
- bool const v = is_constant_expression(expression->value) == EXPR_CLASS_CONSTANT;
+ bool const v = is_constant_expression(expression->value) != EXPR_CLASS_VARIABLE;
return create_Const_from_bool(mode, v);
}
switch (expr->kind) {
case EXPR_UNARY_CAST:
- if (is_type_atomic(skip_typeref(expr->base.type), ATOMIC_TYPE_BOOL)) {
+ if (!is_type_atomic(skip_typeref(expr->base.type), ATOMIC_TYPE_BOOL))
+ return create_cast(&expr->unary);
+ /* FALLTHROUGH */
case EXPR_BINARY_EQUAL:
case EXPR_BINARY_GREATER:
case EXPR_BINARY_GREATEREQUAL:
case EXPR_BINARY_LOGICAL_AND:
case EXPR_BINARY_LOGICAL_OR:
case EXPR_BINARY_NOTEQUAL:
- case EXPR_UNARY_NOT:;
- jump_target true_target;
- jump_target false_target;
- init_jump_target(&true_target, NULL);
- init_jump_target(&false_target, NULL);
- expression_to_control_flow(expr, &true_target, &false_target);
- return control_flow_to_1_0(expr, &true_target, &false_target);
- } else {
- return create_cast(&expr->unary);
- }
+ case EXPR_UNARY_NOT: {
+ jump_target true_target;
+ jump_target false_target;
+ init_jump_target(&true_target, NULL);
+ init_jump_target(&false_target, NULL);
+ expression_to_control_flow(expr, &true_target, &false_target);
+ return control_flow_to_1_0(expr, &true_target, &false_target);
+ }
case EXPR_BINARY_ADD:
case EXPR_BINARY_BITWISE_AND:
jump_target *const true_target, jump_target *const false_target,
ir_relation relation);
-static complex_value create_complex_condition_evaluation(
- const expression_t *const expression, jump_target *const true_target,
- jump_target *const false_target);
+static complex_value complex_to_control_flow(const expression_t *expression,
+ jump_target *true_target,
+ jump_target *false_target);
/**
* create a short-circuit expression evaluation that tries to construct
evaluate_expression_discard_result(expr->binary.left);
return expression_to_control_flow(expr->binary.right, true_target, false_target);
- ir_node *val;
- ir_node *left;
- ir_node *right;
- ir_relation relation;
-
case EXPR_BINARY_EQUAL:
case EXPR_BINARY_GREATER:
case EXPR_BINARY_GREATEREQUAL:
case EXPR_BINARY_LESS:
case EXPR_BINARY_LESSEQUAL:
case EXPR_BINARY_NOTEQUAL: {
- type_t *const type = skip_typeref(expr->binary.left->base.type);
- relation = get_relation(expr->kind);
+ type_t *const type = skip_typeref(expr->binary.left->base.type);
+ ir_relation const relation = get_relation(expr->kind);
if (is_type_complex(type)) {
complex_equality_evaluation(&expr->binary, true_target,
false_target, relation);
- /* TODO return something sensible */
return NULL;
}
- dbg_info *const dbgi = get_dbg_info(&expr->base.pos);
- ir_mode *const mode = get_ir_mode_arithmetic(type);
- val = NULL;
- left = create_conv(dbgi, expression_to_value(expr->binary.left), mode);
- right = create_conv(dbgi, expression_to_value(expr->binary.right), mode);
- goto make_cmp;
+ dbg_info *const dbgi = get_dbg_info(&expr->base.pos);
+ ir_mode *const mode = get_ir_mode_arithmetic(type);
+ ir_node *const left = create_conv(dbgi, expression_to_value(expr->binary.left), mode);
+ ir_node *const right = create_conv(dbgi, expression_to_value(expr->binary.right), mode);
+ compare_to_control_flow(expr, left, right, relation, true_target, false_target);
+ return NULL;
}
case EXPR_UNARY_CAST:
if (is_type_atomic(skip_typeref(expr->base.type), ATOMIC_TYPE_BOOL)) {
expression_to_control_flow(expr->unary.value, true_target, false_target);
return NULL;
- } else {
- default:;
- type_t *const type = skip_typeref(expr->base.type);
- if (is_type_complex(type)) {
- create_complex_condition_evaluation(expr, true_target, false_target);
- return NULL;
- }
-
- dbg_info *const dbgi = get_dbg_info(&expr->base.pos);
- ir_mode *const mode = get_ir_mode_arithmetic(type);
- val = create_conv(dbgi, expression_to_value(expr), mode);
- left = val;
- right = new_Const(get_mode_null(get_irn_mode(val)));
- relation = ir_relation_unordered_less_greater;
-make_cmp:
- compare_to_control_flow(expr, left, right, relation, true_target, false_target);
- return val;
}
+ /* FALLTHROUGH */
+ default: {
+ type_t *const type = skip_typeref(expr->base.type);
+ if (is_type_complex(type)) {
+ complex_to_control_flow(expr, true_target, false_target);
+ return NULL;
+ }
+
+ dbg_info *const dbgi = get_dbg_info(&expr->base.pos);
+ ir_mode *const mode = get_ir_mode_arithmetic(type);
+ ir_node *const val = create_conv(dbgi, expression_to_value(expr), mode);
+ ir_node *const left = val;
+ ir_node *const right = new_Const(get_mode_null(get_irn_mode(val)));
+ ir_relation const relation = ir_relation_unordered_less_greater;
+ compare_to_control_flow(expr, left, right, relation, true_target, false_target);
+ return val;
+ }
}
}
complex_value value)
{
value = complex_conv_to_storage(dbgi, value, type);
- ir_graph *irg = current_ir_graph;
- ir_type *irtype = get_ir_type(type);
- ir_node *mem = get_store();
- ir_node *nomem = get_irg_no_mem(irg);
- ir_mode *mode = get_complex_mode_storage(type);
- ir_node *real = create_conv(dbgi, value.real, mode);
- ir_node *imag = create_conv(dbgi, value.imag, mode);
- ir_node *storer = new_d_Store(dbgi, mem, addr, real, cons_floats);
- ir_node *memr = new_Proj(storer, mode_M, pn_Store_M);
- set_store(memr);
- ir_node *mem2 = get_store();
- ir_mode *mode_uint = atomic_modes[ATOMIC_TYPE_UINT];
- ir_node *one = new_Const(get_mode_one(mode_uint));
- ir_node *in[1] = { one };
- ir_entity *arrent = get_array_element_entity(irtype);
- ir_node *addri = new_d_Sel(dbgi, nomem, addr, 1, in, arrent);
- ir_node *storei = new_d_Store(dbgi, mem2, addri, imag, cons_floats);
- ir_node *memi = new_Proj(storei, mode_M, pn_Store_M);
+ ir_graph *const irg = current_ir_graph;
+ ir_type *const irtype = get_ir_type(type);
+ ir_node *const mem = get_store();
+ ir_node *const nomem = get_irg_no_mem(irg);
+ ir_mode *const mode = get_complex_mode_storage(type);
+ ir_node *const real = create_conv(dbgi, value.real, mode);
+ ir_node *const imag = create_conv(dbgi, value.imag, mode);
+ ir_node *const storer = new_d_Store(dbgi, mem, addr, real, cons_floats);
+ ir_node *const memr = new_Proj(storer, mode_M, pn_Store_M);
+ ir_mode *const muint = atomic_modes[ATOMIC_TYPE_UINT];
+ ir_node *const one = new_Const(get_mode_one(muint));
+ ir_node *const in[1] = { one };
+ ir_entity *const arrent = get_array_element_entity(irtype);
+ ir_node *const addri = new_d_Sel(dbgi, nomem, addr, 1, in, arrent);
+ ir_node *const storei = new_d_Store(dbgi, memr, addri, imag, cons_floats);
+ ir_node *const memi = new_Proj(storei, mode_M, pn_Store_M);
set_store(memi);
}
static ir_node *complex_to_memory(dbg_info *dbgi, type_t *type,
complex_value value)
{
- ir_graph *irg = current_ir_graph;
- ir_type *frame_type = get_irg_frame_type(irg);
- ident *id = id_unique("cmplex_tmp.%u");
- ir_type *irtype = get_ir_type(type);
- ir_entity *tmp_storage = new_entity(frame_type, id, irtype);
+ ir_graph *const irg = current_ir_graph;
+ ir_type *const frame_type = get_irg_frame_type(irg);
+ ident *const id = id_unique("cmplex_tmp.%u");
+ ir_type *const irtype = get_ir_type(type);
+ ir_entity *const tmp_storage = new_entity(frame_type, id, irtype);
+ ir_node *const frame = get_irg_frame(irg);
+ ir_node *const nomem = get_irg_no_mem(irg);
+ ir_node *const addr = new_simpleSel(nomem, frame, tmp_storage);
set_entity_compiler_generated(tmp_storage, 1);
- ir_node *frame = get_irg_frame(irg);
- ir_node *nomem = get_irg_no_mem(irg);
- ir_node *addr = new_simpleSel(nomem, frame, tmp_storage);
store_complex(dbgi, addr, type, value);
return addr;
}
if (type->base.qualifiers & TYPE_QUALIFIER_VOLATILE)
flags |= cons_volatile;
- ir_mode *const mode = get_complex_mode_storage(type);
- ir_node *const memory = get_store();
- ir_node *const load = new_d_Load(dbgi, memory, addr, mode, flags);
- ir_node *const load_mem = new_Proj(load, mode_M, pn_Load_M);
- ir_node *const load_res = new_Proj(load, mode, pn_Load_res);
- set_store(load_mem);
+ ir_mode *const mode = get_complex_mode_storage(type);
+ ir_node *const memory = get_store();
+ ir_node *const load = new_d_Load(dbgi, memory, addr, mode, flags);
+ ir_node *const load_mem = new_Proj(load, mode_M, pn_Load_M);
+ ir_node *const load_res = new_Proj(load, mode, pn_Load_res);
ir_type *const irtype = get_ir_type(type);
ir_mode *const mode_uint = atomic_modes[ATOMIC_TYPE_UINT];
ir_entity *const entity = get_array_element_entity(irtype);
ir_node *const nomem = get_irg_no_mem(current_ir_graph);
ir_node *const addr2 = new_Sel(nomem, addr, 1, in, entity);
- ir_node *const mem2 = get_store();
- ir_node *const load2 = new_d_Load(dbgi, mem2, addr2, mode, flags);
+ ir_node *const load2 = new_d_Load(dbgi, load_mem, addr2, mode, flags);
ir_node *const load_mem2 = new_Proj(load2, mode_M, pn_Load_M);
ir_node *const load_res2 = new_Proj(load2, mode, pn_Load_res);
set_store(load_mem2);
static complex_value complex_select_to_firm(const select_expression_t *select)
{
- dbg_info *dbgi = get_dbg_info(&select->base.pos);
- ir_node *addr = select_addr(select);
- type_t *type = skip_typeref(select->base.type);
- assert(is_type_complex(type));
+ dbg_info *const dbgi = get_dbg_info(&select->base.pos);
+ ir_node *const addr = select_addr(select);
+ type_t *const type = skip_typeref(select->base.type);
return complex_deref_address(dbgi, type, addr, cons_none);
}
static complex_value complex_cast_to_firm(const unary_expression_t *expression)
{
- const expression_t *value = expression->value;
- dbg_info *dbgi = get_dbg_info(&expression->base.pos);
- type_t *from_type = skip_typeref(value->base.type);
- type_t *to_type = skip_typeref(expression->base.type);
- ir_mode *mode = get_complex_mode_storage(to_type);
-
- assert(is_type_complex(to_type));
+ const expression_t *const value = expression->value;
+ dbg_info *const dbgi = get_dbg_info(&expression->base.pos);
+ type_t *const from_type = skip_typeref(value->base.type);
+ type_t *const to_type = skip_typeref(expression->base.type);
+ ir_mode *const mode = get_complex_mode_storage(to_type);
if (is_type_complex(from_type)) {
complex_value cvalue = expression_to_complex(value);
return complex_conv(dbgi, cvalue, mode);
} else {
- ir_node *value_node = expression_to_value(value);
- ir_node *zero = new_Const(get_mode_null(mode));
- ir_node *casted = create_conv(dbgi, value_node, mode);
+ ir_node *const value_node = expression_to_value(value);
+ ir_node *const zero = new_Const(get_mode_null(mode));
+ ir_node *const casted = create_conv(dbgi, value_node, mode);
return (complex_value) { casted, zero };
}
}
complex_value value,
ir_node *addr)
{
- type_t *type = skip_typeref(expression->base.type);
- assert(is_type_complex(type));
-
- ir_mode *mode = get_complex_mode_storage(type);
- ir_node *real = create_conv(dbgi, value.real, mode);
- ir_node *imag = create_conv(dbgi, value.imag, mode);
+ type_t *const type = skip_typeref(expression->base.type);
+ ir_mode *const mode = get_complex_mode_storage(type);
+ ir_node *const real = create_conv(dbgi, value.real, mode);
+ ir_node *const imag = create_conv(dbgi, value.imag, mode);
if (expression->kind == EXPR_REFERENCE) {
const reference_expression_t *ref = &expression->reference;
set_unreachable_now();
}
-static complex_value create_complex_condition_evaluation(
+static complex_value complex_to_control_flow(
const expression_t *const expression, jump_target *const true_target,
jump_target *const false_target)
{
jump_target extra_target;
init_jump_target(&extra_target, NULL);
complex_value value = expression_to_complex(expression);
+ if (is_Const(value.real) && is_Const(value.imag)) {
+ ir_tarval *tv_real = get_Const_tarval(value.real);
+ ir_tarval *tv_imag = get_Const_tarval(value.imag);
+ if (tarval_is_null(tv_real) && tarval_is_null(tv_imag)) {
+ jump_to_target(false_target);
+ } else {
+ jump_to_target(true_target);
+ }
+ set_unreachable_now();
+ return value;
+ }
+
dbg_info *const dbgi = get_dbg_info(&expression->base.pos);
type_t *const type = expression->base.type;
ir_mode *const mode = get_complex_mode_arithmetic(type);
static complex_value complex_conditional_to_firm(
const conditional_expression_t *const expression)
{
- /* first try to fold a constant condition */
- if (is_constant_expression(expression->condition) == EXPR_CLASS_CONSTANT) {
- bool val = fold_constant_to_bool(expression->condition);
- if (val) {
- expression_t *true_expression = expression->true_expression;
- if (true_expression == NULL) {
- /* we will evaluate true_expression a second time here, but in
- * this case it is harmless since constant expression have no
- * side effects */
- true_expression = expression->condition;
- }
- return expression_to_complex(true_expression);
- } else {
- return expression_to_complex(expression->false_expression);
- }
- }
-
jump_target true_target;
jump_target false_target;
init_jump_target(&true_target, NULL);
memset(&cond_val, 0, sizeof(cond_val));
if (expression->true_expression == NULL) {
assert(is_type_complex(skip_typeref(expression->condition->base.type)));
- cond_val
- = create_complex_condition_evaluation(expression->condition,
- &true_target, &false_target);
+ cond_val = complex_to_control_flow(expression->condition,
+ &true_target, &false_target);
} else {
expression_to_control_flow(expression->condition, &true_target, &false_target);
}
- complex_value val;
+ complex_value val;
memset(&val, 0, sizeof(val));
- jump_target exit_target;
+ jump_target exit_target;
init_jump_target(&exit_target, NULL);
+ type_t *const type = skip_typeref(expression->base.type);
+ ir_mode *const mode = get_complex_mode_arithmetic(type);
+ dbg_info *const dbgi = get_dbg_info(&expression->base.pos);
if (enter_jump_target(&true_target)) {
if (expression->true_expression) {
assert(cond_val.real != NULL);
val = cond_val;
}
+ val = complex_conv(dbgi, val, mode);
jump_to_target(&exit_target);
}
- type_t *const type = skip_typeref(expression->base.type);
if (enter_jump_target(&false_target)) {
complex_value false_val
= expression_to_complex(expression->false_expression);
+ false_val = complex_conv(dbgi, false_val, mode);
jump_to_target(&exit_target);
if (val.real != NULL) {
ir_node *const inr[] = { val.real, false_val.real };
ir_node *const ini[] = { val.imag, false_val.imag };
- dbg_info *const dbgi = get_dbg_info(&expression->base.pos);
- ir_mode *const mode = get_complex_mode_arithmetic(type);
ir_node *const block = exit_target.block;
val.real = new_rd_Phi(dbgi, block, lengthof(inr), inr, mode);
val.imag = new_rd_Phi(dbgi, block, lengthof(ini), ini, mode);
if (!enter_jump_target(&exit_target)) {
set_cur_block(new_Block(0, NULL));
assert(!is_type_void(type));
- ir_mode *mode = get_complex_mode_arithmetic(type);
- val.real = new_Unknown(mode);
- val.imag = val.real;
+ val.real = val.imag = new_Bad(mode);
}
return val;
}
+static void create_local_declarations(entity_t*);
+
+static complex_value compound_statement_to_firm_complex(
+ const compound_statement_t *compound)
+{
+ create_local_declarations(compound->scope.entities);
+
+ complex_value result = { NULL, NULL };
+ statement_t *statement = compound->statements;
+ statement_t *next;
+ for ( ; statement != NULL; statement = next) {
+ next = statement->base.next;
+ /* last statement is the return value */
+ if (next == NULL) {
+ /* it must be an expression, otherwise we wouldn't be in the
+ * complex variant of compound_statement_to_firm */
+ if (statement->kind != STATEMENT_EXPRESSION)
+ panic("last member of complex statement expression not an expression statement");
+ expression_t *expression = statement->expression.expression;
+ assert(is_type_complex(skip_typeref(expression->base.type)));
+ result = expression_to_complex(expression);
+ } else {
+ statement_to_firm(statement);
+ }
+ }
+
+ return result;
+}
+
+static complex_value complex_assign_to_firm(const binary_expression_t *expr)
+{
+ dbg_info *const dbgi = get_dbg_info(&expr->base.pos);
+ complex_value const value = expression_to_complex(expr->right);
+ ir_node *const addr = expression_to_addr(expr->left);
+ set_complex_value_for_expression(dbgi, expr->left, value, addr);
+ return value;
+}
+
+static complex_value complex_statement_expression_to_firm(
+ const statement_expression_t *const expr)
+{
+ const statement_t *const statement = expr->statement;
+ assert(statement->kind == STATEMENT_COMPOUND);
+
+ return compound_statement_to_firm_complex(&statement->compound);
+}
+
static complex_value expression_to_complex(const expression_t *expression)
{
switch (expression->kind) {
return complex_negate_to_firm(&expression->unary);
case EXPR_UNARY_COMPLEMENT:
return complex_complement_to_firm(&expression->unary);
- case EXPR_BINARY_ASSIGN: {
- const binary_expression_t *binexpr = &expression->binary;
- dbg_info *dbgi = get_dbg_info(&binexpr->base.pos);
- complex_value value = expression_to_complex(binexpr->right);
- ir_node *addr = expression_to_addr(binexpr->left);
- set_complex_value_for_expression(dbgi, binexpr->left, value, addr);
- return value;
- }
+ case EXPR_BINARY_ASSIGN:
+ return complex_assign_to_firm(&expression->binary);
case EXPR_LITERAL_CASES:
return complex_literal_to_firm(&expression->literal);
case EXPR_CALL:
return complex_call_to_firm(&expression->call);
case EXPR_CONDITIONAL:
return complex_conditional_to_firm(&expression->conditional);
-
+ case EXPR_STATEMENT:
+ return complex_statement_expression_to_firm(&expression->statement);
default:
- break;
+ panic("unexpected complex expression");
}
- panic("complex expression not implemented yet");
}
{
assert(entity->kind == ENTITY_VARIABLE);
initializer_t *initializer = entity->variable.initializer;
+ if (entity->variable.alias != NULL) {
+ const namespace_tag_t namespc = (namespace_tag_t)entity->base.namespc;
+ entity_t *a = entity->variable.alias->entity;
+ for (; a != NULL; a = a->base.symbol_next) {
+ if ((namespace_tag_t)a->base.namespc == namespc)
+ break;
+ }
+ assert(a != NULL && a->kind == ENTITY_VARIABLE && a->variable.v.entity != NULL);
+ set_entity_alias(entity->variable.v.entity, a->variable.v.entity);
+ /* prevent usage assumption to be made about aliased variables */
+ add_entity_linkage(a->variable.v.entity, IR_LINKAGE_HIDDEN_USER);
+ }
if (initializer == NULL)
return;
&& get_entity_owner(irentity) != get_tls_type()) {
add_entity_linkage(irentity, IR_LINKAGE_CONSTANT);
}
- ir_initializer_t *initializer = create_initializer_compound(2);
+ ir_initializer_t *complex_init = create_initializer_compound(2);
ir_initializer_t *reali = create_initializer_const(real);
- set_initializer_compound_value(initializer, 0, reali);
+ set_initializer_compound_value(complex_init, 0, reali);
ir_initializer_t *imagi = create_initializer_const(imag);
- set_initializer_compound_value(initializer, 1, imagi);
- set_entity_initializer(irentity, initializer);
+ set_initializer_compound_value(complex_init, 1, imagi);
+ set_entity_initializer(irentity, complex_init);
}
return;
} else if (!is_type_scalar(init_type)) {
type_t *type = skip_typeref(expression->base.type);
if (is_type_complex(type)) {
expression_to_complex(expression);
- return NULL; /* TODO */
+ return NULL;
} else {
return expression_to_value(statement->expression);
}
}
-static void create_local_declarations(entity_t*);
-
static ir_node *compound_statement_to_firm(compound_statement_t *compound)
{
create_local_declarations(compound->scope.entities);
expression_t *const cond = statement->condition;
/* Avoid an explicit body block in case of do ... while (0);. */
- if (is_constant_expression(cond) == EXPR_CLASS_CONSTANT && !fold_constant_to_bool(cond)) {
+ if (is_constant_expression(cond) != EXPR_CLASS_VARIABLE && !fold_constant_to_bool(cond)) {
/* do ... while (0);. */
statement_to_firm(statement->body);
jump_to_target(&continue_target);
/* Create the condition. */
expression_t *const cond = statement->condition;
- if (cond && (is_constant_expression(cond) != EXPR_CLASS_CONSTANT || !fold_constant_to_bool(cond))) {
+ if (cond && (is_constant_expression(cond) == EXPR_CLASS_VARIABLE || !fold_constant_to_bool(cond))) {
jump_target body_target;
init_jump_target(&body_target, NULL);
expression_to_control_flow(cond, &body_target, &break_target);
for (; entity != end; entity = entity->base.next) {
if ((entity->kind == ENTITY_VARIABLE || entity->kind == ENTITY_PARAMETER) &&
!var_needs_entity(&entity->variable)) {
- ++count;
- if (is_type_complex(skip_typeref(entity->declaration.type)))
- ++count;
+ type_t *type = skip_typeref(entity->declaration.type);
+ count += is_type_complex(type) ? 2 : 1;
}
}
return count;
assert(entity->kind == ENTITY_FUNCTION);
ir_entity *function_entity = get_function_entity(entity, current_outer_frame);
+ if (entity->function.alias != NULL) {
+ const namespace_tag_t namespc = (namespace_tag_t)entity->base.namespc;
+ entity_t *a = entity->function.alias->entity;
+ for (; a != NULL; a = a->base.symbol_next) {
+ if ((namespace_tag_t)a->base.namespc == namespc)
+ break;
+ }
+// TODO: or use entitymap
+// ir_entity *a = entitymap_get(&entitymap, entity->function.alias);
+ assert(a != NULL && a->kind == ENTITY_VARIABLE && a->function.irentity != NULL);
+ set_entity_alias(entity->function.irentity, a->function.irentity);
+ /* prevent usage assumption to be made about aliased functions */
+ add_entity_linkage(a->function.irentity, IR_LINKAGE_HIDDEN_USER);
+ }
+
if (entity->function.body == NULL)
return;
irg_finalize_cons(irg);
- /* finalize the frame type */
- ir_type *frame_type = get_irg_frame_type(irg);
- int n = get_compound_n_members(frame_type);
- int align_all = 4;
- int offset = 0;
- for (int i = 0; i < n; ++i) {
- ir_entity *member = get_compound_member(frame_type, i);
- ir_type *entity_type = get_entity_type(member);
-
- int align = get_type_alignment_bytes(entity_type);
- if (align > align_all)
- align_all = align;
- int misalign = 0;
- if (align > 0) {
- misalign = offset % align;
- if (misalign > 0) {
- offset += align - misalign;
- }
- }
-
- set_entity_offset(member, offset);
- offset += get_type_size_bytes(entity_type);
- }
- set_type_size_bytes(frame_type, offset);
- set_type_alignment_bytes(frame_type, align_all);
-
irg_verify(irg, VERIFY_ENFORCE_SSA);
current_vararg_entity = old_current_vararg_entity;
current_function = old_current_function;