Changeset fd4df379
- Timestamp:
- Jul 25, 2024, 7:12:46 PM (8 months ago)
- Branches:
- master
- Children:
- bb20aa6, daa4cc1
- Parents:
- 3cb693c
- Files:
-
- 5 added
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
TabularUnified src/GenPoly/Box.cpp ¶
r3cb693c rfd4df379 673 673 TypeVarMap const & typeVars, 674 674 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 ); 680 687 } 681 688 } … … 1192 1199 assert( 2 == expr->args.size() ); 1193 1200 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 1198 1208 // If neither argument is a polymorphic pointer, do nothing. 1199 if ( ! baseType1 && !baseType2 ) {1209 if ( !isPoly1 && !isPoly2 ) { 1200 1210 return expr; 1201 1211 } 1202 1212 // The arguments cannot both be polymorphic pointers. 1203 assert( ! baseType1 || !baseType2 );1213 assert( !isPoly1 || !isPoly2 ); 1204 1214 // (So exactly one of the arguments is a polymorphic pointer.) 1205 1215 … … 1210 1220 ast::UntypedExpr * ret = new ast::UntypedExpr( location, 1211 1221 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 ); 1213 1226 auto multiply = ast::UntypedExpr::createCall( location2, "?*?", { 1214 1227 expr->args.back(), 1215 new ast::SizeofExpr( location1, deepCopy( baseType1) ),1228 new ast::SizeofExpr( location1, deepCopy( arg1TyPtr->base ) ), 1216 1229 } ); 1217 1230 ret->args.push_back( expr->args.front() ); 1218 1231 ret->args.push_back( multiply ); 1219 1232 } else { 1220 assert( baseType2 ); 1233 assert( isPoly2 ); 1234 assert( arg2Ty ); 1235 auto arg2TyPtr = dynamic_cast<ast::PointerType const * >( arg2Ty ); 1236 assert( arg2TyPtr ); 1221 1237 auto multiply = ast::UntypedExpr::createCall( location1, "?*?", { 1222 1238 expr->args.front(), 1223 new ast::SizeofExpr( location2, deepCopy( baseType2) ),1239 new ast::SizeofExpr( location2, deepCopy( arg2TyPtr->base ) ), 1224 1240 } ); 1225 1241 ret->args.push_back( multiply ); … … 1234 1250 assert( 1 == expr->args.size() ); 1235 1251 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 1236 1258 // If this isn't for a poly type, then do nothing. 1237 if ( !isPolyType( expr->result, scopeTypeVars, typeSubs ) ) {1259 if ( !isPolyType( referentTy, scopeTypeVars, typeSubs ) ) { 1238 1260 return expr; 1239 1261 } … … 1243 1265 // Fix expression type to remove pointer. 1244 1266 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 } 1245 1271 ret->env = expr->env ? expr->env : ret->env; 1246 1272 return ret; … … 1291 1317 return makeIncrDecrExpr( 1292 1318 expr->location, expr, baseType, "++?" == varName ); 1293 // Addition and Subtra tion Intrinsics:1319 // Addition and Subtraction Intrinsics: 1294 1320 } else if ( "?+?" == varName || "?-?" == varName ) { 1295 1321 assert( expr->result ); 1296 1322 assert( 2 == expr->args.size() ); 1297 1323 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; 1302 1329 1303 1330 CodeLocation const & location = expr->location; 1304 1331 CodeLocation const & location1 = expr->args.front()->location; 1305 1332 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 ); 1308 1339 auto divide = ast::UntypedExpr::createCall( location, "?/?", { 1309 1340 expr, 1310 new ast::SizeofExpr( location, deepCopy( baseType1) ),1341 new ast::SizeofExpr( location, deepCopy( arg1TyPtr->base ) ), 1311 1342 } ); 1312 1343 if ( expr->env ) divide->env = expr->env; 1313 1344 return divide; 1314 1345 // 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 ); 1316 1350 auto multiply = ast::UntypedExpr::createCall( location2, "?*?", { 1317 1351 expr->args.back(), 1318 new ast::SizeofExpr( location1, deepCopy( baseType1) ),1352 new ast::SizeofExpr( location1, deepCopy( arg1TyPtr->base ) ), 1319 1353 } ); 1320 1354 return ast::mutate_field_index( 1321 1355 expr, &ast::ApplicationExpr::args, 1, multiply ); 1322 1356 // 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 ); 1324 1361 auto multiply = ast::UntypedExpr::createCall( location1, "?*?", { 1325 1362 expr->args.front(), 1326 new ast::SizeofExpr( location2, deepCopy( baseType2) ),1363 new ast::SizeofExpr( location2, deepCopy( arg2TyPtr->base ) ), 1327 1364 } ); 1328 1365 return ast::mutate_field_index( … … 1588 1625 /// Change the type of generic aggregate members to char[]. 1589 1626 void mutateMembers( ast::AggregateDecl * aggr ); 1590 /// Returns the calculated sizeof expression for type, or nullptr for use1591 /// C sizeof().1627 /// Returns the calculated sizeof/alignof expressions for type, or 1628 /// nullptr for use C size/alignof(). 1592 1629 ast::Expr const * genSizeof( CodeLocation const &, ast::Type const * ); 1630 ast::Expr const * genAlignof( CodeLocation const &, ast::Type const * ); 1593 1631 /// Enters a new scope for type-variables, 1594 1632 /// adding the type variables from the provided type. … … 1613 1651 {} 1614 1652 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 1615 1672 /// 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]; 1675 ast::Type * polyToMonoType( CodeLocation const & loc, ast::Type const * ty ) { 1676 auto ret = polyToMonoTypeRec( loc, ty ); 1624 1677 ret->attributes.emplace_back( new ast::Attribute( "aligned", 1625 { ast::ConstantExpr::from_int( loc ation, 8 ) } ) );1678 { ast::ConstantExpr::from_int( loc, 8 ) } ) ); 1626 1679 return ret; 1627 1680 } … … 1716 1769 // Forally, side effects are not safe in this function. But it works. 1717 1770 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 } 1718 1792 1719 1793 mutDecl->init = new ast::SingleInit( decl->location, … … 1869 1943 ast::AlignofExpr const * expr ) { 1870 1944 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; 1877 1947 } 1878 1948 … … 2095 2165 2096 2166 return true; 2167 2168 } else if ( auto inst = dynamic_cast<ast::ArrayType const *>( type ) ) { 2169 return findGeneric( location, inst->base ); 2097 2170 } 2098 2171 return false; … … 2155 2228 return makeOp( location, "?*?", sizeofBase, dim ); 2156 2229 } else if ( findGeneric( location, type ) ) { 2157 // Generate calculated size for generic type.2230 // Generate reference to _sizeof parameter 2158 2231 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( 2159 2246 Mangle::mangleType( type ) ) ); 2160 2247 } else { -
TabularUnified tests/Makefile.am ¶
r3cb693c rfd4df379 69 69 .PHONY : concurrency list .validate .test_makeflags 70 70 .INTERMEDIATE : .validate .validate.cfa .test_makeflags 71 EXTRA_PROGRAMS = a vl_test linkonce linking/mangling/anon .dummy_hack # build but do not install71 EXTRA_PROGRAMS = array-collections/boxed avl_test linkonce linking/mangling/anon .dummy_hack # build but do not install 72 72 EXTRA_DIST = test.py \ 73 73 pybin/__init__.py \ … … 77 77 pybin/tools.py \ 78 78 long_tests.hfa \ 79 array-collections/boxed.hfa \ 80 array-collections/boxed.cases.hfa \ 79 81 avltree/avl-private.h \ 80 82 avltree/avl.h \ … … 104 106 done 105 107 108 array_collections_boxed_SOURCES = array-collections/boxed.main.cfa array-collections/boxed.bookend.cfa 106 109 avl_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 107 110 linkonce_SOURCES = link-once/main.cfa link-once/partner.cfa
Note: See TracChangeset
for help on using the changeset viewer.