#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\n",
+ declaration->type, declaration->symbol);
return new_r_Unknown(irg, mode);
}
return get_array_type_size(&type->array);
case TYPE_BUILTIN:
return get_type_size(type->builtin.real_type);
+ case TYPE_BITFIELD:
+ panic("type size of bitfield request");
case TYPE_TYPEDEF:
case TYPE_TYPEOF:
case TYPE_INVALID:
ident *id = get_mode_ident(mode);
ir_type *irtype = new_type_primitive(id, mode);
- if(type->atype == ATOMIC_TYPE_LONG_DOUBLE) {
+ if(type->atype == ATOMIC_TYPE_LONG_DOUBLE
+ || type->atype == ATOMIC_TYPE_DOUBLE) {
set_type_alignment_bytes(irtype, 4);
}
return ir_type;
}
+/**
+ * Return the signed integer type of size bits.
+ *
+ * @param size the size
+ */
+static ir_type *get_signed_int_type_for_bit_size(ir_type *base_tp,
+ unsigned size)
+{
+ static ir_mode *s_modes[64 + 1] = {NULL, };
+ ir_type *res;
+ ir_mode *mode;
+
+ if (size <= 0 || size > 64)
+ return NULL;
+
+ mode = s_modes[size];
+ if (mode == NULL) {
+ char name[32];
+
+ snprintf(name, sizeof(name), "bf_I%u", size);
+ mode = new_ir_mode(name, irms_int_number, size, 1, irma_twos_complement,
+ size <= 32 ? 32 : size );
+ s_modes[size] = mode;
+ }
+
+ char name[32];
+ snprintf(name, sizeof(name), "I%u", size);
+ ident *id = new_id_from_str(name);
+ res = new_type_primitive(mangle_u(get_type_ident(base_tp), id), mode);
+ set_primitive_base_type(res, base_tp);
+
+ return res;
+}
+
+/**
+ * Return the unsigned integer type of size bits.
+ *
+ * @param size the size
+ */
+static ir_type *get_unsigned_int_type_for_bit_size(ir_type *base_tp,
+ unsigned size)
+{
+ static ir_mode *u_modes[64 + 1] = {NULL, };
+ ir_type *res;
+ ir_mode *mode;
+
+ if (size <= 0 || size > 64)
+ return NULL;
+
+ mode = u_modes[size];
+ if (mode == NULL) {
+ char name[32];
+
+ snprintf(name, sizeof(name), "bf_U%u", size);
+ mode = new_ir_mode(name, irms_int_number, size, 0, irma_twos_complement,
+ size <= 32 ? 32 : size );
+ u_modes[size] = mode;
+ }
+
+ char name[32];
+
+ snprintf(name, sizeof(name), "U%u", size);
+ ident *id = new_id_from_str(name);
+ res = new_type_primitive(mangle_u(get_type_ident(base_tp), id), mode);
+ set_primitive_base_type(res, base_tp);
+
+ return res;
+}
+
+static ir_type *create_bitfield_type(bitfield_type_t *const type)
+{
+ type_t *base = skip_typeref(type->base);
+ assert(base->kind == TYPE_ATOMIC);
+ ir_type *irbase = get_ir_type(base);
+
+ unsigned size = fold_constant(type->size);
+
+ assert(!is_type_floating(base));
+ if(is_type_signed(base)) {
+ return get_signed_int_type_for_bit_size(irbase, size);
+ } else {
+ return get_unsigned_int_type_for_bit_size(irbase, size);
+ }
+}
+
#define INVALID_TYPE ((ir_type_ptr)-1)
static ir_type *create_struct_type(compound_type_t *type)
} else {
id = unique_ident("__anonymous_struct");
}
- ir_type *ir_type = new_type_struct(id);
+ ir_type *irtype = new_type_struct(id);
- type->type.firm_type = ir_type;
+ type->type.firm_type = irtype;
- int align_all = 1;
- int offset = 0;
+ size_t align_all = 1;
+ size_t offset = 0;
+ size_t bit_offset = 0;
declaration_t *entry = type->declaration->context.declarations;
for( ; entry != NULL; entry = entry->next) {
if(entry->namespc != NAMESPACE_NORMAL)
continue;
- ident *ident = new_id_from_str(entry->symbol->string);
- ir_type_ptr entry_ir_type = get_ir_type(entry->type);
+ type_t *entry_type = skip_typeref(entry->type);
+ ir_type *base_irtype;
+ if(entry_type->kind == TYPE_BITFIELD) {
+ base_irtype = get_ir_type(entry_type->bitfield.base);
+ } else {
+ base_irtype = get_ir_type(entry_type);
+ }
- int entry_size = get_type_size_bytes(entry_ir_type);
- int entry_alignment = get_type_alignment_bytes(entry_ir_type);
- int misalign = offset % entry_alignment;
- if (misalign != 0)
- offset += entry_alignment - misalign;
+ size_t entry_alignment = get_type_alignment_bytes(base_irtype);
+ size_t misalign = offset % entry_alignment;
- dbg_info *const dbgi = get_dbg_info(&entry->source_position);
- ir_entity *const entity = new_d_entity(ir_type, ident, entry_ir_type, dbgi);
- set_entity_offset(entity, offset);
- add_struct_member(ir_type, entity);
- entry->declaration_kind = DECLARATION_KIND_COMPOUND_MEMBER;
- entry->v.entity = entity;
+ dbg_info *dbgi = get_dbg_info(&entry->source_position);
+ ir_entity *entity = NULL;
+ if(entry->symbol != NULL) {
+ ident *ident = new_id_from_str(entry->symbol->string);
+ ir_type *entry_irtype = get_ir_type(entry_type);
+ entity = new_d_entity(irtype, ident, entry_irtype, dbgi);
+ } else {
+ /* only bitfields are allowed to be anonymous */
+ assert(entry_type->kind == TYPE_BITFIELD);
+ }
+
+ size_t base;
+ size_t bits_remainder;
+ if(entry_type->kind == TYPE_BITFIELD) {
+ size_t size_bits = fold_constant(entry_type->bitfield.size);
+ size_t rest_size_bits = (entry_alignment - misalign)*8 - bit_offset;
+
+ if(size_bits > rest_size_bits) {
+ /* start a new bucket */
+ offset += entry_alignment - misalign;
+ bit_offset = 0;
+
+ base = offset;
+ bits_remainder = 0;
+ } else {
+ /* put into current bucket */
+ base = offset - misalign;
+ bits_remainder = misalign * 8 + bit_offset;
+ }
+
+ offset += size_bits / 8;
+ bit_offset = bit_offset + (size_bits % 8);
+ } else {
+ size_t entry_size = get_type_size_bytes(base_irtype);
+ if(misalign > 0 || bit_offset > 0)
+ offset += entry_alignment - misalign;
+
+ base = offset;
+ bits_remainder = 0;
+ offset += entry_size;
+ bit_offset = 0;
+ }
- offset += entry_size;
if(entry_alignment > align_all) {
if(entry_alignment % align_all != 0) {
- panic("Uneven alignments not supported yet");
+ panic("uneven alignments not supported yet");
}
align_all = entry_alignment;
}
+
+ if(entity != NULL) {
+ set_entity_offset(entity, base);
+ set_entity_offset_bits_remainder(entity,
+ (unsigned char) bits_remainder);
+ add_struct_member(irtype, entity);
+ entry->declaration_kind = DECLARATION_KIND_COMPOUND_MEMBER;
+ entry->v.entity = entity;
+ }
}
- int misalign = offset % align_all;
- offset += misalign;
- set_type_alignment_bytes(ir_type, align_all);
- set_type_size_bytes(ir_type, offset);
- set_type_state(ir_type, layout_fixed);
+ size_t misalign = offset % align_all;
+ if(misalign > 0 || bit_offset > 0) {
+ offset += align_all - misalign;
+ }
+ set_type_alignment_bytes(irtype, align_all);
+ set_type_size_bytes(irtype, offset);
+ set_type_state(irtype, layout_fixed);
- return ir_type;
+ return irtype;
}
static ir_type *create_union_type(compound_type_t *type)
} else {
id = unique_ident("__anonymous_union");
}
- ir_type *ir_type = new_type_union(id);
+ ir_type *irtype = new_type_union(id);
- type->type.firm_type = ir_type;
+ type->type.firm_type = irtype;
int align_all = 1;
int size = 0;
if(entry->namespc != NAMESPACE_NORMAL)
continue;
- ident *ident = new_id_from_str(entry->symbol->string);
- ir_type_ptr entry_ir_type = get_ir_type(entry->type);
+ ident *ident = new_id_from_str(entry->symbol->string);
+ ir_type *entry_ir_type = get_ir_type(entry->type);
int entry_size = get_type_size_bytes(entry_ir_type);
int entry_alignment = get_type_alignment_bytes(entry_ir_type);
dbg_info *const dbgi = get_dbg_info(&entry->source_position);
- ir_entity *const entity = new_d_entity(ir_type, ident, entry_ir_type, dbgi);
- add_union_member(ir_type, entity);
+ ir_entity *const entity = new_d_entity(irtype, ident, entry_ir_type,
+ dbgi);
+ add_union_member(irtype, entity);
set_entity_offset(entity, 0);
entry->declaration_kind = DECLARATION_KIND_COMPOUND_MEMBER;
entry->v.entity = entity;
}
}
- set_type_alignment_bytes(ir_type, align_all);
- set_type_size_bytes(ir_type, size);
- set_type_state(ir_type, layout_fixed);
+ set_type_alignment_bytes(irtype, align_all);
+ set_type_size_bytes(irtype, size);
+ set_type_state(irtype, layout_fixed);
- return ir_type;
+ return irtype;
}
static ir_node *expression_to_firm(const expression_t *expression);
case TYPE_BUILTIN:
firm_type = get_ir_type(type->builtin.real_type);
break;
+ case TYPE_BITFIELD:
+ firm_type = create_bitfield_type(&type->bitfield);
+ break;
+
case TYPE_TYPEOF:
case TYPE_TYPEDEF:
case TYPE_INVALID:
/* We should check for file scope here, but as long as we compile C only
this is not needed. */
- int n_params = get_method_n_params(ir_type_method);
- int n_res = get_method_n_ress(ir_type_method);
- ir_ident_ptr id = get_entity_ident(entity);
- int i;
+ int n_params = get_method_n_params(ir_type_method);
+ int n_res = get_method_n_ress(ir_type_method);
+ int i;
if (n_params == 0 && n_res == 0 && id == predef_idents[rts_abort]) {
/* found abort(), store for later */
return new_d_Const(dbgi, mode, tv);
}
-static ir_node *create_symconst(dbg_info *dbgi, ir_mode *mode, ir_entity *entity)
+static ir_node *create_symconst(dbg_info *dbgi, ir_mode *mode,
+ ir_entity *entity)
{
assert(entity != NULL);
union symconst_symbol sym;
}
}
+/* Returns the correct base address depending on whether it is a parameter or a
+ * normal local variable */
+static ir_node *get_local_frame(ir_entity *const ent)
+{
+ ir_graph *const irg = current_ir_graph;
+ const ir_type *const owner = get_entity_owner(ent);
+ if (owner == get_irg_frame_type(irg)) {
+ return get_irg_frame(irg);
+ } else {
+ assert(owner == get_method_value_param_type(get_entity_type(get_irg_entity(irg))));
+ return get_irg_value_param_base(irg);
+ }
+}
+
static ir_node *reference_expression_to_firm(const reference_expression_t *ref)
{
dbg_info *dbgi = get_dbg_info(&ref->expression.source_position);
case DECLARATION_KIND_LOCAL_VARIABLE_ENTITY: {
ir_entity *entity = declaration->v.entity;
- ir_node *frame = get_irg_frame(current_ir_graph);
+ ir_node *frame = get_local_frame(entity);
ir_node *sel = new_d_simpleSel(dbgi, new_NoMem(), frame, entity);
ir_type *irtype = get_entity_type(entity);
return deref_address(irtype, sel, dbgi);
}
case DECLARATION_KIND_LOCAL_VARIABLE_ENTITY: {
ir_entity *entity = declaration->v.entity;
- ir_node *frame = get_irg_frame(current_ir_graph);
+ ir_node *frame = get_local_frame(entity);
ir_node *sel = new_d_simpleSel(dbgi, new_NoMem(), frame, entity);
return sel;
{
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);
* - const rel val
* - var rel var
*/
-static ir_node *handle_assume_compare(dbg_info *dbi, const binary_expression_t *expression)
+static ir_node *handle_assume_compare(dbg_info *dbi,
+ const binary_expression_t *expression)
{
expression_t *op1 = expression->left;
expression_t *op2 = expression->right;
}
}
+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;
panic("trying to get address of non-lvalue");
}
+static ir_node *builtin_constant_to_firm(
+ const builtin_constant_expression_t *expression)
+{
+ ir_mode *mode = get_ir_mode(expression->expression.datatype);
+ long v;
+
+ if (is_constant_expression(expression->value)) {
+ v = 1;
+ } else {
+ v = 0;
+ }
+ return new_Const_long(mode, v);
+}
+
+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 */
+ (void) adr;
+ return NULL;
+}
+
static ir_node *_expression_to_firm(const expression_t *expression)
{
switch(expression->kind) {
case EXPR_OFFSETOF:
case EXPR_BUILTIN_SYMBOL:
panic("unimplemented expression found");
+ case EXPR_BUILTIN_CONSTANT_P:
+ return builtin_constant_to_firm(&expression->builtin_constant);
+ case EXPR_BUILTIN_PREFETCH:
+ return builtin_prefetch_to_firm(&expression->builtin_prefetch);
case EXPR_UNKNOWN:
case EXPR_INVALID:
}
}
+/**
+ * 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;
}
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);
}
}
{
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) {
switch(expression->base.kind) {
case EXPR_STATEMENT:
return count_decls_in_stmts(expression->statement.statement);
- EXPR_BINARY_CASES
- return count_decls_in_expression(expression->binary.left)
- + count_decls_in_expression(expression->binary.right);
+ EXPR_BINARY_CASES {
+ int count_left = count_decls_in_expression(expression->binary.left);
+ int count_right = count_decls_in_expression(expression->binary.right);
+ return count_left + count_right;
+ }
EXPR_UNARY_CASES
return count_decls_in_expression(expression->unary.value);
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);
/* set inline flags */
if (declaration->is_inline)
set_irg_inline_property(irg, irg_inline_recomended);
- handle_decl_modifier_irg(irg, declaration->decl_modifiers);
+ handle_decl_modifier_irg(irg, declaration->modifiers);
next_value_number_function = 0;
initialize_function_parameters(declaration);
goto create_var;
create_var:
- create_declaration_entity(declaration, DECLARATION_KIND_GLOBAL_VARIABLE,
+ create_declaration_entity(declaration,
+ DECLARATION_KIND_GLOBAL_VARIABLE,
var_type);
set_entity_visibility(declaration->v.entity, vis);