Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/GenPoly/Box.cpp

    rfd4df379 rc92bdcc  
    673673                TypeVarMap const & typeVars,
    674674                ast::TypeSubstitution const * typeSubs ) {
    675         if ( auto name = expr->func.as<ast::NameExpr>() ) {
    676                 if ( "*?" == name->name ) {
    677                         // It's a deref.
    678                         // Must look under the * (and strip its ptr-ty) because expr's
    679                         // result could be ar/ptr-decayed.  If expr.inner:T(*)[n], then
    680                         // expr is a poly deref, even though expr:T*, which is not poly.
    681                         auto ptrExpr = expr->args.front();
    682                         auto ptrTy = ptrExpr->result.as<ast::PointerType>();
    683                         assert(ptrTy); // thing being deref'd must be pointer
    684                         auto referentTy = ptrTy->base;
    685                         assert(referentTy);
    686                         return isPolyType( referentTy, typeVars, typeSubs );
     675        if ( expr->result && isPolyType( expr->result, typeVars, typeSubs ) ) {
     676                if ( auto name = expr->func.as<ast::NameExpr>() ) {
     677                        if ( "*?" == name->name ) {
     678                                return true;
     679                        }
    687680                }
    688681        }
     
    11991192                assert( 2 == expr->args.size() );
    12001193
    1201                 ast::Type const * arg1Ty = expr->args.front()->result;
    1202                 ast::Type const * arg2Ty = expr->args.back()->result;
    1203 
    1204                 // two cases: a[i] with first arg poly ptr, i[a] with second arg poly ptr
    1205                 bool isPoly1 = isPolyPtr( arg1Ty, scopeTypeVars, typeSubs ) != nullptr;
    1206                 bool isPoly2 = isPolyPtr( arg2Ty, scopeTypeVars, typeSubs ) != nullptr;
    1207 
     1194                ast::Type const * baseType1 =
     1195                        isPolyPtr( expr->args.front()->result, scopeTypeVars, typeSubs );
     1196                ast::Type const * baseType2 =
     1197                        isPolyPtr( expr->args.back()->result, scopeTypeVars, typeSubs );
    12081198                // If neither argument is a polymorphic pointer, do nothing.
    1209                 if ( !isPoly1 && !isPoly2 ) {
     1199                if ( !baseType1 && !baseType2 ) {
    12101200                        return expr;
    12111201                }
    12121202                // The arguments cannot both be polymorphic pointers.
    1213                 assert( !isPoly1 || !isPoly2 );
     1203                assert( !baseType1 || !baseType2 );
    12141204                // (So exactly one of the arguments is a polymorphic pointer.)
    12151205
     
    12201210                ast::UntypedExpr * ret = new ast::UntypedExpr( location,
    12211211                                new ast::NameExpr( location, "?+?" ) );
    1222                 if ( isPoly1 ) {
    1223                         assert( arg1Ty );
    1224                         auto arg1TyPtr = dynamic_cast<ast::PointerType const * >( arg1Ty );
    1225                         assert( arg1TyPtr );
     1212                if ( baseType1 ) {
    12261213                        auto multiply = ast::UntypedExpr::createCall( location2, "?*?", {
    12271214                                expr->args.back(),
    1228                                 new ast::SizeofExpr( location1, deepCopy( arg1TyPtr->base ) ),
     1215                                new ast::SizeofExpr( location1, deepCopy( baseType1 ) ),
    12291216                        } );
    12301217                        ret->args.push_back( expr->args.front() );
    12311218                        ret->args.push_back( multiply );
    12321219                } else {
    1233                         assert( isPoly2 );
    1234                         assert( arg2Ty );
    1235                         auto arg2TyPtr = dynamic_cast<ast::PointerType const * >( arg2Ty );
    1236                         assert( arg2TyPtr );
     1220                        assert( baseType2 );
    12371221                        auto multiply = ast::UntypedExpr::createCall( location1, "?*?", {
    12381222                                expr->args.front(),
    1239                                 new ast::SizeofExpr( location2, deepCopy( arg2TyPtr->base ) ),
     1223                                new ast::SizeofExpr( location2, deepCopy( baseType2 ) ),
    12401224                        } );
    12411225                        ret->args.push_back( multiply );
     
    12501234                assert( 1 == expr->args.size() );
    12511235
    1252                 auto ptrExpr = expr->args.front();
    1253                 auto ptrTy = ptrExpr->result.as<ast::PointerType>();
    1254                 assert(ptrTy); // thing being deref'd must be pointer
    1255                 auto referentTy = ptrTy->base;
    1256                 assert(referentTy);
    1257 
    12581236                // If this isn't for a poly type, then do nothing.
    1259                 if ( !isPolyType( referentTy, scopeTypeVars, typeSubs ) ) {
     1237                if ( !isPolyType( expr->result, scopeTypeVars, typeSubs ) ) {
    12601238                        return expr;
    12611239                }
     
    12651243                // Fix expression type to remove pointer.
    12661244                ret->result = expr->result;
    1267                 // apply pointer decay
    1268                 if (auto retArTy = ret->result.as<ast::ArrayType>()) {
    1269                         ret->result = new ast::PointerType( retArTy->base );
    1270                 }
    12711245                ret->env = expr->env ? expr->env : ret->env;
    12721246                return ret;
     
    13171291                return makeIncrDecrExpr(
    13181292                        expr->location, expr, baseType, "++?" == varName );
    1319         // Addition and Subtraction Intrinsics:
     1293        // Addition and Subtration Intrinsics:
    13201294        } else if ( "?+?" == varName || "?-?" == varName ) {
    13211295                assert( expr->result );
    13221296                assert( 2 == expr->args.size() );
    13231297
    1324                 ast::Type const * arg1Ty = expr->args.front()->result;
    1325                 ast::Type const * arg2Ty = expr->args.back()->result;
    1326 
    1327                 bool isPoly1 = isPolyPtr( arg1Ty, scopeTypeVars, typeSubs ) != nullptr;
    1328                 bool isPoly2 = isPolyPtr( arg2Ty, scopeTypeVars, typeSubs ) != nullptr;
     1298                auto baseType1 =
     1299                        isPolyPtr( expr->args.front()->result, scopeTypeVars, typeSubs );
     1300                auto baseType2 =
     1301                        isPolyPtr( expr->args.back()->result, scopeTypeVars, typeSubs );
    13291302
    13301303                CodeLocation const & location = expr->location;
    13311304                CodeLocation const & location1 = expr->args.front()->location;
    13321305                CodeLocation const & location2 = expr->args.back()->location;
    1333                 // LHS minus RHS -> (LHS minus RHS) / sizeof(LHS)
    1334                 if ( isPoly1 && isPoly2 ) {
    1335                         assert( "?-?" == varName );
    1336                         assert( arg1Ty );
    1337                         auto arg1TyPtr = dynamic_cast<ast::PointerType const * >( arg1Ty );
    1338                         assert( arg1TyPtr );
     1306                // LHS op RHS -> (LHS op RHS) / sizeof(LHS)
     1307                if ( baseType1 && baseType2 ) {
    13391308                        auto divide = ast::UntypedExpr::createCall( location, "?/?", {
    13401309                                expr,
    1341                                 new ast::SizeofExpr( location, deepCopy( arg1TyPtr->base ) ),
     1310                                new ast::SizeofExpr( location, deepCopy( baseType1 ) ),
    13421311                        } );
    13431312                        if ( expr->env ) divide->env = expr->env;
    13441313                        return divide;
    13451314                // LHS op RHS -> LHS op (RHS * sizeof(LHS))
    1346                 } else if ( isPoly1 ) {
    1347                         assert( arg1Ty );
    1348                         auto arg1TyPtr = dynamic_cast<ast::PointerType const * >( arg1Ty );
    1349                         assert( arg1TyPtr );
     1315                } else if ( baseType1 ) {
    13501316                        auto multiply = ast::UntypedExpr::createCall( location2, "?*?", {
    13511317                                expr->args.back(),
    1352                                 new ast::SizeofExpr( location1, deepCopy( arg1TyPtr->base ) ),
     1318                                new ast::SizeofExpr( location1, deepCopy( baseType1 ) ),
    13531319                        } );
    13541320                        return ast::mutate_field_index(
    13551321                                expr, &ast::ApplicationExpr::args, 1, multiply );
    13561322                // LHS op RHS -> (LHS * sizeof(RHS)) op RHS
    1357                 } else if ( isPoly2 ) {
    1358                         assert( arg2Ty );
    1359                         auto arg2TyPtr = dynamic_cast<ast::PointerType const * >( arg2Ty );
    1360                         assert( arg2TyPtr );
     1323                } else if ( baseType2 ) {
    13611324                        auto multiply = ast::UntypedExpr::createCall( location1, "?*?", {
    13621325                                expr->args.front(),
    1363                                 new ast::SizeofExpr( location2, deepCopy( arg2TyPtr->base ) ),
     1326                                new ast::SizeofExpr( location2, deepCopy( baseType2 ) ),
    13641327                        } );
    13651328                        return ast::mutate_field_index(
     
    16251588        /// Change the type of generic aggregate members to char[].
    16261589        void mutateMembers( ast::AggregateDecl * aggr );
    1627         /// Returns the calculated sizeof/alignof expressions for type, or
    1628         /// nullptr for use C size/alignof().
     1590        /// Returns the calculated sizeof expression for type, or nullptr for use
     1591        /// C sizeof().
    16291592        ast::Expr const * genSizeof( CodeLocation const &, ast::Type const * );
    1630         ast::Expr const * genAlignof( CodeLocation const &, ast::Type const * );
    16311593        /// Enters a new scope for type-variables,
    16321594        /// adding the type variables from the provided type.
     
    16511613{}
    16521614
    1653 static ast::Type * polyToMonoTypeRec( CodeLocation const & loc,
    1654                 ast::Type const * ty ) {
    1655         ast::Type * ret;
    1656         if ( auto aTy = dynamic_cast<ast::ArrayType const *>( ty ) ) {
    1657                 // recursive case
    1658                 auto monoBase = polyToMonoTypeRec( loc, aTy->base );
    1659                 ret = new ast::ArrayType( monoBase, aTy->dimension,
    1660                         aTy->isVarLen, aTy->isStatic, aTy->qualifiers );
    1661         } else {
    1662                 // base case
    1663                 auto charType = new ast::BasicType( ast::BasicKind::Char );
    1664                 auto size = new ast::NameExpr( loc,
    1665                         sizeofName( Mangle::mangleType( ty ) ) );
    1666                 ret = new ast::ArrayType( charType, size,
    1667                         ast::VariableLen, ast::DynamicDim, ast::CV::Qualifiers() );
    1668         }
    1669         return ret;
    1670 }
    1671 
    16721615/// Converts polymorphic type into a suitable monomorphic representation.
    1673 /// Simple cases: T -> __attribute__(( aligned(8) )) char[sizeof_T];
    1674 /// Array cases: T[eOut][eIn] ->  __attribute__(( aligned(8) )) char[eOut][eIn][sizeof_T];
    1675 ast::Type * polyToMonoType( CodeLocation const & loc, ast::Type const * ty ) {
    1676         auto ret = polyToMonoTypeRec( loc, ty );
     1616/// Currently: __attribute__(( aligned(8) )) char[size_T];
     1617ast::Type * polyToMonoType( CodeLocation const & location,
     1618                ast::Type const * declType ) {
     1619        auto charType = new ast::BasicType( ast::BasicKind::Char );
     1620        auto size = new ast::NameExpr( location,
     1621                sizeofName( Mangle::mangleType( declType ) ) );
     1622        auto ret = new ast::ArrayType( charType, size,
     1623                ast::VariableLen, ast::DynamicDim, ast::CV::Qualifiers() );
    16771624        ret->attributes.emplace_back( new ast::Attribute( "aligned",
    1678                 { ast::ConstantExpr::from_int( loc, 8 ) } ) );
     1625                { ast::ConstantExpr::from_int( location, 8 ) } ) );
    16791626        return ret;
    16801627}
     
    17691716        // Forally, side effects are not safe in this function. But it works.
    17701717        erase_if( mutDecl->attributes, matchAndMove );
    1771 
    1772         // Change the decl's type.
    1773         // Upon finishing the box pass, it shall be void*.
    1774         // At this middle-of-box-pass point, that type is T.
    1775 
    1776         // example 1
    1777         // before box:                                  T     t ;
    1778         // before here:  char _bufxx    [_sizeof_Y1T];  T     t = _bufxx;
    1779         // after here:   char _bufxx    [_sizeof_Y1T];  T     t = _bufxx;  (no change here - non array case)
    1780         // after box:    char _bufxx    [_sizeof_Y1T];  void *t = _bufxx;
    1781 
    1782         // example 2
    1783         // before box:                                  T     t[42] ;
    1784         // before here:  char _bufxx[42][_sizeof_Y1T];  T     t[42] = _bufxx;
    1785         // after here:   char _bufxx[42][_sizeof_Y1T];  T     t     = _bufxx;
    1786         // after box:    char _bufxx[42][_sizeof_Y1T];  void *t     = _bufxx;
    1787 
    1788         // Strip all "array of" wrappers
    1789         while ( auto arrayType = dynamic_cast<ast::ArrayType const *>( mutDecl->type.get() ) ) {
    1790                 mutDecl->type = arrayType->base;
    1791         }
    17921718
    17931719        mutDecl->init = new ast::SingleInit( decl->location,
     
    19431869                ast::AlignofExpr const * expr ) {
    19441870        ast::Type const * type = expr->type ? expr->type : expr->expr->result;
    1945         ast::Expr const * gen = genAlignof( expr->location, type );
    1946         return ( gen ) ? gen : expr;
     1871        if ( findGeneric( expr->location, type ) ) {
     1872                return new ast::NameExpr( expr->location,
     1873                        alignofName( Mangle::mangleType( type ) ) );
     1874        } else {
     1875                return expr;
     1876        }
    19471877}
    19481878
     
    21652095
    21662096                return true;
    2167 
    2168         } else if ( auto inst = dynamic_cast<ast::ArrayType const *>( type ) ) {
    2169                 return findGeneric( location, inst->base );
    21702097        }
    21712098        return false;
     
    22282155                return makeOp( location, "?*?", sizeofBase, dim );
    22292156        } else if ( findGeneric( location, type ) ) {
    2230                 // Generate reference to _sizeof parameter
     2157                // Generate calculated size for generic type.
    22312158                return new ast::NameExpr( location, sizeofName(
    2232                                 Mangle::mangleType( type ) ) );
    2233         } else {
    2234                 return nullptr;
    2235         }
    2236 }
    2237 
    2238 ast::Expr const * PolyGenericCalculator::genAlignof(
    2239                 CodeLocation const & location, ast::Type const * type ) {
    2240         if ( auto * array = dynamic_cast<ast::ArrayType const *>( type ) ) {
    2241                 // alignof array is alignof element
    2242                 return genAlignof( location, array->base );
    2243         } else if ( findGeneric( location, type ) ) {
    2244                 // Generate reference to _alignof parameter
    2245                 return new ast::NameExpr( location, alignofName(
    22462159                                Mangle::mangleType( type ) ) );
    22472160        } else {
Note: See TracChangeset for help on using the changeset viewer.