diff options
Diffstat (limited to 'gcc/type-reconstructor.c')
-rw-r--r-- | gcc/type-reconstructor.c | 81 |
1 files changed, 54 insertions, 27 deletions
diff --git a/gcc/type-reconstructor.c b/gcc/type-reconstructor.c index 530569c074f..350d9bd4989 100644 --- a/gcc/type-reconstructor.c +++ b/gcc/type-reconstructor.c @@ -49,7 +49,6 @@ get_new_identifier(const_tree type) gcc_assert(!is_new_type); char *new_name; asprintf(&new_name, "%s.reorg", identifier); - log("old %s new %s\n", identifier, new_name); return get_identifier(new_name); } @@ -58,6 +57,8 @@ get_new_identifier(const_tree type) // // Invariant for all _post functions: // _reorg_map[TREE_TYPE(t)] != NULL +// unless TREE_TYPE(t) is not a type which points to a record +// a.k.a. no modifications // // To preserve invariant, we must include // the following at the end of all _post functions: @@ -80,16 +81,17 @@ TypeReconstructor::_walk_ARRAY_TYPE_post(const_tree t) { const_tree inner_type = TREE_TYPE(t); gcc_assert(inner_type); - tree inner_reorg_type = (tree)_reorg_map[inner_type]; - gcc_assert(inner_reorg_type); - tree t_reorg = (tree)_working_stack.top(); + 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; - - + log("working type %s\n", t_reorg ? "t" : "f"); } void @@ -103,23 +105,19 @@ TypeReconstructor::_walk_POINTER_TYPE_pre(const_tree t) void TypeReconstructor::_walk_POINTER_TYPE_post(const_tree t) { - const bool already_changed = _reorg_map.find(t) != _reorg_map.end(); - const_tree modifications = _working_stack.top(); + tree t_reorg = _working_stack.top(); _working_stack.pop(); - if (already_changed) return; - tree tt = TREE_TYPE(t); - bool field_type_in_reorg_map = _reorg_map.find(tt) != _reorg_map.end(); - if (!field_type_in_reorg_map) { - TYPE_NAME((tree)modifications) = get_new_identifier(modifications); - _reorg_map[t] = modifications; - return; - } + 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 tf = (tree)_reorg_map[tt]; - TREE_TYPE((tree)modifications) = tf; - TYPE_NAME((tree)modifications) = get_new_identifier(modifications); - _reorg_map[t] = modifications; + 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;; + log("working type %s\n", t_reorg ? "t" : "f"); } void @@ -143,6 +141,34 @@ TypeReconstructor::_walk_RECORD_TYPE_pre(const_tree t) _eliminated_fields.push(vec2); } +void +TypeReconstructor::_walk_UNION_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. + 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); +} + +void +TypeReconstructor::_walk_UNION_TYPE_post(const_tree t) +{ + _walk_RECORD_TYPE_post(t); +} + void TypeReconstructor::_walk_RECORD_TYPE_post(const_tree t) @@ -156,7 +182,7 @@ TypeReconstructor::_walk_RECORD_TYPE_post(const_tree t) type_vector_t fields_to_eliminate = _eliminated_fields.top(); _eliminated_fields.pop(); _field_decls.pop(); - const_tree working_type = _working_stack.top(); + tree working_type = _working_stack.top(); _working_stack.pop(); _record_stack.pop(); const bool should_be_modified = _modifying.top(); @@ -175,8 +201,8 @@ TypeReconstructor::_walk_RECORD_TYPE_post(const_tree t) if (fields_to_keep.empty()) { - layout_type((tree)working_type); - TYPE_NAME((tree)working_type) = get_new_identifier(working_type); + layout_type(working_type); + TYPE_NAME(working_type) = get_new_identifier(working_type); _reorg_map[t] = working_type; return; } @@ -186,7 +212,7 @@ TypeReconstructor::_walk_RECORD_TYPE_post(const_tree t) bool field_type_in_reorg_map = _reorg_map.find(tf) != _reorg_map.end(); if (field_type_in_reorg_map) { - TREE_TYPE(f) = (tree) _reorg_map[tf]; + TREE_TYPE(f) = _reorg_map[tf]; } TYPE_FIELDS((tree)working_type) = f; unsigned s = fields_to_keep.size(); @@ -198,14 +224,15 @@ TypeReconstructor::_walk_RECORD_TYPE_post(const_tree t) field_type_in_reorg_map = _reorg_map.find(tf) != _reorg_map.end(); if (field_type_in_reorg_map) { - TREE_TYPE(current) = (tree) _reorg_map[tf]; + TREE_TYPE(current) = _reorg_map[tf]; } DECL_CHAIN(f) = current; f = current; } - layout_type((tree)working_type); - TYPE_NAME((tree)working_type) = get_new_identifier(working_type); + layout_type(working_type); + TYPE_NAME(working_type) = get_new_identifier(working_type); + log("working type %s\n", working_type ? "t" : "f"); _reorg_map[t] = working_type; } |