From 1b8afbd1568b390d1839b4d8cd10c1d4e63570b8 Mon Sep 17 00:00:00 2001 From: mmitchel Date: Tue, 21 Dec 1999 20:42:21 +0000 Subject: [PATCH] * class.c (create_vtable_ptr): Put the vtable at the beginning of the class, not the end, in the new ABI. * decl2.c (flag_new_ab): Initialize it to one. * tree.c (propagate_binfo_offsets): Do the right thing for the new ABI. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/new-abi-branch@31060 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/cp/ChangeLog | 8 +++++ gcc/cp/class.c | 17 +++++++++- gcc/cp/decl2.c | 2 +- gcc/cp/tree.c | 95 +++++++++++++++++++++++++++++++++++++++++--------------- 4 files changed, 95 insertions(+), 27 deletions(-) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 9fa42692d0d..31ea8258329 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,11 @@ +1999-12-21 Mark Mitchell + + * class.c (create_vtable_ptr): Put the vtable at the beginning of + the class, not the end, in the new ABI. + * decl2.c (flag_new_ab): Initialize it to one. + * tree.c (propagate_binfo_offsets): Do the right thing for the new + ABI. + 1999-12-20 Mark Mitchell * cp-tree.h (CLASSTYPE_VFIELD_PARENT): Update comments. diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 14c67af4a77..94869e8c7e9 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -4105,7 +4105,22 @@ create_vtable_ptr (t, empty_p, has_virtual_p, max_has_virtual_p, empty_p); /* Add the new field to the list of fields in this class. */ - TYPE_FIELDS (t) = chainon (TYPE_FIELDS (t), TYPE_VFIELD (t)); + if (!flag_new_abi) + /* In the old ABI, the vtable pointer goes at the end of the + class. */ + TYPE_FIELDS (t) = chainon (TYPE_FIELDS (t), TYPE_VFIELD (t)); + else + { + /* But in the new ABI, the vtable pointer is the first thing + in the class. */ + TYPE_FIELDS (t) = chainon (TYPE_VFIELD (t), TYPE_FIELDS (t)); + /* If there were any baseclasses, they can't possibly be at + offset zero any more, because that's where the vtable + pointer is. So, converting to a base class is going to + take work. */ + if (CLASSTYPE_N_BASECLASSES (t)) + TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (t) = 1; + } /* We can't yet add this new field to the list of all virtual function table pointers in this class. The diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 58cbf3cf074..5cc3da59488 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -439,7 +439,7 @@ int flag_weak = 1; /* Nonzero to enable experimental ABI changes. */ -int flag_new_abi; +int flag_new_abi = 1; /* Nonzero to use __cxa_atexit, rather than atexit, to register destructors for local statics and global objects. */ diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 39447eee1c7..52532646cb9 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -671,36 +671,81 @@ propagate_binfo_offsets (binfo, offset) tree binfos = BINFO_BASETYPES (binfo); int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0; - for (i = 0; i < n_baselinks; /* note increment is done in the loop. */) + if (flag_new_abi) { - tree base_binfo = TREE_VEC_ELT (binfos, i); - - if (TREE_VIA_VIRTUAL (base_binfo)) - i += 1; - else + for (i = 0; i < n_baselinks; ++i) { - int j; - tree delta = NULL_TREE; - - for (j = i+1; j < n_baselinks; j++) - if (! TREE_VIA_VIRTUAL (TREE_VEC_ELT (binfos, j))) - { - /* The next basetype offset must take into account the space - between the classes, not just the size of each class. */ - delta = size_binop (MINUS_EXPR, - BINFO_OFFSET (TREE_VEC_ELT (binfos, j)), - BINFO_OFFSET (base_binfo)); - break; - } - - BINFO_OFFSET (base_binfo) = offset; + tree base_binfo; + + /* Figure out which base we're looking at. */ + base_binfo = TREE_VEC_ELT (binfos, i); + + /* Skip virtual bases. Their BINFO_OFFSET doesn't matter + since they are always reached by using offsets looked up + at run-time. */ + if (TREE_VIA_VIRTUAL (base_binfo)) + continue; + + /* Whatever offset this class used to have in its immediate + derived class, it is not at OFFSET more bytes in its + final derived class, since the immediate derived class is + already at the indicated OFFSET. */ + BINFO_OFFSET (base_binfo) + = size_binop (PLUS_EXPR, BINFO_OFFSET (base_binfo), offset); propagate_binfo_offsets (base_binfo, offset); + } + } + else + { + /* This algorithm, used for the old ABI, is neither simple, nor + general. For example, it mishandles the case of: + + struct A; + struct B : public A; + struct C : public B; + + if B is at offset zero in C, but A is not in offset zero in + B. In that case, it sets the BINFO_OFFSET for A to zero. + (This sitution arises in the new ABI if B has virtual + functions, but A does not.) Rather than change this + algorithm, and risking breaking the old ABI, it is preserved + here. */ + for (i = 0; i < n_baselinks; /* note increment is done in the + loop. */) + { + tree base_binfo = TREE_VEC_ELT (binfos, i); - /* Go to our next class that counts for offset propagation. */ - i = j; - if (i < n_baselinks) - offset = size_binop (PLUS_EXPR, offset, delta); + if (TREE_VIA_VIRTUAL (base_binfo)) + i += 1; + else + { + int j; + tree delta = NULL_TREE; + + for (j = i+1; j < n_baselinks; j++) + if (! TREE_VIA_VIRTUAL (TREE_VEC_ELT (binfos, j))) + { + /* The next basetype offset must take into account + the space between the classes, not just the + size of each class. */ + delta = size_binop (MINUS_EXPR, + BINFO_OFFSET (TREE_VEC_ELT (binfos, + j)), + BINFO_OFFSET (base_binfo)); + break; + } + + BINFO_OFFSET (base_binfo) = offset; + + propagate_binfo_offsets (base_binfo, offset); + + /* Go to our next class that counts for offset + propagation. */ + i = j; + if (i < n_baselinks) + offset = size_binop (PLUS_EXPR, offset, delta); + } } } } -- 2.11.4.GIT