#include "type_t.h"
#include "ast_t.h"
#include "parser.h"
+#include "diagnostic.h"
#include "lang_features.h"
#include "driver/firm_opt.h"
#include "driver/firm_cmdline.h"
ir_node *uninitialized_local_var(ir_graph *irg, ir_mode *mode, int pos)
{
- (void) pos;
-#if 0
- const declaration_t *declaration = & value_numbers[pos]->declaration;
+ const declaration_t *declaration = get_irg_loc_description(irg, pos);
- print_warning_prefix(declaration->source_position);
- fprintf(stderr, "variable '%s' might be used uninitialized\n",
- declaration->symbol->string);
-#endif
- fprintf(stderr, "Some variable might be used uninitialized\n");
+ warningf(declaration->source_position, "variable '%#T' might be used uninitialized",
+ declaration->type, declaration->symbol);
return new_r_Unknown(irg, mode);
}
static ir_mode *get_atomic_mode(const atomic_type_t* atomic_type)
{
ir_mode *res = NULL;
- if ((unsigned)atomic_type->atype < (unsigned)ATOMIC_TYPE_LAST)
- res = _atomic_modes[(unsigned)atomic_type->atype];
+ if ((unsigned)atomic_type->akind < (unsigned)ATOMIC_TYPE_LAST)
+ res = _atomic_modes[(unsigned)atomic_type->akind];
if (res == NULL)
panic("Encountered unknown atomic type");
return res;
static unsigned get_atomic_type_size(const atomic_type_t *type)
{
- switch(type->atype) {
+ switch(type->akind) {
case ATOMIC_TYPE_CHAR:
case ATOMIC_TYPE_SCHAR:
case ATOMIC_TYPE_UCHAR:
type = skip_typeref(type);
switch(type->kind) {
+ case TYPE_ERROR:
+ panic("error type occured");
case TYPE_ATOMIC:
return get_atomic_type_size(&type->atomic);
case TYPE_ENUM:
ident *id = get_mode_ident(mode);
ir_type *irtype = new_type_primitive(id, mode);
- if(type->atype == ATOMIC_TYPE_LONG_DOUBLE
- || type->atype == ATOMIC_TYPE_DOUBLE) {
+ if(type->akind == ATOMIC_TYPE_LONG_DOUBLE
+ || type->akind == ATOMIC_TYPE_DOUBLE) {
set_type_alignment_bytes(irtype, 4);
}
unsigned size = fold_constant(type->size);
- assert(!is_type_floating(base));
+ assert(!is_type_float(base));
if(is_type_signed(base)) {
return get_signed_int_type_for_bit_size(irbase, size);
} else {
size_t align_all = 1;
size_t offset = 0;
size_t bit_offset = 0;
- declaration_t *entry = type->declaration->context.declarations;
+ declaration_t *entry = type->declaration->scope.declarations;
for( ; entry != NULL; entry = entry->next) {
if(entry->namespc != NAMESPACE_NORMAL)
continue;
}
size_t misalign = offset % align_all;
- if(misalign > 0) {
+ if(misalign > 0 || bit_offset > 0) {
offset += align_all - misalign;
}
set_type_alignment_bytes(irtype, align_all);
int align_all = 1;
int size = 0;
- declaration_t *entry = declaration->context.declarations;
+ declaration_t *entry = declaration->scope.declarations;
for( ; entry != NULL; entry = entry->next) {
if(entry->namespc != NAMESPACE_NORMAL)
continue;
ir_type *firm_type = NULL;
switch(type->kind) {
+ case TYPE_ERROR:
+ panic("error type occured");
case TYPE_ATOMIC:
firm_type = create_atomic_type(&type->atomic);
break;
static ir_node *string_to_firm(const source_position_t *const src_pos,
const char *const id_prefix,
- const char *const string)
+ const string_t *const value)
{
ir_type *const global_type = get_glob_type();
ir_type *const type = new_type_array(unique_ident("strtype"), 1,
ir_type *const elem_type = ir_type_const_char;
ir_mode *const mode = get_type_mode(elem_type);
- const size_t slen = strlen(string) + 1;
+ const char* const string = value->begin;
+ const size_t slen = value->size;
set_array_lower_bound_int(type, 0, 0);
set_array_upper_bound_int(type, 0, slen);
const string_literal_expression_t* literal)
{
return string_to_firm(&literal->expression.source_position, "Lstr",
- literal->value);
+ &literal->value);
}
static ir_node *wide_string_literal_to_firm(
{
value = do_strict_conv(dbgi, value);
- ir_node *memory = get_store();
+ ir_node *memory = get_store();
if(is_type_scalar(type)) {
ir_node *store = new_d_Store(dbgi, memory, addr, value);
}
}
+static tarval *create_bitfield_mask(ir_mode *mode, int offset, int size)
+{
+ tarval *all_one = get_mode_all_one(mode);
+ int mode_size = get_mode_size_bits(mode);
+
+ assert(offset >= 0 && size >= 0);
+ assert(offset + size <= mode_size);
+ if(size == mode_size) {
+ return all_one;
+ }
+
+ long shiftr = get_mode_size_bits(mode) - size;
+ long shiftl = offset;
+ tarval *tv_shiftr = new_tarval_from_long(shiftr, mode_uint);
+ tarval *tv_shiftl = new_tarval_from_long(shiftl, mode_uint);
+ tarval *mask0 = tarval_shr(all_one, tv_shiftr);
+ tarval *mask1 = tarval_shl(mask0, tv_shiftl);
+
+ return mask1;
+}
+
+static void bitfield_store_to_firm(const unary_expression_t *expression,
+ ir_node *value)
+{
+ expression_t *select = expression->value;
+ assert(select->kind == EXPR_SELECT);
+ type_t *type = select->base.datatype;
+ assert(type->kind == TYPE_BITFIELD);
+ ir_mode *mode = get_ir_mode(type->bitfield.base);
+ ir_node *addr = expression_to_addr(select);
+
+ assert(get_irn_mode(value) == mode);
+
+ dbg_info *dbgi = get_dbg_info(&expression->expression.source_position);
+
+ /* kill upper bits of value and shift to right position */
+ ir_entity *entity = select->select.compound_entry->v.entity;
+ int bitoffset = get_entity_offset_bits_remainder(entity);
+ ir_type *entity_type = get_entity_type(entity);
+ int bitsize = get_mode_size_bits(get_type_mode(entity_type));
+
+ tarval *mask = create_bitfield_mask(mode, 0, bitsize);
+ ir_node *mask_node = new_d_Const(dbgi, mode, mask);
+ ir_node *value_masked = new_d_And(dbgi, value, mask_node, mode);
+ tarval *shiftl = new_tarval_from_long(bitoffset, mode_uint);
+ ir_node *shiftcount = new_d_Const(dbgi, mode_uint, shiftl);
+ ir_node *value_maskshift = new_d_Shl(dbgi, value_masked, shiftcount, mode);
+
+ /* load current value */
+ ir_node *mem = get_store();
+ ir_node *load = new_d_Load(dbgi, mem, addr, mode);
+ ir_node *load_mem = new_d_Proj(dbgi, load, mode_M, pn_Load_M);
+ ir_node *load_res = new_d_Proj(dbgi, load, mode, pn_Load_res);
+ tarval *shift_mask = create_bitfield_mask(mode, bitoffset, bitsize);
+ tarval *inv_mask = tarval_not(shift_mask);
+ ir_node *inv_mask_node = new_d_Const(dbgi, mode, inv_mask);
+ ir_node *load_res_masked = new_d_And(dbgi, load_res, inv_mask_node, mode);
+
+ /* construct new value and store */
+ ir_node *new_val = new_d_Or(dbgi, load_res_masked, value_maskshift, mode);
+ ir_node *store = new_d_Store(dbgi, load_mem, addr, new_val);
+ ir_node *store_mem = new_d_Proj(dbgi, store, mode_M, pn_Store_M);
+ set_store(store_mem);
+}
+
static void set_value_for_expression(const expression_t *expression,
ir_node *value)
{
}
}
+ if(expression->kind == EXPR_UNARY_BITFIELD_EXTRACT) {
+ bitfield_store_to_firm(&expression->unary, value);
+ return;
+ }
+
ir_node *addr = expression_to_addr(expression);
type_t *type = skip_typeref(expression->base.datatype);
assign_value(dbgi, addr, type, value);
}
}
+static ir_node *bitfield_extract_to_firm(const unary_expression_t *expression)
+{
+ expression_t *select = expression->value;
+ assert(select->kind == EXPR_SELECT);
+
+ type_t *type = select->base.datatype;
+ assert(type->kind == TYPE_BITFIELD);
+ ir_mode *mode = get_ir_mode(type->bitfield.base);
+ dbg_info *dbgi = get_dbg_info(&expression->expression.source_position);
+ ir_node *addr = expression_to_addr(select);
+ ir_node *mem = get_store();
+ ir_node *load = new_d_Load(dbgi, mem, addr, mode);
+ ir_node *load_mem = new_d_Proj(dbgi, load, mode_M, pn_Load_M);
+ ir_node *load_res = new_d_Proj(dbgi, load, mode, pn_Load_res);
+
+ load_res = create_conv(dbgi, load_res, mode_int);
+
+ set_store(load_mem);
+
+ /* kill upper bits */
+ ir_entity *entity = select->select.compound_entry->v.entity;
+ int bitoffset = get_entity_offset_bits_remainder(entity);
+ ir_type *entity_type = get_entity_type(entity);
+ int bitsize = get_mode_size_bits(get_type_mode(entity_type));
+ long shift_bitsl = machine_size - bitoffset - bitsize;
+ assert(shift_bitsl >= 0);
+ tarval *tvl = new_tarval_from_long(shift_bitsl, mode_uint);
+ ir_node *countl = new_d_Const(dbgi, mode_uint, tvl);
+ ir_node *shiftl = new_d_Shl(dbgi, load_res, countl, mode_int);
+
+ long shift_bitsr = bitoffset + shift_bitsl;
+ assert(shift_bitsr <= (long) machine_size);
+ tarval *tvr = new_tarval_from_long(shift_bitsr, mode_uint);
+ ir_node *countr = new_d_Const(dbgi, mode_uint, tvr);
+ ir_node *shiftr;
+ if(mode_is_signed(mode)) {
+ shiftr = new_d_Shrs(dbgi, shiftl, countr, mode_int);
+ } else {
+ shiftr = new_d_Shr(dbgi, shiftl, countr, mode_int);
+ }
+
+ return create_conv(dbgi, shiftr, mode);
+}
+
static ir_node *unary_expression_to_firm(const unary_expression_t *expression)
{
dbg_info *dbgi = get_dbg_info(&expression->expression.source_position);
return handle_assume(dbgi, value);
else
return NULL;
+ case EXPR_UNARY_BITFIELD_EXTRACT:
+ return bitfield_extract_to_firm(expression);
default:
break;
return deref_address(irtype, addr, dbgi);
}
-static ir_node *sizeof_to_firm(const sizeof_expression_t *expression)
+/**
+ * Transform a sizeof expression into Firm code.
+ */
+static ir_node *sizeof_to_firm(const typeprop_expression_t *expression)
{
type_t *type = expression->type;
if(type == NULL) {
- type = expression->size_expression->base.datatype;
+ type = expression->tp_expression->base.datatype;
assert(type != NULL);
}
return new_SymConst(mode, sym, symconst_type_size);
}
-static ir_node *alignof_to_firm(const alignof_expression_t *expression)
+/**
+ * Transform an alignof expression into Firm code.
+ */
+static ir_node *alignof_to_firm(const typeprop_expression_t *expression)
{
- type_t *const type = expression->type;
+ type_t *type = expression->type;
+ if(type == NULL) {
+ /* beware: if expression is a variable reference, return the
+ alignment of the variable. */
+ const expression_t *tp_expression = expression->tp_expression;
+ const declaration_t *declaration = expr_is_variable(tp_expression);
+ if (declaration != NULL) {
+ /* TODO: get the alignment of this variable. */
+ }
+ type = tp_expression->base.datatype;
+ assert(type != NULL);
+ }
+
ir_mode *const mode = get_ir_mode(expression->expression.datatype);
symconst_symbol sym;
sym.type_p = get_ir_type(type);
{
case TYPE_ATOMIC: {
const atomic_type_t *const atomic_type = &type->atomic;
- switch (atomic_type->atype) {
+ switch (atomic_type->akind) {
/* should not be reached */
case ATOMIC_TYPE_INVALID:
tc = no_type_class;
const source_position_t *const src_pos =
&expr->expression.source_position;
const char *const name = current_function_decl->symbol->string;
- current_function_name = string_to_firm(src_pos, "__func__", name);
+ const string_t string = { name, strlen(name) + 1 };
+ current_function_name = string_to_firm(src_pos, "__func__", &string);
}
return current_function_name;
panic("trying to get address of non-lvalue");
}
-static ir_node *builtin_constant_to_firm(const builtin_constant_expression_t *expression)
+static ir_node *builtin_constant_to_firm(
+ const builtin_constant_expression_t *expression)
{
ir_mode *mode = get_ir_mode(expression->expression.datatype);
long v;
return new_Const_long(mode, v);
}
-static ir_node *builtin_prefetch_to_firm(const builtin_prefetch_expression_t *expression)
+static ir_node *builtin_prefetch_to_firm(
+ const builtin_prefetch_expression_t *expression)
{
ir_node *adr = expression_to_firm(expression->adr);
/* no Firm support for prefetch yet */
case EXPR_ARRAY_ACCESS:
return array_access_to_firm(&expression->array_access);
case EXPR_SIZEOF:
- return sizeof_to_firm(&expression->sizeofe);
+ return sizeof_to_firm(&expression->typeprop);
case EXPR_ALIGNOF:
- return alignof_to_firm(&expression->alignofe);
+ return alignof_to_firm(&expression->typeprop);
case EXPR_CONDITIONAL:
return conditional_to_firm(&expression->conditional);
case EXPR_SELECT:
{
declaration_t *compound_declaration = type->declaration;
- declaration_t *compound_entry = compound_declaration->context.declarations;
+ declaration_t *compound_entry = compound_declaration->scope.declarations;
compound_graph_path_entry_t entry;
entry.type = COMPOUND_GRAPH_ENTRY_COMPOUND;
entry.prev = last_entry;
++len;
- ir_type *irtype = get_entity_type(entity);
- size_t arr_len = get_array_type_size(type);
- const char *p = initializer->string;
- size_t i = 0;
- for(i = 0; i < arr_len; ++i, ++p) {
+ ir_type *const irtype = get_entity_type(entity);
+ size_t arr_len = get_array_type_size(type);
+ const char *const p = initializer->string.begin;
+ if (initializer->string.size < arr_len) {
+ arr_len = initializer->string.size;
+ }
+ for (size_t i = 0; i < arr_len; ++i) {
entry.v.array_index = i;
- ir_node *node = new_Const_long(mode_Bs, *p);
+ ir_node *node = new_Const_long(mode_Bs, p[i]);
compound_graph_path *path = create_compound_path(irtype, &entry, len);
add_compound_ent_value_w_path(entity, node, path);
-
- if(*p == '\0')
- break;
}
}
}
}
+/**
+ * Creates a Firm local variable from a declaration.
+ */
static void create_local_variable(declaration_t *declaration)
{
assert(declaration->declaration_kind == DECLARATION_KIND_UNKNOWN);
} else {
declaration->declaration_kind = DECLARATION_KIND_LOCAL_VARIABLE;
declaration->v.value_number = next_value_number_function;
+ set_irg_loc_description(current_ir_graph, next_value_number_function, declaration);
++next_value_number_function;
}
ir_node *result = NULL;
statement_t *statement = compound->statements;
for( ; statement != NULL; statement = statement->base.next) {
- //context2firm(&statement->context);
+ //context2firm(&statement->scope);
if(statement->base.next == NULL
&& statement->kind == STATEMENT_EXPRESSION) {
declaration_t *declaration = statement->declarations_begin;
declaration_t *end = statement->declarations_end->next;
for( ; declaration != end; declaration = declaration->next) {
+ if(declaration->namespc != NAMESPACE_NORMAL)
+ continue;
create_local_variable(declaration);
}
}
}
/* create declarations */
- declaration_t *declaration = statement->context.declarations;
+ declaration_t *declaration = statement->scope.declarations;
for( ; declaration != NULL; declaration = declaration->next) {
create_local_declaration(declaration);
}
current_switch_cond = cond;
break_label = break_block;
- statement_to_firm(statement->body);
+ if (statement->body != NULL) {
+ statement_to_firm(statement->body);
+ }
if(get_cur_block() != NULL) {
ir_node *jmp = new_Jmp();
{
int count = 0;
for (; decl != end; decl = decl->next) {
+ if(decl->namespc != NAMESPACE_NORMAL)
+ continue;
const type_t *type = skip_typeref(decl->type);
- switch (type->kind) {
- case TYPE_ATOMIC:
- case TYPE_ENUM:
- case TYPE_POINTER:
- if (!decl->address_taken)
- ++count;
- break;
-
- default: break;
- }
+ if (!decl->address_taken && is_type_scalar(type))
+ ++count;
const initializer_t *initializer = decl->init.initializer;
/* FIXME: should walk initializer hierarchies... */
if(initializer != NULL && initializer->kind == INITIALIZER_VALUE) {
case STATEMENT_FOR: {
const for_statement_t *const for_stmt = &stmt->fors;
- count += count_local_declarations(for_stmt->context.declarations, NULL);
+ count += count_local_declarations(for_stmt->scope.declarations, NULL);
count += count_decls_in_expression(for_stmt->initialisation);
count += count_decls_in_expression(for_stmt->condition);
count += count_decls_in_expression(for_stmt->step);
int count = 0;
/* count parameters */
- count += count_local_declarations(declaration->context.declarations, NULL);
+ count += count_local_declarations(declaration->scope.declarations, NULL);
/* count local variables declared in body */
count += count_decls_in_stmts(declaration->init.statement);
ir_type *function_irtype = get_ir_type(declaration->type);
int n = 0;
- declaration_t *parameter = declaration->context.declarations;
+ declaration_t *parameter = declaration->scope.declarations;
for( ; parameter != NULL; parameter = parameter->next, ++n) {
assert(parameter->declaration_kind == DECLARATION_KIND_UNKNOWN);
type_t *type = skip_typeref(parameter->type);
parameter->declaration_kind = DECLARATION_KIND_LOCAL_VARIABLE;
parameter->v.value_number = next_value_number_function;
+ set_irg_loc_description(current_ir_graph, next_value_number_function, parameter);
++next_value_number_function;
set_value(parameter->v.value_number, proj);
panic("Invalid storage class for global variable");
}
-static void context_to_firm(context_t *context)
+static void scope_to_firm(scope_t *scope)
{
/* first pass: create declarations */
- declaration_t *declaration = context->declarations;
+ declaration_t *declaration = scope->declarations;
for( ; declaration != NULL; declaration = declaration->next) {
if(declaration->namespc != NAMESPACE_NORMAL)
continue;
}
/* second pass: create code */
- declaration = context->declarations;
+ declaration = scope->declarations;
for( ; declaration != NULL; declaration = declaration->next) {
if(declaration->namespc != NAMESPACE_NORMAL)
continue;
break_label = NULL;
current_switch_cond = NULL;
- context_to_firm(&unit->context);
+ scope_to_firm(&unit->scope);
}