Changes in / [8a0a64d9:d5a52cc]


Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/GenPoly/InstantiateGeneric.cc

    r8a0a64d9 rd5a52cc  
    2121#include <vector>                      // for vector
    2222
     23#include "CodeGen/OperatorTable.h"
    2324#include "Common/PassVisitor.h"        // for PassVisitor, WithDeclsToAdd
    2425#include "Common/ScopedMap.h"          // for ScopedMap
     
    2728#include "Common/utility.h"            // for deleteAll, cloneAll
    2829#include "GenPoly.h"                   // for isPolyType, typesPolyCompatible
     30#include "InitTweak/InitTweak.h"
    2931#include "ResolvExpr/typeops.h"
    3032#include "ScopedSet.h"                 // for ScopedSet, ScopedSet<>::iterator
     
    154156
    155157        /// Add cast to dtype-static member expressions so that type information is not lost in GenericInstantiator
    156         struct FixDtypeStatic final {
     158        struct FixDtypeStatic final : public WithGuards, public WithVisitorRef<FixDtypeStatic>, public WithShortCircuiting, public WithStmtsToAdd {
    157159                Expression * postmutate( MemberExpr * memberExpr );
     160
     161                void premutate( ApplicationExpr * appExpr );
     162                void premutate( AddressExpr * addrExpr );
    158163
    159164                template<typename AggrInst>
    160165                Expression * fixMemberExpr( AggrInst * inst, MemberExpr * memberExpr );
     166
     167                bool isLvalueArg = false;
    161168        };
    162169
     
    501508                if ( isDtypeStatic( baseParams ) ) {
    502509                        if ( ! ResolvExpr::typesCompatible( memberExpr->result, memberExpr->member->get_type(), SymTab::Indexer() ) ) {
    503                                 // type of member and type of expression differ, so add cast to actual type
    504                                 return new CastExpr( memberExpr, memberExpr->result->clone() );
     510                                // type of member and type of expression differ
     511                                Type * concType = memberExpr->result->clone();
     512                                if ( isLvalueArg ) {
     513                                        // result must be C lvalue, so make a new reference variable with the correct actual type to replace the member expression
     514                                        //   forall(dtype T)
     515                                        //   struct Ptr {
     516                                        //     T * x
     517                                        //   };
     518                                        //   Ptr(int) p;
     519                                        //   int i;
     520                                        //   p.x = &i;
     521                                        // becomes
     522                                        //   int *& _dtype_static_member_0 = (int **)&p.x;
     523                                        //   _dtype_static_member_0 = &i;
     524                                        // Note: this currently creates more temporaries than is strictly necessary, since it does not check for duplicate uses of the same member expression.
     525                                        static UniqueName tmpNamer( "_dtype_static_member_" );
     526                                        Expression * init = new CastExpr( new AddressExpr( memberExpr ), new PointerType( Type::Qualifiers(), concType->clone() ) );
     527                                        ObjectDecl * tmp = ObjectDecl::newObject( tmpNamer.newName(), new ReferenceType( Type::Qualifiers(), concType ), new SingleInit( init ) );
     528                                        stmtsToAddBefore.push_back( new DeclStmt( noLabels, tmp ) );
     529                                        return new VariableExpr( tmp );
     530                                } else {
     531                                        // can simply add a cast to actual type
     532                                        return new CastExpr( memberExpr, concType );
     533                                }
    505534                        }
    506535                }
     
    520549        }
    521550
     551        void FixDtypeStatic::premutate( ApplicationExpr * appExpr ) {
     552                GuardValue( isLvalueArg );
     553                isLvalueArg = false;
     554                DeclarationWithType * function = InitTweak::getFunction( appExpr );
     555                if ( function->linkage == LinkageSpec::Intrinsic && CodeGen::isAssignment( function->name ) ) {
     556                        // explicitly visit children because only the first argument must be a C lvalue.
     557                        visit_children = false;
     558                        appExpr->env = maybeMutate( appExpr->env, *visitor );
     559                        appExpr->result = maybeMutate( appExpr->result, *visitor );
     560                        appExpr->function = maybeMutate( appExpr->function, *visitor );
     561                        isLvalueArg = true;
     562                        for ( Expression * arg : appExpr->args ) {
     563                                arg = maybeMutate( arg, *visitor );
     564                                isLvalueArg = false;
     565                        }
     566                }
     567        }
     568
     569        void FixDtypeStatic::premutate( AddressExpr * ) {
     570                // argument of & must be C lvalue
     571                GuardValue( isLvalueArg );
     572                isLvalueArg = true;
     573        }
    522574} // namespace GenPoly
    523575
Note: See TracChangeset for help on using the changeset viewer.