/**
* Creates a Firm type for an imaginary type
*/
-static ir_type *create_imaginary_type(const imaginary_type_t *type)
+static ir_type *create_imaginary_type(imaginary_type_t *type)
{
atomic_type_kind_t kind = type->akind;
ir_mode *mode = atomic_modes[kind];
ident *id = get_mode_ident(mode);
ir_type *irtype = new_type_primitive(id, mode);
- il_alignment_t alignment = get_type_alignment((const type_t*) type);
+ il_alignment_t alignment = get_type_alignment((type_t*) type);
set_type_alignment_bytes(irtype, alignment);
/**
* Construct firm type from ast struct type.
- *
- * As anonymous inner structs get flattened to a single firm type, we might get
- * irtype, outer_offset and out_align passed (they represent the position of
- * the anonymous inner struct inside the resulting firm struct)
*/
-static ir_type *create_compound_type(compound_type_t *type, ir_type *irtype,
- size_t *outer_offset, size_t *outer_align,
+static ir_type *create_compound_type(compound_type_t *type,
bool incomplete, bool is_union)
{
compound_t *compound = type->compound;
return compound->irtype;
}
- size_t align_all = 1;
- size_t offset = 0;
- size_t bit_offset = 0;
- size_t size = 0;
-
- if (irtype == NULL) {
- symbol_t *symbol = compound->base.symbol;
- ident *id;
- if (symbol != NULL) {
- id = new_id_from_str(symbol->string);
- } else {
- if (is_union) {
- id = id_unique("__anonymous_union.%u");
- } else {
- id = id_unique("__anonymous_struct.%u");
- }
- }
- dbg_info *dbgi = get_dbg_info(&compound->base.source_position);
-
+ symbol_t *symbol = compound->base.symbol;
+ ident *id;
+ if (symbol != NULL) {
+ id = new_id_from_str(symbol->string);
+ } else {
if (is_union) {
- irtype = new_d_type_union(id, dbgi);
+ id = id_unique("__anonymous_union.%u");
} else {
- irtype = new_d_type_struct(id, dbgi);
+ id = id_unique("__anonymous_struct.%u");
}
+ }
+ dbg_info *dbgi = get_dbg_info(&compound->base.source_position);
- compound->irtype_complete = false;
- compound->irtype = irtype;
+ ir_type *irtype;
+ if (is_union) {
+ irtype = new_d_type_union(id, dbgi);
} else {
- offset = *outer_offset;
- align_all = *outer_align;
+ irtype = new_d_type_struct(id, dbgi);
}
+ compound->irtype_complete = false;
+ compound->irtype = irtype;
+
if (incomplete)
return irtype;
+ if (is_union) {
+ layout_union_type(type);
+ } else {
+ layout_struct_type(type);
+ }
+
compound->irtype_complete = true;
entity_t *entry = compound->members.entities;
if (entry->kind != ENTITY_COMPOUND_MEMBER)
continue;
- size_t prev_offset = offset;
-
symbol_t *symbol = entry->base.symbol;
- type_t *entry_type = skip_typeref(entry->declaration.type);
- dbg_info *dbgi = get_dbg_info(&entry->base.source_position);
-
+ type_t *entry_type = entry->declaration.type;
ident *ident;
- if (symbol != NULL) {
- ident = new_id_from_str(symbol->string);
- } else {
- if (entry_type->kind == TYPE_COMPOUND_STRUCT) {
- create_compound_type(&entry_type->compound, irtype, &offset,
- &align_all, false, COMPOUND_IS_STRUCT);
- goto finished_member;
- } else if (entry_type->kind == TYPE_COMPOUND_UNION) {
- create_compound_type(&entry_type->compound, irtype, &offset,
- &align_all, false, COMPOUND_IS_UNION);
- goto finished_member;
- } else {
- assert(entry_type->kind == TYPE_BITFIELD);
- }
+ if (symbol == NULL) {
+ /* anonymous bitfield member, skip */
+ if (entry_type->kind == TYPE_BITFIELD)
+ continue;
+ assert(entry_type->kind == TYPE_COMPOUND_STRUCT
+ || entry_type->kind == TYPE_COMPOUND_UNION);
ident = id_unique("anon.%u");
- }
-
- ir_type *base_irtype;
- if (entry_type->kind == TYPE_BITFIELD) {
- base_irtype = get_ir_type(entry_type->bitfield.base_type);
} else {
- base_irtype = get_ir_type(entry_type);
+ ident = new_id_from_str(symbol->string);
}
- size_t entry_alignment = get_type_alignment_bytes(base_irtype);
- size_t misalign = offset % entry_alignment;
+ dbg_info *dbgi = get_dbg_info(&entry->base.source_position);
ir_type *entry_irtype = get_ir_type(entry_type);
ir_entity *entity = new_d_entity(irtype, ident, entry_irtype, dbgi);
- size_t base;
- size_t bits_remainder;
- if (entry_type->kind == TYPE_BITFIELD) {
- size_t size_bits = entry_type->bitfield.bit_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;
- }
-
- if (entry_alignment > align_all) {
- if (entry_alignment % align_all != 0) {
- panic("uneven alignments not supported yet");
- }
- align_all = entry_alignment;
- }
-
- set_entity_offset(entity, base);
+ set_entity_offset(entity, entry->compound_member.offset);
set_entity_offset_bits_remainder(entity,
- (unsigned char) bits_remainder);
- //add_struct_member(irtype, entity);
- entry->declaration.kind = DECLARATION_KIND_COMPOUND_MEMBER;
- assert(entry->compound_member.entity == NULL);
- entry->compound_member.entity = entity;
+ entry->compound_member.bit_offset);
-finished_member:
- if (is_union) {
- size_t entry_size = offset - prev_offset;
- if (entry_size > size) {
- size = entry_size;
- }
- offset = 0;
- bit_offset = 0;
- }
- }
-
- if (!is_union) {
- size = offset;
- }
-
- size_t misalign = offset % align_all;
- if (misalign > 0 || bit_offset > 0) {
- size += align_all - misalign;
+ assert(entry->declaration.kind == DECLARATION_KIND_UNKNOWN);
+ entry->declaration.kind = DECLARATION_KIND_COMPOUND_MEMBER;
+ entry->compound_member.entity = entity;
}
- if (outer_offset != NULL) {
- if (!is_union) {
- *outer_offset = offset;
- } else {
- *outer_offset += size;
- }
-
- if (align_all > *outer_align) {
- if (align_all % *outer_align != 0) {
- panic("uneven alignments not supported yet");
- }
- *outer_align = align_all;
- }
- } else {
- set_type_alignment_bytes(irtype, align_all);
- set_type_size_bytes(irtype, size);
- set_type_state(irtype, layout_fixed);
- }
+ set_type_alignment_bytes(irtype, compound->alignment);
+ set_type_size_bytes(irtype, compound->size);
+ set_type_state(irtype, layout_fixed);
return irtype;
}
switch (type->kind) {
case TYPE_COMPOUND_STRUCT:
- return create_compound_type(&type->compound, NULL, NULL, NULL,
- true, COMPOUND_IS_STRUCT);
+ return create_compound_type(&type->compound, true, COMPOUND_IS_STRUCT);
case TYPE_COMPOUND_UNION:
- return create_compound_type(&type->compound, NULL, NULL, NULL,
- true, COMPOUND_IS_UNION);
+ return create_compound_type(&type->compound, true, COMPOUND_IS_UNION);
default:
return get_ir_type(type);
}
firm_type = create_array_type(&type->array);
break;
case TYPE_COMPOUND_STRUCT:
- firm_type = create_compound_type(&type->compound, NULL, NULL, NULL,
- false, COMPOUND_IS_STRUCT);
+ firm_type = create_compound_type(&type->compound, false, COMPOUND_IS_STRUCT);
break;
case TYPE_COMPOUND_UNION:
- firm_type = create_compound_type(&type->compound, NULL, NULL, NULL,
- false, COMPOUND_IS_UNION);
+ firm_type = create_compound_type(&type->compound, false, COMPOUND_IS_UNION);
break;
case TYPE_ENUM:
firm_type = create_enum_type(&type->enumt);
static ir_entity *get_function_entity(entity_t *entity, ir_type *owner_type)
{
assert(entity->kind == ENTITY_FUNCTION);
- if (entity->function.entity != NULL) {
- return entity->function.entity;
+ if (entity->function.irentity != NULL) {
+ return entity->function.irentity;
}
if (is_main(entity)) {
entitymap_insert(&entitymap, symbol, irentity);
entity_created:
- entity->declaration.kind = DECLARATION_KIND_FUNCTION;
- entity->function.entity = irentity;
+ entity->declaration.kind = DECLARATION_KIND_FUNCTION;
+ entity->function.irentity = irentity;
return irentity;
}
set_entity_ld_ident(entity, id);
set_entity_variability(entity, variability_constant);
set_entity_allocation(entity, allocation_static);
+ set_entity_visibility(entity, visibility_local);
ir_type *const elem_type = ir_type_const_char;
ir_mode *const mode = get_type_mode(elem_type);
return res;
}
- return create_symconst(dbgi, mode, entity->function.entity);
+ return create_symconst(dbgi, mode, entity->function.irentity);
}
case DECLARATION_KIND_INNER_FUNCTION: {
ir_mode *const mode = get_ir_mode_storage(type);
if (!entity->function.goto_to_outer && !entity->function.need_closure) {
/* inner function not using the closure */
- return create_symconst(dbgi, mode, entity->function.entity);
+ return create_symconst(dbgi, mode, entity->function.irentity);
} else {
/* need trampoline here */
- return create_trampoline(dbgi, mode, entity->function.entity);
+ return create_trampoline(dbgi, mode, entity->function.irentity);
}
}
case DECLARATION_KIND_GLOBAL_VARIABLE: {
case DECLARATION_KIND_FUNCTION: {
type_t *const type = skip_typeref(entity->declaration.type);
ir_mode *const mode = get_ir_mode_storage(type);
- return create_symconst(dbgi, mode, entity->function.entity);
+ return create_symconst(dbgi, mode, entity->function.irentity);
}
case DECLARATION_KIND_INNER_FUNCTION: {
ir_mode *const mode = get_ir_mode_storage(type);
if (!entity->function.goto_to_outer && !entity->function.need_closure) {
/* inner function not using the closure */
- return create_symconst(dbgi, mode, entity->function.entity);
+ return create_symconst(dbgi, mode, entity->function.irentity);
} else {
/* need trampoline here */
- return create_trampoline(dbgi, mode, entity->function.entity);
+ return create_trampoline(dbgi, mode, entity->function.irentity);
}
}
return NULL;
case bk_gnu_builtin_frame_address: {
expression_t *const expression = call->arguments->expression;
- long val = fold_constant(expression);
- if (val == 0) {
+ bool val = fold_constant_to_bool(expression);
+ if (!val) {
/* the nice case */
return get_irg_frame(current_ir_graph);
} else {
const reference_expression_t *ref = &function->reference;
entity_t *entity = ref->entity;
- if (ref->entity->kind == ENTITY_FUNCTION &&
- ref->entity->function.btk != bk_none) {
- return process_builtin_call(call);
- }
+ if (entity->kind == ENTITY_FUNCTION) {
+ if (entity->function.btk != bk_none) {
+ return process_builtin_call(call);
+ }
- if (entity->kind == ENTITY_FUNCTION
- && entity->function.entity == rts_entities[rts_alloca]) {
- /* handle alloca() call */
- expression_t *argument = call->arguments->expression;
- ir_node *size = expression_to_firm(argument);
- ir_mode *mode = get_ir_mode_arithmetic(type_size_t);
+ ir_entity *irentity = entity->function.irentity;
+ if (irentity == NULL)
+ irentity = get_function_entity(entity, NULL);
- size = create_conv(dbgi, size, mode);
+ if (irentity == rts_entities[rts_alloca]) {
+ /* handle alloca() call */
+ expression_t *argument = call->arguments->expression;
+ ir_node *size = expression_to_firm(argument);
+ ir_mode *mode = get_ir_mode_arithmetic(type_size_t);
- ir_node *store = get_store();
- ir_node *alloca = new_d_Alloc(dbgi, store, size, firm_unknown_type,
- stack_alloc);
- ir_node *proj_m = new_Proj(alloca, mode_M, pn_Alloc_M);
- set_store(proj_m);
- ir_node *res = new_Proj(alloca, mode_P_data, pn_Alloc_res);
+ size = create_conv(dbgi, size, mode);
- return res;
+ ir_node *store = get_store();
+ ir_node *alloca = new_d_Alloc(dbgi, store, size,
+ firm_unknown_type, stack_alloc);
+ ir_node *proj_m = new_Proj(alloca, mode_M, pn_Alloc_M);
+ set_store(proj_m);
+ ir_node *res = new_Proj(alloca, mode_P_data, pn_Alloc_res);
+
+ return res;
+ }
}
}
ir_node *callee = expression_to_firm(function);
ir_mode *mode = get_ir_mode_arithmetic(type);
if (is_constant_expression(expression->left)) {
- long val = fold_constant(expression->left);
+ bool val = fold_constant_to_bool(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) {
- if (val == 0) {
+ if (!val) {
return new_Const(get_mode_null(mode));
}
} else {
- if (val != 0) {
+ if (val) {
return new_Const(get_mode_one(mode));
}
}
if (is_constant_expression(expression->right)) {
- long const valr = fold_constant(expression->right);
- return valr != 0 ?
+ bool valr = fold_constant_to_bool(expression->right);
+ return valr ?
new_Const(get_mode_one(mode)) :
new_Const(get_mode_null(mode));
}
assert(designator->array_index != NULL);
assert(is_type_array(type));
- long index = fold_constant(array_index);
+ long index = fold_constant_to_int(array_index);
ir_type *arr_type = get_ir_type(type);
ir_type *elem_type = get_array_element_type(arr_type);
long elem_size = get_type_size_bytes(elem_type);
static void init_ir_types(void);
-long fold_constant(const expression_t *expression)
+static tarval *fold_constant_to_tarval(const expression_t *expression)
{
- if (expression->kind == EXPR_INVALID)
- return 0;
-
assert(is_type_valid(skip_typeref(expression->base.type)));
bool constant_folding_old = constant_folding;
panic("couldn't fold constant");
}
+ constant_folding = constant_folding_old;
+
tarval *tv = get_Const_tarval(cnst);
+ return tv;
+}
+
+long fold_constant_to_int(const expression_t *expression)
+{
+ if (expression->kind == EXPR_INVALID)
+ return 0;
+
+ tarval *tv = fold_constant_to_tarval(expression);
if (!tarval_is_long(tv)) {
panic("result of constant folding is not integer");
}
- constant_folding = constant_folding_old;
-
return get_tarval_long(tv);
}
+bool fold_constant_to_bool(const expression_t *expression)
+{
+ if (expression->kind == EXPR_INVALID)
+ return false;
+ tarval *tv = fold_constant_to_tarval(expression);
+ return !tarval_is_null(tv);
+}
+
static ir_node *conditional_to_firm(const conditional_expression_t *expression)
{
dbg_info *const dbgi = get_dbg_info(&expression->base.source_position);
/* first try to fold a constant condition */
if (is_constant_expression(expression->condition)) {
- long val = fold_constant(expression->condition);
+ bool val = fold_constant_to_bool(expression->condition);
if (val) {
expression_t *true_expression = expression->true_expression;
if (true_expression == NULL)
if (is_builtin_expect(expression) && is_Cond(cond)) {
call_argument_t *argument = expression->call.arguments->next;
if (is_constant_expression(argument->expression)) {
- long cnst = fold_constant(argument->expression);
+ bool cnst = fold_constant_to_bool(argument->expression);
cond_jmp_predicate pred;
- if (cnst == 0) {
+ if (cnst == false) {
pred = COND_JMP_PRED_FALSE;
} else {
pred = COND_JMP_PRED_TRUE;
assert(designator->array_index != NULL);
assert(is_type_array(type));
- long index = fold_constant(array_index);
+ long index = fold_constant_to_int(array_index);
assert(index >= 0);
#ifndef NDEBUG
if (type->array.size_constant) {
/* shortcut for while(true) */
if (is_constant_expression(statement->condition)
- && fold_constant(statement->condition) != 0) {
+ && fold_constant_to_bool(statement->condition) != 0) {
set_cur_block(header_block);
ir_node *header_jmp = new_Jmp();
add_immBlock_pred(body_block, header_jmp);
if (entity->function.statement == NULL)
return;
+ if (is_main(entity) && firm_opt.os_support == OS_SUPPORT_MINGW) {
+ prepare_main_collect2(entity);
+ }
+
inner_functions = NULL;
current_trampolines = NULL;