Commit 4d2ff733 authored by Matthias Braun's avatar Matthias Braun
Browse files

support for variable sized compound/array types

This adds support for C99/gcc style compound types where the last
element is an array of unspecified size. The compound size is the
minimum size (assuming the array has no elements), or is calculated
by the size of an initializer.
parent a4e78581
......@@ -1880,6 +1880,19 @@ FIRM_API void set_array_element_entity(ir_type *array, ir_entity *ent);
/** Returns the array element entity. */
FIRM_API ir_entity *get_array_element_entity(const ir_type *array);
/**
* Sets the array variable size flag.
* If this flag is set then no upper/lower bounds need to be set and
* get_type_size_bytes() returns -1
*/
FIRM_API void set_array_variable_size(ir_type *array, int variable_size_flag);
/**
* Returns the array variable size flag.
* @see set_array_variable_size()
*/
FIRM_API int is_array_variable_size(const ir_type *array);
/** Returns true if a type is an array type. */
FIRM_API int is_Array_type(const ir_type *array);
......@@ -2188,6 +2201,20 @@ FIRM_API size_t get_compound_member_index(const ir_type *tp, ir_entity *member);
/** Remove a member from a compound type. */
FIRM_API void remove_compound_member(ir_type *compound, ir_entity *entity);
/**
* Sets the variable size flag of a compound type.
* The last member of a variable size compound type may be an array type
* without explicit size. So the get_type_size_bytes() of a variable size
* compound type only returns a minimum size for the type (the size if the
* last members size is 0)
*/
FIRM_API void set_compound_variable_size(ir_type *compound, int variable_size);
/**
* Returns the variable size flag. @see set_compound_variable_size()
*/
FIRM_API int is_compound_variable_size(const ir_type *compound);
/**
* layout members of a struct/union or class type in a default way.
*/
......
......@@ -930,13 +930,6 @@ typedef struct {
} v;
} normal_or_bitfield;
static int is_type_variable_size(ir_type *type)
{
(void) type;
/* TODO */
return 0;
}
static size_t get_initializer_size(const ir_initializer_t *initializer,
ir_type *type)
{
......@@ -948,28 +941,34 @@ static size_t get_initializer_size(const ir_initializer_t *initializer,
case IR_INITIALIZER_NULL:
return get_type_size_bytes(type);
case IR_INITIALIZER_COMPOUND:
if (!is_type_variable_size(type)) {
return get_type_size_bytes(type);
if (is_Array_type(type)) {
if (is_array_variable_size(type)) {
ir_type *element_type = get_array_element_type(type);
unsigned element_size = get_type_size_bytes(element_type);
unsigned element_align
= get_type_alignment_bytes(element_type);
unsigned misalign = element_size % element_align;
size_t n_inits
= get_initializer_compound_n_entries(initializer);
element_size += element_align - misalign;
return n_inits * element_size;
} else {
return get_type_size_bytes(type);
}
} else {
size_t n_entries
= get_initializer_compound_n_entries(initializer);
size_t i;
unsigned initializer_size = get_type_size_bytes(type);
for (i = 0; i < n_entries; ++i) {
ir_entity *entity = get_compound_member(type, i);
ir_type *type = get_entity_type(entity);
const ir_initializer_t *sub_initializer
= get_initializer_compound_value(initializer, i);
unsigned offset = get_entity_offset(entity);
unsigned size = get_initializer_size(sub_initializer, type);
if (offset + size > initializer_size) {
initializer_size = offset + size;
}
assert(is_compound_type(type));
size_t size = get_type_size_bytes(type);
if (is_compound_variable_size(type)) {
/* last initializer has to be an array of variable size */
size_t l = get_initializer_compound_n_entries(initializer)-1;
const ir_initializer_t *last
= get_initializer_compound_value(initializer, l);
const ir_entity *last_ent = get_compound_member(type, l);
ir_type *last_type = get_entity_type(last_ent);
assert(is_array_variable_size(last_type));
size += get_initializer_size(last, last_type);
}
return initializer_size;
return size;
}
}
......
......@@ -46,6 +46,7 @@
#include <string.h>
#include <stdlib.h>
#include <stddef.h>
#include <stdbool.h>
#include "type_t.h"
......@@ -1448,7 +1449,7 @@ ir_type *new_type_array(size_t n_dimensions, ir_type *element_type)
void free_array_automatic_entities(ir_type *array)
{
assert(array && (array->type_op == type_array));
assert(array->type_op == type_array);
free_entity(get_array_element_entity(array));
}
......@@ -1475,7 +1476,7 @@ size_t get_array_n_dimensions(const ir_type *array)
void set_array_bounds(ir_type *array, size_t dimension, ir_node *lower_bound,
ir_node *upper_bound)
{
assert(array && (array->type_op == type_array));
assert(array->type_op == type_array);
assert(lower_bound && "lower_bound node may not be NULL.");
assert(upper_bound && "upper_bound node may not be NULL.");
assert(dimension < array->attr.aa.n_dimensions);
......@@ -1495,7 +1496,7 @@ void set_array_bounds_int(ir_type *array, size_t dimension, int lower_bound,
void set_array_lower_bound(ir_type *array, size_t dimension,
ir_node *lower_bound)
{
assert(array && (array->type_op == type_array));
assert(array->type_op == type_array);
assert(lower_bound && "lower_bound node may not be NULL.");
array->attr.aa.lower_bound[dimension] = lower_bound;
}
......@@ -1509,7 +1510,7 @@ void set_array_lower_bound_int(ir_type *array, size_t dimension, int lower_bound
void set_array_upper_bound(ir_type *array, size_t dimension, ir_node *upper_bound)
{
assert(array && (array->type_op == type_array));
assert(array->type_op == type_array);
assert(upper_bound && "upper_bound node may not be NULL.");
array->attr.aa.upper_bound[dimension] = upper_bound;
}
......@@ -1523,20 +1524,20 @@ void set_array_upper_bound_int(ir_type *array, size_t dimension, int upper_bound
int has_array_lower_bound(const ir_type *array, size_t dimension)
{
assert(array && (array->type_op == type_array));
assert(array->type_op == type_array);
return !is_Unknown(array->attr.aa.lower_bound[dimension]);
}
ir_node *get_array_lower_bound(const ir_type *array, size_t dimension)
{
assert(array && (array->type_op == type_array));
assert(array->type_op == type_array);
return array->attr.aa.lower_bound[dimension];
}
long get_array_lower_bound_int(const ir_type *array, size_t dimension)
{
ir_node *node;
assert(array && (array->type_op == type_array));
assert(array->type_op == type_array);
node = array->attr.aa.lower_bound[dimension];
assert(is_Const(node));
return get_tarval_long(get_Const_tarval(node));
......@@ -1544,20 +1545,20 @@ long get_array_lower_bound_int(const ir_type *array, size_t dimension)
int has_array_upper_bound(const ir_type *array, size_t dimension)
{
assert(array && (array->type_op == type_array));
assert(array->type_op == type_array);
return !is_Unknown(array->attr.aa.upper_bound[dimension]);
}
ir_node *get_array_upper_bound(const ir_type *array, size_t dimension)
{
assert(array && (array->type_op == type_array));
assert(array->type_op == type_array);
return array->attr.aa.upper_bound[dimension];
}
long get_array_upper_bound_int(const ir_type *array, size_t dimension)
{
ir_node *node;
assert(array && (array->type_op == type_array));
assert(array->type_op == type_array);
node = array->attr.aa.upper_bound[dimension];
assert(is_Const(node));
return get_tarval_long(get_Const_tarval(node));
......@@ -1565,13 +1566,13 @@ long get_array_upper_bound_int(const ir_type *array, size_t dimension)
void set_array_order(ir_type *array, size_t dimension, size_t order)
{
assert(array && (array->type_op == type_array));
assert(array->type_op == type_array);
array->attr.aa.order[dimension] = order;
}
size_t get_array_order(const ir_type *array, size_t dimension)
{
assert(array && (array->type_op == type_array));
assert(array->type_op == type_array);
return array->attr.aa.order[dimension];
}
......@@ -1590,20 +1591,20 @@ size_t find_array_dimension(const ir_type *array, size_t order)
void set_array_element_type(ir_type *array, ir_type *tp)
{
assert(array && (array->type_op == type_array));
assert(array->type_op == type_array);
assert(!is_Method_type(tp));
array->attr.aa.element_type = tp;
}
ir_type *get_array_element_type(const ir_type *array)
{
assert(array && (array->type_op == type_array));
assert(array->type_op == type_array);
return array->attr.aa.element_type;
}
void set_array_element_entity(ir_type *array, ir_entity *ent)
{
assert(array && (array->type_op == type_array));
assert(array->type_op == type_array);
assert((get_entity_type(ent)->type_op != type_method));
array->attr.aa.element_ent = ent;
array->attr.aa.element_type = get_entity_type(ent);
......@@ -1611,10 +1612,23 @@ void set_array_element_entity(ir_type *array, ir_entity *ent)
ir_entity *get_array_element_entity(const ir_type *array)
{
assert(array && (array->type_op == type_array));
assert(array->type_op == type_array);
return array->attr.aa.element_ent;
}
int is_array_variable_size(const ir_type *array)
{
assert(array->type_op == type_array);
return (array->flags & tf_variable_size) != 0;
}
void set_array_variable_size(ir_type *array, int flag)
{
assert(array->type_op == type_array);
array->flags = (array->flags & ~tf_variable_size)
| (flag != 0 ? tf_variable_size : 0);
}
int (is_Array_type)(const ir_type *array)
{
return _is_array_type(array);
......@@ -1880,6 +1894,19 @@ size_t get_compound_member_index(const ir_type *tp, ir_entity *member)
return op->ops.get_member_index(tp, member);
}
void set_compound_variable_size(ir_type *tp, int variable_size_flag)
{
assert(is_compound_type(tp));
tp->flags = (tp->flags & ~tf_variable_size)
| (variable_size_flag != 0 ? tf_variable_size : 0);
}
int is_compound_variable_size(const ir_type *tp)
{
assert(is_compound_type(tp));
return (tp->flags & tf_variable_size) != 0;
}
int is_compound_type(const ir_type *tp)
{
assert(tp->kind == k_type);
......@@ -1982,21 +2009,29 @@ void set_default_size(ir_type *tp, unsigned size)
void default_layout_compound_type(ir_type *type)
{
size_t i;
size_t n = get_compound_n_members(type);
int size = 0;
size_t i;
size_t n = get_compound_n_members(type);
int size = 0;
unsigned align_all = 1;
bool var_size = is_compound_variable_size(type);
for (i = 0; i < n; ++i) {
ir_entity *entity = get_compound_member(type, i);
ir_type *entity_type = get_entity_type(entity);
unsigned align;
unsigned misalign;
unsigned entity_size;
if (is_Method_type(entity_type))
continue;
assert(get_type_state(entity_type) == layout_fixed);
if (i+1 < n || !var_size) {
assert(get_type_state(entity_type) == layout_fixed);
entity_size = get_type_size_bytes(entity_type);
} else {
entity_size = 0;
}
align = get_type_alignment_bytes(entity_type);
align_all = align > align_all ? align : align_all;
misalign = (align ? size % align : 0);
......@@ -2004,7 +2039,7 @@ void default_layout_compound_type(ir_type *type)
set_entity_offset(entity, size);
if (!is_Union_type(type)) {
size += get_type_size_bytes(entity_type);
size += entity_size;
}
}
if (align_all > 0 && size % align_all) {
......
......@@ -139,6 +139,7 @@ enum type_flags {
tf_tls_type = 1U << 5, /**< Set only for the tls type */
tf_constructors = 1U << 6, /**< Set only for the constructors segment type */
tf_destructors = 1U << 7, /**< Set only for the destructors segment type */
tf_variable_size = 1U << 8, /**< compound or array type may have variable size last element */
};
ENUM_BITSET(type_flags)
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment