Changeset fd4df379


Ignore:
Timestamp:
Jul 25, 2024, 7:12:46 PM (8 months ago)
Author:
Michael Brooks <mlbrooks@…>
Branches:
master
Children:
bb20aa6, daa4cc1
Parents:
3cb693c
Message:

Implement boxing for arrays.

The added test is things that did not work before.

Files:
5 added
2 edited

Legend:

Unmodified
Added
Removed
  • TabularUnified src/GenPoly/Box.cpp

    r3cb693c rfd4df379  
    673673                TypeVarMap const & typeVars,
    674674                ast::TypeSubstitution const * 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                         }
     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 );
    680687                }
    681688        }
     
    11921199                assert( 2 == expr->args.size() );
    11931200
    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 );
     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
    11981208                // If neither argument is a polymorphic pointer, do nothing.
    1199                 if ( !baseType1 && !baseType2 ) {
     1209                if ( !isPoly1 && !isPoly2 ) {
    12001210                        return expr;
    12011211                }
    12021212                // The arguments cannot both be polymorphic pointers.
    1203                 assert( !baseType1 || !baseType2 );
     1213                assert( !isPoly1 || !isPoly2 );
    12041214                // (So exactly one of the arguments is a polymorphic pointer.)
    12051215
     
    12101220                ast::UntypedExpr * ret = new ast::UntypedExpr( location,
    12111221                                new ast::NameExpr( location, "?+?" ) );
    1212                 if ( baseType1 ) {
     1222                if ( isPoly1 ) {
     1223                        assert( arg1Ty );
     1224                        auto arg1TyPtr = dynamic_cast<ast::PointerType const * >( arg1Ty );
     1225                        assert( arg1TyPtr );
    12131226                        auto multiply = ast::UntypedExpr::createCall( location2, "?*?", {
    12141227                                expr->args.back(),
    1215                                 new ast::SizeofExpr( location1, deepCopy( baseType1 ) ),
     1228                                new ast::SizeofExpr( location1, deepCopy( arg1TyPtr->base ) ),
    12161229                        } );
    12171230                        ret->args.push_back( expr->args.front() );
    12181231                        ret->args.push_back( multiply );
    12191232                } else {
    1220                         assert( baseType2 );
     1233                        assert( isPoly2 );
     1234                        assert( arg2Ty );
     1235                        auto arg2TyPtr = dynamic_cast<ast::PointerType const * >( arg2Ty );
     1236                        assert( arg2TyPtr );
    12211237                        auto multiply = ast::UntypedExpr::createCall( location1, "?*?", {
    12221238                                expr->args.front(),
    1223                                 new ast::SizeofExpr( location2, deepCopy( baseType2 ) ),
     1239                                new ast::SizeofExpr( location2, deepCopy( arg2TyPtr->base ) ),
    12241240                        } );
    12251241                        ret->args.push_back( multiply );
     
    12341250                assert( 1 == expr->args.size() );
    12351251
     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
    12361258                // If this isn't for a poly type, then do nothing.
    1237                 if ( !isPolyType( expr->result, scopeTypeVars, typeSubs ) ) {
     1259                if ( !isPolyType( referentTy, scopeTypeVars, typeSubs ) ) {
    12381260                        return expr;
    12391261                }
     
    12431265                // Fix expression type to remove pointer.
    12441266                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                }
    12451271                ret->env = expr->env ? expr->env : ret->env;
    12461272                return ret;
     
    12911317                return makeIncrDecrExpr(
    12921318                        expr->location, expr, baseType, "++?" == varName );
    1293         // Addition and Subtration Intrinsics:
     1319        // Addition and Subtraction Intrinsics:
    12941320        } else if ( "?+?" == varName || "?-?" == varName ) {
    12951321                assert( expr->result );
    12961322                assert( 2 == expr->args.size() );
    12971323
    1298                 auto baseType1 =
    1299                         isPolyPtr( expr->args.front()->result, scopeTypeVars, typeSubs );
    1300                 auto baseType2 =
    1301                         isPolyPtr( expr->args.back()->result, scopeTypeVars, typeSubs );
     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;
    13021329
    13031330                CodeLocation const & location = expr->location;
    13041331                CodeLocation const & location1 = expr->args.front()->location;
    13051332                CodeLocation const & location2 = expr->args.back()->location;
    1306                 // LHS op RHS -> (LHS op RHS) / sizeof(LHS)
    1307                 if ( baseType1 && baseType2 ) {
     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 );
    13081339                        auto divide = ast::UntypedExpr::createCall( location, "?/?", {
    13091340                                expr,
    1310                                 new ast::SizeofExpr( location, deepCopy( baseType1 ) ),
     1341                                new ast::SizeofExpr( location, deepCopy( arg1TyPtr->base ) ),
    13111342                        } );
    13121343                        if ( expr->env ) divide->env = expr->env;
    13131344                        return divide;
    13141345                // LHS op RHS -> LHS op (RHS * sizeof(LHS))
    1315                 } else if ( baseType1 ) {
     1346                } else if ( isPoly1 ) {
     1347                        assert( arg1Ty );
     1348                        auto arg1TyPtr = dynamic_cast<ast::PointerType const * >( arg1Ty );
     1349                        assert( arg1TyPtr );
    13161350                        auto multiply = ast::UntypedExpr::createCall( location2, "?*?", {
    13171351                                expr->args.back(),
    1318                                 new ast::SizeofExpr( location1, deepCopy( baseType1 ) ),
     1352                                new ast::SizeofExpr( location1, deepCopy( arg1TyPtr->base ) ),
    13191353                        } );
    13201354                        return ast::mutate_field_index(
    13211355                                expr, &ast::ApplicationExpr::args, 1, multiply );
    13221356                // LHS op RHS -> (LHS * sizeof(RHS)) op RHS
    1323                 } else if ( baseType2 ) {
     1357                } else if ( isPoly2 ) {
     1358                        assert( arg2Ty );
     1359                        auto arg2TyPtr = dynamic_cast<ast::PointerType const * >( arg2Ty );
     1360                        assert( arg2TyPtr );
    13241361                        auto multiply = ast::UntypedExpr::createCall( location1, "?*?", {
    13251362                                expr->args.front(),
    1326                                 new ast::SizeofExpr( location2, deepCopy( baseType2 ) ),
     1363                                new ast::SizeofExpr( location2, deepCopy( arg2TyPtr->base ) ),
    13271364                        } );
    13281365                        return ast::mutate_field_index(
     
    15881625        /// Change the type of generic aggregate members to char[].
    15891626        void mutateMembers( ast::AggregateDecl * aggr );
    1590         /// Returns the calculated sizeof expression for type, or nullptr for use
    1591         /// C sizeof().
     1627        /// Returns the calculated sizeof/alignof expressions for type, or
     1628        /// nullptr for use C size/alignof().
    15921629        ast::Expr const * genSizeof( CodeLocation const &, ast::Type const * );
     1630        ast::Expr const * genAlignof( CodeLocation const &, ast::Type const * );
    15931631        /// Enters a new scope for type-variables,
    15941632        /// adding the type variables from the provided type.
     
    16131651{}
    16141652
     1653static 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
    16151672/// Converts polymorphic type into a suitable monomorphic representation.
    1616 /// Currently: __attribute__(( aligned(8) )) char[size_T];
    1617 ast::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() );
     1673/// Simple cases: T -> __attribute__(( aligned(8) )) char[sizeof_T];
     1674/// Array cases: T[eOut][eIn] ->  __attribute__(( aligned(8) )) char[eOut][eIn][sizeof_T];
     1675ast::Type * polyToMonoType( CodeLocation const & loc, ast::Type const * ty ) {
     1676        auto ret = polyToMonoTypeRec( loc, ty );
    16241677        ret->attributes.emplace_back( new ast::Attribute( "aligned",
    1625                 { ast::ConstantExpr::from_int( location, 8 ) } ) );
     1678                { ast::ConstantExpr::from_int( loc, 8 ) } ) );
    16261679        return ret;
    16271680}
     
    17161769        // Forally, side effects are not safe in this function. But it works.
    17171770        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        }
    17181792
    17191793        mutDecl->init = new ast::SingleInit( decl->location,
     
    18691943                ast::AlignofExpr const * expr ) {
    18701944        ast::Type const * type = expr->type ? expr->type : expr->expr->result;
    1871         if ( findGeneric( expr->location, type ) ) {
    1872                 return new ast::NameExpr( expr->location,
    1873                         alignofName( Mangle::mangleType( type ) ) );
    1874         } else {
    1875                 return expr;
    1876         }
     1945        ast::Expr const * gen = genAlignof( expr->location, type );
     1946        return ( gen ) ? gen : expr;
    18771947}
    18781948
     
    20952165
    20962166                return true;
     2167
     2168        } else if ( auto inst = dynamic_cast<ast::ArrayType const *>( type ) ) {
     2169                return findGeneric( location, inst->base );
    20972170        }
    20982171        return false;
     
    21552228                return makeOp( location, "?*?", sizeofBase, dim );
    21562229        } else if ( findGeneric( location, type ) ) {
    2157                 // Generate calculated size for generic type.
     2230                // Generate reference to _sizeof parameter
    21582231                return new ast::NameExpr( location, sizeofName(
     2232                                Mangle::mangleType( type ) ) );
     2233        } else {
     2234                return nullptr;
     2235        }
     2236}
     2237
     2238ast::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(
    21592246                                Mangle::mangleType( type ) ) );
    21602247        } else {
  • TabularUnified tests/Makefile.am

    r3cb693c rfd4df379  
    6969.PHONY : concurrency list .validate .test_makeflags
    7070.INTERMEDIATE : .validate .validate.cfa .test_makeflags
    71 EXTRA_PROGRAMS = avl_test linkonce linking/mangling/anon .dummy_hack # build but do not install
     71EXTRA_PROGRAMS = array-collections/boxed avl_test linkonce linking/mangling/anon .dummy_hack # build but do not install
    7272EXTRA_DIST = test.py \
    7373        pybin/__init__.py \
     
    7777        pybin/tools.py \
    7878        long_tests.hfa \
     79        array-collections/boxed.hfa \
     80        array-collections/boxed.cases.hfa \
    7981        avltree/avl-private.h \
    8082        avltree/avl.h \
     
    104106        done
    105107
     108array_collections_boxed_SOURCES = array-collections/boxed.main.cfa array-collections/boxed.bookend.cfa
    106109avl_test_SOURCES = avltree/avl_test.cfa avltree/avl0.cfa avltree/avl1.cfa avltree/avl2.cfa avltree/avl3.cfa avltree/avl4.cfa avltree/avl-private.cfa
    107110linkonce_SOURCES = link-once/main.cfa link-once/partner.cfa
Note: See TracChangeset for help on using the changeset viewer.