summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorErick Ochoa <erick.ochoa@theobroma-systems.com>2020-06-16 18:05:32 +0200
committerErick Ochoa <erick.ochoa@theobroma-systems.com>2020-06-16 18:05:32 +0200
commit83dd5007061373f2066d1ad050383fc40bece0d3 (patch)
tree0fa35f14674ad73302f4ba86e713834d98166070
parent5468db8b6e1d8220707fe2d9debbc09bd5f49159 (diff)
we have a good layout for new types
-rw-r--r--gcc/expr-rewriter.c13
-rw-r--r--gcc/expr-rewriter.hpp2
-rw-r--r--gcc/type-reconstructor.c226
-rw-r--r--gcc/type-reconstructor.hpp23
4 files changed, 113 insertions, 151 deletions
diff --git a/gcc/expr-rewriter.c b/gcc/expr-rewriter.c
index 4ada49a3a7c..616271d96c7 100644
--- a/gcc/expr-rewriter.c
+++ b/gcc/expr-rewriter.c
@@ -20,7 +20,7 @@ ExprTypeRewriter::_walk_post(const_tree e)
}
void
-ExprTypeRewriter::_walk_COMPONENT_REF_pre(const_tree e)
+ExprTypeRewriter::_walk_COMPONENT_REF_post(const_tree e)
{
// TODO: I need to rewrite the field
const_tree f = TREE_OPERAND(e, 1);
@@ -30,5 +30,14 @@ ExprTypeRewriter::_walk_COMPONENT_REF_pre(const_tree e)
tree n_f = _map2[f];
TREE_OPERAND(e, 1) = n_f;
- log("replacing field %s with %s\n", TypeStringifier::get_field_identifier(f).c_str(), TypeStringifier::get_field_identifier(n_f).c_str());
+ unsigned f_byte_offset = tree_to_uhwi(DECL_FIELD_OFFSET(f));
+ unsigned f_bit_offset = tree_to_uhwi(DECL_FIELD_BIT_OFFSET(f));
+ unsigned f_offset = 8 * f_byte_offset + f_bit_offset;
+
+ unsigned nf_byte_offset = tree_to_uhwi(DECL_FIELD_OFFSET(n_f));
+ unsigned nf_bit_offset = tree_to_uhwi(DECL_FIELD_BIT_OFFSET(n_f));
+ unsigned nf_offset = 8 * nf_byte_offset + nf_bit_offset;
+
+ log("replacing field %s %d with %s %d\n", TypeStringifier::get_field_identifier(f).c_str(), f_offset, TypeStringifier::get_field_identifier(n_f).c_str(), nf_offset);
+
}
diff --git a/gcc/expr-rewriter.hpp b/gcc/expr-rewriter.hpp
index 29a30a2dc38..48fcaeda8a0 100644
--- a/gcc/expr-rewriter.hpp
+++ b/gcc/expr-rewriter.hpp
@@ -11,5 +11,5 @@ private:
TypeReconstructor::reorg_record_map_t _map;
TypeReconstructor::reorg_field_map_t _map2;
void _walk_post(const_tree e);
- void _walk_COMPONENT_REF_pre(const_tree e);
+ void _walk_COMPONENT_REF_post(const_tree e);
};
diff --git a/gcc/type-reconstructor.c b/gcc/type-reconstructor.c
index 1faae9652af..ac3cb8b6e2e 100644
--- a/gcc/type-reconstructor.c
+++ b/gcc/type-reconstructor.c
@@ -73,181 +73,141 @@ get_new_identifier(const_tree type)
void
TypeReconstructor::_walk_ARRAY_TYPE_pre(const_tree t)
{
- const bool in_map = _reorg_map.find(t) != _reorg_map.end();
- gcc_assert(!in_map);
- _working_stack.push(build_distinct_type_copy((tree)t));
}
void
TypeReconstructor::_walk_ARRAY_TYPE_post(const_tree t)
{
- const_tree inner_type = TREE_TYPE(t);
- gcc_assert(inner_type);
- const bool in_map = _reorg_map.find(inner_type) != _reorg_map.end();
- tree t_reorg = _working_stack.top();
- _working_stack.pop();
-
- if (!in_map) return;
-
- tree inner_reorg_type = _reorg_map[inner_type];
- TREE_TYPE(t_reorg) = inner_reorg_type;
- TYPE_NAME((tree)t_reorg) = get_new_identifier(t_reorg);
- _reorg_map[t] = t_reorg;
- layout_type(t_reorg);
- log("working type %s\n", t_reorg ? "t" : "f");
}
void
TypeReconstructor::_walk_POINTER_TYPE_pre(const_tree t)
{
- // We really should only make a distinct type copy if
- // it points to a pointer that will be rewritten...
- _working_stack.push(build_distinct_type_copy((tree)t));
}
void
TypeReconstructor::_walk_POINTER_TYPE_post(const_tree t)
{
- tree t_reorg = _working_stack.top();
- _working_stack.pop();
-
- const_tree inner_type = TREE_TYPE(t);
- const bool in_map = _reorg_map.find(inner_type) != _reorg_map.end();
- // We are pointing to an integer or something like that.
- if (!in_map) return;
-
- tree inner_type_reorg = _reorg_map[inner_type];
- TREE_TYPE((tree)t_reorg) = inner_type_reorg;
- TYPE_NAME((tree)t_reorg) = get_new_identifier(t_reorg);
- _reorg_map[t] = t_reorg;;
- layout_type(t_reorg);
- log("working type %s\n", t_reorg ? "t" : "f");
}
void
TypeReconstructor::_walk_RECORD_TYPE_pre(const_tree t)
{
- const bool in_map = _records.find(t) != _records.end();
- // The modifying stack let's us know if the current record
- // type is being modified.
- _modifying.push(in_map);
-
- field_offsets_t empty;
- _record_stack.push(in_map ? _records[t] : empty);
-
- // We really should only make a distinct type copy if
- // it points to a pointer that will be rewritten...
- _working_stack.push(build_distinct_type_copy((tree)t));
-
- type_vector_t vec;
- type_vector_t vec2;
- _field_decls.push(vec);
- _eliminated_fields.push(vec2);
+ for_reference.push(t);
+ // We don't know if we will modify this type t
+ // So, let's make a copy. Just in case.
+ tree copy = build_distinct_type_copy((tree) t);
+ in_progress.push(copy);
+ field_list_stack.push( field_tuple_list_t() );
}
void
-TypeReconstructor::_walk_UNION_TYPE_pre(const_tree t)
+TypeReconstructor::_walk_RECORD_TYPE_post(const_tree t)
{
- const bool in_map = _records.find(t) != _records.end();
- // The modifying stack let's us know if the current record
- // type is being modified.
- gcc_assert(!in_map);
- _modifying.push(in_map);
-
- field_offsets_t empty;
- _record_stack.push(in_map ? _records[t] : empty);
-
- // We really should only make a distinct type copy if
- // it points to a pointer that will be rewritten...
- _working_stack.push(build_distinct_type_copy((tree)t));
-
- type_vector_t vec;
- type_vector_t vec2;
- _field_decls.push(vec);
- _eliminated_fields.push(vec2);
+ const_tree t2 = for_reference.top();
+ gcc_assert(t2 == t);
+ for_reference.pop();
+
+ tree copy = in_progress.top();
+ in_progress.pop();
+ field_tuple_list_t field_tuple_list = field_list_stack.top();
+ field_list_stack.pop();
+
+ // So, here all the work has been done to make sure
+ // that the fields produced a field_tuple_list_t
+ // with old fields and pointers to new fields.
+ // There might be NULL values if new fields are eliminated.
+ // So, now we want to do a couple of things.
+ // First, is we need to change the TYPE_FIELDS
+ // of the copy
+ tree prev_field = NULL;
+ for (auto i = field_tuple_list.cbegin(), e = field_tuple_list.cend(); i != e; ++i)
+ {
+ field_tuple_t field_tuple = *i;
+ const_tree original_field = field_tuple.first;
+ tree modified_field = field_tuple.second;
+ if (!modified_field) {
+ continue;
+ }
+
+ tree current_field = modified_field;
+ if (!prev_field) {
+ TYPE_FIELDS(copy) = current_field;
+ } else {
+ DECL_CHAIN(prev_field) = current_field;
+ }
+ prev_field = current_field;
+ }
+
+
+ // Ok, so now that we have fixed the TYPE_FIELDS of the copy...
+ // We need to call layout_type
+ TYPE_NAME(copy) = get_new_identifier(copy);
+ // This is useful so that we go again through type layout
+ TYPE_SIZE(copy) = NULL;
+ layout_type(copy);
+ _reorg_map[t] = copy;
}
void
-TypeReconstructor::_walk_UNION_TYPE_post(const_tree t)
+TypeReconstructor::_walk_UNION_TYPE_pre(const_tree t)
{
- _walk_RECORD_TYPE_post(t);
}
-
void
-TypeReconstructor::_walk_RECORD_TYPE_post(const_tree t)
+TypeReconstructor::_walk_UNION_TYPE_post(const_tree t)
{
- type_vector_t fields_to_keep = _field_decls.top();
- type_vector_t fields_to_eliminate = _eliminated_fields.top();
- _eliminated_fields.pop();
- _field_decls.pop();
- tree working_type = _working_stack.top();
- _working_stack.pop();
- _record_stack.pop();
- const bool should_be_modified = _modifying.top();
- _modifying.pop();
-
- // There are no fields to eliminate
- // if (fields_to_eliminate.empty()) return;
- // But, we can have a nested struct that will be rewritten
- // so, we should keep not exit early
-
- // There are no fields to keep
- // Can be an incomplete type
-
- // TODO: What if all fields have been deleted?
- if (fields_to_keep.empty())
- {
- layout_type(working_type);
- TYPE_NAME(working_type) = get_new_identifier(working_type);
- _reorg_map[t] = working_type;
- return;
- }
-
- for (auto i = fields_to_keep.cbegin(), e = fields_to_keep.cend(); i != e; ++i)
- {
- const_tree original_field = *i;
- const_tree original_type = TREE_TYPE(original_field);
- const bool is_rewritten = _reorg_map.find(original_type) != _reorg_map.end();
- //tree modified_field = is_rewritten ? copy_node((tree)original_field) : NULL;
- //if (modified_field) TREE_TYPE(modified_field) = _reorg_map[original_type];
- // Ok, so now we are keeping track of which fields
- // are rewritten...
- //_reorg_fields[original_field] = is_rewritten ? modified_field : (tree)original_field;
- }
-
-
- layout_type(working_type);
- TYPE_NAME(working_type) = get_new_identifier(working_type);
- _reorg_map[t] = working_type;
}
-
-
void
TypeReconstructor::_walk_field_pre(const_tree t)
{
- // What do I want?
- // I want something that after going through all fields
- // I get a map from old fields to new field...
+ for_reference.push(t);
+ // We don't know if we will rewrite the field
+ // that we are working on. So proactively, let's make
+ // a copy
+ tree copy = copy_node((tree) t);
+ tree type_copy = build_distinct_type_copy((tree)(TREE_TYPE(t)));
+ TREE_TYPE(copy) = type_copy;
+ // To communicate this field to the other methods,
+ // let's put it in the "in_progress" stack.
+ in_progress.push(copy);
}
void
TypeReconstructor::_walk_field_post(const_tree t)
{
- unsigned f_offset = tree_to_uhwi(DECL_FIELD_OFFSET(t));
- unsigned f_offset_2 = tree_to_uhwi(DECL_FIELD_BIT_OFFSET(t));
- unsigned f_offset_3 = f_offset * 8 + f_offset_2;
- field_offsets_t field_offsets = _record_stack.top();
- const bool should_be_deleted = field_offsets.find(f_offset_3) != field_offsets.end();
- const bool should_be_modified = _modifying.top();
- if (should_be_modified && should_be_deleted) {
- type_vector_t &vec_ = _eliminated_fields.top();
- vec_.push_back(t);
- return;
+ const_tree t2 = for_reference.top();
+ gcc_assert(t2 == t);
+ for_reference.pop();
+
+ // Let's get the copy we were working on.
+ tree copy = in_progress.top();
+ // Let's put the stack in the same position...
+ in_progress.pop();
+
+ // What record does this field belongs to?
+ const_tree record = for_reference.top();
+
+ // Is this a record that has a field that might be deleted?
+ const bool is_record_interesting = _records.find(record) != _records.end();
+ if (!is_record_interesting) {
+ return;
}
- // This is a field declaration, that should be saved.
- type_vector_t &vec = _field_decls.top();
- vec.push_back(t);
+ field_offsets_t field_offsets = _records[record];
+ // What's the field offset?
+ unsigned f_byte_offset = tree_to_uhwi(DECL_FIELD_OFFSET(t));
+ unsigned f_bit_offset = tree_to_uhwi(DECL_FIELD_BIT_OFFSET(t));
+ unsigned f_offset = 8 * f_byte_offset + f_bit_offset;
+
+ const bool can_field_be_deleted = field_offsets.find(f_offset) != field_offsets.end();
+ field_tuple_t tuple = std::make_pair(t, can_field_be_deleted ? NULL : copy);
+
+ log("can field %s be deleted ? %s\n", TypeStringifier::get_field_identifier(t).c_str(), can_field_be_deleted ? "t" : "f");
+
+ // Put the field into the vector
+ field_tuple_list_t &field_tuple_list = field_list_stack.top();
+ field_tuple_list.push_back(tuple);
+ _reorg_fields[t] = copy;
}
diff --git a/gcc/type-reconstructor.hpp b/gcc/type-reconstructor.hpp
index e0364327300..79e6fad8a73 100644
--- a/gcc/type-reconstructor.hpp
+++ b/gcc/type-reconstructor.hpp
@@ -12,25 +12,18 @@ class TypeReconstructor : public TypeWalker
public:
typedef std::map<const_tree, tree> reorg_record_map_t;
typedef std::map<const_tree, tree> reorg_field_map_t;
-private:
typedef std::set<unsigned> field_offsets_t;
typedef std::map<const_tree, field_offsets_t> record_field_offset_map_t;
- typedef std::stack<bool> field_stack_t;
- typedef std::stack<field_offsets_t> record_stack_t;
- typedef std::stack<tree> type_stack_t;
- typedef std::vector<const_tree> type_vector_t;
- typedef std::stack<type_vector_t> type_vector_stack_t;
- typedef std::stack<bool> bool_stack_t;
+private:
+ std::stack<tree> in_progress;
+ std::stack<const_tree> for_reference;
+ typedef std::pair<const_tree, tree> field_tuple_t;
+ typedef std::vector<field_tuple_t> field_tuple_list_t;
+ typedef std::stack<field_tuple_list_t> field_tuple_list_stack_t;
record_field_offset_map_t _records;
- reorg_field_map_t _reorg_fields;
+ field_tuple_list_stack_t field_list_stack;
reorg_record_map_t _reorg_map;
- field_stack_t _field_stack;
- record_stack_t _record_stack;
- type_stack_t _working_stack;
- type_vector_stack_t _field_decls;
- type_vector_stack_t _eliminated_fields;
- bool_stack_t _modifying;
-
+ reorg_field_map_t _reorg_fields;
virtual void _walk_field_pre(const_tree);
virtual void _walk_field_post(const_tree);
virtual void _walk_RECORD_TYPE_pre(const_tree);