Changeset 486caad for src


Ignore:
Timestamp:
Mar 25, 2024, 7:15:30 PM (9 months ago)
Author:
JiadaL <j82liang@…>
Branches:
master
Children:
d734fa1
Parents:
df78cce (diff), bf050c5 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge branch 'master' of plg.uwaterloo.ca:software/cfa/cfa-cc

Location:
src
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • src/CodeGen/CodeGenerator.cpp

    rdf78cce r486caad  
    192192        }
    193193
    194         assert( decl->returns.size() < 2 );
    195194        if ( 1 == decl->returns.size() ) {
    196195                ast::ptr<ast::Type> const & type = decl->returns[0]->get_type();
    197196                output << genTypeNoAttr( type, acc.str(), subOptions );
    198         } else {
     197        } else if ( 0 == decl->returns.size() ) {
    199198                output << "void " + acc.str();
     199        } else {
     200                assertf( !options.genC, "Multi-return should not reach code generation." );
     201                ast::ptr<ast::Type> type = new ast::TupleType( copy( decl->type->returns ) );
     202                output << genTypeNoAttr( type, acc.str(), subOptions );
    200203        }
    201204
  • src/Parser/DeclarationNode.cc

    rdf78cce r486caad  
    185185        newnode->type->aggregate.fields = fields;
    186186        newnode->type->aggregate.body = body;
    187         newnode->type->aggregate.tagged = false;
    188         newnode->type->aggregate.parent = nullptr;
    189187        return newnode;
    190188} // DeclarationNode::newAggregate
     
    199197        newnode->type->enumeration.typed = typed;
    200198        newnode->type->enumeration.hiding = hiding;
    201         if ( base && base->type )  {
     199        if ( base ) {
     200                assert( typed );
     201                assert( base->type );
    202202                newnode->type->base = base->type;
     203                base->type = nullptr;
     204                delete base;
    203205        } // if
    204206
     
    220222
    221223DeclarationNode * DeclarationNode::newEnumValueGeneric( const string * name, InitializerNode * init ) {
    222         if ( init ) {
    223                 if ( init->get_expression() ) {
    224                         return newEnumConstant( name, init->get_expression() );
    225                 } else {
    226                         DeclarationNode * newnode = newName( name );
    227                         newnode->initializer = init;
    228                         return newnode;
    229                 } // if
     224        if ( nullptr == init ) {
     225                return newName( name );
     226        } else if ( init->get_expression() ) {
     227                return newEnumConstant( name, init->get_expression() );
    230228        } else {
    231                 return newName( name );
     229                DeclarationNode * newnode = newName( name );
     230                newnode->initializer = init;
     231                return newnode;
    232232        } // if
    233233} // DeclarationNode::newEnumValueGeneric
     
    502502}
    503503
     504// This code handles a special issue with the attribute transparent_union.
     505//
     506//    typedef union U { int i; } typedef_name __attribute__(( aligned(16) )) __attribute__(( transparent_union ))
     507//
     508// Here the attribute aligned goes with the typedef_name, so variables declared of this type are
     509// aligned.  However, the attribute transparent_union must be moved from the typedef_name to
     510// alias union U.  Currently, this is the only know attribute that must be moved from typedef to
     511// alias.
     512static void moveUnionAttribute( DeclarationNode * decl, DeclarationNode * unionDecl ) {
     513        assert( decl->type->kind == TypeData::Symbolic );
     514        assert( decl->type->symbolic.isTypedef );
     515        assert( unionDecl->type->kind == TypeData::Aggregate );
     516
     517        if ( unionDecl->type->aggregate.kind != ast::AggregateDecl::Union ) return;
     518
     519        // Ignore the Aggregate_t::attributes. Why did we add that before the rework?
     520        for ( auto attr = decl->attributes.begin() ; attr != decl->attributes.end() ; ) {
     521                if ( (*attr)->name == "transparent_union" || (*attr)->name == "__transparent_union__" ) {
     522                        unionDecl->attributes.emplace_back( attr->release() );
     523                        attr = decl->attributes.erase( attr );
     524                } else {
     525                        ++attr;
     526                }
     527        }
     528}
     529
     530// Helper for addTypedef, handles the case where the typedef wraps an
     531// aggregate declaration (not a type), returns a chain of nodes.
     532static DeclarationNode * addTypedefAggr(
     533                DeclarationNode * olddecl, TypeData * newtype ) {
     534        TypeData *& oldaggr = olddecl->type->aggInst.aggregate;
     535
     536        // Handle anonymous aggregates: typedef struct { int i; } foo
     537        // Give the typedefed type a consistent name across translation units.
     538        if ( oldaggr->aggregate.anon ) {
     539                delete oldaggr->aggregate.name;
     540                oldaggr->aggregate.name = new string( "__anonymous_" + *olddecl->name );
     541                oldaggr->aggregate.anon = false;
     542                oldaggr->qualifiers.reset();
     543        }
     544
     545        // Replace the wrapped TypeData with a forward declaration.
     546        TypeData * newaggr = new TypeData( TypeData::Aggregate );
     547        newaggr->aggregate.kind = oldaggr->aggregate.kind;
     548        newaggr->aggregate.name = oldaggr->aggregate.name ? new string( *oldaggr->aggregate.name ) : nullptr;
     549        newaggr->aggregate.body = false;
     550        newaggr->aggregate.anon = oldaggr->aggregate.anon;
     551        swap( newaggr, oldaggr );
     552
     553        newtype->base = olddecl->type;
     554        olddecl->type = newtype;
     555        DeclarationNode * newdecl = new DeclarationNode;
     556        newdecl->type = newaggr;
     557        newdecl->next = olddecl;
     558
     559        moveUnionAttribute( olddecl, newdecl );
     560
     561        return newdecl;
     562}
     563
     564// Helper for addTypedef, handles the case where the typedef wraps an
     565// enumeration declaration (not a type), returns a chain of nodes.
     566static DeclarationNode * addTypedefEnum(
     567                DeclarationNode * olddecl, TypeData * newtype ) {
     568        TypeData *& oldenum = olddecl->type->aggInst.aggregate;
     569
     570        // Handle anonymous enumeration: typedef enum { A, B, C } foo
     571        // Give the typedefed type a consistent name across translation units.
     572        if ( oldenum->enumeration.anon ) {
     573                delete oldenum->enumeration.name;
     574                oldenum->enumeration.name = new string( "__anonymous_" + *olddecl->name );
     575                oldenum->enumeration.anon = false;
     576                oldenum->qualifiers.reset();
     577        }
     578
     579        // Replace the wrapped TypeData with a forward declaration.
     580        TypeData * newenum = new TypeData( TypeData::Enum );
     581        newenum->enumeration.name = oldenum->enumeration.name ? new string( *oldenum->enumeration.name ) : nullptr;
     582        newenum->enumeration.body = false;
     583        newenum->enumeration.anon = oldenum->enumeration.anon;
     584        newenum->enumeration.typed = oldenum->enumeration.typed;
     585        newenum->enumeration.hiding = oldenum->enumeration.hiding;
     586        swap( newenum, oldenum );
     587
     588        newtype->base = olddecl->type;
     589        olddecl->type = newtype;
     590        DeclarationNode * newdecl = new DeclarationNode;
     591        newdecl->type = newenum;
     592        newdecl->next = olddecl;
     593
     594        return newdecl;
     595}
     596
     597// Wrap the declaration in a typedef. It actually does that by modifying the
     598// existing declaration, and may split it into two declarations.
     599// This only happens if the wrapped type is actually a declaration of a SUE
     600// type. If it does, the DeclarationNode for the SUE declaration is the node
     601// returned, make sure later transformations are applied to the right node.
    504602DeclarationNode * DeclarationNode::addTypedef() {
    505603        TypeData * newtype = new TypeData( TypeData::Symbolic );
     
    507605        newtype->symbolic.isTypedef = true;
    508606        newtype->symbolic.name = name ? new string( *name ) : nullptr;
    509         newtype->base = type;
    510         type = newtype;
    511         return this;
     607        // If this typedef is wrapping an aggregate, separate them out.
     608        if ( TypeData::AggregateInst == type->kind
     609                        && TypeData::Aggregate == type->aggInst.aggregate->kind
     610                        && type->aggInst.aggregate->aggregate.body ) {
     611                return addTypedefAggr( this, newtype );
     612        // If this typedef is wrapping an enumeration, separate them out.
     613        } else if ( TypeData::AggregateInst == type->kind
     614                        && TypeData::Enum == type->aggInst.aggregate->kind
     615                        && type->aggInst.aggregate->enumeration.body ) {
     616                return addTypedefEnum( this, newtype );
     617        // There is no internal declaration, just a type.
     618        } else {
     619                newtype->base = type;
     620                type = newtype;
     621                return this;
     622        }
    512623}
    513624
     
    711822}
    712823
    713 // If a typedef wraps an anonymous declaration, name the inner declaration so it has a consistent name across
    714 // translation units.
    715 static void nameTypedefedDecl(
    716                 DeclarationNode * innerDecl,
    717                 const DeclarationNode * outerDecl ) {
    718         TypeData * outer = outerDecl->type;
    719         assert( outer );
    720         // First make sure this is a typedef:
    721         if ( outer->kind != TypeData::Symbolic || !outer->symbolic.isTypedef ) {
    722                 return;
    723         }
    724         TypeData * inner = innerDecl->type;
    725         assert( inner );
    726         // Always clear any CVs associated with the aggregate:
    727         inner->qualifiers.reset();
    728         // Handle anonymous aggregates: typedef struct { int i; } foo
    729         if ( inner->kind == TypeData::Aggregate && inner->aggregate.anon ) {
    730                 delete inner->aggregate.name;
    731                 inner->aggregate.name = new string( "__anonymous_" + *outerDecl->name );
    732                 inner->aggregate.anon = false;
    733                 assert( outer->base );
    734                 delete outer->base->aggInst.aggregate->aggregate.name;
    735                 outer->base->aggInst.aggregate->aggregate.name = new string( "__anonymous_" + *outerDecl->name );
    736                 outer->base->aggInst.aggregate->aggregate.anon = false;
    737                 outer->base->aggInst.aggregate->qualifiers.reset();
    738         // Handle anonymous enumeration: typedef enum { A, B, C } foo
    739         } else if ( inner->kind == TypeData::Enum && inner->enumeration.anon ) {
    740                 delete inner->enumeration.name;
    741                 inner->enumeration.name = new string( "__anonymous_" + *outerDecl->name );
    742                 inner->enumeration.anon = false;
    743                 assert( outer->base );
    744                 delete outer->base->aggInst.aggregate->enumeration.name;
    745                 outer->base->aggInst.aggregate->enumeration.name = new string( "__anonymous_" + *outerDecl->name );
    746                 outer->base->aggInst.aggregate->enumeration.anon = false;
    747                 // No qualifiers.reset() here.
    748         }
    749 }
    750 
    751 // This code handles a special issue with the attribute transparent_union.
    752 //
    753 //    typedef union U { int i; } typedef_name __attribute__(( aligned(16) )) __attribute__(( transparent_union ))
    754 //
    755 // Here the attribute aligned goes with the typedef_name, so variables declared of this type are
    756 // aligned.  However, the attribute transparent_union must be moved from the typedef_name to
    757 // alias union U.  Currently, this is the only know attribute that must be moved from typedef to
    758 // alias.
    759 static void moveUnionAttribute( ast::Decl * decl, ast::UnionDecl * unionDecl ) {
    760         if ( auto typedefDecl = dynamic_cast<ast::TypedefDecl *>( decl ) ) {
    761                 // Is the typedef alias a union aggregate?
    762                 if ( nullptr == unionDecl ) return;
    763 
    764                 // If typedef is an alias for a union, then its alias type was hoisted above and remembered.
    765                 if ( auto unionInstType = typedefDecl->base.as<ast::UnionInstType>() ) {
    766                         auto instType = ast::mutate( unionInstType );
    767                         // Remove all transparent_union attributes from typedef and move to alias union.
    768                         for ( auto attr = instType->attributes.begin() ; attr != instType->attributes.end() ; ) {
    769                                 assert( *attr );
    770                                 if ( (*attr)->name == "transparent_union" || (*attr)->name == "__transparent_union__" ) {
    771                                         unionDecl->attributes.emplace_back( attr->release() );
    772                                         attr = instType->attributes.erase( attr );
    773                                 } else {
    774                                         attr++;
    775                                 }
    776                         }
    777                         typedefDecl->base = instType;
    778                 }
    779         }
    780 }
    781 
    782824// Get the non-anonymous name of the instance type of the declaration,
    783825// if one exists.
     
    800842                try {
    801843                        bool extracted_named = false;
    802                         ast::UnionDecl * unionDecl = nullptr;
    803844
    804845                        if ( DeclarationNode * extr = cur->extractAggregate() ) {
    805846                                assert( cur->type );
    806                                 nameTypedefedDecl( extr, cur );
    807847
    808848                                if ( ast::Decl * decl = extr->build() ) {
    809                                         // Remember the declaration if it is a union aggregate ?
    810                                         unionDecl = dynamic_cast<ast::UnionDecl *>( decl );
    811 
    812849                                        *out++ = decl;
    813850
     
    828865
    829866                        if ( ast::Decl * decl = cur->build() ) {
    830                                 moveUnionAttribute( decl, unionDecl );
    831 
    832867                                if ( "" == decl->name && !cur->get_inLine() ) {
    833868                                        // Don't include anonymous declaration for named aggregates,
  • src/Parser/TypeData.cc

    rdf78cce r486caad  
    8888                aggregate.fields = nullptr;
    8989                aggregate.body = false;
    90                 aggregate.tagged = false;
    91                 aggregate.parent = nullptr;
    9290                aggregate.anon = false;
    9391                break;
     
    221219                newtype->aggregate.kind = aggregate.kind;
    222220                newtype->aggregate.name = aggregate.name ? new string( *aggregate.name ) : nullptr;
    223                 newtype->aggregate.parent = aggregate.parent ? new string( *aggregate.parent ) : nullptr;
    224221                newtype->aggregate.params = maybeCopy( aggregate.params );
    225222                newtype->aggregate.actuals = maybeCopy( aggregate.actuals );
     
    228225                newtype->aggregate.body = aggregate.body;
    229226                newtype->aggregate.anon = aggregate.anon;
    230                 newtype->aggregate.tagged = aggregate.tagged;
    231227                break;
    232228        case AggregateInst:
  • src/Parser/TypeData.h

    rdf78cce r486caad  
    4848                ast::AggregateDecl::Aggregate kind;
    4949                const std::string * name = nullptr;
    50                 const std::string * parent = nullptr;
    5150                DeclarationNode * params = nullptr;
    5251                ExpressionNode * actuals = nullptr;                             // holds actual parameters later applied to AggInst
     
    5554                bool body;
    5655                bool anon;
    57                 bool tagged;
    5856        };
    5957
  • src/Parser/parser.yy

    rdf78cce r486caad  
    1010// Created On       : Sat Sep  1 20:22:55 2001
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Mar 11 18:30:03 2024
    13 // Update Count     : 6589
     12// Last Modified On : Sat Mar 16 18:19:23 2024
     13// Update Count     : 6617
    1414//
    1515
     
    485485%type<decl> elaborated_type elaborated_type_nobody
    486486
    487 %type<decl> enumerator_list enum_type enum_type_nobody
     487%type<decl> enumerator_list enum_type enum_type_nobody enumerator_type
    488488%type<init> enumerator_value_opt
    489489
     
    27422742
    27432743enum_type:
    2744         ENUM attribute_list_opt '{' enumerator_list comma_opt '}'
    2745                 { $$ = DeclarationNode::newEnum( nullptr, $4, true, false )->addQualifiers( $2 ); }
    2746         | ENUM attribute_list_opt '!' '{' enumerator_list comma_opt '}' // invalid syntax rule
    2747                 { SemanticError( yylloc, "syntax error, hiding ('!') the enumerator names of an anonymous enumeration means the names are inaccessible." ); $$ = nullptr; }
     2744                // anonymous, no type name
     2745        ENUM attribute_list_opt hide_opt '{' enumerator_list comma_opt '}'
     2746                {
     2747                        if ( $3 == EnumHiding::Hide ) {
     2748                                SemanticError( yylloc, "syntax error, hiding ('!') the enumerator names of an anonymous enumeration means the names are inaccessible." ); $$ = nullptr;
     2749                        } // if
     2750                        $$ = DeclarationNode::newEnum( nullptr, $5, true, false )->addQualifiers( $2 );
     2751                }
     2752        | ENUM enumerator_type attribute_list_opt hide_opt '{' enumerator_list comma_opt '}'
     2753                {
     2754                        if ( $2 && ($2->storageClasses.val != 0 || $2->type->qualifiers.any()) ) {
     2755                                SemanticError( yylloc, "syntax error, storage-class and CV qualifiers are not meaningful for enumeration constants, which are const." );
     2756                        }
     2757                        if ( $4 == EnumHiding::Hide ) {
     2758                                SemanticError( yylloc, "syntax error, hiding ('!') the enumerator names of an anonymous enumeration means the names are inaccessible." ); $$ = nullptr;
     2759                        } // if
     2760                        $$ = DeclarationNode::newEnum( nullptr, $6, true, true, $2 )->addQualifiers( $3 );
     2761                }
     2762
     2763                // named type
    27482764        | ENUM attribute_list_opt identifier
    27492765                { typedefTable.makeTypedef( *$3, "enum_type 1" ); }
     
    27522768        | ENUM attribute_list_opt typedef_name hide_opt '{' enumerator_list comma_opt '}' // unqualified type name
    27532769                { $$ = DeclarationNode::newEnum( $3->name, $6, true, false, nullptr, $4 )->addQualifiers( $2 ); }
    2754         | ENUM '(' cfa_abstract_parameter_declaration ')' attribute_list_opt '{' enumerator_list comma_opt '}'
    2755                 {
    2756                         if ( $3->storageClasses.val != 0 || $3->type->qualifiers.any() ) {
     2770        | ENUM enumerator_type attribute_list_opt identifier attribute_list_opt
     2771                {
     2772                        if ( $2 && ($2->storageClasses.any() || $2->type->qualifiers.val != 0) ) {
    27572773                                SemanticError( yylloc, "syntax error, storage-class and CV qualifiers are not meaningful for enumeration constants, which are const." );
    27582774                        }
    2759                         $$ = DeclarationNode::newEnum( nullptr, $7, true, true, $3 )->addQualifiers( $5 );
    2760                 }
    2761         | ENUM '(' cfa_abstract_parameter_declaration ')' attribute_list_opt '!' '{' enumerator_list comma_opt '}' // unqualified type name
    2762                 { SemanticError( yylloc, "syntax error, hiding ('!') the enumerator names of an anonymous enumeration means the names are inaccessible." ); $$ = nullptr; }
    2763         | ENUM '(' ')' attribute_list_opt '{' enumerator_list comma_opt '}'
    2764                 {
    2765                         $$ = DeclarationNode::newEnum( nullptr, $6, true, true )->addQualifiers( $4 );
    2766                 }
    2767         | ENUM '(' ')' attribute_list_opt '!' '{' enumerator_list comma_opt '}' // invalid syntax rule
    2768                 { SemanticError( yylloc, "syntax error, hiding ('!') the enumerator names of an anonymous enumeration means the names are inaccessible." ); $$ = nullptr; }
    2769         | ENUM '(' cfa_abstract_parameter_declaration ')' attribute_list_opt identifier attribute_list_opt
    2770                 {
    2771                         if ( $3 && ($3->storageClasses.any() || $3->type->qualifiers.val != 0) ) {
    2772                                 SemanticError( yylloc, "syntax error, storage-class and CV qualifiers are not meaningful for enumeration constants, which are const." );
    2773                         }
    2774                         typedefTable.makeTypedef( *$6, "enum_type 2" );
     2775                        typedefTable.makeTypedef( *$4, "enum_type 2" );
    27752776                }
    27762777          hide_opt '{' enumerator_list comma_opt '}'
    2777                 {
    2778                         $$ = DeclarationNode::newEnum( $6, $11, true, true, $3, $9 )->addQualifiers( $5 )->addQualifiers( $7 );
    2779                 }
    2780         | ENUM '(' ')' attribute_list_opt identifier attribute_list_opt hide_opt '{' enumerator_list comma_opt '}'
    2781                 {
    2782                         $$ = DeclarationNode::newEnum( $5, $9, true, true, nullptr, $7 )->addQualifiers( $4 )->addQualifiers( $6 );
    2783                 }
    2784         | ENUM '(' cfa_abstract_parameter_declaration ')' attribute_list_opt typedef_name attribute_list_opt hide_opt '{' enumerator_list comma_opt '}'
    2785                 {
    2786                         $$ = DeclarationNode::newEnum( $6->name, $10, true, true, $3, $8 )->addQualifiers( $5 )->addQualifiers( $7 );
    2787                 }
    2788         | ENUM '(' ')' attribute_list_opt typedef_name attribute_list_opt hide_opt '{' enumerator_list comma_opt '}'
    2789                 {
    2790                         $$ = DeclarationNode::newEnum( $5->name, $9, true, true, nullptr, $7 )->addQualifiers( $4 )->addQualifiers( $6 );
    2791                 }
     2778                { $$ = DeclarationNode::newEnum( $4, $9, true, true, $2, $7 )->addQualifiers( $3 )->addQualifiers( $5 ); }
     2779        | ENUM enumerator_type attribute_list_opt typedef_name attribute_list_opt hide_opt '{' enumerator_list comma_opt '}'
     2780                { $$ = DeclarationNode::newEnum( $4->name, $8, true, true, $2, $6 )->addQualifiers( $3 )->addQualifiers( $5 ); }
     2781
     2782                // forward declaration
    27922783        | enum_type_nobody
     2784        ;
     2785
     2786enumerator_type:
     2787        '(' ')'                                                                                         // pure enumeration
     2788                { $$ = nullptr; }
     2789        | '(' cfa_abstract_parameter_declaration ')'            // typed enumeration
     2790                { $$ = $2; }
    27932791        ;
    27942792
  • src/main.cc

    rdf78cce r486caad  
    101101}
    102102
    103 // Helpers for checkInvariant:
    104 void checkInvariants( std::list< Declaration * > & ) {}
    105 using ast::checkInvariants;
    106 
    107103#define PASS( name, pass, unit, ... )       \
    108104        if ( errorp ) { cerr << name << endl; } \
     
    112108        Stats::Time::StopBlock();               \
    113109        if ( invariant ) {                      \
    114                 checkInvariants(unit);              \
     110                ast::checkInvariants(unit);         \
    115111        }
    116112
Note: See TracChangeset for help on using the changeset viewer.