[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:06:26 PDT 2009
Nevermind, I see it was the next commit.
On Wed, Sep 16, 2009 at 12:05 AM, Daniel Dunbar <daniel at zuster.org> wrote:
> 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