[llvm-commits] [llvm-gcc-4.2] r81399 - in /llvm-gcc-4.2/trunk/gcc: llvm-types.cpp tree.h
Daniel Dunbar
daniel at zuster.org
Wed Sep 16 00:05:45 PDT 2009
Hi Dale,
Is there a testcase for this?
- Daniel
On Wed, Sep 9, 2009 at 4:36 PM, Dale Johannesen <dalej at apple.com> wrote:
> Author: johannes
> Date: Wed Sep 9 18:36:04 2009
> New Revision: 81399
>
> URL: http://llvm.org/viewvc/llvm-project?rev=81399&view=rev
> Log:
> In the presence of #pragma pack, layouts
> can be created where a base class has different alignments
> in different derived classes. The code for dealing with
> base classes wasn't handling this correctly, leading to
> assertions. Rewrite the base class remapper to key off
> a <type, alignment> pair instead of handling the size and
> alignment cases separately.
>
>
> Modified:
> llvm-gcc-4.2/trunk/gcc/llvm-types.cpp
> llvm-gcc-4.2/trunk/gcc/tree.h
>
> Modified: llvm-gcc-4.2/trunk/gcc/llvm-types.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/llvm-types.cpp?rev=81399&r1=81398&r2=81399&view=diff
>
> ==============================================================================
> --- llvm-gcc-4.2/trunk/gcc/llvm-types.cpp (original)
> +++ llvm-gcc-4.2/trunk/gcc/llvm-types.cpp Wed Sep 9 18:36:04 2009
> @@ -1685,10 +1685,7 @@
> }
>
> /// Mapping from type to type-used-as-base-class and back.
> -static DenseMap<tree, tree> BaseTypesMap;
> -
> -/// Mapping from type to less-aligned-type-used-within-struct and back.
> -static DenseMap<std::pair<tree, unsigned int>, tree> LessAlignedTypesMap;
> +static DenseMap<std::pair<tree, unsigned int>, tree > BaseTypesMap;
>
> /// FixBaseClassField - This method is called when we have a field Field
> /// of Record type within a Record, and the size of Field is smaller than the
> @@ -1702,7 +1699,9 @@
>
> static tree FixBaseClassField(tree Field) {
> tree oldTy = TREE_TYPE(Field);
> - tree newTy = BaseTypesMap[oldTy];
> + std::pair<tree, unsigned int> p = std::make_pair(oldTy,
> + std::min(DECL_ALIGN(Field), TYPE_ALIGN(oldTy)));
> + tree newTy = BaseTypesMap[p];
> // If already in table, reuse.
> if (!newTy) {
> newTy = copy_node(oldTy);
> @@ -1727,11 +1726,11 @@
> // to the C++ virtual base case to get this far, but these don't have
> // the TYPE_DECL sentinel, nor the virtual base class allocation problem.
> if (!F || TREE_CODE(F) != TYPE_DECL) {
> - BaseTypesMap[oldTy] = oldTy;
> + BaseTypesMap[p] = oldTy;
> return oldTy;
> }
> - BaseTypesMap[oldTy] = newTy;
> - BaseTypesMap[newTy] = oldTy;
> + BaseTypesMap[p] = newTy;
> + BaseTypesMap[std::make_pair(newTy, 0U)] = oldTy;
> // Prevent gcc's garbage collector from destroying newTy. The
> // GC code doesn't understand DenseMaps:(
> llvm_note_type_used(newTy);
> @@ -1750,57 +1749,8 @@
> p = IDENTIFIER_POINTER(TYPE_NAME(oldTy));
> else if (DECL_NAME(TYPE_NAME(oldTy)))
> p = IDENTIFIER_POINTER(DECL_NAME(TYPE_NAME(oldTy)));
> - char *q = (char *)xmalloc(strlen(p)+6);
> - strcpy(q,p);
> - strcat(q,".base");
> - TYPE_NAME(newTy) = get_identifier(q);
> - free(q);
> - }
> - }
> - return newTy;
> -}
> -
> -/// FixLessAlignedClassField - This method is called when we have a field Field
> -/// of Record type within a Record, and the alignment of Field is smaller than
> -/// alignment of its Record type. The field may not get as much tail padding
> -/// as the type would in other contexts. Replace Field's original
> -/// type with a modified one that has the Field's alignment.
> -
> -static tree FixLessAlignedClassField(tree Field) {
> - tree oldTy = TREE_TYPE(Field);
> - std::pair<tree, unsigned int> p = std::make_pair(oldTy, DECL_ALIGN(Field));
> - tree newTy = LessAlignedTypesMap[p];
> - // If already in table, reuse.
> - if (!newTy) {
> - newTy = copy_node(oldTy);
> - tree F2 = 0, prevF2 = 0, F;
> - // Copy all the fields.
> - for (F = TYPE_FIELDS(oldTy); F; prevF2 = F2, F = TREE_CHAIN(F)) {
> - F2 = copy_node(F);
> - if (prevF2)
> - TREE_CHAIN(prevF2) = F2;
> - else
> - TYPE_FIELDS(newTy) = F2;
> - TREE_CHAIN(F2) = 0;
> - }
> - LessAlignedTypesMap[p] = newTy;
> - LessAlignedTypesMap[std::make_pair(newTy, 0U)] = oldTy;
> - /* Prevent gcc's garbage collector from destroying newTy. The
> - GC code doesn't understand DenseMaps:( */
> - llvm_note_type_used(newTy);
> - TYPE_ALIGN(newTy) = DECL_ALIGN(Field);
> - TYPE_MAIN_VARIANT(newTy) = newTy;
> - TYPE_STUB_DECL(newTy) = TYPE_STUB_DECL(oldTy);
> - // Change the name.
> - if (TYPE_NAME(oldTy)) {
> - const char *p = "anon";
> - if (TREE_CODE(TYPE_NAME(oldTy)) ==IDENTIFIER_NODE)
> - p = IDENTIFIER_POINTER(TYPE_NAME(oldTy));
> - else if (DECL_NAME(TYPE_NAME(oldTy)))
> - p = IDENTIFIER_POINTER(DECL_NAME(TYPE_NAME(oldTy)));
> - char *q = (char *)xmalloc(strlen(p)+7);
> - strcpy(q,p);
> - strcat(q,".align");
> + char *q = (char *)xmalloc(strlen(p)+20);
> + sprintf(q, "%s.base.%d", p, TYPE_ALIGN(newTy));
> TYPE_NAME(newTy) = get_identifier(q);
> free(q);
> }
> @@ -1822,12 +1772,12 @@
> // node for it, but not when A is a nonvirtual base class. So we can't
> // use that.)
> //
> -// Also alter the types referred to by Field nodes that have greater alignment
> -// than the Field does; these might not get the tail padding as a Field that
> -// they get elsewhere.
> -//
> -// Both transformations can be needed for the same type (in different contexts),
> -// so we need two mappings.
> +// If #pragma pack is involved, different derived classes may use different
> +// sizes for the base class. We also alter the types referred to by Field nodes
> +// that have greater alignment than the Field does; these might not get the
> +// tail padding as a Field that they get elsewhere. To handle these additional
> +// cases the size and alignment of the field are used as parts of the index
> +// into the map of base classes already created.
>
> static void FixUpFields(tree type) {
> if (TREE_CODE(type)!=RECORD_TYPE)
> @@ -1839,29 +1789,17 @@
> TREE_CODE(TREE_TYPE(Field))==RECORD_TYPE &&
> TYPE_SIZE(TREE_TYPE(Field)) &&
> DECL_SIZE(Field) &&
> - TREE_CODE(DECL_SIZE(Field))==INTEGER_CST &&
> - TREE_CODE(TYPE_SIZE(TREE_TYPE(Field)))==INTEGER_CST &&
> - TREE_INT_CST_LOW(DECL_SIZE(Field)) <
> - TREE_INT_CST_LOW(TYPE_SIZE(TREE_TYPE(Field)))) {
> + ((TREE_CODE(DECL_SIZE(Field))==INTEGER_CST &&
> + TREE_CODE(TYPE_SIZE(TREE_TYPE(Field)))==INTEGER_CST &&
> + TREE_INT_CST_LOW(DECL_SIZE(Field)) <
> + TREE_INT_CST_LOW(TYPE_SIZE(TREE_TYPE(Field)))) ||
> + (DECL_ALIGN(Field) < TYPE_ALIGN(TREE_TYPE(Field))))) {
> tree newType = FixBaseClassField(Field);
> if (newType != TREE_TYPE(Field)) {
> TREE_TYPE(Field) = newType;
> DECL_FIELD_BASE_REPLACED(Field) = 1;
> }
> }
> - if (TREE_CODE(Field)==FIELD_DECL &&
> - !DECL_BIT_FIELD_TYPE(Field) &&
> - TREE_CODE(DECL_FIELD_OFFSET(Field))==INTEGER_CST &&
> - TREE_CODE(TREE_TYPE(Field))==RECORD_TYPE &&
> - TYPE_SIZE(TREE_TYPE(Field)) &&
> - DECL_SIZE(Field) &&
> - DECL_ALIGN(Field) < TYPE_ALIGN(TREE_TYPE(Field))) {
> - tree newType = FixLessAlignedClassField(Field);
> - if (newType != TREE_TYPE(Field)) {
> - TREE_TYPE(Field) = newType;
> - DECL_FIELD_ALIGN_REPLACED(Field) = 1;
> - }
> - }
> }
> // Size of the complete type will be a multiple of its alignment.
> // In some cases involving empty C++ classes this is not true coming in.
> @@ -1900,17 +1838,11 @@
> for (tree Field = TYPE_FIELDS(type); Field; Field = TREE_CHAIN(Field)) {
> if (TREE_CODE(Field) == FIELD_DECL) {
> if (DECL_FIELD_BASE_REPLACED(Field)) {
> - tree &oldTy = BaseTypesMap[TREE_TYPE(Field)];
> + tree &oldTy = BaseTypesMap[std::make_pair(TREE_TYPE(Field), 0U)];
> assert(oldTy);
> TREE_TYPE(Field) = oldTy;
> DECL_FIELD_BASE_REPLACED(Field) = 0;
> }
> - if (DECL_FIELD_ALIGN_REPLACED(Field)) {
> - tree &oldTy = LessAlignedTypesMap[std::make_pair(TREE_TYPE(Field), 0U)];
> - assert(oldTy);
> - TREE_TYPE(Field) = oldTy;
> - DECL_FIELD_ALIGN_REPLACED(Field) = 0;
> - }
> }
> }
> }
> @@ -2111,7 +2043,7 @@
> // class D : public virtual B, public virtual C { public: int i3; };
> //
> // The TYPE nodes gcc builds for classes represent that class as it looks
> -// standing alone. Thus B is size 12 and looks like { vptr; i2; baseclass A; }
> +// standing alone. Thus B is size 12 and looks like { vptr; i1; baseclass A; }
> // However, this is not the layout used when that class is a base class for
> // some other class, yet the same TYPE node is still used. D in the above has
> // both a BINFO list entry and a FIELD that reference type B, but the virtual
>
> Modified: llvm-gcc-4.2/trunk/gcc/tree.h
> URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/tree.h?rev=81399&r1=81398&r2=81399&view=diff
>
> ==============================================================================
> --- llvm-gcc-4.2/trunk/gcc/tree.h (original)
> +++ llvm-gcc-4.2/trunk/gcc/tree.h Wed Sep 9 18:36:04 2009
> @@ -2751,10 +2751,6 @@
> /* In a FIELD_DECL, marks that the type is temporarily replaced in ConvertType
> because it is used as a base class of another type. */
> #define DECL_FIELD_BASE_REPLACED(NODE) (FIELD_DECL_CHECK (NODE)->decl_common.decl_flag_0)
> -/* In a FIELD_DECL, marks that the type is temporarily replaced in ConvertType
> - because it is used as the type of a field with less alignment than the
> - type, which means the type may not get tail padding in this case. */
> -#define DECL_FIELD_ALIGN_REPLACED(NODE) (FIELD_DECL_CHECK (NODE)->decl_common.gimple_reg_flag)
> #endif
> /* LLVM LOCAL end */
>
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>
More information about the llvm-commits
mailing list