diff options
author | Erick Ochoa <erick.ochoa@theobroma-systems.com> | 2020-06-16 18:05:32 +0200 |
---|---|---|
committer | Erick Ochoa <erick.ochoa@theobroma-systems.com> | 2020-06-16 18:05:32 +0200 |
commit | 83dd5007061373f2066d1ad050383fc40bece0d3 (patch) | |
tree | 0fa35f14674ad73302f4ba86e713834d98166070 | |
parent | 5468db8b6e1d8220707fe2d9debbc09bd5f49159 (diff) |
we have a good layout for new types
-rw-r--r-- | gcc/expr-rewriter.c | 13 | ||||
-rw-r--r-- | gcc/expr-rewriter.hpp | 2 | ||||
-rw-r--r-- | gcc/type-reconstructor.c | 226 | ||||
-rw-r--r-- | gcc/type-reconstructor.hpp | 23 |
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); |